Compare commits
10 Commits
pre_frontp
...
feat/packa
| Author | SHA1 | Date | |
|---|---|---|---|
| 2e95837116 | |||
| debbef8158 | |||
| 2799718951 | |||
| d9e4660fd4 | |||
| 305fdc41fb | |||
| 9deca8867e | |||
| df6056fb86 | |||
| c1553d9cd4 | |||
| 2b79adc2f7 | |||
| ddf1fd3515 |
@ -105,7 +105,7 @@ jobs:
|
|||||||
until pg_isready -h postgres -U postgres; do sleep 2; done
|
until pg_isready -h postgres -U postgres; do sleep 2; done
|
||||||
# until redis-cli -h redis ping; do sleep 2; done
|
# until redis-cli -h redis ping; do sleep 2; done
|
||||||
|
|
||||||
- name: Run Django migrations
|
- name: Run Django Migrations
|
||||||
run: |
|
run: |
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
python manage.py migrate --noinput
|
python manage.py migrate --noinput
|
||||||
|
|||||||
5
.gitignore
vendored
@ -10,3 +10,8 @@ scratches/
|
|||||||
data/
|
data/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
node_modules/
|
||||||
|
static/css/output.css
|
||||||
|
|
||||||
|
*.code-workspace
|
||||||
|
|||||||
@ -8,6 +8,7 @@ repos:
|
|||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
|
exclude: ^static/images/
|
||||||
|
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.13.3
|
rev: v0.13.3
|
||||||
@ -20,6 +21,15 @@ repos:
|
|||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
types_or: [python, pyi]
|
types_or: [python, pyi]
|
||||||
|
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: prettier-jinja-templates
|
||||||
|
name: Format Jinja templates with Prettier
|
||||||
|
entry: pnpm exec prettier --plugin=prettier-plugin-jinja-template --parser=jinja-template --write
|
||||||
|
language: system
|
||||||
|
types: [file]
|
||||||
|
files: ^templates/.*\.html$
|
||||||
|
|
||||||
# - repo: local
|
# - repo: local
|
||||||
# hooks:
|
# hooks:
|
||||||
# - id: django-check
|
# - id: django-check
|
||||||
|
|||||||
11
.prettierrc.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier-plugin-jinja-template", "prettier-plugin-tailwindcss"],
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "templates/**/*.html",
|
||||||
|
"options": {
|
||||||
|
"parser": "jinja-template"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
22
README.md
@ -7,11 +7,13 @@ These instructions will guide you through setting up the project for local devel
|
|||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Python 3.11 or later
|
- Python 3.11 or later
|
||||||
- [uv](https://github.com/astral-sh/uv) - A fast Python package installer and resolver.
|
- [uv](https://github.com/astral-sh/uv) - Python package manager
|
||||||
- **Docker and Docker Compose** - Required for running the PostgreSQL database.
|
- **Docker and Docker Compose** - Required for running PostgreSQL database
|
||||||
- Git
|
- Git
|
||||||
|
- Make
|
||||||
|
|
||||||
|
> **Note:** This application requires PostgreSQL (uses `ArrayField`). Docker is the easiest way to run PostgreSQL locally.
|
||||||
|
|
||||||
> **Note:** This application requires PostgreSQL, which uses `ArrayField`. Docker is the recommended way to run PostgreSQL locally.
|
|
||||||
|
|
||||||
### 1. Install Dependencies
|
### 1. Install Dependencies
|
||||||
|
|
||||||
@ -23,7 +25,12 @@ Then, sync the project dependencies. This will create a virtual environment in `
|
|||||||
uv sync --dev
|
uv sync --dev
|
||||||
```
|
```
|
||||||
|
|
||||||
> **Note on RDkit:** If you have a different version of rdkit installed globally, the dependency installation may fail. If this happens, please uninstall the global version and run `uv sync` again.
|
Note on RDkit installation: if you have rdkit installed on your system globally with a different version of python, the installation will try to link against that and subsequent calls fail. Only option remove global rdkit and rerun sync.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
The frontend requires `pnpm` to correctly display in development.
|
||||||
|
[Install it here](https://pnpm.io/installation).
|
||||||
|
|
||||||
### 2. Set Up Environment File
|
### 2. Set Up Environment File
|
||||||
|
|
||||||
@ -44,6 +51,7 @@ uv run poe setup
|
|||||||
```
|
```
|
||||||
|
|
||||||
This single command will:
|
This single command will:
|
||||||
|
|
||||||
1. Start the PostgreSQL database using Docker Compose.
|
1. Start the PostgreSQL database using Docker Compose.
|
||||||
2. Run database migrations.
|
2. Run database migrations.
|
||||||
3. Bootstrap initial data (anonymous user, default packages, models).
|
3. Bootstrap initial data (anonymous user, default packages, models).
|
||||||
@ -54,9 +62,12 @@ After setup, start the development server:
|
|||||||
uv run poe dev
|
uv run poe dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This will start the css-watcher as well as the django-development server,
|
||||||
The application will be available at `http://localhost:8000`.
|
The application will be available at `http://localhost:8000`.
|
||||||
|
|
||||||
#### Other useful Poe commands:
|
**Note:** The development server automatically starts a CSS watcher (`pnpm run dev`) alongside the Django server to rebuild CSS files when changes are detected. This ensures your styles are always up-to-date during development.
|
||||||
|
|
||||||
|
#### Other useful Poe commands
|
||||||
|
|
||||||
You can list all available commands by running `uv run poe --help`.
|
You can list all available commands by running `uv run poe --help`.
|
||||||
|
|
||||||
@ -66,6 +77,7 @@ uv run poe db-down # Stop PostgreSQL
|
|||||||
uv run poe migrate # Run migrations only
|
uv run poe migrate # Run migrations only
|
||||||
uv run poe bootstrap # Bootstrap data only
|
uv run poe bootstrap # Bootstrap data only
|
||||||
uv run poe shell # Open the Django shell
|
uv run poe shell # Open the Django shell
|
||||||
|
uv run poe build # Build frontend assets and collect static files
|
||||||
uv run poe clean # Remove database volumes (WARNING: destroys all data)
|
uv run poe clean # Remove database volumes (WARNING: destroys all data)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -87,12 +87,13 @@ TEMPLATES = [
|
|||||||
"django.template.context_processors.request",
|
"django.template.context_processors.request",
|
||||||
"django.contrib.auth.context_processors.auth",
|
"django.contrib.auth.context_processors.auth",
|
||||||
"django.contrib.messages.context_processors.messages",
|
"django.contrib.messages.context_processors.messages",
|
||||||
|
"epdb.context_processors.package_context",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
ALLOWED_HTML_TAGS = {'b', 'i', 'u', 'br', 'em', 'mark', 'p', 's', 'strong'}
|
ALLOWED_HTML_TAGS = {"b", "i", "u", "br", "em", "mark", "p", "s", "strong"}
|
||||||
|
|
||||||
WSGI_APPLICATION = "envipath.wsgi.application"
|
WSGI_APPLICATION = "envipath.wsgi.application"
|
||||||
|
|
||||||
@ -245,6 +246,7 @@ LOGGING = {
|
|||||||
ENVIFORMER_PRESENT = os.environ.get("ENVIFORMER_PRESENT", "False") == "True"
|
ENVIFORMER_PRESENT = os.environ.get("ENVIFORMER_PRESENT", "False") == "True"
|
||||||
ENVIFORMER_DEVICE = os.environ.get("ENVIFORMER_DEVICE", "cpu")
|
ENVIFORMER_DEVICE = os.environ.get("ENVIFORMER_DEVICE", "cpu")
|
||||||
|
|
||||||
|
|
||||||
# If celery is not present set always eager to true which will cause delayed tasks to block until finished
|
# If celery is not present set always eager to true which will cause delayed tasks to block until finished
|
||||||
FLAG_CELERY_PRESENT = os.environ.get("FLAG_CELERY_PRESENT", "False") == "True"
|
FLAG_CELERY_PRESENT = os.environ.get("FLAG_CELERY_PRESENT", "False") == "True"
|
||||||
if not FLAG_CELERY_PRESENT:
|
if not FLAG_CELERY_PRESENT:
|
||||||
@ -345,6 +347,14 @@ LOGIN_EXEMPT_URLS = [
|
|||||||
"/password_reset/",
|
"/password_reset/",
|
||||||
"/reset/",
|
"/reset/",
|
||||||
"/microsoft/",
|
"/microsoft/",
|
||||||
|
"/terms",
|
||||||
|
"/privacy",
|
||||||
|
"/cookie-policy",
|
||||||
|
"/about",
|
||||||
|
"/contact",
|
||||||
|
"/jobs",
|
||||||
|
"/cite",
|
||||||
|
"/legal",
|
||||||
]
|
]
|
||||||
|
|
||||||
# MS AD/Entra
|
# MS AD/Entra
|
||||||
|
|||||||
@ -21,6 +21,7 @@ from .models import (
|
|||||||
ExternalDatabase,
|
ExternalDatabase,
|
||||||
ExternalIdentifier,
|
ExternalIdentifier,
|
||||||
JobLog,
|
JobLog,
|
||||||
|
License,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -62,6 +63,10 @@ class EnviFormerAdmin(EPAdmin):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class LicenseAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ["cc_string", "link", "image_link"]
|
||||||
|
|
||||||
|
|
||||||
class CompoundAdmin(EPAdmin):
|
class CompoundAdmin(EPAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -118,6 +123,7 @@ admin.site.register(JobLog, JobLogAdmin)
|
|||||||
admin.site.register(Package, PackageAdmin)
|
admin.site.register(Package, PackageAdmin)
|
||||||
admin.site.register(MLRelativeReasoning, MLRelativeReasoningAdmin)
|
admin.site.register(MLRelativeReasoning, MLRelativeReasoningAdmin)
|
||||||
admin.site.register(EnviFormer, EnviFormerAdmin)
|
admin.site.register(EnviFormer, EnviFormerAdmin)
|
||||||
|
admin.site.register(License, LicenseAdmin)
|
||||||
admin.site.register(Compound, CompoundAdmin)
|
admin.site.register(Compound, CompoundAdmin)
|
||||||
admin.site.register(CompoundStructure, CompoundStructureAdmin)
|
admin.site.register(CompoundStructure, CompoundStructureAdmin)
|
||||||
admin.site.register(SimpleAmbitRule, SimpleAmbitRuleAdmin)
|
admin.site.register(SimpleAmbitRule, SimpleAmbitRuleAdmin)
|
||||||
|
|||||||
32
epdb/context_processors.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
"""
|
||||||
|
Context processors for enviPy application.
|
||||||
|
|
||||||
|
Context processors automatically make variables available to all templates.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .logic import PackageManager
|
||||||
|
from .models import Package
|
||||||
|
|
||||||
|
|
||||||
|
def package_context(request):
|
||||||
|
"""
|
||||||
|
Provides package data for the search modal which is included globally
|
||||||
|
in framework_modern.html.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: Context dictionary with reviewed and unreviewed packages
|
||||||
|
"""
|
||||||
|
current_user = request.user
|
||||||
|
|
||||||
|
reviewed_package_qs = PackageManager.get_reviewed_packages()
|
||||||
|
|
||||||
|
unreviewed_package_qs = Package.objects.none()
|
||||||
|
|
||||||
|
# Only get user-specific packages if user is authenticated
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
unreviewed_package_qs = PackageManager.get_all_readable_packages(current_user)
|
||||||
|
|
||||||
|
return {
|
||||||
|
"reviewed_packages": reviewed_package_qs,
|
||||||
|
"unreviewed_packages": unreviewed_package_qs,
|
||||||
|
}
|
||||||
@ -12,10 +12,16 @@ from epdb.models import (
|
|||||||
Permission,
|
Permission,
|
||||||
User,
|
User,
|
||||||
ExternalDatabase,
|
ExternalDatabase,
|
||||||
|
License,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"-ol", "--only-licenses", action="store_true", help="Only create licenses."
|
||||||
|
)
|
||||||
|
|
||||||
def create_users(self):
|
def create_users(self):
|
||||||
# Anonymous User
|
# Anonymous User
|
||||||
if not User.objects.filter(email="anon@envipath.com").exists():
|
if not User.objects.filter(email="anon@envipath.com").exists():
|
||||||
@ -83,6 +89,17 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
return anon, admin, g, user0
|
return anon, admin, g, user0
|
||||||
|
|
||||||
|
def create_licenses(self):
|
||||||
|
"""Create the six default licenses supported by enviPath"""
|
||||||
|
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
|
||||||
|
for cc_string in cc_strings:
|
||||||
|
if not License.objects.filter(cc_string=cc_string).exists():
|
||||||
|
new_license = License()
|
||||||
|
new_license.cc_string = cc_string
|
||||||
|
new_license.link = f"https://creativecommons.org/licenses/{cc_string}/4.0/"
|
||||||
|
new_license.image_link = f"https://licensebuttons.net/l/{cc_string}/4.0/88x31.png"
|
||||||
|
new_license.save()
|
||||||
|
|
||||||
def import_package(self, data, owner):
|
def import_package(self, data, owner):
|
||||||
return PackageManager.import_legacy_package(
|
return PackageManager.import_legacy_package(
|
||||||
data, owner, keep_ids=True, add_import_timestamp=False, trust_reviewed=True
|
data, owner, keep_ids=True, add_import_timestamp=False, trust_reviewed=True
|
||||||
@ -157,6 +174,10 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
# Create licenses
|
||||||
|
self.create_licenses()
|
||||||
|
if options.get("only_licenses", False):
|
||||||
|
return
|
||||||
# Create users
|
# Create users
|
||||||
anon, admin, g, user0 = self.create_users()
|
anon, admin, g, user0 = self.create_users()
|
||||||
|
|
||||||
|
|||||||
18
epdb/migrations/0010_license_cc_string.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2025-11-11 14:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("epdb", "0009_joblog"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="license",
|
||||||
|
name="cc_string",
|
||||||
|
field=models.TextField(default="by-nc-sa", verbose_name="CC string"),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
59
epdb/migrations/0011_auto_20251111_1413.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2025-11-11 14:13
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.contrib.postgres.aggregates import ArrayAgg
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db.models import Min
|
||||||
|
|
||||||
|
|
||||||
|
def set_cc(apps, schema_editor):
|
||||||
|
License = apps.get_model("epdb", "License")
|
||||||
|
|
||||||
|
# For all existing licenses extract cc_string from link
|
||||||
|
for license in License.objects.all():
|
||||||
|
pattern = r"/licenses/([^/]+)/4\.0"
|
||||||
|
match = re.search(pattern, license.link)
|
||||||
|
if match:
|
||||||
|
license.cc_string = match.group(1)
|
||||||
|
license.save()
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Could not find license for {license.link}")
|
||||||
|
|
||||||
|
# Ensure we have all licenses
|
||||||
|
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
|
||||||
|
for cc_string in cc_strings:
|
||||||
|
if not License.objects.filter(cc_string=cc_string).exists():
|
||||||
|
new_license = License()
|
||||||
|
new_license.cc_string = cc_string
|
||||||
|
new_license.link = f"https://creativecommons.org/licenses/{cc_string}/4.0/"
|
||||||
|
new_license.image_link = f"https://licensebuttons.net/l/{cc_string}/4.0/88x31.png"
|
||||||
|
new_license.save()
|
||||||
|
|
||||||
|
# As we might have existing Licenses representing the same License,
|
||||||
|
# get min pk and all pks as a list
|
||||||
|
license_lookup_qs = License.objects.values("cc_string").annotate(
|
||||||
|
lowest_pk=Min("id"), all_pks=ArrayAgg("id", order_by=("id",))
|
||||||
|
)
|
||||||
|
|
||||||
|
license_lookup = {
|
||||||
|
row["cc_string"]: (row["lowest_pk"], row["all_pks"]) for row in license_lookup_qs
|
||||||
|
}
|
||||||
|
|
||||||
|
Packages = apps.get_model("epdb", "Package")
|
||||||
|
|
||||||
|
for k, v in license_lookup.items():
|
||||||
|
# Set min pk to all packages pointing to any of the duplicates
|
||||||
|
Packages.objects.filter(pk__in=v[1]).update(license_id=v[0])
|
||||||
|
# remove the min pk from "other" pks as we use them for deletion
|
||||||
|
v[1].remove(v[0])
|
||||||
|
# Delete redundant License objects
|
||||||
|
License.objects.filter(pk__in=v[1]).delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("epdb", "0010_license_cc_string"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [migrations.RunPython(set_cc)]
|
||||||
@ -655,6 +655,7 @@ class ScenarioMixin(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class License(models.Model):
|
class License(models.Model):
|
||||||
|
cc_string = models.TextField(blank=False, null=False, verbose_name="CC string")
|
||||||
link = models.URLField(blank=False, null=False, verbose_name="link")
|
link = models.URLField(blank=False, null=False, verbose_name="link")
|
||||||
image_link = models.URLField(blank=False, null=False, verbose_name="Image link")
|
image_link = models.URLField(blank=False, null=False, verbose_name="Image link")
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import csv
|
import csv
|
||||||
import io
|
import io
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable, List, Optional
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
from celery.utils.functional import LRUCache
|
from celery.utils.functional import LRUCache
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
from epdb.logic import SPathway
|
from epdb.logic import SPathway
|
||||||
from epdb.models import EPModel, JobLog, Node, Package, Pathway, Rule, Setting, User, Edge
|
from epdb.models import Edge, EPModel, JobLog, Node, Package, Pathway, Rule, Setting, User
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
ML_CACHE = LRUCache(3) # Cache the three most recent ML models to reduce load times.
|
ML_CACHE = LRUCache(3) # Cache the three most recent ML models to reduce load times.
|
||||||
@ -29,7 +29,7 @@ def dispatch_eager(user: "User", job: Callable, *args, **kwargs):
|
|||||||
log.task_id = uuid4()
|
log.task_id = uuid4()
|
||||||
log.job_name = job.__name__
|
log.job_name = job.__name__
|
||||||
log.status = "SUCCESS"
|
log.status = "SUCCESS"
|
||||||
log.done_at = datetime.now()
|
log.done_at = timezone.now()
|
||||||
log.task_result = str(x) if x else None
|
log.task_result = str(x) if x else None
|
||||||
log.save()
|
log.save()
|
||||||
|
|
||||||
|
|||||||
15
epdb/urls.py
@ -48,6 +48,7 @@ urlpatterns = [
|
|||||||
re_path(r"^user$", v.users, name="users"),
|
re_path(r"^user$", v.users, name="users"),
|
||||||
re_path(r"^group$", v.groups, name="groups"),
|
re_path(r"^group$", v.groups, name="groups"),
|
||||||
re_path(r"^search$", v.search, name="search"),
|
re_path(r"^search$", v.search, name="search"),
|
||||||
|
re_path(r"^predict$", v.predict_pathway, name="predict_pathway"),
|
||||||
# User Detail
|
# User Detail
|
||||||
re_path(rf"^user/(?P<user_uuid>{UUID})", v.user, name="user"),
|
re_path(rf"^user/(?P<user_uuid>{UUID})", v.user, name="user"),
|
||||||
# Group Detail
|
# Group Detail
|
||||||
@ -141,6 +142,11 @@ urlpatterns = [
|
|||||||
v.package_pathway,
|
v.package_pathway,
|
||||||
name="package pathway detail",
|
name="package pathway detail",
|
||||||
),
|
),
|
||||||
|
re_path(
|
||||||
|
rf"^package/(?P<package_uuid>{UUID})/predict$",
|
||||||
|
v.package_predict_pathway,
|
||||||
|
name="package predict pathway",
|
||||||
|
),
|
||||||
# Pathway Nodes
|
# Pathway Nodes
|
||||||
re_path(
|
re_path(
|
||||||
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/node$",
|
rf"^package/(?P<package_uuid>{UUID})/pathway/(?P<pathway_uuid>{UUID})/node$",
|
||||||
@ -193,4 +199,13 @@ urlpatterns = [
|
|||||||
re_path(r"^jobs", v.jobs, name="jobs"),
|
re_path(r"^jobs", v.jobs, name="jobs"),
|
||||||
# OAuth Stuff
|
# OAuth Stuff
|
||||||
path("o/userinfo/", v.userinfo, name="oauth_userinfo"),
|
path("o/userinfo/", v.userinfo, name="oauth_userinfo"),
|
||||||
|
# Static Pages
|
||||||
|
re_path(r"^terms$", v.static_terms_of_use, name="terms_of_use"),
|
||||||
|
re_path(r"^privacy$", v.static_privacy_policy, name="privacy_policy"),
|
||||||
|
re_path(r"^cookie-policy$", v.static_cookie_policy, name="cookie_policy"),
|
||||||
|
re_path(r"^about$", v.static_about_us, name="about_us"),
|
||||||
|
re_path(r"^contact$", v.static_contact_support, name="contact_support"),
|
||||||
|
re_path(r"^careers$", v.static_careers, name="careers"),
|
||||||
|
re_path(r"^cite$", v.static_cite, name="cite"),
|
||||||
|
re_path(r"^legal$", v.static_legal, name="legal"),
|
||||||
]
|
]
|
||||||
|
|||||||
149
epdb/views.py
@ -90,6 +90,7 @@ def login(request):
|
|||||||
if username != request.POST.get("username"):
|
if username != request.POST.get("username"):
|
||||||
context["message"] = "Login failed!"
|
context["message"] = "Login failed!"
|
||||||
return render(request, "static/login.html", context)
|
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
|
||||||
@ -104,6 +105,7 @@ def login(request):
|
|||||||
except get_user_model().DoesNotExist:
|
except get_user_model().DoesNotExist:
|
||||||
context["message"] = "Login failed!"
|
context["message"] = "Login failed!"
|
||||||
return render(request, "static/login.html", context)
|
return render(request, "static/login.html", context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
user = authenticate(username=email, password=password)
|
user = authenticate(username=email, password=password)
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -141,9 +143,14 @@ def register(request):
|
|||||||
context = get_base_context(request)
|
context = get_base_context(request)
|
||||||
|
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
context["title"] = "enviPath"
|
# Redirect to unified login page with signup tab
|
||||||
context["next"] = request.GET.get("next", "")
|
next_url = request.GET.get("next", "")
|
||||||
return render(request, "static/register.html", context)
|
redirect_url = reverse("login") + "#signup"
|
||||||
|
|
||||||
|
if next_url:
|
||||||
|
redirect_url += f"?next={next_url}"
|
||||||
|
|
||||||
|
return redirect(redirect_url)
|
||||||
elif request.method == "POST":
|
elif request.method == "POST":
|
||||||
context["title"] = "enviPath"
|
context["title"] = "enviPath"
|
||||||
if next := request.POST.get("next"):
|
if next := request.POST.get("next"):
|
||||||
@ -156,18 +163,18 @@ def register(request):
|
|||||||
|
|
||||||
if not (username and email and password):
|
if not (username and email and password):
|
||||||
context["message"] = "Invalid username/email/password"
|
context["message"] = "Invalid username/email/password"
|
||||||
return render(request, "static/register.html", context)
|
return render(request, "static/login.html", context)
|
||||||
|
|
||||||
if password != rpassword or password == "":
|
if password != rpassword or password == "":
|
||||||
context["message"] = "Registration failed, provided passwords differ!"
|
context["message"] = "Registration failed, provided passwords differ!"
|
||||||
return render(request, "static/register.html", context)
|
return render(request, "static/login.html", context)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
u = UserManager.create_user(username, email, password)
|
u = UserManager.create_user(username, email, password)
|
||||||
logger.info(f"Created user {u.username} ({u.pk})")
|
logger.info(f"Created user {u.username} ({u.pk})")
|
||||||
except Exception:
|
except Exception:
|
||||||
context["message"] = "Registration failed! Couldn't create User Account."
|
context["message"] = "Registration failed! Couldn't create User Account."
|
||||||
return render(request, "static/register.html", context)
|
return render(request, "static/login.html", context)
|
||||||
|
|
||||||
if s.ADMIN_APPROVAL_REQUIRED:
|
if s.ADMIN_APPROVAL_REQUIRED:
|
||||||
context["success_message"] = (
|
context["success_message"] = (
|
||||||
@ -355,6 +362,34 @@ def index(request):
|
|||||||
return render(request, "index/index.html", context)
|
return render(request, "index/index.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def predict_pathway(request):
|
||||||
|
"""Top-level predict pathway view using user's default package."""
|
||||||
|
if request.method != "GET":
|
||||||
|
return HttpResponseNotAllowed(["GET"])
|
||||||
|
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Predict Pathway"
|
||||||
|
context["meta"]["current_package"] = context["meta"]["user"].default_package
|
||||||
|
|
||||||
|
return render(request, "predict_pathway.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
@package_permission_required()
|
||||||
|
def package_predict_pathway(request, package_uuid):
|
||||||
|
"""Package-specific predict pathway view."""
|
||||||
|
if request.method != "GET":
|
||||||
|
return HttpResponseNotAllowed(["GET"])
|
||||||
|
|
||||||
|
current_user = _anonymous_or_real(request)
|
||||||
|
current_package = PackageManager.get_package_by_id(current_user, package_uuid)
|
||||||
|
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = f"enviPath - {current_package.name} - Predict Pathway"
|
||||||
|
context["meta"]["current_package"] = current_package
|
||||||
|
|
||||||
|
return render(request, "predict_pathway.html", context)
|
||||||
|
|
||||||
|
|
||||||
def packages(request):
|
def packages(request):
|
||||||
current_user = _anonymous_or_real(request)
|
current_user = _anonymous_or_real(request)
|
||||||
|
|
||||||
@ -674,8 +709,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", "").strip()
|
||||||
|
|
||||||
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 +810,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")
|
||||||
|
|
||||||
@ -936,6 +971,12 @@ def package_model(request, package_uuid, model_uuid):
|
|||||||
]
|
]
|
||||||
dispatch(current_user, evaluate_model, current_model.pk, multigen, eval_package_ids)
|
dispatch(current_user, evaluate_model, current_model.pk, multigen, eval_package_ids)
|
||||||
|
|
||||||
|
return redirect(current_model.url)
|
||||||
|
elif hidden == "retrain":
|
||||||
|
from .tasks import dispatch, retrain
|
||||||
|
|
||||||
|
dispatch(current_user, retrain, current_model.pk)
|
||||||
|
|
||||||
return redirect(current_model.url)
|
return redirect(current_model.url)
|
||||||
else:
|
else:
|
||||||
return HttpResponseBadRequest()
|
return HttpResponseBadRequest()
|
||||||
@ -1065,9 +1106,7 @@ def package(request, package_uuid):
|
|||||||
write = request.POST.get("write") == "on"
|
write = request.POST.get("write") == "on"
|
||||||
owner = request.POST.get("owner") == "on"
|
owner = request.POST.get("owner") == "on"
|
||||||
|
|
||||||
license = request.POST.get("license")
|
cc_string = request.POST.get("license")
|
||||||
license_link = request.POST.get("license-link")
|
|
||||||
license_image_link = request.POST.get("license-image-link")
|
|
||||||
|
|
||||||
if new_package_name:
|
if new_package_name:
|
||||||
current_package.name = new_package_name
|
current_package.name = new_package_name
|
||||||
@ -1095,24 +1134,15 @@ def package(request, package_uuid):
|
|||||||
|
|
||||||
PackageManager.update_permissions(current_user, current_package, grantee, max_perm)
|
PackageManager.update_permissions(current_user, current_package, grantee, max_perm)
|
||||||
return redirect(current_package.url)
|
return redirect(current_package.url)
|
||||||
elif license is not None:
|
|
||||||
if license == "no-license":
|
|
||||||
if current_package.license is not None:
|
|
||||||
current_package.license.delete()
|
|
||||||
|
|
||||||
|
elif cc_string is not None:
|
||||||
|
cc_string = cc_string.strip()
|
||||||
|
if cc_string == "no-license": # Reset the package's license
|
||||||
current_package.license = None
|
current_package.license = None
|
||||||
current_package.save()
|
current_package.save()
|
||||||
return redirect(current_package.url)
|
return redirect(current_package.url)
|
||||||
else:
|
else: # Get the license and assign it to the package
|
||||||
if current_package.license is not None:
|
current_package.license = License.objects.get(cc_string=cc_string)
|
||||||
current_package.license.delete()
|
|
||||||
|
|
||||||
license = License()
|
|
||||||
license.link = license_link
|
|
||||||
license.image_link = license_image_link
|
|
||||||
license.save()
|
|
||||||
|
|
||||||
current_package.license = license
|
|
||||||
current_package.save()
|
current_package.save()
|
||||||
|
|
||||||
return redirect(current_package.url)
|
return redirect(current_package.url)
|
||||||
@ -1167,7 +1197,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)
|
||||||
@ -1294,7 +1324,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:
|
||||||
@ -1476,11 +1506,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":
|
||||||
@ -1677,8 +1707,7 @@ 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(".")
|
||||||
|
|
||||||
@ -2252,6 +2281,7 @@ 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")
|
||||||
|
|
||||||
@ -2894,3 +2924,60 @@ def userinfo(request):
|
|||||||
"email_verified": user.is_active,
|
"email_verified": user.is_active,
|
||||||
}
|
}
|
||||||
return JsonResponse(res)
|
return JsonResponse(res)
|
||||||
|
|
||||||
|
|
||||||
|
# Static Pages
|
||||||
|
def static_terms_of_use(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Terms of Use"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/terms_of_use.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_privacy_policy(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Privacy Policy"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/privacy_policy.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_cookie_policy(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Cookie Policy"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/cookie_policy.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_about_us(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - About Us"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/about_us.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_contact_support(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Contact & Support"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/contact.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_careers(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Careers"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/careers.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_cite(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - How to Cite"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/cite.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def static_legal(request):
|
||||||
|
context = get_base_context(request)
|
||||||
|
context["title"] = "enviPath - Legal Information"
|
||||||
|
context["public_mode"] = True
|
||||||
|
return render(request, "static/legal.html", context)
|
||||||
|
|||||||
25
package.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "envipy",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"description": "enviPath UI - Tailwind CSS + DaisyUI",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "tailwindcss -i static/css/input.css -o static/css/output.css --watch=always",
|
||||||
|
"build": "tailwindcss -i static/css/input.css -o static/css/output.css --minify"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/cli": "^4.1.16",
|
||||||
|
"@tailwindcss/postcss": "^4.1.16",
|
||||||
|
"daisyui": "^5.4.3",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"prettier": "^3.6.2",
|
||||||
|
"prettier-plugin-jinja-template": "^2.1.0",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.7.1",
|
||||||
|
"tailwindcss": "^4.1.16"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"django",
|
||||||
|
"tailwindcss",
|
||||||
|
"daisyui"
|
||||||
|
]
|
||||||
|
}
|
||||||
744
pnpm-lock.yaml
generated
@ -1,4 +1,740 @@
|
|||||||
lockfileVersion: 6.0
|
lockfileVersion: '9.0'
|
||||||
specifiers: {}
|
|
||||||
dependencies: {}
|
settings:
|
||||||
packages: {}
|
autoInstallPeers: true
|
||||||
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
importers:
|
||||||
|
|
||||||
|
.:
|
||||||
|
devDependencies:
|
||||||
|
'@tailwindcss/cli':
|
||||||
|
specifier: ^4.1.16
|
||||||
|
version: 4.1.16
|
||||||
|
'@tailwindcss/postcss':
|
||||||
|
specifier: ^4.1.16
|
||||||
|
version: 4.1.16
|
||||||
|
daisyui:
|
||||||
|
specifier: ^5.4.3
|
||||||
|
version: 5.4.3
|
||||||
|
postcss:
|
||||||
|
specifier: ^8.5.6
|
||||||
|
version: 8.5.6
|
||||||
|
prettier:
|
||||||
|
specifier: ^3.6.2
|
||||||
|
version: 3.6.2
|
||||||
|
prettier-plugin-jinja-template:
|
||||||
|
specifier: ^2.1.0
|
||||||
|
version: 2.1.0(prettier@3.6.2)
|
||||||
|
prettier-plugin-tailwindcss:
|
||||||
|
specifier: ^0.7.1
|
||||||
|
version: 0.7.1(prettier@3.6.2)
|
||||||
|
tailwindcss:
|
||||||
|
specifier: ^4.1.16
|
||||||
|
version: 4.1.16
|
||||||
|
|
||||||
|
packages:
|
||||||
|
|
||||||
|
'@alloc/quick-lru@5.2.0':
|
||||||
|
resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2':
|
||||||
|
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||||
|
engines: {node: '>=6.0.0'}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5':
|
||||||
|
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||||
|
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||||
|
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.1':
|
||||||
|
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [ia32]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.1':
|
||||||
|
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.1':
|
||||||
|
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||||
|
engines: {node: '>= 10.0.0'}
|
||||||
|
|
||||||
|
'@tailwindcss/cli@4.1.16':
|
||||||
|
resolution: {integrity: sha512-dsnANPrh2ZooHyZ/8uJhc9ecpcYtufToc21NY09NS9vF16rxPCjJ8dP7TUAtPqlUJTHSmRkN2hCdoYQIlgh4fw==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.1.16':
|
||||||
|
resolution: {integrity: sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw==}
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.1.16':
|
||||||
|
resolution: {integrity: sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.1.16':
|
||||||
|
resolution: {integrity: sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.1.16':
|
||||||
|
resolution: {integrity: sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.1.16':
|
||||||
|
resolution: {integrity: sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16':
|
||||||
|
resolution: {integrity: sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.1.16':
|
||||||
|
resolution: {integrity: sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.1.16':
|
||||||
|
resolution: {integrity: sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.1.16':
|
||||||
|
resolution: {integrity: sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.1.16':
|
||||||
|
resolution: {integrity: sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.1.16':
|
||||||
|
resolution: {integrity: sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q==}
|
||||||
|
engines: {node: '>=14.0.0'}
|
||||||
|
cpu: [wasm32]
|
||||||
|
bundledDependencies:
|
||||||
|
- '@napi-rs/wasm-runtime'
|
||||||
|
- '@emnapi/core'
|
||||||
|
- '@emnapi/runtime'
|
||||||
|
- '@tybys/wasm-util'
|
||||||
|
- '@emnapi/wasi-threads'
|
||||||
|
- tslib
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.1.16':
|
||||||
|
resolution: {integrity: sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.1.16':
|
||||||
|
resolution: {integrity: sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.1.16':
|
||||||
|
resolution: {integrity: sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg==}
|
||||||
|
engines: {node: '>= 10'}
|
||||||
|
|
||||||
|
'@tailwindcss/postcss@4.1.16':
|
||||||
|
resolution: {integrity: sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A==}
|
||||||
|
|
||||||
|
braces@3.0.3:
|
||||||
|
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
daisyui@5.4.3:
|
||||||
|
resolution: {integrity: sha512-dfDCJnN4utErGoWfElgdEE252FtfHV9Mxj5Dq1+JzUq3nVkluWdF3JYykP0Xy/y/yArnPXYztO1tLNCow3kjmg==}
|
||||||
|
|
||||||
|
detect-libc@1.0.3:
|
||||||
|
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
|
||||||
|
engines: {node: '>=0.10'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
detect-libc@2.1.2:
|
||||||
|
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
enhanced-resolve@5.18.3:
|
||||||
|
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
|
||||||
|
engines: {node: '>=10.13.0'}
|
||||||
|
|
||||||
|
fill-range@7.1.1:
|
||||||
|
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
graceful-fs@4.2.11:
|
||||||
|
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||||
|
|
||||||
|
is-extglob@2.1.1:
|
||||||
|
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-glob@4.0.3:
|
||||||
|
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
is-number@7.0.0:
|
||||||
|
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
|
||||||
|
engines: {node: '>=0.12.0'}
|
||||||
|
|
||||||
|
jiti@2.6.1:
|
||||||
|
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [android]
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [darwin]
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.30.2:
|
||||||
|
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [freebsd]
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||||
|
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
|
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
|
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
|
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
|
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [linux]
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.30.2:
|
||||||
|
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [arm64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.30.2:
|
||||||
|
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
cpu: [x64]
|
||||||
|
os: [win32]
|
||||||
|
|
||||||
|
lightningcss@1.30.2:
|
||||||
|
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
|
||||||
|
engines: {node: '>= 12.0.0'}
|
||||||
|
|
||||||
|
magic-string@0.30.21:
|
||||||
|
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
|
||||||
|
|
||||||
|
micromatch@4.0.8:
|
||||||
|
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||||
|
engines: {node: '>=8.6'}
|
||||||
|
|
||||||
|
mri@1.2.0:
|
||||||
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
nanoid@3.3.11:
|
||||||
|
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||||
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
node-addon-api@7.1.1:
|
||||||
|
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
|
||||||
|
|
||||||
|
picocolors@1.1.1:
|
||||||
|
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||||
|
|
||||||
|
picomatch@2.3.1:
|
||||||
|
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||||
|
engines: {node: '>=8.6'}
|
||||||
|
|
||||||
|
postcss@8.5.6:
|
||||||
|
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
|
||||||
|
engines: {node: ^10 || ^12 || >=14}
|
||||||
|
|
||||||
|
prettier-plugin-jinja-template@2.1.0:
|
||||||
|
resolution: {integrity: sha512-mzoCp2Oy9BDSug80fw3B3J4n4KQj1hRvoQOL1akqcDKBb5nvYxrik9zUEDs4AEJ6nK7QDTGoH0y9rx7AlnQ78Q==}
|
||||||
|
peerDependencies:
|
||||||
|
prettier: ^3.0.0
|
||||||
|
|
||||||
|
prettier-plugin-tailwindcss@0.7.1:
|
||||||
|
resolution: {integrity: sha512-Bzv1LZcuiR1Sk02iJTS1QzlFNp/o5l2p3xkopwOrbPmtMeh3fK9rVW5M3neBQzHq+kGKj/4LGQMTNcTH4NGPtQ==}
|
||||||
|
engines: {node: '>=20.19'}
|
||||||
|
peerDependencies:
|
||||||
|
'@ianvs/prettier-plugin-sort-imports': '*'
|
||||||
|
'@prettier/plugin-hermes': '*'
|
||||||
|
'@prettier/plugin-oxc': '*'
|
||||||
|
'@prettier/plugin-pug': '*'
|
||||||
|
'@shopify/prettier-plugin-liquid': '*'
|
||||||
|
'@trivago/prettier-plugin-sort-imports': '*'
|
||||||
|
'@zackad/prettier-plugin-twig': '*'
|
||||||
|
prettier: ^3.0
|
||||||
|
prettier-plugin-astro: '*'
|
||||||
|
prettier-plugin-css-order: '*'
|
||||||
|
prettier-plugin-jsdoc: '*'
|
||||||
|
prettier-plugin-marko: '*'
|
||||||
|
prettier-plugin-multiline-arrays: '*'
|
||||||
|
prettier-plugin-organize-attributes: '*'
|
||||||
|
prettier-plugin-organize-imports: '*'
|
||||||
|
prettier-plugin-sort-imports: '*'
|
||||||
|
prettier-plugin-svelte: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@ianvs/prettier-plugin-sort-imports':
|
||||||
|
optional: true
|
||||||
|
'@prettier/plugin-hermes':
|
||||||
|
optional: true
|
||||||
|
'@prettier/plugin-oxc':
|
||||||
|
optional: true
|
||||||
|
'@prettier/plugin-pug':
|
||||||
|
optional: true
|
||||||
|
'@shopify/prettier-plugin-liquid':
|
||||||
|
optional: true
|
||||||
|
'@trivago/prettier-plugin-sort-imports':
|
||||||
|
optional: true
|
||||||
|
'@zackad/prettier-plugin-twig':
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-astro:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-css-order:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-jsdoc:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-marko:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-multiline-arrays:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-organize-attributes:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-organize-imports:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-sort-imports:
|
||||||
|
optional: true
|
||||||
|
prettier-plugin-svelte:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
prettier@3.6.2:
|
||||||
|
resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==}
|
||||||
|
engines: {node: '>=14'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
source-map-js@1.2.1:
|
||||||
|
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
|
tailwindcss@4.1.16:
|
||||||
|
resolution: {integrity: sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==}
|
||||||
|
|
||||||
|
tapable@2.3.0:
|
||||||
|
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
|
||||||
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
to-regex-range@5.0.1:
|
||||||
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
|
engines: {node: '>=8.0'}
|
||||||
|
|
||||||
|
snapshots:
|
||||||
|
|
||||||
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
|
|
||||||
|
'@jridgewell/gen-mapping@0.3.13':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/remapping@2.3.5':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/gen-mapping': 0.3.13
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
|
||||||
|
'@jridgewell/resolve-uri@3.1.2': {}
|
||||||
|
|
||||||
|
'@jridgewell/sourcemap-codec@1.5.5': {}
|
||||||
|
|
||||||
|
'@jridgewell/trace-mapping@0.3.31':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
'@parcel/watcher-android-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-darwin-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-freebsd-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-arm64-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-glibc@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-linux-x64-musl@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-arm64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-ia32@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher-win32-x64@2.5.1':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@parcel/watcher@2.5.1':
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 1.0.3
|
||||||
|
is-glob: 4.0.3
|
||||||
|
micromatch: 4.0.8
|
||||||
|
node-addon-api: 7.1.1
|
||||||
|
optionalDependencies:
|
||||||
|
'@parcel/watcher-android-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-darwin-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-darwin-x64': 2.5.1
|
||||||
|
'@parcel/watcher-freebsd-x64': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm-musl': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm64-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-arm64-musl': 2.5.1
|
||||||
|
'@parcel/watcher-linux-x64-glibc': 2.5.1
|
||||||
|
'@parcel/watcher-linux-x64-musl': 2.5.1
|
||||||
|
'@parcel/watcher-win32-arm64': 2.5.1
|
||||||
|
'@parcel/watcher-win32-ia32': 2.5.1
|
||||||
|
'@parcel/watcher-win32-x64': 2.5.1
|
||||||
|
|
||||||
|
'@tailwindcss/cli@4.1.16':
|
||||||
|
dependencies:
|
||||||
|
'@parcel/watcher': 2.5.1
|
||||||
|
'@tailwindcss/node': 4.1.16
|
||||||
|
'@tailwindcss/oxide': 4.1.16
|
||||||
|
enhanced-resolve: 5.18.3
|
||||||
|
mri: 1.2.0
|
||||||
|
picocolors: 1.1.1
|
||||||
|
tailwindcss: 4.1.16
|
||||||
|
|
||||||
|
'@tailwindcss/node@4.1.16':
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/remapping': 2.3.5
|
||||||
|
enhanced-resolve: 5.18.3
|
||||||
|
jiti: 2.6.1
|
||||||
|
lightningcss: 1.30.2
|
||||||
|
magic-string: 0.30.21
|
||||||
|
source-map-js: 1.2.1
|
||||||
|
tailwindcss: 4.1.16
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-android-arm64@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-arm64@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-darwin-x64@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-freebsd-x64@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc@4.1.16':
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
'@tailwindcss/oxide@4.1.16':
|
||||||
|
optionalDependencies:
|
||||||
|
'@tailwindcss/oxide-android-arm64': 4.1.16
|
||||||
|
'@tailwindcss/oxide-darwin-arm64': 4.1.16
|
||||||
|
'@tailwindcss/oxide-darwin-x64': 4.1.16
|
||||||
|
'@tailwindcss/oxide-freebsd-x64': 4.1.16
|
||||||
|
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.16
|
||||||
|
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.16
|
||||||
|
'@tailwindcss/oxide-linux-arm64-musl': 4.1.16
|
||||||
|
'@tailwindcss/oxide-linux-x64-gnu': 4.1.16
|
||||||
|
'@tailwindcss/oxide-linux-x64-musl': 4.1.16
|
||||||
|
'@tailwindcss/oxide-wasm32-wasi': 4.1.16
|
||||||
|
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.16
|
||||||
|
'@tailwindcss/oxide-win32-x64-msvc': 4.1.16
|
||||||
|
|
||||||
|
'@tailwindcss/postcss@4.1.16':
|
||||||
|
dependencies:
|
||||||
|
'@alloc/quick-lru': 5.2.0
|
||||||
|
'@tailwindcss/node': 4.1.16
|
||||||
|
'@tailwindcss/oxide': 4.1.16
|
||||||
|
postcss: 8.5.6
|
||||||
|
tailwindcss: 4.1.16
|
||||||
|
|
||||||
|
braces@3.0.3:
|
||||||
|
dependencies:
|
||||||
|
fill-range: 7.1.1
|
||||||
|
|
||||||
|
daisyui@5.4.3: {}
|
||||||
|
|
||||||
|
detect-libc@1.0.3: {}
|
||||||
|
|
||||||
|
detect-libc@2.1.2: {}
|
||||||
|
|
||||||
|
enhanced-resolve@5.18.3:
|
||||||
|
dependencies:
|
||||||
|
graceful-fs: 4.2.11
|
||||||
|
tapable: 2.3.0
|
||||||
|
|
||||||
|
fill-range@7.1.1:
|
||||||
|
dependencies:
|
||||||
|
to-regex-range: 5.0.1
|
||||||
|
|
||||||
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
|
is-extglob@2.1.1: {}
|
||||||
|
|
||||||
|
is-glob@4.0.3:
|
||||||
|
dependencies:
|
||||||
|
is-extglob: 2.1.1
|
||||||
|
|
||||||
|
is-number@7.0.0: {}
|
||||||
|
|
||||||
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
|
lightningcss-android-arm64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-arm64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-darwin-x64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-freebsd-x64@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm-gnueabihf@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-gnu@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-arm64-musl@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-gnu@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-linux-x64-musl@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-arm64-msvc@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss-win32-x64-msvc@1.30.2:
|
||||||
|
optional: true
|
||||||
|
|
||||||
|
lightningcss@1.30.2:
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.1.2
|
||||||
|
optionalDependencies:
|
||||||
|
lightningcss-android-arm64: 1.30.2
|
||||||
|
lightningcss-darwin-arm64: 1.30.2
|
||||||
|
lightningcss-darwin-x64: 1.30.2
|
||||||
|
lightningcss-freebsd-x64: 1.30.2
|
||||||
|
lightningcss-linux-arm-gnueabihf: 1.30.2
|
||||||
|
lightningcss-linux-arm64-gnu: 1.30.2
|
||||||
|
lightningcss-linux-arm64-musl: 1.30.2
|
||||||
|
lightningcss-linux-x64-gnu: 1.30.2
|
||||||
|
lightningcss-linux-x64-musl: 1.30.2
|
||||||
|
lightningcss-win32-arm64-msvc: 1.30.2
|
||||||
|
lightningcss-win32-x64-msvc: 1.30.2
|
||||||
|
|
||||||
|
magic-string@0.30.21:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
|
micromatch@4.0.8:
|
||||||
|
dependencies:
|
||||||
|
braces: 3.0.3
|
||||||
|
picomatch: 2.3.1
|
||||||
|
|
||||||
|
mri@1.2.0: {}
|
||||||
|
|
||||||
|
nanoid@3.3.11: {}
|
||||||
|
|
||||||
|
node-addon-api@7.1.1: {}
|
||||||
|
|
||||||
|
picocolors@1.1.1: {}
|
||||||
|
|
||||||
|
picomatch@2.3.1: {}
|
||||||
|
|
||||||
|
postcss@8.5.6:
|
||||||
|
dependencies:
|
||||||
|
nanoid: 3.3.11
|
||||||
|
picocolors: 1.1.1
|
||||||
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
prettier-plugin-jinja-template@2.1.0(prettier@3.6.2):
|
||||||
|
dependencies:
|
||||||
|
prettier: 3.6.2
|
||||||
|
|
||||||
|
prettier-plugin-tailwindcss@0.7.1(prettier@3.6.2):
|
||||||
|
dependencies:
|
||||||
|
prettier: 3.6.2
|
||||||
|
|
||||||
|
prettier@3.6.2: {}
|
||||||
|
|
||||||
|
source-map-js@1.2.1: {}
|
||||||
|
|
||||||
|
tailwindcss@4.1.16: {}
|
||||||
|
|
||||||
|
tapable@2.3.0: {}
|
||||||
|
|
||||||
|
to-regex-range@5.0.1:
|
||||||
|
dependencies:
|
||||||
|
is-number: 7.0.0
|
||||||
|
|||||||
@ -67,22 +67,54 @@ docstring-code-format = true
|
|||||||
[tool.poe.tasks]
|
[tool.poe.tasks]
|
||||||
# Main tasks
|
# Main tasks
|
||||||
setup = { sequence = ["db-up", "migrate", "bootstrap"], help = "Complete setup: start database, run migrations, and bootstrap data" }
|
setup = { sequence = ["db-up", "migrate", "bootstrap"], help = "Complete setup: start database, run migrations, and bootstrap data" }
|
||||||
dev = { cmd = "python manage.py runserver", help = "Start the development server", deps = ["db-up"] }
|
dev = { shell = """
|
||||||
|
# Start pnpm CSS watcher in background
|
||||||
|
pnpm run dev &
|
||||||
|
PNPM_PID=$!
|
||||||
|
echo "Started CSS watcher (PID: $PNPM_PID)"
|
||||||
|
|
||||||
|
# Cleanup function
|
||||||
|
cleanup() {
|
||||||
|
echo "\nShutting down..."
|
||||||
|
if kill -0 $PNPM_PID 2>/dev/null; then
|
||||||
|
kill $PNPM_PID
|
||||||
|
echo "✓ CSS watcher stopped"
|
||||||
|
fi
|
||||||
|
if [ ! -z "${DJ_PID:-}" ] && kill -0 $DJ_PID 2>/dev/null; then
|
||||||
|
kill $DJ_PID
|
||||||
|
echo "✓ Django server stopped"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set trap for cleanup
|
||||||
|
trap cleanup EXIT INT TERM
|
||||||
|
|
||||||
|
# Start Django dev server in background
|
||||||
|
uv run python manage.py runserver &
|
||||||
|
DJ_PID=$!
|
||||||
|
|
||||||
|
# Wait for Django to finish
|
||||||
|
wait $DJ_PID
|
||||||
|
""", help = "Start the development server with CSS watcher", deps = ["db-up", "js-deps"] }
|
||||||
|
build = { sequence = ["build-frontend", "collectstatic"], help = "Build frontend assets and collect static files" }
|
||||||
|
|
||||||
# Database tasks
|
# Database tasks
|
||||||
db-up = { cmd = "docker compose -f docker-compose.dev.yml up -d", help = "Start PostgreSQL database using Docker Compose" }
|
db-up = { cmd = "docker compose -f docker-compose.dev.yml up -d", help = "Start PostgreSQL database using Docker Compose" }
|
||||||
db-down = { cmd = "docker compose -f docker-compose.dev.yml down", help = "Stop PostgreSQL database" }
|
db-down = { cmd = "docker compose -f docker-compose.dev.yml down", help = "Stop PostgreSQL database" }
|
||||||
|
|
||||||
|
# Frontend tasks
|
||||||
|
js-deps = { cmd = "pnpm install", help = "Install frontend dependencies" }
|
||||||
|
|
||||||
# Full cleanup tasks
|
# Full cleanup tasks
|
||||||
clean = { sequence = ["clean-db"], help = "Remove model files and database volumes (WARNING: destroys all data!)" }
|
clean = { sequence = ["clean-db"], help = "Remove model files and database volumes (WARNING: destroys all data!)" }
|
||||||
clean-db = { cmd = "docker compose -f docker-compose.dev.yml down -v", help = "Removes the database container and volume." }
|
clean-db = { cmd = "docker compose -f docker-compose.dev.yml down -v", help = "Removes the database container and volume." }
|
||||||
|
|
||||||
# Django tasks
|
# Django tasks
|
||||||
migrate = { cmd = "python manage.py migrate", help = "Run database migrations" }
|
migrate = { cmd = "uv run python manage.py migrate", help = "Run database migrations" }
|
||||||
bootstrap = { shell = """
|
bootstrap = { shell = """
|
||||||
echo "Bootstrapping initial data..."
|
echo "Bootstrapping initial data..."
|
||||||
echo "This will take a bit ⏱️. Get yourself some coffee..."
|
echo "This will take a bit ⏱️. Get yourself some coffee..."
|
||||||
python manage.py bootstrap
|
uv run python manage.py bootstrap
|
||||||
echo "✓ Bootstrap complete"
|
echo "✓ Bootstrap complete"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Default admin credentials:"
|
echo "Default admin credentials:"
|
||||||
@ -90,4 +122,8 @@ echo " Username: admin"
|
|||||||
echo " Email: admin@envipath.com"
|
echo " Email: admin@envipath.com"
|
||||||
echo " Password: SuperSafe"
|
echo " Password: SuperSafe"
|
||||||
""", help = "Bootstrap initial data (anonymous user, packages, models)" }
|
""", help = "Bootstrap initial data (anonymous user, packages, models)" }
|
||||||
shell = { cmd = "python manage.py shell", help = "Open Django shell" }
|
shell = { cmd = "uv run python manage.py shell", help = "Open Django shell" }
|
||||||
|
|
||||||
|
# Build tasks
|
||||||
|
build-frontend = { cmd = "pnpm run build", help = "Build frontend assets using pnpm", deps = ["js-deps"] }
|
||||||
|
collectstatic = { cmd = "uv run python manage.py collectstatic --noinput", help = "Collect static files for production", deps = ["build-frontend"] }
|
||||||
|
|||||||
84
static/css/daisyui-theme.css
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/**
|
||||||
|
* DaisyUI Themes - Generated by Style Dictionary
|
||||||
|
* Theme mappings defined in tokens/daisyui-themes.json
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Light theme (default) */
|
||||||
|
@plugin "daisyui/theme" {
|
||||||
|
name: "envipath";
|
||||||
|
default: true;
|
||||||
|
color-scheme: light;
|
||||||
|
|
||||||
|
--color-base-100: var(--color-neutral-50);
|
||||||
|
--color-base-200: var(--color-neutral-100);
|
||||||
|
--color-base-300: var(--color-neutral-200);
|
||||||
|
--color-base-content: var(--color-neutral-900);
|
||||||
|
--color-primary: var(--color-primary-500);
|
||||||
|
--color-primary-content: var(--color-primary-50);
|
||||||
|
--color-secondary: var(--color-secondary-500);
|
||||||
|
--color-secondary-content: var(--color-secondary-50);
|
||||||
|
--color-accent: var(--color-accent-500);
|
||||||
|
--color-accent-content: var(--color-accent-50);
|
||||||
|
--color-neutral: var(--color-neutral-950);
|
||||||
|
--color-neutral-content: var(--color-neutral-100);
|
||||||
|
--color-info: var(--color-info-500);
|
||||||
|
--color-info-content: var(--color-info-950);
|
||||||
|
--color-success: var(--color-success-500);
|
||||||
|
--color-success-content: var(--color-success-950);
|
||||||
|
--color-warning: var(--color-warning-500);
|
||||||
|
--color-warning-content: var(--color-warning-950);
|
||||||
|
--color-error: var(--color-error-500);
|
||||||
|
--color-error-content: var(--color-error-950);
|
||||||
|
|
||||||
|
/* border radius */
|
||||||
|
--radius-selector: 1rem;
|
||||||
|
--radius-field: 0.25rem;
|
||||||
|
--radius-box: 0.5rem;
|
||||||
|
|
||||||
|
/* base sizes */
|
||||||
|
--size-selector: 0.25rem;
|
||||||
|
--size-field: 0.25rem;
|
||||||
|
|
||||||
|
/* border size */
|
||||||
|
--border: 1px;
|
||||||
|
|
||||||
|
/* effects */
|
||||||
|
--depth: 1;
|
||||||
|
--noise: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark theme (prefers-color-scheme: dark) */
|
||||||
|
@plugin "daisyui/theme" {
|
||||||
|
name: "envipath-dark";
|
||||||
|
prefersdark: true;
|
||||||
|
color-scheme: dark;
|
||||||
|
|
||||||
|
--color-primary: var(--color-primary-400);
|
||||||
|
--color-primary-content: var(--color-neutral-950);
|
||||||
|
--color-secondary: var(--color-secondary-400);
|
||||||
|
--color-secondary-content: var(--color-neutral-950);
|
||||||
|
--color-accent: var(--color-primary-500);
|
||||||
|
--color-accent-content: var(--color-neutral-950);
|
||||||
|
--color-neutral: var(--color-neutral-300);
|
||||||
|
--color-neutral-content: var(--color-neutral-900);
|
||||||
|
--color-base-100: var(--color-neutral-900);
|
||||||
|
--color-base-200: var(--color-neutral-800);
|
||||||
|
--color-base-300: var(--color-neutral-700);
|
||||||
|
--color-base-content: var(--color-neutral-50);
|
||||||
|
--color-info: var(--color-primary-400);
|
||||||
|
--color-info-content: var(--color-neutral-950);
|
||||||
|
--color-success: var(--color-success-400);
|
||||||
|
--color-success-content: var(--color-neutral-950);
|
||||||
|
--color-warning: var(--color-warning-400);
|
||||||
|
--color-warning-content: var(--color-neutral-950);
|
||||||
|
--color-error: var(--color-error-400);
|
||||||
|
--color-error-content: var(--color-neutral-950);
|
||||||
|
--radius-selector: 1rem;
|
||||||
|
--radius-field: 0.25rem;
|
||||||
|
--radius-box: 0.5rem;
|
||||||
|
--size-selector: 0.25rem;
|
||||||
|
--size-field: 0.25rem;
|
||||||
|
--border: 1px;
|
||||||
|
--depth: 1;
|
||||||
|
--noise: 0;
|
||||||
|
}
|
||||||
36
static/css/input.css
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* fira-code-latin-wght-normal */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Fira Code Variable';
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
font-weight: 300 700;
|
||||||
|
src: url(https://cdn.jsdelivr.net/fontsource/fonts/fira-code:vf@latest/latin-wght-normal.woff2) format('woff2-variations');
|
||||||
|
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inter-latin-wght-normal */
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter Variable';
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
font-weight: 100 900;
|
||||||
|
src: url(https://cdn.jsdelivr.net/fontsource/fonts/inter:vf@latest/latin-wght-normal.woff2) format('woff2-variations');
|
||||||
|
unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tell Tailwind where to find Django templates and Python files */
|
||||||
|
@source "../../templates";
|
||||||
|
|
||||||
|
/* Custom theme configuration - must come before plugins */
|
||||||
|
@import "./theme.css";
|
||||||
|
|
||||||
|
/* Import DaisyUI plugin */
|
||||||
|
@plugin "daisyui" {
|
||||||
|
logs: true;
|
||||||
|
exclude: rootscrollgutter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@import "./daisyui-theme.css";
|
||||||
111
static/css/theme.css
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* Tailwind v4 Theme - Generated by Style Dictionary
|
||||||
|
* This creates Tailwind utility classes from design tokens
|
||||||
|
*/
|
||||||
|
|
||||||
|
@theme {
|
||||||
|
/* Colors */
|
||||||
|
--color-primary-50: oklch(0.98 0.02 201);
|
||||||
|
--color-primary-100: oklch(0.96 0.04 203);
|
||||||
|
--color-primary-200: oklch(0.92 0.08 205);
|
||||||
|
--color-primary-300: oklch(0.87 0.12 207);
|
||||||
|
--color-primary-400: oklch(0.80 0.13 212);
|
||||||
|
--color-primary-500: oklch(0.71 0.13 215);
|
||||||
|
--color-primary-600: oklch(0.61 0.11 222);
|
||||||
|
--color-primary-700: oklch(0.52 0.09 223);
|
||||||
|
--color-primary-800: oklch(0.45 0.08 224);
|
||||||
|
--color-primary-900: oklch(0.40 0.07 227);
|
||||||
|
--color-primary-950: oklch(0.30 0.05 230);
|
||||||
|
--color-secondary-50: oklch(0.98 0.02 166);
|
||||||
|
--color-secondary-100: oklch(0.95 0.05 163);
|
||||||
|
--color-secondary-200: oklch(0.90 0.09 164);
|
||||||
|
--color-secondary-300: oklch(0.85 0.13 165);
|
||||||
|
--color-secondary-400: oklch(0.77 0.15 163);
|
||||||
|
--color-secondary-500: oklch(0.70 0.15 162);
|
||||||
|
--color-secondary-600: oklch(0.60 0.13 163);
|
||||||
|
--color-secondary-700: oklch(0.51 0.10 166);
|
||||||
|
--color-secondary-800: oklch(0.43 0.09 167);
|
||||||
|
--color-secondary-900: oklch(0.38 0.07 169);
|
||||||
|
--color-secondary-950: oklch(0.26 0.05 173);
|
||||||
|
--color-success-50: oklch(0.98 0.02 156);
|
||||||
|
--color-success-100: oklch(0.96 0.04 157);
|
||||||
|
--color-success-200: oklch(0.93 0.08 156);
|
||||||
|
--color-success-300: oklch(0.87 0.14 154);
|
||||||
|
--color-success-400: oklch(0.80 0.18 152);
|
||||||
|
--color-success-500: oklch(0.72 0.19 150);
|
||||||
|
--color-success-600: oklch(0.63 0.17 149);
|
||||||
|
--color-success-700: oklch(0.53 0.14 150);
|
||||||
|
--color-success-800: oklch(0.45 0.11 151);
|
||||||
|
--color-success-900: oklch(0.39 0.09 153);
|
||||||
|
--color-success-950: oklch(0.27 0.06 153);
|
||||||
|
--color-warning-50: oklch(0.99 0.03 102);
|
||||||
|
--color-warning-100: oklch(0.97 0.07 103);
|
||||||
|
--color-warning-200: oklch(0.95 0.12 102);
|
||||||
|
--color-warning-300: oklch(0.91 0.17 98);
|
||||||
|
--color-warning-400: oklch(0.86 0.17 92);
|
||||||
|
--color-warning-500: oklch(0.80 0.16 86);
|
||||||
|
--color-warning-600: oklch(0.68 0.14 76);
|
||||||
|
--color-warning-700: oklch(0.55 0.12 66);
|
||||||
|
--color-warning-800: oklch(0.48 0.10 62);
|
||||||
|
--color-warning-900: oklch(0.42 0.09 58);
|
||||||
|
--color-warning-950: oklch(0.29 0.06 54);
|
||||||
|
--color-error-50: oklch(0.97 0.01 17);
|
||||||
|
--color-error-100: oklch(0.94 0.03 18);
|
||||||
|
--color-error-200: oklch(0.88 0.06 18);
|
||||||
|
--color-error-300: oklch(0.81 0.10 20);
|
||||||
|
--color-error-400: oklch(0.71 0.17 22);
|
||||||
|
--color-error-500: oklch(0.64 0.21 25);
|
||||||
|
--color-error-600: oklch(0.58 0.22 27);
|
||||||
|
--color-error-700: oklch(0.51 0.19 28);
|
||||||
|
--color-error-800: oklch(0.44 0.16 27);
|
||||||
|
--color-error-900: oklch(0.40 0.13 26);
|
||||||
|
--color-error-950: oklch(0.26 0.09 26);
|
||||||
|
--color-neutral-50: oklch(0.98 0.00 248);
|
||||||
|
--color-neutral-100: oklch(0.97 0.01 248);
|
||||||
|
--color-neutral-200: oklch(0.93 0.01 256);
|
||||||
|
--color-neutral-300: oklch(0.87 0.02 253);
|
||||||
|
--color-neutral-400: oklch(0.71 0.04 257);
|
||||||
|
--color-neutral-500: oklch(0.55 0.04 257);
|
||||||
|
--color-neutral-600: oklch(0.45 0.04 257);
|
||||||
|
--color-neutral-700: oklch(0.37 0.04 257);
|
||||||
|
--color-neutral-800: oklch(0.28 0.04 260);
|
||||||
|
--color-neutral-900: oklch(0.28 0.04 260);
|
||||||
|
--color-neutral-950: oklch(0.28 0.04 260);
|
||||||
|
|
||||||
|
/* Spacing */
|
||||||
|
--spacing-0: 0;
|
||||||
|
--spacing-1: 0.25rem;
|
||||||
|
--spacing-2: 0.5rem;
|
||||||
|
--spacing-3: 0.75rem;
|
||||||
|
--spacing-4: 1rem;
|
||||||
|
--spacing-5: 1.25rem;
|
||||||
|
--spacing-6: 1.5rem;
|
||||||
|
--spacing-7: 1.75rem;
|
||||||
|
--spacing-8: 2rem;
|
||||||
|
--spacing-10: 2.5rem;
|
||||||
|
--spacing-12: 3rem;
|
||||||
|
--spacing-16: 4rem;
|
||||||
|
--spacing-20: 5rem;
|
||||||
|
--spacing-24: 6rem;
|
||||||
|
--spacing-32: 8rem;
|
||||||
|
--spacing-40: 10rem;
|
||||||
|
--spacing-48: 12rem;
|
||||||
|
--spacing-56: 14rem;
|
||||||
|
--spacing-64: 16rem;
|
||||||
|
|
||||||
|
/* Typography */
|
||||||
|
--font-family-sans: 'Inter Variable', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
--font-family-mono: 'Fira Code Variable', 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, monospace;
|
||||||
|
--font-family-base: 'Inter Variable', system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
||||||
|
--font-size-xs: 0.75rem;
|
||||||
|
--font-size-sm: 0.875rem;
|
||||||
|
--font-size-base: 1rem;
|
||||||
|
--font-size-lg: 1.125rem;
|
||||||
|
--font-size-xl: 1.25rem;
|
||||||
|
--font-size-2xl: 1.5rem;
|
||||||
|
--font-size-3xl: 1.875rem;
|
||||||
|
--font-size-4xl: 2.25rem;
|
||||||
|
--font-size-5xl: 3rem;
|
||||||
|
--font-size-6xl: 3.75rem;
|
||||||
|
--font-size-7xl: 4.5rem;
|
||||||
|
}
|
||||||
BIN
static/images/ep-rule-artwork.png
Normal file
|
After Width: | Height: | Size: 252 KiB |
BIN
static/images/hero.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
static/images/linkedin.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
3
static/images/logo-eawag.svg
Normal file
|
After Width: | Height: | Size: 21 KiB |
@ -1,225 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
||||||
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
version="1.1"
|
|
||||||
width="314.98749"
|
|
||||||
height="28.8125"
|
|
||||||
id="svg3004"
|
|
||||||
xml:space="preserve"><metadata
|
|
||||||
id="metadata3010"><rdf:RDF><cc:Work
|
|
||||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
|
||||||
id="defs3008" /><g
|
|
||||||
transform="matrix(1.25,0,0,-1.25,0,28.8125)"
|
|
||||||
id="g3012"><g
|
|
||||||
transform="scale(0.1,0.1)"
|
|
||||||
id="g3014"><path
|
|
||||||
d="m 957.473,175.816 0,-4.296 -18.453,0 0,-48.614 -5.04,0 0,48.614 -18.378,0 0,4.296 41.871,0"
|
|
||||||
id="path3016"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 969.695,175.816 0,-22.968 31.425,0 0,22.968 5.04,0 0,-52.91 -5.04,0 0,25.637 -31.425,0 0,-25.637 -5.039,0 0,52.91 5.039,0"
|
|
||||||
id="path3018"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1055.58,175.816 0,-4.296 -31.49,0 0,-19.122 29.49,0 0,-4.293 -29.49,0 0,-20.898 31.87,0 0,-4.301 -36.91,0 0,52.91 36.53,0"
|
|
||||||
id="path3020"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1124.58,175.816 0,-4.296 -31.5,0 0,-19.122 29.49,0 0,-4.293 -29.49,0 0,-20.898 31.87,0 0,-4.301 -36.91,0 0,52.91 36.54,0"
|
|
||||||
id="path3022"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1139.76,175.816 30.83,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.64,0 -30.82,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
|
||||||
id="path3024"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1188.15,175.816 17.19,-47.355 0.15,0 17.06,47.355 5.34,0 -19.65,-52.91 -5.86,0 -19.56,52.91 5.33,0"
|
|
||||||
id="path3026"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1235.15,122.906 5.043,0 0,52.9102 -5.043,0 0,-52.9102 z"
|
|
||||||
id="path3028"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1277.3,150.691 c 1.54,0 2.99,0.243 4.38,0.711 1.39,0.469 2.59,1.145 3.63,2.036 1.04,0.886 1.86,1.968 2.48,3.222 0.63,1.258 0.92,2.703 0.92,4.336 0,3.262 -0.94,5.824 -2.81,7.703 -1.88,1.875 -4.74,2.821 -8.6,2.821 l -18.82,0 0,-20.829 18.82,0 z m 0.38,25.125 c 2.16,0 4.23,-0.269 6.19,-0.816 1.95,-0.543 3.65,-1.367 5.1,-2.48 1.46,-1.118 2.62,-2.54 3.49,-4.297 0.86,-1.758 1.29,-3.821 1.29,-6.192 0,-3.359 -0.86,-6.273 -2.6,-8.742 -1.72,-2.473 -4.29,-4.055 -7.69,-4.746 l 0,-0.145 c 1.73,-0.25 3.16,-0.703 4.29,-1.367 1.14,-0.668 2.06,-1.527 2.78,-2.558 0.72,-1.035 1.23,-2.239 1.56,-3.594 0.31,-1.363 0.53,-2.832 0.62,-4.41 0.05,-0.887 0.1,-1.977 0.16,-3.262 0.05,-1.285 0.15,-2.582 0.29,-3.891 0.15,-1.312 0.38,-2.543 0.71,-3.711 0.32,-1.156 0.74,-2.054 1.3,-2.699 l -5.56,0 c -0.29,0.496 -0.54,1.098 -0.7,1.809 -0.18,0.723 -0.31,1.461 -0.37,2.234 -0.08,0.762 -0.14,1.512 -0.2,2.254 -0.05,0.742 -0.1,1.387 -0.14,1.926 -0.09,1.875 -0.26,3.742 -0.49,5.598 -0.22,1.851 -0.69,3.503 -1.4,4.961 -0.72,1.46 -1.76,2.632 -3.11,3.523 -1.36,0.887 -3.23,1.281 -5.6,1.191 l -19.12,0 0,-23.496 -5.03,0 0,52.91 24.23,0"
|
|
||||||
id="path3030"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1308.46,140.879 c 0.77,-2.793 1.95,-5.289 3.56,-7.484 1.61,-2.2 3.66,-3.965 6.19,-5.301 2.52,-1.336 5.54,-2.004 9.04,-2.004 3.51,0 6.51,0.668 9,2.004 2.5,1.336 4.55,3.101 6.15,5.301 1.6,2.195 2.8,4.691 3.56,7.484 0.77,2.789 1.15,5.613 1.15,8.48 0,2.914 -0.38,5.758 -1.15,8.52 -0.76,2.769 -1.96,5.25 -3.56,7.449 -1.6,2.199 -3.65,3.969 -6.15,5.297 -2.49,1.336 -5.49,2.008 -9,2.008 -3.5,0 -6.52,-0.672 -9.04,-2.008 -2.53,-1.328 -4.58,-3.098 -6.19,-5.297 -1.61,-2.199 -2.79,-4.68 -3.56,-7.449 -0.75,-2.762 -1.15,-5.606 -1.15,-8.52 0,-2.867 0.4,-5.691 1.15,-8.48 z m -4.63,18.934 c 1.04,3.308 2.6,6.23 4.67,8.777 2.08,2.547 4.68,4.57 7.82,6.078 3.14,1.504 6.79,2.254 10.93,2.254 4.15,0 7.78,-0.75 10.89,-2.254 3.11,-1.508 5.71,-3.531 7.78,-6.078 2.08,-2.547 3.64,-5.469 4.67,-8.777 1.05,-3.313 1.56,-6.797 1.56,-10.454 0,-3.656 -0.51,-7.136 -1.56,-10.449 -1.03,-3.308 -2.59,-6.226 -4.67,-8.738 -2.07,-2.52 -4.67,-4.531 -7.78,-6.043 -3.11,-1.5 -6.74,-2.266 -10.89,-2.266 -4.14,0 -7.79,0.766 -10.93,2.266 -3.14,1.512 -5.74,3.523 -7.82,6.043 -2.07,2.512 -3.63,5.43 -4.67,8.738 -1.04,3.313 -1.54,6.793 -1.54,10.449 0,3.657 0.5,7.141 1.54,10.454"
|
|
||||||
id="path3032"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1367.77,175.816 30.84,-44.757 0.15,0 0,44.757 5.05,0 0,-52.91 -5.64,0 -30.83,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.62,0"
|
|
||||||
id="path3034"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1423.89,175.816 18.3,-46.386 18.22,46.386 7.41,0 0,-52.91 -5.03,0 0,45.723 -0.15,0 -18.09,-45.723 -4.74,0 -18.15,45.723 -0.15,0 0,-45.723 -5.04,0 0,52.91 7.42,0"
|
|
||||||
id="path3036"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1517.1,175.816 0,-4.296 -31.48,0 0,-19.122 29.48,0 0,-4.293 -29.48,0 0,-20.898 31.86,0 0,-4.301 -36.9,0 0,52.91 36.52,0"
|
|
||||||
id="path3038"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1532.29,175.816 30.82,-44.757 0.14,0 0,44.757 5.03,0 0,-52.91 -5.62,0 -30.81,44.754 -0.15,0 0,-44.754 -5.03,0 0,52.91 5.62,0"
|
|
||||||
id="path3040"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1617.34,175.816 0,-4.296 -18.44,0 0,-48.614 -5.04,0 0,48.614 -18.38,0 0,4.296 41.86,0"
|
|
||||||
id="path3042"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1647.8,143.656 -10.22,27.121 -10.6,-27.121 20.82,0 z m -7.18,32.16 20.74,-52.91 -5.4,0 -6.46,16.449 -24.07,0 -6.38,-16.449 -5.33,0 21.26,52.91 5.64,0"
|
|
||||||
id="path3044"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1673.44,175.816 0,-48.609 29.65,0 0,-4.301 -34.68,0 0,52.91 5.03,0"
|
|
||||||
id="path3046"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1769.74,165.254 c -1.02,1.605 -2.25,2.953 -3.71,4.043 -1.46,1.082 -3.06,1.914 -4.81,2.48 -1.76,0.567 -3.6,0.856 -5.52,0.856 -3.51,0 -6.53,-0.672 -9.05,-2.008 -2.52,-1.328 -4.58,-3.098 -6.18,-5.297 -1.61,-2.199 -2.8,-4.68 -3.56,-7.449 -0.77,-2.762 -1.15,-5.606 -1.15,-8.52 0,-2.867 0.38,-5.691 1.15,-8.48 0.76,-2.793 1.95,-5.289 3.56,-7.484 1.6,-2.2 3.66,-3.965 6.18,-5.301 2.52,-1.336 5.54,-2.004 9.05,-2.004 2.46,0 4.69,0.449 6.66,1.336 1.98,0.89 3.68,2.101 5.12,3.633 1.43,1.523 2.59,3.324 3.48,5.371 0.89,2.05 1.45,4.261 1.71,6.633 l 5.03,0 c -0.35,-3.258 -1.11,-6.204 -2.3,-8.821 -1.18,-2.617 -2.7,-4.84 -4.59,-6.664 -1.88,-1.824 -4.08,-3.238 -6.63,-4.223 -2.54,-0.992 -5.37,-1.492 -8.48,-1.492 -4.17,0 -7.81,0.766 -10.93,2.266 -3.15,1.512 -5.76,3.523 -7.83,6.043 -2.07,2.512 -3.62,5.43 -4.65,8.738 -1.04,3.313 -1.57,6.793 -1.57,10.449 0,3.657 0.53,7.141 1.57,10.454 1.03,3.308 2.58,6.23 4.65,8.777 2.07,2.547 4.68,4.57 7.83,6.078 3.12,1.504 6.76,2.254 10.93,2.254 2.52,0 4.97,-0.371 7.38,-1.106 2.39,-0.738 4.56,-1.843 6.51,-3.296 1.95,-1.461 3.58,-3.254 4.89,-5.372 1.3,-2.125 2.13,-4.574 2.47,-7.335 l -5.04,0 c -0.43,2.019 -1.16,3.839 -2.17,5.441"
|
|
||||||
id="path3048"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1791.01,140.879 c 0.76,-2.793 1.95,-5.289 3.56,-7.484 1.6,-2.2 3.66,-3.965 6.18,-5.301 2.52,-1.336 5.53,-2.004 9.04,-2.004 3.51,0 6.5,0.668 9.01,2.004 2.49,1.336 4.54,3.101 6.14,5.301 1.61,2.195 2.79,4.691 3.57,7.484 0.75,2.789 1.14,5.613 1.14,8.48 0,2.914 -0.39,5.758 -1.14,8.52 -0.78,2.769 -1.96,5.25 -3.57,7.449 -1.6,2.199 -3.65,3.969 -6.14,5.297 -2.51,1.336 -5.5,2.008 -9.01,2.008 -3.51,0 -6.52,-0.672 -9.04,-2.008 -2.52,-1.328 -4.58,-3.098 -6.18,-5.297 -1.61,-2.199 -2.8,-4.68 -3.56,-7.449 -0.78,-2.762 -1.16,-5.606 -1.16,-8.52 0,-2.867 0.38,-5.691 1.16,-8.48 z m -4.64,18.934 c 1.04,3.308 2.6,6.23 4.67,8.777 2.08,2.547 4.68,4.57 7.82,6.078 3.13,1.504 6.77,2.254 10.93,2.254 4.15,0 7.78,-0.75 10.89,-2.254 3.11,-1.508 5.72,-3.531 7.79,-6.078 2.07,-2.547 3.62,-5.469 4.66,-8.777 1.04,-3.313 1.56,-6.797 1.56,-10.454 0,-3.656 -0.52,-7.136 -1.56,-10.449 -1.04,-3.308 -2.59,-6.226 -4.66,-8.738 -2.07,-2.52 -4.68,-4.531 -7.79,-6.043 -3.11,-1.5 -6.74,-2.266 -10.89,-2.266 -4.16,0 -7.8,0.766 -10.93,2.266 -3.14,1.512 -5.74,3.523 -7.82,6.043 -2.07,2.512 -3.63,5.43 -4.67,8.738 -1.04,3.313 -1.56,6.793 -1.56,10.449 0,3.657 0.52,7.141 1.56,10.454"
|
|
||||||
id="path3050"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1850.33,175.816 30.82,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.64,0 -30.82,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.64,0"
|
|
||||||
id="path3052"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1935.39,175.816 0,-4.296 -18.45,0 0,-48.614 -5.04,0 0,48.614 -18.37,0 0,4.296 41.86,0"
|
|
||||||
id="path3054"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1965.86,143.656 -10.23,27.121 -10.6,-27.121 20.83,0 z m -7.21,32.16 20.76,-52.91 -5.41,0 -6.44,16.449 -24.08,0 -6.38,-16.449 -5.33,0 21.26,52.91 5.62,0"
|
|
||||||
id="path3056"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1993.71,175.816 18.3,-46.386 18.24,46.386 7.41,0 0,-52.91 -5.04,0 0,45.723 -0.15,0 -18.09,-45.723 -4.73,0 -18.16,45.723 -0.14,0 0,-45.723 -5.05,0 0,52.91 7.41,0"
|
|
||||||
id="path3058"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2050.78,122.906 5.0273,0 0,52.9102 -5.0273,0 0,-52.9102 z"
|
|
||||||
id="path3060"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2074.63,175.816 30.83,-44.757 0.15,0 0,44.757 5.04,0 0,-52.91 -5.63,0 -30.83,44.754 -0.15,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
|
||||||
id="path3062"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2151.78,143.656 -10.24,27.121 -10.58,-27.121 20.82,0 z m -7.2,32.16 20.76,-52.91 -5.41,0 -6.45,16.449 -24.09,0 -6.36,-16.449 -5.34,0 21.27,52.91 5.62,0"
|
|
||||||
id="path3064"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2177.93,175.816 30.82,-44.757 0.16,0 0,44.757 5.05,0 0,-52.91 -5.64,0 -30.84,44.754 -0.14,0 0,-44.754 -5.04,0 0,52.91 5.63,0"
|
|
||||||
id="path3066"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2263.01,175.816 0,-4.296 -18.46,0 0,-48.614 -5.04,0 0,48.614 -18.38,0 0,4.296 41.88,0"
|
|
||||||
id="path3068"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 945.785,32.6602 c 1.875,0 3.656,0.1562 5.336,0.4804 1.676,0.3164 3.16,0.8985 4.445,1.7383 1.286,0.8477 2.301,1.9649 3.043,3.375 0.739,1.4102 1.11,3.1719 1.11,5.2969 0,3.4101 -1.203,5.9648 -3.602,7.668 -2.387,1.7031 -5.836,2.5585 -10.332,2.5585 l -17.344,0 0,-21.1171 17.344,0 z m 0,25.414 c 2.028,0 3.778,0.2344 5.262,0.711 1.48,0.4609 2.719,1.1015 3.711,1.9218 0.98,0.8125 1.726,1.7696 2.215,2.8555 0.5,1.082 0.742,2.2422 0.742,3.4766 0,6.6211 -3.977,9.9375 -11.93,9.9375 l -17.344,0 0,-18.9024 17.344,0 z m 0,23.1953 c 2.223,0 4.36,-0.2109 6.41,-0.6289 2.051,-0.4218 3.852,-1.1328 5.41,-2.1484 1.559,-1.0156 2.805,-2.3438 3.743,-4 0.937,-1.6563 1.406,-3.7227 1.406,-6.1914 0,-1.3867 -0.219,-2.7305 -0.668,-4.0391 -0.445,-1.3086 -1.074,-2.4961 -1.887,-3.5547 -0.808,-1.0625 -1.781,-1.9687 -2.89,-2.7031 -1.114,-0.7422 -2.36,-1.2617 -3.739,-1.5586 l 0,-0.1523 c 3.403,-0.4453 6.121,-1.8321 8.145,-4.1797 2.031,-2.3477 3.043,-5.25 3.043,-8.711 0,-0.8398 -0.074,-1.7851 -0.227,-2.8515 -0.144,-1.0625 -0.437,-2.1524 -0.886,-3.2617 -0.446,-1.1133 -1.086,-2.2149 -1.93,-3.2969 -0.836,-1.0859 -1.957,-2.0391 -3.363,-2.8516 -1.414,-0.8203 -3.141,-1.4883 -5.192,-2.0039 -2.051,-0.5195 -4.508,-0.7812 -7.375,-0.7812 l -22.379,0 0,52.914 22.379,0"
|
|
||||||
id="path3070"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 975.426,28.3555 5.04297,0 0,52.9141 -5.04297,0 0,-52.9141 z"
|
|
||||||
id="path3072"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 997.105,46.3281 c 0.762,-2.789 1.95,-5.2812 3.555,-7.4804 1.6,-2.1993 3.67,-3.9688 6.18,-5.2969 2.53,-1.3399 5.54,-2.0039 9.04,-2.0039 3.51,0 6.52,0.664 9.01,2.0039 2.5,1.3281 4.54,3.0976 6.15,5.2969 1.61,2.1992 2.79,4.6914 3.55,7.4804 0.77,2.793 1.16,5.6211 1.16,8.4844 0,2.918 -0.39,5.7578 -1.16,8.5273 -0.76,2.7618 -1.94,5.2461 -3.55,7.4454 -1.61,2.2031 -3.65,3.9648 -6.15,5.3007 -2.49,1.3321 -5.5,2 -9.01,2 -3.5,0 -6.51,-0.6679 -9.04,-2 -2.51,-1.3359 -4.58,-3.0976 -6.18,-5.3007 -1.605,-2.1993 -2.793,-4.6836 -3.555,-7.4454 -0.773,-2.7695 -1.152,-5.6093 -1.152,-8.5273 0,-2.8633 0.379,-5.6914 1.152,-8.4844 z m -4.632,18.9336 c 1.035,3.3125 2.59,6.2383 4.668,8.7813 2.074,2.5429 4.679,4.5742 7.819,6.0781 3.13,1.5078 6.77,2.2578 10.92,2.2578 4.15,0 7.79,-0.75 10.9,-2.2578 3.11,-1.5039 5.71,-3.5352 7.78,-6.0781 2.08,-2.543 3.63,-5.4688 4.67,-8.7813 1.04,-3.3047 1.56,-6.789 1.56,-10.4492 0,-3.6602 -0.52,-7.1406 -1.56,-10.4414 -1.04,-3.3164 -2.59,-6.2305 -4.67,-8.7461 -2.07,-2.5195 -4.67,-4.5312 -7.78,-6.0391 -3.11,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.15,0 -7.79,0.7617 -10.92,2.2656 -3.14,1.5079 -5.745,3.5196 -7.819,6.0391 -2.078,2.5156 -3.633,5.4297 -4.668,8.7461 -1.035,3.3008 -1.559,6.7812 -1.559,10.4414 0,3.6602 0.524,7.1445 1.559,10.4492"
|
|
||||||
id="path3074"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1087.1,81.2695 0,-4.2929 -18.45,0 0,-48.6211 -5.04,0 0,48.6211 -18.38,0 0,4.2929 41.87,0"
|
|
||||||
id="path3076"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1118.15,56.1484 c 1.53,0 2.99,0.2383 4.37,0.7071 1.39,0.4687 2.6,1.1484 3.63,2.0351 1.04,0.8907 1.86,1.9688 2.49,3.2227 0.61,1.2617 0.93,2.7109 0.93,4.332 0,3.2656 -0.95,5.836 -2.82,7.7031 -1.88,1.8829 -4.75,2.8282 -8.6,2.8282 l -18.82,0 0,-20.8282 18.82,0 z m 0.37,25.1211 c 2.17,0 4.23,-0.2695 6.19,-0.8203 1.95,-0.539 3.65,-1.3633 5.11,-2.4765 1.46,-1.1133 2.62,-2.543 3.49,-4.3008 0.86,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.86,-6.2696 -2.59,-8.7461 -1.73,-2.4688 -4.3,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.73,-0.25 3.16,-0.7032 4.3,-1.3672 1.14,-0.668 2.06,-1.5235 2.78,-2.5586 0.71,-1.0391 1.23,-2.2344 1.55,-3.5977 0.33,-1.3593 0.54,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.3,-3.8868 0.15,-1.3125 0.38,-2.5468 0.71,-3.707 0.31,-1.1562 0.74,-2.0586 1.29,-2.707 l -5.56,0 c -0.29,0.5 -0.53,1.1015 -0.7,1.8203 -0.17,0.7187 -0.3,1.4531 -0.37,2.2265 -0.07,0.7618 -0.14,1.5118 -0.19,2.25 -0.04,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.26,3.7461 -0.48,5.6016 -0.22,1.8555 -0.69,3.5 -1.41,4.9609 -0.71,1.4532 -1.75,2.6289 -3.11,3.5235 -1.36,0.8906 -3.22,1.2812 -5.59,1.1875 l -19.12,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
|
||||||
id="path3078"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1174.25,49.1055 -10.23,27.125 -10.6,-27.125 20.83,0 z m -7.19,32.164 20.75,-52.914 -5.41,0 -6.45,16.457 -24.08,0 -6.38,-16.457 -5.33,0 21.27,52.914 5.63,0"
|
|
||||||
id="path3080"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1200.41,81.2695 30.83,-44.7617 0.15,0 0,44.7617 5.04,0 0,-52.914 -5.63,0 -30.84,44.7578 -0.15,0 0,-44.7578 -5.04,0 0,52.914 5.64,0"
|
|
||||||
id="path3082"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1252.87,38.9609 c 0.9,-1.8281 2.12,-3.289 3.67,-4.375 1.57,-1.0898 3.4,-1.8671 5.52,-2.3359 2.12,-0.4727 4.4,-0.7031 6.83,-0.7031 1.37,0 2.89,0.1914 4.52,0.5976 1.62,0.3907 3.14,1.0196 4.55,1.8828 1.42,0.8711 2.58,1.9727 3.52,3.336 0.94,1.3515 1.41,3.0039 1.41,4.9258 0,1.4843 -0.33,2.7695 -1.01,3.8593 -0.66,1.086 -1.53,1.9961 -2.58,2.7383 -1.07,0.7422 -2.24,1.3438 -3.53,1.8164 -1.28,0.4688 -2.55,0.8555 -3.78,1.1524 l -11.78,2.8789 c -1.54,0.4062 -3.02,0.8906 -4.49,1.4922 -1.44,0.5898 -2.72,1.375 -3.81,2.3672 -1.09,0.9843 -1.95,2.2031 -2.63,3.6289 -0.67,1.4336 -1,3.1875 -1,5.2617 0,1.289 0.25,2.7929 0.74,4.5234 0.49,1.7266 1.42,3.3594 2.79,4.8906 1.35,1.5274 3.21,2.8243 5.59,3.8907 2.37,1.0625 5.4,1.5898 9.1,1.5898 2.62,0 5.13,-0.3398 7.49,-1.0351 2.38,-0.6915 4.47,-1.7305 6.22,-3.1133 1.8,-1.3789 3.21,-3.0977 4.26,-5.1446 1.08,-2.0546 1.6,-4.4453 1.6,-7.1601 l -5.03,0 c -0.1,2.0351 -0.56,3.7969 -1.37,5.3047 -0.82,1.5039 -1.88,2.7617 -3.19,3.7773 -1.3,1.0117 -2.81,1.7852 -4.53,2.3008 -1.7,0.5195 -3.49,0.7773 -5.37,0.7773 -1.72,0 -3.39,-0.1914 -5,-0.5586 -1.61,-0.371 -3.01,-0.9609 -4.22,-1.7812 -1.21,-0.8164 -2.18,-1.8906 -2.93,-3.2227 -0.74,-1.332 -1.11,-2.9882 -1.11,-4.9648 0,-1.2305 0.22,-2.3086 0.64,-3.2227 0.42,-0.914 0.98,-1.6953 1.72,-2.332 0.75,-0.6484 1.61,-1.1601 2.56,-1.5547 0.98,-0.4023 1.99,-0.7226 3.08,-0.9687 l 12.9,-3.1875 c 1.88,-0.4883 3.64,-1.0938 5.3,-1.8164 1.65,-0.711 3.11,-1.6055 4.37,-2.6602 1.27,-1.0625 2.24,-2.3633 2.97,-3.8945 0.71,-1.5313 1.07,-3.3867 1.07,-5.5586 0,-0.5899 -0.07,-1.3828 -0.2,-2.3672 -0.11,-0.9922 -0.41,-2.0313 -0.87,-3.1523 -0.47,-1.1133 -1.14,-2.2344 -2,-3.3711 -0.87,-1.1368 -2.06,-2.1602 -3.56,-3.0782 -1.51,-0.9062 -3.37,-1.6562 -5.6,-2.2226 -2.22,-0.5586 -4.88,-0.8516 -8,-0.8516 -3.11,0 -6,0.3594 -8.68,1.0781 -2.65,0.7188 -4.94,1.8125 -6.81,3.2969 -1.88,1.4844 -3.32,3.3789 -4.34,5.707 -1,2.3204 -1.43,5.1055 -1.3,8.375 l 5.05,0 c -0.06,-2.7148 0.37,-4.9921 1.25,-6.8164"
|
|
||||||
id="path3084"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1331.72,81.2695 0,-4.2929 -28.53,0 0,-19.1211 25.35,0 0,-4.3008 -25.35,0 0,-25.1992 -5.04,0 0,52.914 33.57,0"
|
|
||||||
id="path3086"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1343.54,46.3281 c 0.78,-2.789 1.95,-5.2812 3.55,-7.4804 1.6,-2.1993 3.68,-3.9688 6.2,-5.2969 2.51,-1.3399 5.53,-2.0039 9.03,-2.0039 3.51,0 6.51,0.664 9.01,2.0039 2.5,1.3281 4.55,3.0976 6.15,5.2969 1.6,2.1992 2.78,4.6914 3.56,7.4804 0.76,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.39,5.7578 -1.15,8.5273 -0.78,2.7618 -1.96,5.2461 -3.56,7.4454 -1.6,2.2031 -3.65,3.9648 -6.15,5.3007 -2.5,1.3321 -5.5,2 -9.01,2 -3.5,0 -6.52,-0.6679 -9.03,-2 -2.52,-1.3359 -4.6,-3.0976 -6.2,-5.3007 -1.6,-2.1993 -2.77,-4.6836 -3.55,-7.4454 -0.77,-2.7695 -1.14,-5.6093 -1.14,-8.5273 0,-2.8633 0.37,-5.6914 1.14,-8.4844 z m -4.63,18.9336 c 1.03,3.3125 2.59,6.2383 4.66,8.7813 2.09,2.5429 4.69,4.5742 7.82,6.0781 3.14,1.5078 6.79,2.2578 10.93,2.2578 4.15,0 7.8,-0.75 10.9,-2.2578 3.11,-1.5039 5.7,-3.5352 7.78,-6.0781 2.09,-2.543 3.63,-5.4688 4.66,-8.7813 1.04,-3.3047 1.57,-6.789 1.57,-10.4492 0,-3.6602 -0.53,-7.1406 -1.57,-10.4414 -1.03,-3.3164 -2.57,-6.2305 -4.66,-8.7461 -2.08,-2.5195 -4.67,-4.5312 -7.78,-6.0391 -3.1,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.14,0 -7.79,0.7617 -10.93,2.2656 -3.13,1.5079 -5.73,3.5196 -7.82,6.0391 -2.07,2.5156 -3.63,5.4297 -4.66,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492"
|
|
||||||
id="path3088"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1421.16,56.1484 c 1.54,0 3,0.2383 4.39,0.7071 1.37,0.4687 2.58,1.1484 3.62,2.0351 1.04,0.8907 1.87,1.9688 2.49,3.2227 0.61,1.2617 0.91,2.7109 0.91,4.332 0,3.2656 -0.93,5.836 -2.81,7.7031 -1.88,1.8829 -4.73,2.8282 -8.6,2.8282 l -18.83,0 0,-20.8282 18.83,0 z m 0.37,25.1211 c 2.18,0 4.24,-0.2695 6.18,-0.8203 1.96,-0.539 3.67,-1.3633 5.12,-2.4765 1.47,-1.1133 2.63,-2.543 3.49,-4.3008 0.86,-1.7578 1.3,-3.8125 1.3,-6.1875 0,-3.3594 -0.87,-6.2696 -2.6,-8.7461 -1.72,-2.4688 -4.3,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.74,-0.25 3.17,-0.7032 4.3,-1.3672 1.13,-0.668 2.06,-1.5235 2.78,-2.5586 0.72,-1.0391 1.24,-2.2344 1.56,-3.5977 0.32,-1.3593 0.52,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.29,-3.8868 0.16,-1.3125 0.38,-2.5468 0.7,-3.707 0.33,-1.1562 0.76,-2.0586 1.3,-2.707 l -5.55,0 c -0.31,0.5 -0.54,1.1015 -0.71,1.8203 -0.17,0.7187 -0.29,1.4531 -0.37,2.2265 -0.08,0.7618 -0.13,1.5118 -0.18,2.25 -0.05,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.25,3.7461 -0.48,5.6016 -0.22,1.8555 -0.7,3.5 -1.41,4.9609 -0.73,1.4532 -1.76,2.6289 -3.12,3.5235 -1.36,0.8906 -3.21,1.2812 -5.59,1.1875 l -19.13,0 0,-23.5 -5.03,0 0,52.914 24.23,0"
|
|
||||||
id="path3090"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1456.21,81.2695 18.3,-46.3906 18.24,46.3906 7.41,0 0,-52.914 -5.04,0 0,45.7265 -0.15,0 -18.08,-45.7265 -4.74,0 -18.17,45.7265 -0.13,0 0,-45.7265 -5.05,0 0,52.914 7.41,0"
|
|
||||||
id="path3092"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1541.21,49.1055 -10.22,27.125 -10.6,-27.125 20.82,0 z m -7.19,32.164 20.74,-52.914 -5.42,0 -6.42,16.457 -24.08,0 -6.38,-16.457 -5.33,0 21.27,52.914 5.62,0"
|
|
||||||
id="path3094"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1593,81.2695 0,-4.2929 -18.47,0 0,-48.6211 -5.04,0 0,48.6211 -18.37,0 0,4.2929 41.88,0"
|
|
||||||
id="path3096"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1600.55,28.3555 5.0391,0 0,52.9141 -5.0391,0 0,-52.9141 z"
|
|
||||||
id="path3098"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1622.23,46.3281 c 0.76,-2.789 1.94,-5.2812 3.55,-7.4804 1.6,-2.1993 3.67,-3.9688 6.19,-5.2969 2.52,-1.3399 5.53,-2.0039 9.04,-2.0039 3.5,0 6.5,0.664 9.01,2.0039 2.48,1.3281 4.54,3.0976 6.14,5.2969 1.61,2.1992 2.8,4.6914 3.56,7.4804 0.76,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.39,5.7578 -1.15,8.5273 -0.76,2.7618 -1.95,5.2461 -3.56,7.4454 -1.6,2.2031 -3.66,3.9648 -6.14,5.3007 -2.51,1.3321 -5.51,2 -9.01,2 -3.51,0 -6.52,-0.6679 -9.04,-2 -2.52,-1.3359 -4.59,-3.0976 -6.19,-5.3007 -1.61,-2.1993 -2.79,-4.6836 -3.55,-7.4454 -0.77,-2.7695 -1.16,-5.6093 -1.16,-8.5273 0,-2.8633 0.39,-5.6914 1.16,-8.4844 z m -4.64,18.9336 c 1.03,3.3125 2.6,6.2383 4.68,8.7813 2.07,2.5429 4.67,4.5742 7.8,6.0781 3.14,1.5078 6.79,2.2578 10.94,2.2578 4.16,0 7.78,-0.75 10.88,-2.2578 3.13,-1.5039 5.72,-3.5352 7.8,-6.0781 2.07,-2.543 3.62,-5.4688 4.66,-8.7813 1.03,-3.3047 1.55,-6.789 1.55,-10.4492 0,-3.6602 -0.52,-7.1406 -1.55,-10.4414 -1.04,-3.3164 -2.59,-6.2305 -4.66,-8.7461 -2.08,-2.5195 -4.67,-4.5312 -7.8,-6.0391 -3.1,-1.5039 -6.72,-2.2656 -10.88,-2.2656 -4.15,0 -7.8,0.7617 -10.94,2.2656 -3.13,1.5079 -5.73,3.5196 -7.8,6.0391 -2.08,2.5156 -3.65,5.4297 -4.68,8.7461 -1.03,3.3008 -1.55,6.7812 -1.55,10.4414 0,3.6602 0.52,7.1445 1.55,10.4492"
|
|
||||||
id="path3100"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1681.55,81.2695 30.82,-44.7617 0.15,0 0,44.7617 5.04,0 0,-52.914 -5.64,0 -30.82,44.7578 -0.15,0 0,-44.7578 -5.03,0 0,52.914 5.63,0"
|
|
||||||
id="path3102"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1775.58,55.332 c 3.51,0 6.35,0.8946 8.52,2.6719 2.17,1.7774 3.26,4.4922 3.26,8.1484 0,3.6602 -1.09,6.3711 -3.26,8.1485 -2.17,1.7851 -5.01,2.6758 -8.52,2.6758 l -17.35,0 0,-21.6446 17.35,0 z m 1.12,25.9375 c 2.36,0 4.51,-0.3359 6.43,-0.9961 1.94,-0.6679 3.58,-1.6562 4.99,-2.9648 1.37,-1.3125 2.43,-2.9063 3.17,-4.7852 0.74,-1.875 1.11,-4.0039 1.11,-6.3711 0,-2.3671 -0.37,-4.4921 -1.11,-6.371 -0.74,-1.8829 -1.8,-3.4766 -3.17,-4.7852 -1.41,-1.3047 -3.05,-2.293 -4.99,-2.9609 -1.92,-0.6641 -4.07,-0.9961 -6.43,-0.9961 l -18.47,0 0,-22.6836 -5.04,0 0,52.914 23.51,0"
|
|
||||||
id="path3104"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1824.93,49.1055 -10.22,27.125 -10.6,-27.125 20.82,0 z m -7.19,32.164 20.76,-52.914 -5.41,0 -6.45,16.457 -24.09,0 -6.38,-16.457 -5.33,0 21.28,52.914 5.62,0"
|
|
||||||
id="path3106"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1876.73,81.2695 0,-4.2929 -18.45,0 0,-48.6211 -5.04,0 0,48.6211 -18.38,0 0,4.2929 41.87,0"
|
|
||||||
id="path3108"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1888.96,81.2695 0,-22.9687 31.41,0 0,22.9687 5.04,0 0,-52.914 -5.04,0 0,25.6445 -31.41,0 0,-25.6445 -5.04,0 0,52.914 5.04,0"
|
|
||||||
id="path3110"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 1938.38,81.2695 12.01,-46.3125 0.15,0 12.9,46.3125 6.3,0 12.96,-46.3125 0.15,0 12.07,46.3125 5.04,0 -14.59,-52.914 -5.34,0 -13.42,47.3515 -0.14,0 -13.34,-47.3515 -5.48,0 -14.67,52.914 5.4,0"
|
|
||||||
id="path3112"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2034.73,49.1055 -10.24,27.125 -10.59,-27.125 20.83,0 z m -7.2,32.164 20.75,-52.914 -5.41,0 -6.44,16.457 -24.09,0 -6.37,-16.457 -5.34,0 21.27,52.914 5.63,0"
|
|
||||||
id="path3114"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2043.84,81.2695 5.93,0 17.41,-26.8281 17.33,26.8281 6.01,0 -20.9,-31.125 0,-21.789 -5.04,0 0,21.789 -20.74,31.125"
|
|
||||||
id="path3116"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2144.01,56.1484 c 1.55,0 3,0.2383 4.38,0.7071 1.39,0.4687 2.6,1.1484 3.63,2.0351 1.05,0.8907 1.88,1.9688 2.48,3.2227 0.62,1.2617 0.93,2.7109 0.93,4.332 0,3.2656 -0.94,5.836 -2.81,7.7031 -1.89,1.8829 -4.75,2.8282 -8.61,2.8282 l -18.81,0 0,-20.8282 18.81,0 z m 0.38,25.1211 c 2.18,0 4.23,-0.2695 6.19,-0.8203 1.95,-0.539 3.66,-1.3633 5.1,-2.4765 1.47,-1.1133 2.63,-2.543 3.5,-4.3008 0.86,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.86,-6.2696 -2.59,-8.7461 -1.73,-2.4688 -4.3,-4.0469 -7.7,-4.7383 l 0,-0.1484 c 1.72,-0.25 3.15,-0.7032 4.28,-1.3672 1.15,-0.668 2.07,-1.5235 2.79,-2.5586 0.72,-1.0391 1.24,-2.2344 1.55,-3.5977 0.32,-1.3593 0.54,-2.8281 0.63,-4.4062 0.05,-0.8867 0.1,-1.9766 0.15,-3.2656 0.05,-1.2852 0.15,-2.5782 0.29,-3.8868 0.15,-1.3125 0.39,-2.5468 0.71,-3.707 0.33,-1.1562 0.76,-2.0586 1.3,-2.707 l -5.55,0 c -0.3,0.5 -0.54,1.1015 -0.71,1.8203 -0.17,0.7187 -0.3,1.4531 -0.38,2.2265 -0.07,0.7618 -0.13,1.5118 -0.18,2.25 -0.04,0.7461 -0.1,1.3946 -0.15,1.9297 -0.1,1.875 -0.26,3.7461 -0.49,5.6016 -0.22,1.8555 -0.68,3.5 -1.39,4.9609 -0.73,1.4532 -1.76,2.6289 -3.13,3.5235 -1.35,0.8906 -3.21,1.2812 -5.59,1.1875 l -19.11,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
|
||||||
id="path3118"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2208.34,81.2695 0,-4.2929 -31.49,0 0,-19.1211 29.49,0 0,-4.3008 -29.49,0 0,-20.8945 31.87,0 0,-4.3047 -36.91,0 0,52.914 36.53,0"
|
|
||||||
id="path3120"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2221.6,38.9609 c 0.9,-1.8281 2.13,-3.289 3.66,-4.375 1.58,-1.0898 3.4,-1.8671 5.53,-2.3359 2.12,-0.4727 4.41,-0.7031 6.82,-0.7031 1.38,0 2.9,0.1914 4.53,0.5976 1.62,0.3907 3.13,1.0196 4.55,1.8828 1.41,0.8711 2.58,1.9727 3.52,3.336 0.94,1.3515 1.4,3.0039 1.4,4.9258 0,1.4843 -0.32,2.7695 -0.99,3.8593 -0.66,1.086 -1.55,1.9961 -2.59,2.7383 -1.06,0.7422 -2.24,1.3438 -3.53,1.8164 -1.28,0.4688 -2.54,0.8555 -3.78,1.1524 l -11.77,2.8789 c -1.55,0.4062 -3.03,0.8906 -4.5,1.4922 -1.45,0.5898 -2.73,1.375 -3.82,2.3672 -1.08,0.9843 -1.95,2.2031 -2.62,3.6289 -0.66,1.4336 -1,3.1875 -1,5.2617 0,1.289 0.24,2.7929 0.74,4.5234 0.5,1.7266 1.42,3.3594 2.78,4.8906 1.36,1.5274 3.23,2.8243 5.59,3.8907 2.38,1.0625 5.41,1.5898 9.12,1.5898 2.61,0 5.11,-0.3398 7.48,-1.0351 2.37,-0.6915 4.46,-1.7305 6.24,-3.1133 1.77,-1.3789 3.19,-3.0977 4.24,-5.1446 1.08,-2.0546 1.6,-4.4453 1.6,-7.1601 l -5.03,0 c -0.1,2.0351 -0.55,3.7969 -1.38,5.3047 -0.81,1.5039 -1.87,2.7617 -3.18,3.7773 -1.31,1.0117 -2.82,1.7852 -4.53,2.3008 -1.71,0.5195 -3.48,0.7773 -5.37,0.7773 -1.73,0 -3.4,-0.1914 -5.01,-0.5586 -1.6,-0.371 -3,-0.9609 -4.21,-1.7812 -1.21,-0.8164 -2.19,-1.8906 -2.94,-3.2227 -0.74,-1.332 -1.1,-2.9882 -1.1,-4.9648 0,-1.2305 0.21,-2.3086 0.63,-3.2227 0.43,-0.914 0.99,-1.6953 1.73,-2.332 0.75,-0.6484 1.62,-1.1601 2.56,-1.5547 0.97,-0.4023 1.99,-0.7226 3.08,-0.9687 l 12.9,-3.1875 c 1.87,-0.4883 3.64,-1.0938 5.3,-1.8164 1.65,-0.711 3.11,-1.6055 4.37,-2.6602 1.26,-1.0625 2.24,-2.3633 2.97,-3.8945 0.71,-1.5313 1.07,-3.3867 1.07,-5.5586 0,-0.5899 -0.07,-1.3828 -0.2,-2.3672 -0.11,-0.9922 -0.41,-2.0313 -0.87,-3.1523 -0.48,-1.1133 -1.15,-2.2344 -2.01,-3.3711 -0.86,-1.1368 -2.05,-2.1602 -3.55,-3.0782 -1.5,-0.9062 -3.37,-1.6562 -5.6,-2.2226 -2.22,-0.5586 -4.89,-0.8516 -8.01,-0.8516 -3.11,0 -5.99,0.3594 -8.67,1.0781 -2.66,0.7188 -4.94,1.8125 -6.8,3.2969 -1.89,1.4844 -3.33,3.3789 -4.36,5.707 -0.99,2.3204 -1.43,5.1055 -1.29,8.375 l 5.04,0 c -0.05,-2.7148 0.38,-4.9921 1.26,-6.8164"
|
|
||||||
id="path3122"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2270.24,46.3281 c 0.79,-2.789 1.96,-5.2812 3.57,-7.4804 1.6,-2.1993 3.67,-3.9688 6.18,-5.2969 2.52,-1.3399 5.54,-2.0039 9.04,-2.0039 3.51,0 6.52,0.664 9.02,2.0039 2.49,1.3281 4.54,3.0976 6.15,5.2969 1.6,2.1992 2.77,4.6914 3.55,7.4804 0.77,2.793 1.15,5.6211 1.15,8.4844 0,2.918 -0.38,5.7578 -1.15,8.5273 -0.78,2.7618 -1.95,5.2461 -3.55,7.4454 -1.61,2.2031 -3.66,3.9648 -6.15,5.3007 -2.5,1.3321 -5.51,2 -9.02,2 -3.5,0 -6.52,-0.6679 -9.04,-2 -2.51,-1.3359 -4.58,-3.0976 -6.18,-5.3007 -1.61,-2.1993 -2.78,-4.6836 -3.57,-7.4454 -0.75,-2.7695 -1.13,-5.6093 -1.13,-8.5273 0,-2.8633 0.38,-5.6914 1.13,-8.4844 z m -4.62,18.9336 c 1.04,3.3125 2.59,6.2383 4.66,8.7813 2.09,2.5429 4.68,4.5742 7.83,6.0781 3.14,1.5078 6.78,2.2578 10.92,2.2578 4.15,0 7.8,-0.75 10.9,-2.2578 3.11,-1.5039 5.7,-3.5352 7.79,-6.0781 2.07,-2.543 3.63,-5.4688 4.66,-8.7813 1.04,-3.3047 1.56,-6.789 1.56,-10.4492 0,-3.6602 -0.52,-7.1406 -1.56,-10.4414 -1.03,-3.3164 -2.59,-6.2305 -4.66,-8.7461 -2.09,-2.5195 -4.68,-4.5312 -7.79,-6.0391 -3.1,-1.5039 -6.75,-2.2656 -10.9,-2.2656 -4.14,0 -7.78,0.7617 -10.92,2.2656 -3.15,1.5079 -5.74,3.5196 -7.83,6.0391 -2.07,2.5156 -3.62,5.4297 -4.66,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492"
|
|
||||||
id="path3124"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2328.53,81.2695 0,-32.7539 c 0,-3.0625 0.35,-5.664 1.03,-7.8242 0.69,-2.1406 1.71,-3.8984 3.05,-5.2578 1.33,-1.3555 2.97,-2.3477 4.88,-2.9648 1.93,-0.6172 4.11,-0.9219 6.52,-0.9219 2.47,0 4.67,0.3047 6.61,0.9219 1.93,0.6171 3.55,1.6093 4.88,2.9648 1.34,1.3594 2.35,3.1172 3.04,5.2578 0.69,2.1602 1.04,4.7617 1.04,7.8242 l 0,32.7539 5.04,0 0,-33.8672 c 0,-2.7148 -0.38,-5.2968 -1.14,-7.7382 -0.77,-2.4493 -1.99,-4.5899 -3.65,-6.418 -1.66,-1.8242 -3.76,-3.2695 -6.36,-4.332 -2.6,-1.0586 -5.74,-1.5938 -9.46,-1.5938 -3.65,0 -6.77,0.5352 -9.37,1.5938 -2.59,1.0625 -4.71,2.5078 -6.37,4.332 -1.66,1.8281 -2.87,3.9687 -3.63,6.418 -0.77,2.4414 -1.13,5.0234 -1.13,7.7382 l 0,33.8672 5.02,0"
|
|
||||||
id="path3126"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2400.87,56.1484 c 1.51,0 2.99,0.2383 4.36,0.7071 1.39,0.4687 2.59,1.1484 3.63,2.0351 1.03,0.8907 1.86,1.9688 2.49,3.2227 0.62,1.2617 0.92,2.7109 0.92,4.332 0,3.2656 -0.94,5.836 -2.82,7.7031 -1.86,1.8829 -4.73,2.8282 -8.58,2.8282 l -18.83,0 0,-20.8282 18.83,0 z m 0.36,25.1211 c 2.18,0 4.23,-0.2695 6.2,-0.8203 1.94,-0.539 3.64,-1.3633 5.11,-2.4765 1.45,-1.1133 2.61,-2.543 3.47,-4.3008 0.88,-1.7578 1.29,-3.8125 1.29,-6.1875 0,-3.3594 -0.85,-6.2696 -2.58,-8.7461 -1.73,-2.4688 -4.29,-4.0469 -7.71,-4.7383 l 0,-0.1484 c 1.73,-0.25 3.17,-0.7032 4.31,-1.3672 1.11,-0.668 2.05,-1.5235 2.77,-2.5586 0.71,-1.0391 1.23,-2.2344 1.55,-3.5977 0.32,-1.3593 0.52,-2.8281 0.63,-4.4062 0.05,-0.8867 0.11,-1.9766 0.16,-3.2656 0.04,-1.2852 0.15,-2.5782 0.29,-3.8868 0.14,-1.3125 0.38,-2.5468 0.7,-3.707 0.31,-1.1562 0.75,-2.0586 1.3,-2.707 l -5.56,0 c -0.29,0.5 -0.53,1.1015 -0.71,1.8203 -0.16,0.7187 -0.29,1.4531 -0.36,2.2265 -0.09,0.7618 -0.14,1.5118 -0.19,2.25 -0.05,0.7461 -0.1,1.3946 -0.15,1.9297 -0.09,1.875 -0.27,3.7461 -0.47,5.6016 -0.23,1.8555 -0.69,3.5 -1.42,4.9609 -0.71,1.4532 -1.75,2.6289 -3.1,3.5235 -1.37,0.8906 -3.23,1.2812 -5.6,1.1875 l -19.12,0 0,-23.5 -5.04,0 0,52.914 24.23,0"
|
|
||||||
id="path3128"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2465.16,70.7109 c -1.02,1.6094 -2.27,2.9493 -3.71,4.0391 -1.47,1.0859 -3.08,1.9141 -4.82,2.4844 -1.75,0.5625 -3.59,0.8515 -5.53,0.8515 -3.5,0 -6.51,-0.6679 -9.03,-2 -2.52,-1.3359 -4.6,-3.0976 -6.18,-5.3007 -1.62,-2.1993 -2.8,-4.6836 -3.58,-7.4454 -0.76,-2.7695 -1.14,-5.6093 -1.14,-8.5273 0,-2.8633 0.38,-5.6914 1.14,-8.4844 0.78,-2.789 1.96,-5.2812 3.58,-7.4804 1.58,-2.1993 3.66,-3.9688 6.18,-5.2969 2.52,-1.3399 5.53,-2.0039 9.03,-2.0039 2.47,0 4.7,0.4453 6.66,1.332 2,0.8906 3.7,2.1016 5.13,3.6289 1.44,1.5274 2.6,3.3281 3.48,5.3711 0.9,2.0508 1.46,4.2695 1.71,6.6367 l 5.04,0 c -0.35,-3.2578 -1.13,-6.1953 -2.3,-8.8203 -1.19,-2.6172 -2.72,-4.8359 -4.59,-6.668 -1.88,-1.8281 -4.09,-3.2304 -6.63,-4.2226 -2.56,-0.9844 -5.37,-1.4844 -8.5,-1.4844 -4.15,0 -7.79,0.7617 -10.93,2.2656 -3.13,1.5079 -5.74,3.5196 -7.83,6.0391 -2.05,2.5156 -3.62,5.4297 -4.65,8.7461 -1.04,3.3008 -1.56,6.7812 -1.56,10.4414 0,3.6602 0.52,7.1445 1.56,10.4492 1.03,3.3125 2.6,6.2383 4.65,8.7813 2.09,2.5429 4.7,4.5742 7.83,6.0781 3.14,1.5078 6.78,2.2578 10.93,2.2578 2.52,0 4.97,-0.3711 7.38,-1.1094 2.39,-0.7382 4.57,-1.8398 6.52,-3.2968 1.95,-1.461 3.57,-3.25 4.89,-5.3711 1.31,-2.1289 2.14,-4.5703 2.48,-7.3399 l -5.04,0 c -0.45,2.0274 -1.17,3.8399 -2.17,5.4492"
|
|
||||||
id="path3130"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 2519.59,81.2695 0,-4.2929 -31.5,0 0,-19.1211 29.5,0 0,-4.3008 -29.5,0 0,-20.8945 31.86,0 0,-4.3047 -36.9,0 0,52.914 36.54,0"
|
|
||||||
id="path3132"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 109.109,130.879 c -2.171,6.246 -5.242,11.781 -9.2145,16.601 -3.9765,4.825 -8.8007,8.7 -14.4765,11.637 -5.6758,2.938 -12.1133,4.395 -19.2969,4.395 -7.375,0 -13.9023,-1.457 -19.5781,-4.395 -5.6797,-2.937 -10.5039,-6.812 -14.4766,-11.637 -3.9726,-4.82 -7.1406,-10.41 -9.5078,-16.75 -2.3633,-6.332 -3.9258,-12.816 -4.6758,-19.433 l 94.7732,0 c -0.179,6.812 -1.371,13.348 -3.547,19.582 z M 20.5703,76.2539 c 1.8008,-6.9141 4.6875,-13.1055 8.6563,-18.5937 3.9765,-5.4883 8.9922,-10.0235 15.0429,-13.6133 6.0547,-3.6016 13.336,-5.3985 21.8516,-5.3985 13.0586,0 23.2734,3.4102 30.6484,10.2188 7.3755,6.8008 12.4885,15.8867 15.3205,27.2344 l 17.883,0 C 126.184,59.457 119.234,46.5898 109.109,37.5195 98.9922,28.4258 84.6602,23.8906 66.1211,23.8906 c -11.5352,0 -21.5234,2.043 -29.9336,6.1133 C 27.7578,34.0664 20.9023,39.6445 15.6094,46.7422 10.3125,53.8281 6.39063,62.0586 3.83203,71.4336 1.28125,80.7891 0,90.6719 0,101.086 c 0,9.641 1.28125,19.098 3.83203,28.371 2.5586,9.27 6.48047,17.551 11.77737,24.828 5.2929,7.285 12.1484,13.153 20.5781,17.606 8.4102,4.437 18.3984,6.664 29.9336,6.664 11.7266,0 21.7539,-2.375 30.0859,-7.102 8.32,-4.719 15.078,-10.922 20.285,-18.578 5.196,-7.66 8.938,-16.461 11.203,-26.395 2.278,-9.937 3.219,-20 2.84,-30.2222 l -112.6522,0 c 0,-6.4336 0.8867,-13.1055 2.6875,-20.0039"
|
|
||||||
id="path3134"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 157.859,174.297 0,-25.258 0.571,0 c 3.41,8.895 9.457,16.039 18.164,21.426 8.695,5.398 18.254,8.09 28.66,8.09 10.219,0 18.777,-1.325 25.68,-3.977 6.91,-2.648 12.441,-6.379 16.601,-11.203 4.16,-4.824 7.098,-10.738 8.797,-17.734 1.699,-7.008 2.555,-14.864 2.555,-23.555 l 0,-94.2188 -17.875,0 0,91.3708 c 0,6.246 -0.567,12.059 -1.703,17.461 -1.141,5.387 -3.121,10.067 -5.957,14.047 -2.844,3.969 -6.676,7.09 -11.5,9.359 -4.821,2.274 -10.829,3.407 -18.02,3.407 -7.191,0 -13.578,-1.278 -19.152,-3.828 -5.578,-2.555 -10.309,-6.055 -14.192,-10.5 -3.879,-4.442 -6.91,-9.743 -9.082,-15.895 -2.172,-6.156 -3.355,-12.82 -3.547,-20.004 l 0,-85.4178 -17.871,0 0,146.4298 17.871,0"
|
|
||||||
id="path3136"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 274.938,174.297 45.976,-128.5509 0.566,0 45.407,128.5509 18.449,0 -54.77,-146.4298 -19.019,0 -56.465,146.4298 19.856,0"
|
|
||||||
id="path3138"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 409.707,174.297 0,-146.4298 -17.875,0 0,146.4298 17.875,0 z m 0,56.187 0,-28.664 -17.875,0 0,28.664 17.875,0"
|
|
||||||
id="path3140"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 487.02,104.863 c 3.683,0 7.222,0.27 10.632,0.809 3.407,0.547 6.403,1.601 8.993,3.172 2.589,1.566 4.668,3.785 6.238,6.648 1.558,2.852 2.347,6.613 2.347,11.235 0,4.636 -0.789,8.39 -2.347,11.25 -1.57,2.859 -3.649,5.074 -6.238,6.64 -2.59,1.571 -5.586,2.629 -8.993,3.172 -3.41,0.547 -6.949,0.813 -10.632,0.813 l -24.934,0 0,-43.739 24.934,0 z m 8.793,68.68 c 9.128,0 16.898,-1.32 23.304,-3.988 6.406,-2.66 11.613,-6.16 15.633,-10.524 4.023,-4.359 6.961,-9.34 8.797,-14.922 1.84,-5.589 2.758,-11.379 2.758,-17.382 0,-5.852 -0.918,-11.614 -2.758,-17.27 -1.836,-5.652 -4.774,-10.664 -8.797,-15.0273 -4.02,-4.3633 -9.227,-7.8672 -15.633,-10.5234 -6.406,-2.6602 -14.176,-3.9844 -23.304,-3.9844 l -33.727,0 0,-52.336 -32.102,0 0,145.9571 65.829,0"
|
|
||||||
id="path3142"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 614.273,76.7539 c -1.835,-0.6211 -3.812,-1.1289 -5.929,-1.5351 -2.114,-0.4102 -4.324,-0.75 -6.641,-1.0196 -2.316,-0.2773 -4.637,-0.6211 -6.953,-1.0273 -2.176,-0.4102 -4.328,-0.9571 -6.437,-1.6328 -2.114,-0.6836 -3.958,-1.6016 -5.52,-2.7618 -1.566,-1.1562 -2.832,-2.625 -3.777,-4.3945 -0.957,-1.7773 -1.438,-4.0234 -1.438,-6.7461 0,-2.5937 0.481,-4.7695 1.438,-6.5429 0.945,-1.7696 2.246,-3.168 3.879,-4.1915 1.636,-1.0234 3.543,-1.7382 5.726,-2.1484 2.176,-0.4101 4.426,-0.6094 6.746,-0.6094 5.723,0 10.145,0.9532 13.285,2.8672 3.133,1.9024 5.45,4.1875 6.953,6.8438 1.497,2.6562 2.418,5.3476 2.758,8.0742 0.336,2.7226 0.516,4.9101 0.516,6.543 l 0,10.8398 c -1.234,-1.1055 -2.766,-1.9492 -4.606,-2.5586 z m -57.339,40.9841 c 3,4.496 6.812,8.106 11.449,10.832 4.637,2.723 9.844,4.672 15.637,5.828 5.789,1.157 11.617,1.735 17.48,1.735 5.316,0 10.691,-0.375 16.145,-1.125 5.457,-0.75 10.425,-2.211 14.921,-4.395 4.504,-2.175 8.18,-5.207 11.043,-9.093 2.86,-3.883 4.297,-9.032 4.297,-15.434 l 0,-54.9922 c 0,-4.7774 0.27,-9.336 0.817,-13.6954 0.539,-4.3632 1.496,-7.6328 2.859,-9.8125 l -29.437,0 c -0.543,1.6329 -0.989,3.3008 -1.329,5.0118 -0.343,1.6992 -0.582,3.4414 -0.718,5.2109 -4.633,-4.7734 -10.082,-8.1133 -16.348,-10.0156 -6.273,-1.9063 -12.676,-2.8672 -19.219,-2.8672 -5.043,0 -9.746,0.6172 -14.105,1.8398 -4.367,1.2266 -8.18,3.1367 -11.449,5.7305 -3.27,2.5859 -5.825,5.8594 -7.668,9.8125 -1.84,3.9492 -2.758,8.6523 -2.758,14.1016 0,5.9961 1.058,10.9375 3.168,14.8242 2.109,3.8789 4.836,6.9726 8.179,9.2969 3.34,2.3164 7.157,4.0585 11.446,5.2148 4.297,1.1562 8.617,2.0742 12.98,2.7539 4.364,0.6836 8.656,1.2266 12.879,1.6367 4.227,0.4102 7.973,1.0235 11.25,1.8438 3.266,0.8125 5.856,2.0117 7.762,3.582 1.91,1.5664 2.793,3.8477 2.664,6.8435 0,3.137 -0.516,5.617 -1.535,7.461 -1.028,1.844 -2.395,3.266 -4.09,4.293 -1.707,1.02 -3.68,1.699 -5.93,2.039 -2.25,0.344 -4.672,0.516 -7.258,0.516 -5.718,0 -10.222,-1.223 -13.488,-3.68 -3.277,-2.453 -5.183,-6.543 -5.726,-12.265 l -29.032,0 c 0.41,6.816 2.118,12.46 5.114,16.968"
|
|
||||||
id="path3144"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 720.172,133.277 0,-19.422 -21.254,0 0,-52.3355 c 0,-4.9023 0.812,-8.1718 2.449,-9.8047 1.637,-1.6406 4.903,-2.4609 9.817,-2.4609 1.632,0 3.195,0.0703 4.699,0.2031 1.496,0.1328 2.926,0.3438 4.289,0.6172 l 0,-22.4883 c -2.453,-0.414 -5.176,-0.6836 -8.176,-0.8203 -2.996,-0.1289 -5.926,-0.1992 -8.789,-0.1992 -4.5,0 -8.754,0.3047 -12.773,0.918 -4.024,0.6094 -7.563,1.8086 -10.629,3.5781 -3.071,1.7695 -5.489,4.293 -7.254,7.5586 -1.781,3.2773 -2.664,7.5703 -2.664,12.8828 l 0,62.3511 -17.578,0 0,19.422 17.578,0 0,31.684 29.031,0 0,-31.684 21.254,0"
|
|
||||||
id="path3146"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 755.918,173.543 0,-54.984 0.613,0 c 3.684,6.125 8.387,10.586 14.11,13.379 5.722,2.796 11.312,4.195 16.761,4.195 7.77,0 14.137,-1.059 19.114,-3.164 4.972,-2.114 8.894,-5.043 11.754,-8.793 2.863,-3.75 4.871,-8.317 6.031,-13.699 1.152,-5.383 1.734,-11.3481 1.734,-17.8832 l 0,-65.0079 -29.027,0 0,59.6954 c 0,8.7148 -1.363,15.2227 -4.086,19.5157 -2.731,4.293 -7.567,6.433 -14.516,6.433 -7.902,0 -13.633,-2.343 -17.172,-7.039 -3.543,-4.703 -5.316,-12.441 -5.316,-23.2144 l 0,-55.3907 -29.023,0 0,145.9571 29.023,0"
|
|
||||||
id="path3148"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /><path
|
|
||||||
d="m 863.082,0 21.875,0 0,190.547 -21.875,0 0,-190.547 z"
|
|
||||||
id="path3150"
|
|
||||||
style="fill:#090c0d;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 41 KiB |
9
static/images/logo-mission.svg
Normal file
|
After Width: | Height: | Size: 22 KiB |
3
static/images/logo-name.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 104 26" role="img" fill="currentColor">
|
||||||
|
<path id="ep-logo-name" d="M13.638 12.451a6.613 6.613 0 0 0-1.152-2.075 5.687 5.687 0 0 0-1.81-1.455c-.708-.369-1.513-.55-2.411-.55-.922 0-1.739.181-2.447.55a5.702 5.702 0 0 0-1.81 1.455 7.21 7.21 0 0 0-1.188 2.092 10.28 10.28 0 0 0-.586 2.43h11.848a8.013 8.013 0 0 0-.444-2.447zM2.571 19.277a6.885 6.885 0 0 0 1.082 2.324 6.187 6.187 0 0 0 1.88 1.702c.757.452 1.667.676 2.732.676 1.633 0 2.91-.427 3.83-1.277.923-.852 1.563-1.987 1.917-3.405h2.234c-.474 2.08-1.342 3.689-2.608 4.824-1.264 1.135-3.056 1.702-5.373 1.702-1.442 0-2.69-.254-3.742-.765-1.053-.507-1.91-1.203-2.572-2.092C1.29 22.082.8 21.052.48 19.88A13.991 13.991 0 0 1 0 16.174c0-1.206.16-2.388.479-3.547a9.56 9.56 0 0 1 1.472-3.103c.662-.91 1.519-1.643 2.572-2.2 1.051-.554 2.3-.833 3.742-.833 1.466 0 2.72.296 3.76.887A7.487 7.487 0 0 1 14.562 9.7c.65.959 1.118 2.058 1.401 3.3.284 1.243.402 2.5.354 3.777H2.234c0 .806.113 1.638.337 2.5M19.732 7.024v3.156h.07c.428-1.113 1.184-2.004 2.271-2.678a6.654 6.654 0 0 1 3.584-1.01c1.277 0 2.346.163 3.21.495.862.332 1.555.799 2.075 1.402.52.603.887 1.342 1.1 2.216.212.877.32 1.858.32 2.945v11.777h-2.235v-11.42c0-.782-.071-1.51-.214-2.184-.142-.673-.39-1.26-.745-1.757a3.61 3.61 0 0 0-1.436-1.17c-.603-.283-1.354-.425-2.253-.425-.898 0-1.697.16-2.395.479a5.221 5.221 0 0 0-1.772 1.31 6.034 6.034 0 0 0-1.136 1.988 8.128 8.128 0 0 0-.444 2.5v10.679h-2.234V7.024h2.234M34.367 7.024l5.747 16.067h.071L45.86 7.024h2.307l-6.846 18.303h-2.378L31.885 7.024h2.482M51.214 7.024v18.303h-2.235V7.024h2.235zm0-7.024V3.58h-2.235V0h2.235M61.037 15.703c.46 0 .902-.034 1.33-.103.424-.068.799-.2 1.122-.395.325-.195.584-.474.78-.833.196-.356.294-.825.294-1.404 0-.578-.098-1.047-.294-1.406a2.162 2.162 0 0 0-.78-.83 3.104 3.104 0 0 0-1.123-.395 8.39 8.39 0 0 0-1.329-.103H57.92v5.469h3.117zm1.099-8.587c1.14 0 2.112.166 2.913.498.801.335 1.452.772 1.953 1.316.503.545.871 1.167 1.1 1.866a6.89 6.89 0 0 1 .346 2.172c0 .733-.115 1.453-.346 2.159a5.043 5.043 0 0 1-1.1 1.88c-.501.544-1.152.984-1.953 1.316-.8.332-1.772.498-2.913.498H57.92v6.54h-4.013V7.116h8.229M76.944 19.216a5.26 5.26 0 0 1-.742.19c-.264.052-.54.096-.83.13-.29.034-.579.076-.87.127-.27.051-.54.12-.804.205-.263.085-.494.2-.69.344-.195.144-.354.33-.472.55-.12.222-.18.502-.18.844 0 .323.06.596.18.818.118.22.28.396.485.523.205.129.443.217.716.268.272.051.553.076.844.076.715 0 1.267-.117 1.66-.357.392-.239.68-.525.869-.857.187-.332.303-.668.344-1.008a6.93 6.93 0 0 0 .065-.818v-1.355a1.615 1.615 0 0 1-.575.32zm-7.168-5.124a4.345 4.345 0 0 1 1.43-1.353 6.257 6.257 0 0 1 1.956-.73 11.148 11.148 0 0 1 2.185-.215c.664 0 1.336.047 2.018.14a6.193 6.193 0 0 1 1.866.549 3.69 3.69 0 0 1 1.38 1.137c.356.486.537 1.128.537 1.93v6.874c0 .596.033 1.167.102 1.712.066.544.186.954.357 1.225h-3.68a5.23 5.23 0 0 1-.256-1.277 4.735 4.735 0 0 1-2.043 1.253 8.261 8.261 0 0 1-2.402.356c-.63 0-1.219-.076-1.763-.23a4.016 4.016 0 0 1-1.432-.715 3.34 3.34 0 0 1-.958-1.228c-.23-.493-.344-1.081-.344-1.762 0-.75.131-1.368.395-1.853a3.324 3.324 0 0 1 1.023-1.163 4.648 4.648 0 0 1 1.43-.651 15.515 15.515 0 0 1 1.623-.345 27.623 27.623 0 0 1 1.61-.202c.527-.052.996-.13 1.406-.232.408-.1.732-.252.97-.447.239-.195.349-.48.333-.857 0-.39-.065-.7-.192-.933a1.406 1.406 0 0 0-.511-.534 2.014 2.014 0 0 0-.741-.257 6.208 6.208 0 0 0-.907-.063c-.715 0-1.278.151-1.686.459-.41.308-.648.818-.716 1.533h-3.63c.052-.852.265-1.557.64-2.121M90.181 12.15v2.427h-2.657v6.543c0 .613.101 1.02.306 1.226.205.205.613.308 1.227.308.204 0 .399-.01.587-.027.188-.015.366-.042.537-.076v2.81a8.619 8.619 0 0 1-1.023.103c-.373.017-.74.024-1.098.024a10.41 10.41 0 0 1-1.597-.115 3.728 3.728 0 0 1-1.328-.446 2.356 2.356 0 0 1-.907-.945c-.222-.41-.333-.945-.333-1.61v-7.795h-2.198v-2.426h2.198V8.19h3.629v3.96h2.657M94.703 7.116v6.873h.075c.462-.764 1.05-1.323 1.764-1.672.716-.35 1.415-.523 2.096-.523.97 0 1.767.132 2.388.396.622.263 1.113.63 1.47 1.098.358.47.609 1.04.754 1.712.144.674.217 1.418.217 2.236v8.125h-3.629v-7.46c0-1.09-.17-1.905-.511-2.44-.34-.537-.945-.805-1.814-.805-.988 0-1.704.293-2.146.88-.443.587-.664 1.556-.664 2.901v6.924h-3.628V7.116h3.628" class="logo-main"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.1 KiB |
3
static/images/logo-square.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg fill="currentColor" id="ep-logo-square" role="img" viewBox="0 0 65 65" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M26.538 25.283c-.532-1.519-1.274-2.861-2.24-4.037a11.163 11.163 0 0 0-3.522-2.828c-1.381-.712-2.948-1.07-4.697-1.07-1.791 0-3.379.358-4.76 1.07a11.11 11.11 0 0 0-3.522 2.828c-.966 1.176-1.737 2.533-2.308 4.07a19.839 19.839 0 0 0-1.139 4.728h23.047a15.559 15.559 0 0 0-.86-4.76zM5 38.57c.44 1.685 1.143 3.189 2.11 4.527.966 1.333 2.187 2.436 3.656 3.31 1.475.875 3.243 1.308 5.313 1.308 3.178 0 5.665-.83 7.456-2.485 1.793-1.65 3.037-3.867 3.726-6.626h4.35c-.922 4.054-2.613 7.179-5.073 9.39-2.46 2.208-5.947 3.315-10.46 3.315-2.802 0-5.233-.502-7.274-1.489-2.056-.986-3.721-2.348-5.01-4.072-1.284-1.724-2.241-3.725-2.861-6.005C.313 37.465 0 35.058 0 32.529c0-2.343.313-4.649.933-6.9.62-2.254 1.577-4.267 2.861-6.04 1.289-1.772 2.954-3.197 5.01-4.281 2.041-1.08 4.472-1.616 7.275-1.616 2.856 0 5.293.571 7.32 1.724 2.026 1.147 3.666 2.66 4.931 4.521 1.265 1.86 2.177 3.999 2.725 6.416a27.9 27.9 0 0 1 .692 7.348H4.35c0 1.567.215 3.188.65 4.868M49.301 31.456c.914 0 1.793-.07 2.638-.202.845-.136 1.586-.4 2.23-.78.641-.391 1.159-.942 1.548-1.656.387-.702.582-1.64.582-2.782 0-1.148-.195-2.08-.582-2.79-.39-.707-.907-1.26-1.547-1.65-.645-.386-1.386-.65-2.231-.78a16.554 16.554 0 0 0-2.638-.206h-6.176v10.846h6.176zm2.184-17.032c2.26 0 4.189.331 5.776.995 1.592.66 2.88 1.524 3.877 2.608a10.007 10.007 0 0 1 2.177 3.696c.46 1.393.684 2.828.684 4.313 0 1.455-.224 2.88-.684 4.28a9.955 9.955 0 0 1-2.177 3.727c-.997 1.079-2.285 1.953-3.877 2.607-1.587.664-3.516.992-5.776.992h-8.36v12.974h-7.964V14.424h16.324" class="logo-main"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/images/uoa-logo-small.png
Executable file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 91 KiB |
170
static/js/discourse-api.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/**
|
||||||
|
* Discourse API Integration for enviPath Community
|
||||||
|
* Handles fetching topics from the Discourse forum API
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DiscourseAPI {
|
||||||
|
constructor() {
|
||||||
|
this.baseUrl = 'https://community.envipath.org';
|
||||||
|
this.categoryId = 10; // Announcements category
|
||||||
|
this.limit = 3; // Number of topics to fetch
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch topics from Discourse API
|
||||||
|
* @param {number} limit - Number of topics to fetch
|
||||||
|
* @returns {Promise<Array>} Array of topic objects
|
||||||
|
*/
|
||||||
|
async fetchTopics(limit = this.limit) {
|
||||||
|
try {
|
||||||
|
const url = `${this.baseUrl}/c/announcements/${this.categoryId}.json`;
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
return this.processTopics(data.topic_list.topics, limit);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Discourse topics:', error);
|
||||||
|
return this.getFallbackTopics();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process raw Discourse topics into standardized format
|
||||||
|
* @param {Array} topics - Raw topics from Discourse API
|
||||||
|
* @param {number} limit - Number of topics to return
|
||||||
|
* @returns {Array} Processed topics
|
||||||
|
*/
|
||||||
|
processTopics(topics, limit) {
|
||||||
|
return topics
|
||||||
|
.slice(0, limit)
|
||||||
|
.map(topic => ({
|
||||||
|
id: topic.id,
|
||||||
|
title: topic.title,
|
||||||
|
excerpt: this.extractExcerpt(topic.excerpt),
|
||||||
|
url: `${this.baseUrl}/t/${topic.slug}/${topic.id}`,
|
||||||
|
replies: topic.reply_count,
|
||||||
|
views: topic.views,
|
||||||
|
created_at: topic.created_at,
|
||||||
|
category: 'Announcements',
|
||||||
|
category_id: this.categoryId,
|
||||||
|
author: topic.last_poster_username,
|
||||||
|
author_avatar: this.getAvatarUrl(topic.last_poster_username)
|
||||||
|
}))
|
||||||
|
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); // Latest first
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract excerpt from topic content
|
||||||
|
* @param {string} excerpt - Raw excerpt from Discourse
|
||||||
|
* @returns {string} Cleaned excerpt
|
||||||
|
*/
|
||||||
|
extractExcerpt(excerpt) {
|
||||||
|
if (!excerpt) return 'Click to read more';
|
||||||
|
|
||||||
|
// Remove HTML tags and clean up; collapse whitespace; do not add manual ellipsis
|
||||||
|
return excerpt
|
||||||
|
.replace(/<[^>]*>/g, '') // Remove HTML tags
|
||||||
|
.replace(/ /g, ' ') // Replace with spaces
|
||||||
|
.replace(/&/g, '&') // Replace & with &
|
||||||
|
.replace(/</g, '<') // Replace < with <
|
||||||
|
.replace(/>/g, '>') // Replace > with >
|
||||||
|
.replace(/\s+/g, ' ') // Collapse all whitespace/newlines
|
||||||
|
.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get avatar URL for user
|
||||||
|
* @param {string} username - Username
|
||||||
|
* @returns {string} Avatar URL
|
||||||
|
*/
|
||||||
|
getAvatarUrl(username) {
|
||||||
|
if (!username) return `${this.baseUrl}/letter_avatar_proxy/v4/letter/u/1.png`;
|
||||||
|
return `${this.baseUrl}/user_avatar/${this.baseUrl.replace('https://', '')}/${username}/40/1_1.png`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get fallback topics when API fails
|
||||||
|
* @returns {Array} Fallback topics
|
||||||
|
*/
|
||||||
|
getFallbackTopics() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 110,
|
||||||
|
title: "enviPath Beta Update: Major Improvements to Prediction, Analysis & Collaboration!",
|
||||||
|
excerpt: "We're excited to announce major updates to the enviPath beta platform! This release includes significant improvements to our prediction algorithms, enhanced analysis tools, and new collaboration features that will make environmental biotransformation research more accessible and efficient.",
|
||||||
|
url: "https://community.envipath.org/t/envipath-beta-update-major-improvements-to-prediction-analysis-collaboration/110",
|
||||||
|
replies: 0,
|
||||||
|
views: 16,
|
||||||
|
created_at: "2025-09-23T00:00:00Z",
|
||||||
|
category: "Announcements",
|
||||||
|
category_id: 10,
|
||||||
|
author: "wicker",
|
||||||
|
author_avatar: "https://community.envipath.org/user_avatar/community.envipath.org/wicker/40/1_1.png"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format date for display
|
||||||
|
* @param {string} dateString - ISO date string
|
||||||
|
* @returns {string} Formatted date
|
||||||
|
*/
|
||||||
|
formatDate(dateString) {
|
||||||
|
const date = new Date(dateString);
|
||||||
|
return date.toLocaleDateString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load topics and call render function
|
||||||
|
* @param {string} containerId - ID of container element
|
||||||
|
* @param {Function} renderCallback - Function to render topics
|
||||||
|
*/
|
||||||
|
async loadTopics(containerId = 'community-news-container', renderCallback = null) {
|
||||||
|
const container = document.getElementById(containerId);
|
||||||
|
if (!container) {
|
||||||
|
console.error(`Container with ID '${containerId}' not found`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide loading spinner
|
||||||
|
const loading = document.getElementById('loading');
|
||||||
|
if (loading) {
|
||||||
|
loading.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const topics = await this.fetchTopics();
|
||||||
|
|
||||||
|
if (renderCallback && typeof renderCallback === 'function') {
|
||||||
|
renderCallback(topics);
|
||||||
|
} else {
|
||||||
|
// Default rendering - just log topics
|
||||||
|
console.log('Topics loaded:', topics);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading topics:', error);
|
||||||
|
container.innerHTML = '<p class="text-neutral">No updates found. Head over to the <a href="https://community.envipath.org" target="_blank" class="link link-primary">community</a> to see the latest discussions.</p>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for use in other scripts
|
||||||
|
window.DiscourseAPI = DiscourseAPI;
|
||||||
|
|
||||||
|
// Auto-initialize if container exists
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
if (document.getElementById('community-news-container')) {
|
||||||
|
const discourseAPI = new DiscourseAPI();
|
||||||
|
discourseAPI.loadTopics('community-news-container', function(topics) {
|
||||||
|
// This will be handled by the template's render function
|
||||||
|
if (window.renderDiscourseTopics) {
|
||||||
|
window.renderDiscourseTopics(topics);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -1,6 +1,9 @@
|
|||||||
{% if meta.can_edit %}
|
{% if meta.can_edit %}
|
||||||
<li>
|
<li>
|
||||||
<a role="button" data-toggle="modal" data-target="#predict_modal">
|
<a
|
||||||
<span class="glyphicon glyphicon-plus"></span> New Pathway</a>
|
href="{% if meta.current_package %}{{ meta.current_package.url }}/predict{% else %}{{ meta.server_url }}/predict{% endif %}"
|
||||||
|
>
|
||||||
|
<span class="glyphicon glyphicon-plus"></span> New Pathway</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -1,46 +1,68 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html data-theme="envipath">
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<head>
|
<head>
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token }}" />
|
||||||
|
{# Favicon #}
|
||||||
|
<link
|
||||||
|
rel="shortcut icon"
|
||||||
|
type="image/png"
|
||||||
|
href="{% static 'images/favicon.ico' %}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{# Tailwind CSS disabled for legacy Bootstrap framework #}
|
||||||
|
{# Pages using this framework will be migrated to framework_modern.html incrementally #}
|
||||||
|
{# <link href="{% static 'css/output.css' %}" rel="stylesheet" type="text/css"/> #}
|
||||||
|
|
||||||
|
{# Legacy Bootstrap 3.3.7 - scoped to .legacy-bootstrap #}
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
||||||
|
/>
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||||
|
<script src="https://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script>
|
||||||
|
<link
|
||||||
|
href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.3/css/bootstrap-select.min.css"
|
||||||
|
/>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.3/js/bootstrap-select.min.js"></script>
|
||||||
|
<script src="https://community.envipath.org/javascripts/embed-topics.js"></script>
|
||||||
|
<!-- CDN END -->
|
||||||
|
|
||||||
|
{# Bootstrap compatibility styles #}
|
||||||
<style>
|
<style>
|
||||||
html, body {
|
/* Ensure proper viewport behavior */
|
||||||
|
html,
|
||||||
|
body {
|
||||||
height: 100%; /* ensure body fills viewport */
|
height: 100%; /* ensure body fills viewport */
|
||||||
overflow-x: hidden; /* prevent horizontal scroll */
|
overflow-x: hidden; /* prevent horizontal scroll */
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{# TODO use bundles from bootstrap 3.3.7 #}
|
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
|
||||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
|
||||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
|
||||||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script>
|
|
||||||
<link href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
|
||||||
<link rel="stylesheet"
|
|
||||||
href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.3/css/bootstrap-select.min.css">
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.7.3/js/bootstrap-select.min.js"></script>
|
|
||||||
<script src="https://community.envipath.org/javascripts/embed-topics.js"></script>
|
|
||||||
<!-- CDN END -->
|
|
||||||
<meta name="csrf-token" content="{{ csrf_token }}">
|
|
||||||
<script>
|
<script>
|
||||||
const csrftoken = document.querySelector('[name=csrf-token]').content;
|
const csrftoken = document.querySelector("[name=csrf-token]").content;
|
||||||
|
|
||||||
// Setup CSRF header for all jQuery AJAX requests
|
// Setup CSRF header for all jQuery AJAX requests
|
||||||
$.ajaxSetup({
|
$.ajaxSetup({
|
||||||
beforeSend: function(xhr, settings) {
|
beforeSend: function (xhr, settings) {
|
||||||
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
|
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
|
||||||
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{# Favicon #}
|
|
||||||
<link rel="shortcut icon" type="image/png" href="{% static 'images/favicon.ico' %}"/>
|
|
||||||
<!-- {# C3 CSS #}-->
|
<!-- {# C3 CSS #}-->
|
||||||
<!-- <link id="css-c3" href="{% static 'css/c3.css' %}" rel="stylesheet" type="text/css"/>-->
|
<!-- <link id="css-c3" href="{% static 'css/c3.css' %}" rel="stylesheet" type="text/css"/>-->
|
||||||
<!-- {# EP CSS #}-->
|
<!-- {# EP CSS #}-->
|
||||||
<!-- <link id="css-pps_white_general" href="{% static 'css/epp.css' %}" rel="stylesheet" type="text/css"/>-->
|
<!-- <link id="css-pps_white_general" href="{% static 'css/epp.css' %}" rel="stylesheet" type="text/css"/>-->
|
||||||
|
|
||||||
|
|
||||||
{# General EP JS #}
|
{# General EP JS #}
|
||||||
<script src="{% static 'js/pps.js' %}"></script>
|
<script src="{% static 'js/pps.js' %}"></script>
|
||||||
{# Modal Steps for Stepwise Modal Wizards #}
|
{# Modal Steps for Stepwise Modal Wizards #}
|
||||||
@ -49,26 +71,33 @@
|
|||||||
{% if not debug %}
|
{% if not debug %}
|
||||||
<!-- Matomo -->
|
<!-- Matomo -->
|
||||||
<script>
|
<script>
|
||||||
var _paq = window._paq = window._paq || [];
|
var _paq = (window._paq = window._paq || []);
|
||||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||||
_paq.push(['trackPageView']);
|
_paq.push(["trackPageView"]);
|
||||||
_paq.push(['enableLinkTracking']);
|
_paq.push(["enableLinkTracking"]);
|
||||||
(function () {
|
(function () {
|
||||||
var u = "//matomo.envipath.com/";
|
var u = "//matomo.envipath.com/";
|
||||||
_paq.push(['setTrackerUrl', u + 'matomo.php']);
|
_paq.push(["setTrackerUrl", u + "matomo.php"]);
|
||||||
_paq.push(['setSiteId', '{{ meta.site_id }}']);
|
_paq.push(["setSiteId", "{{ meta.site_id }}"]);
|
||||||
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
var d = document,
|
||||||
|
g = d.createElement("script"),
|
||||||
|
s = d.getElementsByTagName("script")[0];
|
||||||
g.async = true;
|
g.async = true;
|
||||||
g.src = u + 'matomo.js';
|
g.src = u + "matomo.js";
|
||||||
s.parentNode.insertBefore(g, s);
|
s.parentNode.insertBefore(g, s);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<!-- End Matomo Code -->
|
<!-- End Matomo Code -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</head>
|
||||||
</head>
|
<body>
|
||||||
<body>
|
<!-- Legacy Bootstrap navbar - isolated from Tailwind -->
|
||||||
<nav class="navbar navbar-default navbar-inverse" style="border-radius:0px;" role="navigation">
|
<div class="legacy-bootstrap">
|
||||||
|
<nav
|
||||||
|
class="navbar navbar-default navbar-inverse"
|
||||||
|
style="border-radius:0px;"
|
||||||
|
role="navigation"
|
||||||
|
>
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<!-- Brand and toggle get grouped for better mobile display -->
|
<!-- Brand and toggle get grouped for better mobile display -->
|
||||||
<div class="navbar-header navbar-header-framework">
|
<div class="navbar-header navbar-header-framework">
|
||||||
@ -79,96 +108,186 @@
|
|||||||
<!-- <span class="icon-bar"></span>-->
|
<!-- <span class="icon-bar"></span>-->
|
||||||
<!-- <span class="icon-bar"></span>-->
|
<!-- <span class="icon-bar"></span>-->
|
||||||
<!-- </button>-->
|
<!-- </button>-->
|
||||||
<a id="pictureLink" href="{{ meta.server_url }}" class="navbar-brand">
|
<a
|
||||||
<img id="image-logo-short-white.svg" src='{% static "/images/logo-short-white.svg" %}' width="100"
|
id="pictureLink"
|
||||||
alt="enviPath">
|
href="{{ meta.server_url }}"
|
||||||
|
class="navbar-brand"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
id="image-logo-short-white.svg"
|
||||||
|
src="{% static "/images/logo-short-white.svg" %}"
|
||||||
|
width="100"
|
||||||
|
alt="enviPath"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||||
<div class="collapse navbar-collapse collapse-framework navbar-collapse-framework" id="navbarCollapse">
|
<div
|
||||||
|
class="collapse navbar-collapse collapse-framework navbar-collapse-framework"
|
||||||
|
id="navbarCollapse"
|
||||||
|
>
|
||||||
<ul class="nav navbar-nav navbar-nav-framework">
|
<ul class="nav navbar-nav navbar-nav-framework">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" data-toggle="modal" data-target="#predict_modal">
|
<a href="{{ meta.server_url }}/predict"> Predict Pathway </a>
|
||||||
Predict Pathway
|
</li>
|
||||||
</a>
|
{# <li class="dropdown">#}
|
||||||
|
{# <a data-toggle="dropdown" class="dropdown-toggle" href="#">Predict Pathway<b class="caret"></b></a>#}
|
||||||
|
{# <ul role="menu" class="dropdown-menu">#}
|
||||||
|
{# <li>#}
|
||||||
|
{# <a class="button" data-toggle="modal" data-target="#predict_modal">#}
|
||||||
|
{# <i class=" glyphicon glyphicon-tag"></i> Predict Pathway#}
|
||||||
|
{# </a>#}
|
||||||
|
{# </li>#}
|
||||||
|
{# <li>#}
|
||||||
|
{# <a class="button" data-toggle="modal" data-target="#batch_predict_modal">#}
|
||||||
|
{# <i class=" glyphicon glyphicon-tags"></i> Batch Prediction#}
|
||||||
|
{# </a>#}
|
||||||
|
{# </li>#}
|
||||||
|
{# </ul>#}
|
||||||
|
{# </li>#}
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/package" id="packageLink"
|
||||||
|
>Package</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/search" id="searchLink"
|
||||||
|
>Search</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/model" id="modelLink"
|
||||||
|
>Modelling</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
{# <li class="dropdown">#}
|
|
||||||
{# <a data-toggle="dropdown" class="dropdown-toggle" href="#">Predict Pathway<b class="caret"></b></a>#}
|
|
||||||
{# <ul role="menu" class="dropdown-menu">#}
|
|
||||||
{# <li>#}
|
|
||||||
{# <a class="button" data-toggle="modal" data-target="#predict_modal">#}
|
|
||||||
{# <i class=" glyphicon glyphicon-tag"></i> Predict Pathway#}
|
|
||||||
{# </a>#}
|
|
||||||
{# </li>#}
|
|
||||||
{# <li>#}
|
|
||||||
{# <a class="button" data-toggle="modal" data-target="#batch_predict_modal">#}
|
|
||||||
{# <i class=" glyphicon glyphicon-tags"></i> Batch Prediction#}
|
|
||||||
{# </a>#}
|
|
||||||
{# </li>#}
|
|
||||||
{# </ul>#}
|
|
||||||
{# </li>#}
|
|
||||||
<li><a href="{{ meta.server_url }}/package" id="packageLink">Package</a></li>
|
|
||||||
<li><a href="{{ meta.server_url }}/search" id="searchLink">Search</a></li>
|
|
||||||
<li><a href="{{ meta.server_url }}/model" id="modelLink">Modelling</a></li>
|
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">Browse Data<b class="caret"></b></a>
|
<a data-toggle="dropdown" class="dropdown-toggle" href="#"
|
||||||
|
>Browse Data<b class="caret"></b
|
||||||
|
></a>
|
||||||
<ul role="menu" class="dropdown-menu">
|
<ul role="menu" class="dropdown-menu">
|
||||||
<li><a href="{{ meta.server_url }}/pathway" id="pathwayLink">Pathway</a></li>
|
<li>
|
||||||
<li><a href="{{ meta.server_url }}/rule" id="ruleLink">Rule</a></li>
|
<a href="{{ meta.server_url }}/pathway" id="pathwayLink"
|
||||||
<li><a href="{{ meta.server_url }}/compound" id="compoundLink">Compound</a></li>
|
>Pathway</a
|
||||||
<li><a href="{{ meta.server_url }}/reaction" id="reactionLink">Reaction</a></li>
|
>
|
||||||
<li><a href="{{ meta.server_url }}/model" id="relative-reasoningLink">Model</a></li>
|
</li>
|
||||||
<li><a href="{{ meta.server_url }}/scenario" id="scenarioLink">Scenario</a></li>
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/rule" id="ruleLink">Rule</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/compound" id="compoundLink"
|
||||||
|
>Compound</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/reaction" id="reactionLink"
|
||||||
|
>Reaction</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ meta.server_url }}/model"
|
||||||
|
id="relative-reasoningLink"
|
||||||
|
>Model</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/scenario" id="scenarioLink"
|
||||||
|
>Scenario</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
{# <li><a href="{{ meta.server_url }}/setting" id="settingLink">Setting</a></li>#}
|
{# <li><a href="{{ meta.server_url }}/setting" id="settingLink">Setting</a></li>#}
|
||||||
{# <li><a href="{{ meta.server_url }}/user" id="userLink">User</a></li>#}
|
{# <li><a href="{{ meta.server_url }}/user" id="userLink">User</a></li>#}
|
||||||
{# <li><a href="{{ meta.server_url }}/group" id="groupLink">Group</a></li>#}
|
{# <li><a href="{{ meta.server_url }}/group" id="groupLink">Group</a></li>#}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right navbar-nav-framework navbar-right-framework">
|
<ul
|
||||||
<li><a href="https://community.envipath.org/" id="communityLink">Community</a></li>
|
class="nav navbar-nav navbar-right navbar-nav-framework navbar-right-framework"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a href="https://community.envipath.org/" id="communityLink"
|
||||||
|
>Community</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">Info <b class="caret"></b></a>
|
<a data-toggle="dropdown" class="dropdown-toggle" href="#"
|
||||||
|
>Info <b class="caret"></b
|
||||||
|
></a>
|
||||||
<ul role="menu" class="dropdown-menu">
|
<ul role="menu" class="dropdown-menu">
|
||||||
<!--<li><a href="{{ meta.server_url }}/funding" id="fundingLink">Funding</a></li>-->
|
<!--<li><a href="{{ meta.server_url }}/funding" id="fundingLink">Funding</a></li>-->
|
||||||
<li><a href="https://community.envipath.org/t/envipath-license/109" id="licenceLink">Licences</a></li>
|
<li>
|
||||||
<li class="divider"></li>
|
<a
|
||||||
<li><a target="_blank" href="https://wiki.envipath.org/" id="wikiLink">Documentation Wiki</a>
|
href="https://community.envipath.org/t/envipath-license/109"
|
||||||
|
id="licenceLink"
|
||||||
|
>Licences</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://wiki.envipath.org/"
|
||||||
|
id="wikiLink"
|
||||||
|
>Documentation Wiki</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
id="citeButton"
|
||||||
|
data-toggle="modal"
|
||||||
|
data-target="#citemodal"
|
||||||
|
>How to cite enviPath</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="#" id="citeButton" data-toggle="modal" data-target="#citemodal">How to cite
|
|
||||||
enviPath</a></li>
|
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a>Version: {{ meta.version }}</a></li>
|
<li><a>Version: {{ meta.version }}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% if meta.user.username == 'anonymous' %}
|
{% if meta.user.username == 'anonymous' %}
|
||||||
<li>
|
<li>
|
||||||
<a href="#signup" id="loginButton" data-toggle="modal" data-target="#signupmodal"
|
<a
|
||||||
style="margin-right:10px">Login</a>
|
href="{% url 'login' %}"
|
||||||
|
id="loginButton"
|
||||||
|
style="margin-right:10px"
|
||||||
|
>Login</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a data-toggle="dropdown" id="loggedInButton" class="dropdown-toggle" id="logedInButton"
|
<a
|
||||||
href="#">
|
data-toggle="dropdown"
|
||||||
|
id="loggedInButton"
|
||||||
|
class="dropdown-toggle"
|
||||||
|
id="logedInButton"
|
||||||
|
href="#"
|
||||||
|
>
|
||||||
<div id="username">
|
<div id="username">
|
||||||
{{ user.username }}<b class="caret"></b>
|
{{ user.username }}<b class="caret"></b>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<ul role="menu" class="dropdown-menu">
|
<ul role="menu" class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ meta.user.url }}" id="accountbutton">My Account</a>
|
<a href="{{ meta.user.url }}" id="accountbutton"
|
||||||
|
>My Account</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<form class="navbar-form navbar-left navbar-left-framework" role="logout"
|
<form
|
||||||
action="{% url 'logout' %}" method="post">
|
class="navbar-form navbar-left navbar-left-framework"
|
||||||
|
role="logout"
|
||||||
|
action="{% url 'logout' %}"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="hidden" name="logout" value="true">
|
<input type="hidden" name="logout" value="true" />
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-default">Logout</button>
|
<button type="submit" class="btn btn-default">
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@ -176,8 +295,11 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<div id="docContent" class="content container">
|
</div>
|
||||||
|
<!-- End legacy Bootstrap navbar -->
|
||||||
|
|
||||||
|
<div id="docContent" class="content container">
|
||||||
{% if breadcrumbs %}
|
{% if breadcrumbs %}
|
||||||
<div id="bread">
|
<div id="bread">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
@ -196,81 +318,105 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if message %}
|
{% if message %}
|
||||||
<div id="message">
|
<div id="message">{{ message }}</div>
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{% if meta.url_contains_package and meta.current_package.license %}
|
{% if meta.url_contains_package and meta.current_package.license %}
|
||||||
<p></p>
|
<p></p>
|
||||||
<div class="panel-group" id="license_accordion">
|
<div class="panel-group" id="license_accordion">
|
||||||
<div class="panel panel-default list-group-item" style="background-color:#f5f5f5">
|
<div
|
||||||
|
class="panel panel-default list-group-item"
|
||||||
|
style="background-color:#f5f5f5"
|
||||||
|
>
|
||||||
<div class="panel-title">
|
<div class="panel-title">
|
||||||
<a data-toggle="collapse" data-parent="#licence_accordion" href="#license">License</a>
|
<a
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#licence_accordion"
|
||||||
|
href="#license"
|
||||||
|
>License</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="license" class="panel-collapse collapse in">
|
<div id="license" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<a target="_blank" href="{{ meta.current_package.license.link }}">
|
<a target="_blank" href="{{ meta.current_package.license.link }}">
|
||||||
<img src="{{ meta.current_package.license.image_link }}">
|
<img src="{{ meta.current_package.license.image_link }}" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- FOOTER -->
|
<!-- FOOTER - Legacy Bootstrap -->
|
||||||
<div class="container text-center">
|
<div class="legacy-bootstrap">
|
||||||
<hr/>
|
<div class="container text-center">
|
||||||
|
<hr />
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<ul class="nav nav-pills nav-justified">
|
<ul class="nav nav-pills nav-justified">
|
||||||
<li>
|
<li>
|
||||||
<a href="http://ml.auckland.ac.nz" target="_blank">
|
<a href="http://ml.auckland.ac.nz" target="_blank">
|
||||||
<img id="image-uoalogo" height="60" src='{% static "/images/UoA-Logo-Primary-RGB-Small.png" %}'
|
<img
|
||||||
alt="The Univserity of Auckland"/>
|
id="image-uoalogo"
|
||||||
|
height="60"
|
||||||
|
src="{% static "/images/UoA-Logo-Primary-RGB-Small.png" %}"
|
||||||
|
alt="The Univserity of Auckland"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://eawag.ch" target="_blank">
|
<a href="https://eawag.ch" target="_blank">
|
||||||
<img id="image-ealogo" height="60" src='{% static "/images/ealogo.gif" %}' alt="Eawag"/>
|
<img
|
||||||
|
id="image-ealogo"
|
||||||
|
height="60"
|
||||||
|
src="{% static "/images/ealogo.gif" %}"
|
||||||
|
alt="Eawag"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://www.uzh.ch/" target="_blank">
|
<a href="https://www.uzh.ch/" target="_blank">
|
||||||
<img id="image-ufzlogo" height="60" src='{% static "/images/uzh-logo.svg" %}'
|
<img
|
||||||
alt="University of Zurich"/>
|
id="image-ufzlogo"
|
||||||
|
height="60"
|
||||||
|
src="{% static "/images/uzh-logo.svg" %}"
|
||||||
|
alt="University of Zurich"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<ul class="nav nav-pills nav-justified">
|
<ul class="nav nav-pills nav-justified">
|
||||||
<!-- <li><a href="https://envipath.com/imprint/" target="_blank">Impressum/Imprint</a></li>-->
|
<!-- <li><a href="https://envipath.com/imprint/" target="_blank">Impressum/Imprint</a></li>-->
|
||||||
<li><a href="mailto:admin@envipath.org" target="_blank">Contact</a></li>
|
<li>
|
||||||
|
<a href="mailto:admin@envipath.org" target="_blank">Contact</a>
|
||||||
|
</li>
|
||||||
<!-- <li><a href="http://envipath.com" target="_blank"> enviPath UG (haftungsbeschränkt) & Co. KG ©-->
|
<!-- <li><a href="http://envipath.com" target="_blank"> enviPath UG (haftungsbeschränkt) & Co. KG ©-->
|
||||||
<!-- {{ YEAR }}</a></li>-->
|
<!-- {{ YEAR }}</a></li>-->
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
</div>
|
||||||
|
<!-- End legacy Bootstrap footer -->
|
||||||
|
|
||||||
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
// Hide actionsbutton if theres no action defined
|
// Hide actionsbutton if theres no action defined
|
||||||
if ($('#actionsButton ul').children().length > 0) {
|
if ($("#actionsButton ul").children().length > 0) {
|
||||||
$('#actionsButton').show();
|
$("#actionsButton").show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% block modals %}
|
{% block modals %}
|
||||||
{% include "modals/cite_modal.html" %}
|
{% include "modals/cite_modal.html" %}
|
||||||
{% include "modals/signup_modal.html" %}
|
|
||||||
{% include "modals/predict_modal.html" %}
|
{% include "modals/predict_modal.html" %}
|
||||||
{% include "modals/batch_predict_modal.html" %}
|
{% include "modals/batch_predict_modal.html" %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
223
templates/framework_modern.html
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html data-theme="envipath" lang="en">
|
||||||
|
{% load static %}
|
||||||
|
<head>
|
||||||
|
<title>{{ title }}</title>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token }}" />
|
||||||
|
|
||||||
|
{# Favicon #}
|
||||||
|
<link
|
||||||
|
rel="shortcut icon"
|
||||||
|
type="image/png"
|
||||||
|
href="{% static 'images/favicon.ico' %}"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{# Tailwind CSS + DaisyUI Output #}
|
||||||
|
<link
|
||||||
|
href="{% static 'css/output.css' %}"
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{# jQuery - Keep for compatibility with existing JS #}
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
|
||||||
|
|
||||||
|
{# Font Awesome #}
|
||||||
|
<link
|
||||||
|
href="https://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{# Discourse embed for community #}
|
||||||
|
<script src="https://community.envipath.org/javascripts/embed-topics.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const csrftoken = document.querySelector("[name=csrf-token]").content;
|
||||||
|
|
||||||
|
// Setup CSRF header for all jQuery AJAX requests
|
||||||
|
$.ajaxSetup({
|
||||||
|
beforeSend: function (xhr, settings) {
|
||||||
|
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
|
||||||
|
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{# General EP JS #}
|
||||||
|
<script src="{% static 'js/pps.js' %}"></script>
|
||||||
|
{# Modal Steps for Stepwise Modal Wizards #}
|
||||||
|
<script src="{% static 'js/jquery-bootstrap-modal-steps.js' %}"></script>
|
||||||
|
|
||||||
|
{% if not debug %}
|
||||||
|
<!-- Matomo -->
|
||||||
|
<script>
|
||||||
|
var _paq = (window._paq = window._paq || []);
|
||||||
|
_paq.push(["trackPageView"]);
|
||||||
|
_paq.push(["enableLinkTracking"]);
|
||||||
|
(function () {
|
||||||
|
var u = "//matomo.envipath.com/";
|
||||||
|
_paq.push(["setTrackerUrl", u + "matomo.php"]);
|
||||||
|
_paq.push(["setSiteId", "{{ meta.site_id }}"]);
|
||||||
|
var d = document,
|
||||||
|
g = d.createElement("script"),
|
||||||
|
s = d.getElementsByTagName("script")[0];
|
||||||
|
g.async = true;
|
||||||
|
g.src = u + "matomo.js";
|
||||||
|
s.parentNode.insertBefore(g, s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
<!-- End Matomo Code -->
|
||||||
|
{% endif %}
|
||||||
|
</head>
|
||||||
|
<body class="bg-base-300 min-h-screen">
|
||||||
|
{% include "includes/navbar.html" %}
|
||||||
|
|
||||||
|
{# Main Content Area #}
|
||||||
|
<main class="w-full">
|
||||||
|
{% block main_content %}
|
||||||
|
{# Breadcrumbs - outside main content, optional #}
|
||||||
|
{% if breadcrumbs %}
|
||||||
|
<div id="bread" class="max-w-7xl mx-auto px-4 py-4">
|
||||||
|
<div class="breadcrumbs text-sm">
|
||||||
|
<ul>
|
||||||
|
{% for elem in breadcrumbs %}
|
||||||
|
{% for name, url in elem.items %}
|
||||||
|
{% if forloop.parentloop.last %}
|
||||||
|
<li>{{ name }}</li>
|
||||||
|
{% else %}
|
||||||
|
<li><a href="{{ url }}">{{ name }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# Main content container - paper effect on medium+ screens #}
|
||||||
|
<div
|
||||||
|
id="docContent"
|
||||||
|
class="bg-base-100 mx-auto md:my-8 md:max-w-6xl md:rounded-lg md:shadow-xl"
|
||||||
|
>
|
||||||
|
{# Messages - inside paper #}
|
||||||
|
{% if message %}
|
||||||
|
<div id="message" class="alert alert-info m-4">{{ message }}</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# Page content - no enforced styles #}
|
||||||
|
{% block content %}
|
||||||
|
{% endblock content %}
|
||||||
|
|
||||||
|
{# License - inside paper if present #}
|
||||||
|
{% if meta.url_contains_package and meta.current_package.license %}
|
||||||
|
<div class="collapse collapse-arrow bg-base-200 m-8">
|
||||||
|
<input type="checkbox" checked />
|
||||||
|
<div class="collapse-title text-xl font-medium">License</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="{{ meta.current_package.license.link }}"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="{{ meta.current_package.license.image_link }}"
|
||||||
|
alt="License"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{% include "includes/footer.html" %}
|
||||||
|
|
||||||
|
{# Floating Help Tab #}
|
||||||
|
{% if not public_mode %}
|
||||||
|
<div class="fixed right-0 top-1/2 -translate-y-1/2 z-50">
|
||||||
|
<a
|
||||||
|
href="https://community.envipath.org/"
|
||||||
|
target="_blank"
|
||||||
|
class="btn btn-secondary hover:btn-secondary-focus text-secondary-content flex items-center justify-center text-sm shadow-lg transition-all duration-300 hover:-translate-x-1 hover:scale-105"
|
||||||
|
title="Get Help from the Community"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-message-circle-question-mark-icon lucide-message-circle-question-mark"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M2.992 16.342a2 2 0 0 1 .094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413-.998a2 2 0 0 1 1.099.092 10 10 0 1 0-4.777-4.719"
|
||||||
|
/>
|
||||||
|
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
|
||||||
|
<path d="M12 17h.01" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block modals %}
|
||||||
|
{% include "modals/search_modal.html" %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
// Hide actionsbutton if there's no action defined
|
||||||
|
if ($("#actionsButton ul").children().length > 0) {
|
||||||
|
$("#actionsButton").show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open search modal function
|
||||||
|
function openSearchModal() {
|
||||||
|
const searchModal = document.getElementById("search_modal");
|
||||||
|
if (searchModal) {
|
||||||
|
searchModal.showModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click handler for search badge
|
||||||
|
const searchTrigger = document.getElementById("search-trigger");
|
||||||
|
if (searchTrigger) {
|
||||||
|
searchTrigger.addEventListener("click", function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
openSearchModal();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global keyboard shortcut for search (Cmd+K on Mac, Ctrl+K on Windows/Linux)
|
||||||
|
document.addEventListener("keydown", function (event) {
|
||||||
|
// Check if user is typing in an input field
|
||||||
|
const activeElement = document.activeElement;
|
||||||
|
const isInputField =
|
||||||
|
activeElement &&
|
||||||
|
(activeElement.tagName === "INPUT" ||
|
||||||
|
activeElement.tagName === "TEXTAREA" ||
|
||||||
|
activeElement.contentEditable === "true");
|
||||||
|
|
||||||
|
if (isInputField) {
|
||||||
|
return; // Don't trigger shortcut when typing in input fields
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Cmd+K (Mac) or Ctrl+K (Windows/Linux)
|
||||||
|
const isMac = /Mac/.test(navigator.platform);
|
||||||
|
const isCorrectModifier = isMac ? event.metaKey : event.ctrlKey;
|
||||||
|
|
||||||
|
if (isCorrectModifier && event.key === "k") {
|
||||||
|
event.preventDefault();
|
||||||
|
openSearchModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
69
templates/includes/footer.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
{% load static %}
|
||||||
|
<div class="lg:max-w-5xl mt-10 mx-auto bg-base-300 text-base-content">
|
||||||
|
|
||||||
|
<footer class="footer sm:footer-horizontal p-10">
|
||||||
|
{% if not public_mode %}
|
||||||
|
<nav>
|
||||||
|
<h6 class="footer-title">Services</h6>
|
||||||
|
<a class="link link-hover" href="/">Predict</a>
|
||||||
|
<a class="link link-hover" href="/search">Search</a>
|
||||||
|
<a class="link link-hover" href="/package">Browse</a>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a class="link link-hover" href="/model">Your Collections</a>
|
||||||
|
{% endif %}
|
||||||
|
<a href="https://wiki.envipath.org/" target="_blank" class="link link-hover">Documentation</a>
|
||||||
|
</nav>
|
||||||
|
{% endif %}
|
||||||
|
<nav>
|
||||||
|
<h6 class="footer-title">Company</h6>
|
||||||
|
<a class="link link-hover" href="/about">About us</a>
|
||||||
|
<a class="link link-hover" href="/contact">Contact us</a>
|
||||||
|
<a class="link link-hover" href="/careers">Careers</a>
|
||||||
|
<a class="link link-hover" href="/legal">Legal</a>
|
||||||
|
</nav>
|
||||||
|
<nav>
|
||||||
|
<h6 class="footer-title">Legal</h6>
|
||||||
|
<a class="link link-hover" href="/terms">Terms of use</a>
|
||||||
|
<a class="link link-hover" href="/privacy">Privacy policy</a>
|
||||||
|
<a class="link link-hover" href="/cookie-policy">Cookie policy</a>
|
||||||
|
<a class="link link-hover" href="/cite">Cite enviPath</a>
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
<footer class="footer border-neutral-300 border-t-2 px-10 py-4">
|
||||||
|
<div class="flex flex-row justify-between w-full items-start">
|
||||||
|
<aside class="grid-flow-col items-center">
|
||||||
|
<svg class="fill-neutral-content flex-shrink-0 h-14 m-2" viewbox="0 0 65 65" >
|
||||||
|
<use
|
||||||
|
href="{% static "/images/logo-square.svg" %}#ep-logo-square"
|
||||||
|
>
|
||||||
|
</use>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
enviPath Ltd.
|
||||||
|
<br />
|
||||||
|
Biodegredation prediction since 2015.
|
||||||
|
</p>
|
||||||
|
</aside>
|
||||||
|
<aside class="text-sm text-base-200 mt-2"><span class="text-xs tracking-tight">Version</span> <span class="text-base font-bold">{{ meta.version }}</span></aside>
|
||||||
|
</div>
|
||||||
|
<nav class="md:place-self-center md:justify-self-end">
|
||||||
|
<div class="grid grid-flow-col gap-4">
|
||||||
|
<a href="https://www.youtube.com/@envipath7231" target="_blank">
|
||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 fill-current">
|
||||||
|
<title>YouTube</title>
|
||||||
|
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a href="https://community.envipath.org/" target="_blank">
|
||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 fill-current">
|
||||||
|
<title>Discourse</title>
|
||||||
|
<path d="M12.103 0C18.666 0 24 5.485 24 11.997c0 6.51-5.33 11.99-11.9 11.99L0 24V11.79C0 5.28 5.532 0 12.103 0zm.116 4.563c-2.593-.003-4.996 1.352-6.337 3.57-1.33 2.208-1.387 4.957-.148 7.22L4.4 19.61l4.794-1.074c2.745 1.225 5.965.676 8.136-1.39 2.17-2.054 2.86-5.228 1.737-7.997-1.135-2.778-3.84-4.59-6.84-4.585h-.008z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a href="https://www.linkedin.com/company/envipath/" target="_blank">
|
||||||
|
<img src="{% static "/images/linkedin.png" %}" alt="LinkedIn" class="w-6 h-6">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
147
templates/includes/navbar.html
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
{% load static %}
|
||||||
|
{# Modern DaisyUI Navbar #}
|
||||||
|
<div class="navbar bg-neutral-50 text-neutral-950 shadow-lg x-50">
|
||||||
|
<div class="navbar-start">
|
||||||
|
<a href="{{ meta.server_url }}" class="btn btn-ghost normal-case text-xl">
|
||||||
|
<svg class="h-8 fill-base-content" viewBox="0 0 104 26" role="img">
|
||||||
|
<use href="{% static "/images/logo-name.svg" %}#ep-logo-name" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if not public_mode %}
|
||||||
|
<div class="navbar-center hidden lg:flex">
|
||||||
|
<a
|
||||||
|
href="{{ meta.server_url }}/predict"
|
||||||
|
role="button"
|
||||||
|
class="btn btn-ghost"
|
||||||
|
id="predictLink"
|
||||||
|
>Predict</a
|
||||||
|
>
|
||||||
|
<!-- <li><a href="{{ meta.server_url }}/package" id="packageLink">Package</a></li> -->
|
||||||
|
<!--<li><a href="{{ meta.server_url }}/browse" id="browseLink">Browse</a></li>-->
|
||||||
|
<div class="dropdown dropdown-center">
|
||||||
|
<div tabindex="0" role="button" class="btn btn-ghost">Browse</div>
|
||||||
|
<ul
|
||||||
|
tabindex="-1"
|
||||||
|
class="dropdown-content menu bg-base-100 rounded-box z-1 w-52 p-2 shadow-sm"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/pathway" id="pathwayLink">Pathway</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="{{ meta.server_url }}/rule" id="ruleLink">Rule</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/compound" id="compoundLink"
|
||||||
|
>Compound</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/reaction" id="reactionLink"
|
||||||
|
>Reaction</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/model" id="relative-reasoningLink"
|
||||||
|
>Model</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ meta.server_url }}/scenario" id="scenarioLink"
|
||||||
|
>Scenario</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="navbar-end">
|
||||||
|
{% if not public_mode %}
|
||||||
|
<a id="search-trigger" role="button" class="cursor-pointer">
|
||||||
|
<div
|
||||||
|
class="flex items-center badge badge-dash space-x-1 bg-base-200 text-base-content/50 p-2 m-1"
|
||||||
|
>
|
||||||
|
<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-search-icon lucide-search"
|
||||||
|
>
|
||||||
|
<path d="m21 21-4.34-4.34" />
|
||||||
|
<circle cx="11" cy="11" r="8" />
|
||||||
|
</svg>
|
||||||
|
<span id="search-shortcut">⌘K</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if meta.user.username == 'anonymous' or public_mode %}
|
||||||
|
<a href="{% url 'login' %}" id="loginButton" class="p-2">Login</a>
|
||||||
|
{% else %}
|
||||||
|
<div class="dropdown dropdown-end">
|
||||||
|
<div
|
||||||
|
tabindex="0"
|
||||||
|
role="button"
|
||||||
|
class="btn btn-ghost m-1 btn-circle"
|
||||||
|
id="loggedInButton"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="lucide lucide-circle-user-icon lucide-circle-user"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="10" />
|
||||||
|
<circle cx="12" cy="10" r="3" />
|
||||||
|
<path d="M7 20.662V19a2 2 0 0 1 2-2h6a2 2 0 0 1 2 2v1.662" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
tabindex="-1"
|
||||||
|
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2 shadow-sm"
|
||||||
|
>
|
||||||
|
<li><a href="{{ meta.user.url }}" id="accountbutton">Settings</a></li>
|
||||||
|
<li>
|
||||||
|
<form
|
||||||
|
id="logoutForm"
|
||||||
|
action="{% url 'logout' %}"
|
||||||
|
method="post"
|
||||||
|
style="display: none;"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="logout" value="true" />
|
||||||
|
</form>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
id="logoutButton"
|
||||||
|
onclick="event.preventDefault(); document.getElementById('logoutForm').submit();"
|
||||||
|
>Logout</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// OS-aware search shortcut display
|
||||||
|
(function () {
|
||||||
|
const isMac = /Mac/.test(navigator.platform);
|
||||||
|
const shortcutElement = document.getElementById("search-shortcut");
|
||||||
|
if (shortcutElement) {
|
||||||
|
shortcutElement.textContent = isMac ? "⌘K" : "Ctrl+K";
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
@ -1,186 +1,453 @@
|
|||||||
{% extends "framework.html" %}
|
{% extends "framework_modern.html" %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% block content %}
|
{% block main_content %}
|
||||||
<!-- TODO rename ids as well as remove pathways if modal is closed!-->
|
<!-- Hero Section with Logo and Search -->
|
||||||
<div class="modal fade" tabindex="-1" id="foundMatching" role="dialog" aria-labelledby="foundModal"
|
<section class="hero relative mx-auto h-fit w-full max-w-5xl shadow-none">
|
||||||
aria-hidden="true">
|
<div
|
||||||
<div class="modal-dialog">
|
class="hero from-primary-800 to-primary-600 min-h-[calc(100vh*0.4)] bg-gradient-to-br"
|
||||||
<div class="modal-content">
|
style="background-image: url('{% static "/images/hero.png" %}'); background-size: cover; background-position: center;"
|
||||||
<div class="modal-header">
|
>
|
||||||
<button type="button" class="close" data-dismiss="modal">
|
<div class="hero-overlay"></div>
|
||||||
<span aria-hidden="true">×</span>
|
<!-- Predict Pathway text over the image -->
|
||||||
<span class="sr-only">Close</span>
|
<div class="absolute bottom-40 left-1/8 z-10 -translate-x-8">
|
||||||
</button>
|
<h2 class="text-base-100 text-left text-3xl text-shadow-lg">
|
||||||
<h4 class="modal-title" id="newPackMod">Found Pathway in Database</h4>
|
Predict Your Pathway
|
||||||
</div>
|
</h2>
|
||||||
<div class="modal-body">
|
|
||||||
<p>We found at least one pathway in the database with the given root
|
|
||||||
compound. Do you want to open any of the existing pathways or
|
|
||||||
predict a new one? To open an existing pathway, simply click
|
|
||||||
on the pathway, to predict a new one, click Predict. The predicted
|
|
||||||
pathway might differ from the ones in the database due to the
|
|
||||||
settings used in the prediction.</p>
|
|
||||||
<div id="foundPathways"></div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<a id="modal-predict" class="btn btn-primary" href="#">Predict</a>
|
|
||||||
<button type="button" id="cancel-predict" class="btn btn-default" data-dismiss="modal">Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="bg-base-200 mx-auto max-w-5xl shadow-md">
|
||||||
|
<!-- Predict Pathway Section -->
|
||||||
|
<div
|
||||||
|
class="relative z-20 mx-auto -mt-32 mb-10 w-full flex-col lg:flex-row-reverse"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="card bg-base-100 mx-auto w-3/4 shrink-0 shadow-xl transition-all duration-300 ease-in-out"
|
||||||
|
>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="my-4 ml-8 flex h-fit flex-row items-center justify-start">
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<label class="swap btn btn-ghost btn-sm p-1" title="Input Mode">
|
||||||
|
<input type="checkbox" />
|
||||||
|
<span class="swap-on flex items-center gap-1">
|
||||||
|
<div
|
||||||
|
class="bg-neutral/50 text-neutral-content flex items-center justify-center rounded-full p-1"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="smiles mode"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
class="size-5"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-width="2"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="none"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M8 2.75A.75.75 0 0 1 8.75 2h7.5a.75.75 0 0 1 0 1.5h-3.215l-4.483 13h2.698a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1 0-1.5h3.215l4.483-13H8.75A.75.75 0 0 1 8 2.75Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
<span class="ext-xs">SMILES</span>
|
||||||
|
</span>
|
||||||
|
<span class="swap-off flex items-center gap-1">
|
||||||
|
<div
|
||||||
|
class="bg-neutral/50 text-neutral-content flex items-center justify-center rounded-full p-1"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-label="draw mode"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
stroke="none"
|
||||||
|
class="size-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="m2.695 14.762-1.262 3.155a.5.5 0 0 0 .65.65l3.155-1.262a4 4 0 0 0 1.343-.886L17.5 5.501a2.121 2.121 0 0 0-3-3L3.58 13.419a4 4 0 0 0-.885 1.343Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span class="text-base/50 text-xs">Draw</span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-8">
|
|
||||||
<div class="jumbotron">
|
|
||||||
<h1>
|
|
||||||
<img id="image-logo-long" class="img-responsive" alt="enviPath" width="1000ex"
|
|
||||||
src='{% static "/images/logo-long.svg" %}'/>
|
|
||||||
</h1>
|
|
||||||
<p>enviPath is a database and prediction system for the microbial
|
|
||||||
biotransformation of organic environmental contaminants. The
|
|
||||||
database provides the possibility to store and view experimentally
|
|
||||||
observed biotransformation pathways. The pathway prediction system
|
|
||||||
provides different relative reasoning models to predict likely biotransformation
|
|
||||||
pathways and products. You can try it out below.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<a class="btn" style="background-color:#222222;color:#9d9d9d" role="button" target="_blank"
|
|
||||||
href="https://wiki.envipath.org/index.php/Main_Page">Learn more >></a>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
<fieldset
|
||||||
<div id="loading"></div>
|
class="fieldset overflow-hidden transition-all duration-300 ease-in-out"
|
||||||
<div class="col-xs-4">
|
>
|
||||||
<d-topics-list discourse-url="https://community.envipath.org" per-page="10" category="10"
|
<form
|
||||||
template="complete"></d-topics-list>
|
id="index-form"
|
||||||
</div>
|
action="{{ meta.current_package.url }}/pathway"
|
||||||
</div>
|
method="POST"
|
||||||
<div class="row">
|
>
|
||||||
<form id="index-form" action="{{ meta.current_package.url }}/pathway" method="POST">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="input-group" id="index-form-bar">
|
<div
|
||||||
<div class="input-group-btn">
|
id="text-input-container"
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
class="scale-100 transform opacity-100 transition-all duration-300 ease-in-out"
|
||||||
aria-expanded="false">
|
>
|
||||||
<span class="caret"></span>
|
<div class="join mx-auto w-full">
|
||||||
</button>
|
<input
|
||||||
<ul class="dropdown-menu" role="menu">
|
type="text"
|
||||||
<li>
|
id="index-form-text-input"
|
||||||
<iframe id="index-form-ketcher" src="{% static '/js/ketcher2/ketcher.html' %}" width="100%"
|
placeholder="canonical SMILES string"
|
||||||
height="510"></iframe>
|
class="input input-md join-item grow"
|
||||||
</li>
|
/>
|
||||||
</ul>
|
<button class="btn btn-neutral join-item">Predict!</button>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" class="form-control" id='index-form-text-input'
|
<div class="label relative mt-1 w-full">
|
||||||
placeholder="Enter a SMILES to predict a Pathway or type something to search">
|
<div class="flex gap-2">
|
||||||
<div class="input-group-btn">
|
<a
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
href="#"
|
||||||
aria-haspopup="true"
|
class="example-link hover:text-primary cursor-pointer"
|
||||||
aria-expanded="false" id="action-button">Predict <span class="caret"></span></button>
|
data-smiles="CN1C=NC2=C1C(=O)N(C(=O)N2C)C"
|
||||||
<ul class="dropdown-menu">
|
title="load example"
|
||||||
<li><a id="dropdown-predict">Predict</a></li>
|
>Caffeine</a
|
||||||
<li><a id="dropdown-search">Search</a></li>
|
>
|
||||||
</ul>
|
<a
|
||||||
<button class="btn" style="background-color:#222222;color:#9d9d9d" type="button" id="run-button">Go!
|
href="#"
|
||||||
|
class="example-link hover:text-primary cursor-pointer"
|
||||||
|
data-smiles="CC(C)CC1=CC=C(C=C1)C(C)C(=O)O"
|
||||||
|
title="load example"
|
||||||
|
>Ibuprofen</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<a class="absolute top-0 left-[calc(100%-5.4rem)]" href="#"
|
||||||
|
>Advanced</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="ketcher-container"
|
||||||
|
class="hidden w-full scale-95 transform opacity-0 transition-all duration-300 ease-in-out"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
id="index-ketcher"
|
||||||
|
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||||
|
width="100%"
|
||||||
|
height="400"
|
||||||
|
class="rounded-lg"
|
||||||
|
></iframe>
|
||||||
|
<button
|
||||||
|
class="btn btn-lg bg-primary-950 text-primary-50 join-item mt-2 w-full"
|
||||||
|
>
|
||||||
|
Predict!
|
||||||
</button>
|
</button>
|
||||||
|
<div class="mt-1 flex w-full justify-end">
|
||||||
|
<a class="label justify-end" href="/predict">Advanced</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="index-form-smiles" name="smiles" value="smiles">
|
<input
|
||||||
<input type="hidden" id="index-form-predict" name="predict" value="predict">
|
type="hidden"
|
||||||
|
id="index-form-smiles"
|
||||||
|
name="smiles"
|
||||||
|
value="smiles"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
id="index-form-predict"
|
||||||
|
name="predict"
|
||||||
|
value="predict"
|
||||||
|
/>
|
||||||
|
<input type="hidden" id="current-action" value="predict" />
|
||||||
</form>
|
</form>
|
||||||
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<p></p>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Community News Section -->
|
||||||
|
<section class="bg-base-200 z-10 mx-8 py-16">
|
||||||
|
<div class="mx-auto max-w-7xl px-4">
|
||||||
|
<h2 class="h2 mb-8 text-left font-bold">Community Updates</h2>
|
||||||
|
|
||||||
|
<div id="community-news-container" class="flex justify-center gap-4">
|
||||||
|
<!-- News cards will be populated here -->
|
||||||
|
<div id="loading" class="flex w-full justify-center">
|
||||||
|
<span class="loading loading-spinner loading-lg"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6 text-right">
|
||||||
|
<a
|
||||||
|
href="https://community.envipath.org/c/announcements/10"
|
||||||
|
target="_blank"
|
||||||
|
class="btn btn-ghost btn-sm"
|
||||||
|
>
|
||||||
|
Read More Announcements
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Discourse API integration -->
|
||||||
|
<script src="{% static 'js/discourse-api.js' %}"></script>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Mission Statement Section -->
|
||||||
|
<section class="from-base-200 to-base-100 bg-gradient-to-b py-16">
|
||||||
|
<div class="mx-auto px-8 md:px-12">
|
||||||
|
<div class="flex flex-row gap-4">
|
||||||
|
<div class="w-1/3">
|
||||||
|
<img
|
||||||
|
src="{% static "/images/ep-rule-artwork.png" %}"
|
||||||
|
alt="rule-based iterative tree greneration"
|
||||||
|
class="h-full w-full object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mr-8 w-2/3 space-y-4 text-left">
|
||||||
|
<h2 class="h2 mb-8 font-bold">About enviPath</h2>
|
||||||
|
<p class="">
|
||||||
|
enviPath is a database and prediction system for the microbial
|
||||||
|
biotransformation of organic environmental contaminants. The
|
||||||
|
database provides the possibility to store and view experimentally
|
||||||
|
observed biotransformation pathways.
|
||||||
|
</p>
|
||||||
|
<p class="">
|
||||||
|
The pathway prediction system provides different relative
|
||||||
|
reasoning models to predict likely biotransformation pathways and
|
||||||
|
products. Explore our tools and contribute to advancing
|
||||||
|
environmental biotransformation research.
|
||||||
|
</p>
|
||||||
|
<div class="float-right flex flex-row gap-4">
|
||||||
|
<a href="/about" class="btn btn-ghost-neutral">Read More</a>
|
||||||
|
<a href="/about" class="btn btn-neutral">Publications</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- Partners Section -->
|
||||||
|
<section class="bg-base-100 py-14 sm:py-12">
|
||||||
|
<div class="mx-auto px-6 lg:px-8">
|
||||||
|
<div class="divider">
|
||||||
|
<h2 class="text-center text-lg/8 font-semibold">Backed by Science</h2>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mx-auto mt-10 grid max-w-lg grid-cols-4 items-center gap-x-8 gap-y-10 sm:max-w-xl sm:grid-cols-6 sm:gap-x-10 lg:mx-0 lg:max-w-none lg:grid-cols-3"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="{% static "/images/uoa-logo-small.png" %}"
|
||||||
|
alt="The University of Auckland"
|
||||||
|
class="max-h-20 w-full object-contain lg:col-span-1"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="{% static "/images/logo-eawag.svg" %}"
|
||||||
|
alt="Eawag"
|
||||||
|
class="max-h-12 w-full object-contain lg:col-span-1"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
src="{% static "/images/uzh-logo.svg" %}"
|
||||||
|
alt="University of Zurich"
|
||||||
|
class="2 max-h-16 w-full object-contain lg:col-span-1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script language="javascript">
|
<script language="javascript">
|
||||||
var currentPackage = "{{ meta.current_package.url }}";
|
var currentPackage = "{{ meta.current_package.url }}";
|
||||||
|
|
||||||
function goButtonClicked() {
|
// Discourse API integration is now handled by discourse-api.js
|
||||||
$(this).prop("disabled", true);
|
|
||||||
|
|
||||||
var action = $('#action-button').text().trim();
|
// Function to render Discourse topics into cards
|
||||||
|
function renderDiscourseTopics(topics) {
|
||||||
|
const container = document.getElementById("community-news-container");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
var textSmiles = $('#index-form-text-input').val().trim();
|
// Clear container
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
if (textSmiles === '') {
|
// Create cards for each topic
|
||||||
$(this).prop("disabled", false);
|
topics.forEach((topic) => {
|
||||||
return;
|
const card = createDiscourseCard(topic);
|
||||||
|
container.insertAdjacentHTML("beforeend", card);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var ketcherSmiles = getKetcher('index-form-ketcher').getSmiles().trim();
|
// Function to create HTML card for a topic
|
||||||
|
function createDiscourseCard(topic) {
|
||||||
|
const date = new Date(topic.created_at).toLocaleDateString();
|
||||||
|
|
||||||
if (action !== 'Search' && ketcherSmiles !== '' && textSmiles !== ketcherSmiles) {
|
return `
|
||||||
console.log("Ketcher and TextInput differ!");
|
<div class="card bg-white shadow-xs hover:shadow-lg transition-shadow duration-300 h-64 w-75 flex-shrink-0">
|
||||||
|
<div class="card-body flex flex-col h-full">
|
||||||
|
<h3 class="card-title leading-tight font-normal tracking-tight h-12 mb-2 line-clamp-2 text-ellipsis wrap-break-word overflow-hidden">
|
||||||
|
<a href="${topic.url}" target="_blank" class="hover:text-primary">
|
||||||
|
${topic.title}
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
<div class="text-sm line-clamp-4 break-words" >
|
||||||
|
${topic.excerpt}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-row items-center justify-between">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<div class="avatar tooltip tooltip-right" data-tip="${topic.author}">
|
||||||
|
<div class="w-8 rounded-full">
|
||||||
|
<img src="${topic.author_avatar}" alt="${topic.author}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="text-xs text-gray-500">${date}</span>
|
||||||
|
</div>
|
||||||
|
<a href="${topic.url}" target="_blank" class="btn btn-ghost text-neutral-500 rounded-full p-2">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M12 7v14"/>
|
||||||
|
<path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action === 'Search') {
|
// Make render function globally available
|
||||||
var par = {};
|
window.renderDiscourseTopics = renderDiscourseTopics;
|
||||||
par['search'] = textSmiles;
|
|
||||||
par['mode'] = 'text';
|
// Toggle functionality with smooth animations
|
||||||
var queryString = $.param(par, true);
|
function toggleInputMode() {
|
||||||
window.location.href = "/search?" + queryString;
|
const toggle = $('input[type="checkbox"]');
|
||||||
|
const textContainer = $("#text-input-container");
|
||||||
|
const ketcherContainer = $("#ketcher-container");
|
||||||
|
const formCard = $(".card");
|
||||||
|
const fieldset = $(".fieldset");
|
||||||
|
|
||||||
|
if (toggle.is(":checked")) {
|
||||||
|
// Draw mode - show Ketcher, hide text input
|
||||||
|
textContainer.addClass("opacity-0 transform scale-95");
|
||||||
|
textContainer.removeClass("opacity-100 transform scale-100");
|
||||||
|
|
||||||
|
// Adjust fieldset padding for Ketcher mode - reduce padding and make more compact
|
||||||
|
fieldset.removeClass("p-8");
|
||||||
|
fieldset.addClass("p-4");
|
||||||
|
|
||||||
|
// Wait for fade out to complete, then hide and show new content
|
||||||
|
setTimeout(() => {
|
||||||
|
textContainer.addClass("hidden");
|
||||||
|
ketcherContainer.removeClass("hidden opacity-0 transform scale-95");
|
||||||
|
ketcherContainer.addClass("opacity-100 transform scale-100");
|
||||||
|
|
||||||
|
// Force re-evaluation of iframe size
|
||||||
|
const iframe = document.getElementById("index-ketcher");
|
||||||
|
if (iframe) {
|
||||||
|
iframe.style.height = "400px";
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
} else {
|
} else {
|
||||||
$('#index-form-smiles').val(textSmiles);
|
// SMILES mode - show text input, hide Ketcher
|
||||||
$('#index-form').submit();
|
ketcherContainer.addClass("opacity-0 transform scale-95");
|
||||||
|
ketcherContainer.removeClass("opacity-100 transform scale-100");
|
||||||
|
|
||||||
|
// Restore fieldset padding for text input mode
|
||||||
|
fieldset.removeClass("p-4");
|
||||||
|
fieldset.addClass("p-8");
|
||||||
|
|
||||||
|
// Wait for fade out to complete, then hide and show new content
|
||||||
|
setTimeout(() => {
|
||||||
|
ketcherContainer.addClass("hidden");
|
||||||
|
textContainer.removeClass("hidden opacity-0 transform scale-95");
|
||||||
|
textContainer.addClass("opacity-100 transform scale-100");
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
// Transfer SMILES from Ketcher to text input if available
|
||||||
|
if (window.indexKetcher && window.indexKetcher.getSmiles) {
|
||||||
|
const smiles = window.indexKetcher.getSmiles();
|
||||||
|
if (smiles && smiles.trim() !== "") {
|
||||||
|
$("#index-form-text-input").val(smiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function actionDropdownClicked() {
|
// Ketcher integration
|
||||||
var suffix = ' <span class="caret"></span>';
|
function indexKetcherToTextInput() {
|
||||||
var dropdownVal = $(this).text();
|
$("#index-form-smiles").val(this.ketcher.getSmiles());
|
||||||
|
|
||||||
if (dropdownVal === 'Search') {
|
|
||||||
$("#index-form").attr("action", '/search');
|
|
||||||
$("#index-form").attr("method", 'GET');
|
|
||||||
} else {
|
|
||||||
$("#index-form").attr("action", currentPackage + "/pathway");
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#action-button').html(dropdownVal + suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
function ketcherToTextInput() {
|
|
||||||
$('#index-form-text-input').val(this.ketcher.getSmiles());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
// Initialize fieldset with proper padding
|
||||||
|
$(".fieldset").addClass("p-8");
|
||||||
|
|
||||||
$('#index-form').on("keydown", function (e) {
|
// Toggle event listener
|
||||||
if (e.key === "Enter") {
|
$('input[type="checkbox"]').on("change", toggleInputMode);
|
||||||
e.preventDefault();
|
|
||||||
goButtonClicked();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Code that should be executed once DOM is ready goes here
|
// Ketcher iframe load handler
|
||||||
$('#dropdown-predict').on('click', actionDropdownClicked);
|
$("#index-ketcher").on("load", function () {
|
||||||
$('#dropdown-search').on('click', actionDropdownClicked);
|
|
||||||
|
|
||||||
$('#run-button').on('click', goButtonClicked);
|
|
||||||
|
|
||||||
// Update Ketcher Width
|
|
||||||
var fullWidth = $('#index-form-bar').width();
|
|
||||||
$('#index-form-ketcher').width(fullWidth);
|
|
||||||
|
|
||||||
// add a listener that gets triggered whenever the structure in ketcher has changed
|
|
||||||
$('#index-form-ketcher').on('load', function () {
|
|
||||||
const checkKetcherReady = () => {
|
const checkKetcherReady = () => {
|
||||||
win = this.contentWindow
|
const win = this.contentWindow;
|
||||||
if (win.ketcher && 'editor' in win.ketcher) {
|
if (win.ketcher && "editor" in win.ketcher) {
|
||||||
|
window.indexKetcher = win.ketcher;
|
||||||
win.ketcher.editor.event.change.handlers.push({
|
win.ketcher.editor.event.change.handlers.push({
|
||||||
once: false,
|
once: false,
|
||||||
priority: 0,
|
priority: 0,
|
||||||
f: ketcherToTextInput,
|
f: indexKetcherToTextInput,
|
||||||
ketcher: win.ketcher
|
ketcher: win.ketcher,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setTimeout(checkKetcherReady, 100);
|
setTimeout(checkKetcherReady, 100);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
checkKetcherReady();
|
checkKetcherReady();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Handle example link clicks
|
||||||
|
$(".example-link").on("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const smiles = $(this).data("smiles");
|
||||||
|
const title = $(this).attr("title");
|
||||||
|
|
||||||
|
// Check if we're in Ketcher mode or text input mode
|
||||||
|
if ($('input[type="checkbox"]').is(":checked")) {
|
||||||
|
// In Ketcher mode - set the SMILES in Ketcher
|
||||||
|
if (window.indexKetcher && window.indexKetcher.setMolecule) {
|
||||||
|
window.indexKetcher.setMolecule(smiles);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In text input mode - set the SMILES in the text input
|
||||||
|
$("#index-form-text-input").val(smiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show a brief feedback
|
||||||
|
const originalText = $(this).text();
|
||||||
|
$(this).text(`loaded!`);
|
||||||
|
setTimeout(() => {
|
||||||
|
$(this).text(originalText);
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle form submission on Enter
|
||||||
|
$("#index-form").on("submit", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var textSmiles = "";
|
||||||
|
|
||||||
|
// Check if we're in Ketcher mode and extract SMILES
|
||||||
|
if ($('input[type="checkbox"]').is(":checked") && window.indexKetcher) {
|
||||||
|
textSmiles = window.indexKetcher.getSmiles().trim();
|
||||||
|
} else {
|
||||||
|
textSmiles = $("#index-form-text-input").val().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textSmiles === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#index-form-smiles").val(textSmiles);
|
||||||
|
$("#index-form").attr("action", currentPackage + "/pathway");
|
||||||
|
$("#index-form").attr("method", "POST");
|
||||||
|
this.submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Discourse topics are now loaded automatically by discourse-api.js
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
{% endblock content %}
|
{% endblock main_content %}
|
||||||
|
|||||||
@ -1,5 +1,11 @@
|
|||||||
<div class="modal fade" tabindex="-1" id="retrain_model_modal" role="dialog" aria-labelledby="retrain_model_modal"
|
<div
|
||||||
aria-hidden="true">
|
class="modal fade"
|
||||||
|
tabindex="-1"
|
||||||
|
id="retrain_model_modal"
|
||||||
|
role="dialog"
|
||||||
|
aria-labelledby="retrain_model_modal"
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
<div class="modal-dialog modal-lg">
|
<div class="modal-dialog modal-lg">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
@ -10,34 +16,40 @@
|
|||||||
<h4 class="modal-title">Retrain Model</h4>
|
<h4 class="modal-title">Retrain Model</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form id="retrain_model_form" accept-charset="UTF-8" action="{{ meta.current_package.url }}/model"
|
<form
|
||||||
data-remote="true" method="post">
|
id="retrain_model_form"
|
||||||
|
accept-charset="UTF-8"
|
||||||
|
action="{{ meta.current_object.url }}"
|
||||||
|
data-remote="true"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
<div class="jumbotron">
|
<div class="jumbotron">
|
||||||
To reflect changes in the rule or data packages, you can use the "Retrain" button,
|
To reflect changes in the rule or data packages, you can use the
|
||||||
to let the model reflect the changes without creating a new model.
|
"Retrain" button, to let the model reflect the changes without
|
||||||
While the model is retraining, it will be unavailable for prediction.
|
creating a new model. While the model is retraining, it will be
|
||||||
|
unavailable for prediction.
|
||||||
</div>
|
</div>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="action" value="retrain">
|
<input type="hidden" name="hidden" value="retrain" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<a id="retrain_model_form_submit" class="btn btn-primary" href="#">Retrain</a>
|
<a id="retrain_model_form_submit" class="btn btn-primary" href="#"
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
>Retrain</a
|
||||||
|
>
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
$("#retrain_model_form_submit").on("click", function (e) {
|
||||||
$('#retrain_model_form_submit').on('click', function (e) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$('#retrain_model_form').submit();
|
$("#retrain_model_form").submit();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -52,8 +52,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="license" name="license">
|
<input type="hidden" id="license" name="license">
|
||||||
<input type="hidden" id="license-link" name="license-link">
|
|
||||||
<input type="hidden" id="license-image-link" name="license-image-link">
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
@ -128,8 +126,6 @@ function cc() {
|
|||||||
|
|
||||||
$('#ccfig').append(img_tpl);
|
$('#ccfig').append(img_tpl);
|
||||||
$('#license').val(ccstr);
|
$('#license').val(ccstr);
|
||||||
$('#license-link').val(link);
|
|
||||||
$('#license-image-link').val(imageLink);
|
|
||||||
} else {
|
} else {
|
||||||
$('#ccfig').empty();
|
$('#ccfig').empty();
|
||||||
$('#set_license_form_submit').prop('disabled', true);
|
$('#set_license_form_submit').prop('disabled', true);
|
||||||
|
|||||||
686
templates/modals/search_modal.html
Normal file
@ -0,0 +1,686 @@
|
|||||||
|
{% load static %}
|
||||||
|
<dialog id="search_modal" class="modal @max-sm:modal-top justify-center">
|
||||||
|
<div class="modal-box h-full w-lvw p-1 sm:h-8/12 sm:w-[85vw] sm:max-w-5xl">
|
||||||
|
<!-- Search Input and Mode Selector -->
|
||||||
|
<div class="form-control mb-4 w-full shrink-0">
|
||||||
|
<div class="join m-0 w-full items-center p-3">
|
||||||
|
<label class="input join-item input-ghost grow">
|
||||||
|
<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-search-icon lucide-search"
|
||||||
|
>
|
||||||
|
<path d="m21 21-4.34-4.34" />
|
||||||
|
<circle cx="11" cy="11" r="8" />
|
||||||
|
</svg>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
autofocus
|
||||||
|
id="modal_searchbar"
|
||||||
|
placeholder="Benfuracarb"
|
||||||
|
class="grow"
|
||||||
|
aria-label="Search"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<!-- Mode Dropdown -->
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
tabindex="0"
|
||||||
|
id="modal_mode_button"
|
||||||
|
popovertarget="search_dropdown_menu"
|
||||||
|
style="anchor-name:--1"
|
||||||
|
class="btn join-item btn-ghost"
|
||||||
|
>
|
||||||
|
Text
|
||||||
|
<svg
|
||||||
|
class="ml-1 h-4 w-4"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M19 9l-7 7-7-7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<ul
|
||||||
|
tabindex="0"
|
||||||
|
class="dropdown dropdown-end menu bg-base-200 rounded-box w-64 p-2 shadow-lg"
|
||||||
|
popover
|
||||||
|
id="search_dropdown_menu"
|
||||||
|
style="position-anchor:--anchor-2"
|
||||||
|
>
|
||||||
|
<li class="menu-title">Text</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="modal_dropdown_text"
|
||||||
|
class="tooltip tooltip-left"
|
||||||
|
data-tip="Search on object names and descriptions"
|
||||||
|
>
|
||||||
|
Text
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-title">SMILES</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="modal_dropdown_smiles_default"
|
||||||
|
class="tooltip tooltip-left"
|
||||||
|
data-tip="Ignores stereochemistry and charge"
|
||||||
|
>
|
||||||
|
Default
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="modal_dropdown_smiles_canonical"
|
||||||
|
class="tooltip tooltip-left"
|
||||||
|
data-tip="Ignores stereochemistry, preserves charge"
|
||||||
|
>
|
||||||
|
Canonical
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="modal_dropdown_smiles_exact"
|
||||||
|
class="tooltip tooltip-left"
|
||||||
|
data-tip="Exact match for stereochemistry and charge"
|
||||||
|
>
|
||||||
|
Exact
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="menu-title">InChI</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
id="modal_dropdown_inchikey"
|
||||||
|
class="tooltip tooltip-left"
|
||||||
|
data-tip="Search by InChIKey"
|
||||||
|
>
|
||||||
|
InChIKey
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
id="modal_search_button"
|
||||||
|
class="btn btn-xs btn-ghost join-item"
|
||||||
|
>
|
||||||
|
<kbd class="kbd kbd-sm text-base-content/50 p-1">
|
||||||
|
<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-corner-down-left-icon lucide-corner-down-left"
|
||||||
|
>
|
||||||
|
<path d="M20 4v7a4 4 0 0 1-4 4H4" />
|
||||||
|
<path d="m9 10-5 5 5 5" />
|
||||||
|
</svg>
|
||||||
|
</kbd>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Package Selector with Pills -->
|
||||||
|
<div class="form-control mb-4 shrink-0">
|
||||||
|
<!-- Pills Container -->
|
||||||
|
<div
|
||||||
|
id="modal_package_pills_container"
|
||||||
|
class="border-base-300 m-3 flex min-h-12 flex-wrap items-center gap-2 rounded-lg border-2 border-dashed p-3"
|
||||||
|
>
|
||||||
|
<!-- Pills will be added here dynamically -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Package Dropdown Menu -->
|
||||||
|
<ul
|
||||||
|
class="dropdown dropdown-center menu bg-base-200 rounded-box max-h-96 w-80 overflow-y-auto p-2 shadow-lg"
|
||||||
|
popover
|
||||||
|
id="package_dropdown_menu"
|
||||||
|
style="position-anchor:--anchor-packages"
|
||||||
|
>
|
||||||
|
{% if unreviewed_packages %}
|
||||||
|
<li class="menu-title">Reviewed Packages</li>
|
||||||
|
{% for obj in reviewed_packages %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="package-option flex items-center justify-between"
|
||||||
|
data-package-url="{{ obj.url }}"
|
||||||
|
data-package-name="{{ obj.name }}"
|
||||||
|
>
|
||||||
|
<span>{{ obj.name }}</span>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="package-checkmark hidden h-4 w-4"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 13l4 4L19 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
<li class="menu-title">Unreviewed Packages</li>
|
||||||
|
{% for obj in unreviewed_packages %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="package-option flex items-center justify-between"
|
||||||
|
data-package-url="{{ obj.url }}"
|
||||||
|
data-package-name="{{ obj.name }}"
|
||||||
|
>
|
||||||
|
<span>{{ obj.name }}</span>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="package-checkmark hidden h-4 w-4"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 13l4 4L19 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<li class="menu-title">Reviewed Packages</li>
|
||||||
|
{% for obj in reviewed_packages %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
class="package-option flex items-center justify-between"
|
||||||
|
data-package-url="{{ obj.url }}"
|
||||||
|
data-package-name="{{ obj.name }}"
|
||||||
|
>
|
||||||
|
<span>{{ obj.name }}</span>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="package-checkmark hidden h-4 w-4"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 13l4 4L19 7"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Loading Indicator -->
|
||||||
|
<div id="search_loading" class="hidden shrink-0 justify-center py-8">
|
||||||
|
<span class="loading loading-spinner loading-lg text-primary"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Results Container - scrollable -->
|
||||||
|
<div id="search_results" class="min-h-0 flex-1 overflow-y-auto p-2"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Backdrop to close -->
|
||||||
|
<form method="dialog" class="modal-backdrop">
|
||||||
|
<button>close</button>
|
||||||
|
</form>
|
||||||
|
</dialog>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
// Package Selector Module - Data-driven multiselect package selection
|
||||||
|
const PackageSelector = {
|
||||||
|
// Single source of truth: array of selected packages
|
||||||
|
selectedPackages: [],
|
||||||
|
|
||||||
|
elements: {
|
||||||
|
pillsContainer: null,
|
||||||
|
packageDropdown: null,
|
||||||
|
packageOptions: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.cacheElements();
|
||||||
|
this.loadInitialSelection();
|
||||||
|
this.attachEventListeners();
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
cacheElements() {
|
||||||
|
this.elements.pillsContainer = document.getElementById(
|
||||||
|
"modal_package_pills_container",
|
||||||
|
);
|
||||||
|
this.elements.packageDropdown = document.getElementById(
|
||||||
|
"package_dropdown_menu",
|
||||||
|
);
|
||||||
|
this.elements.packageOptions =
|
||||||
|
document.querySelectorAll(".package-option");
|
||||||
|
},
|
||||||
|
|
||||||
|
loadInitialSelection() {
|
||||||
|
// Load pre-selected packages from server-rendered pills
|
||||||
|
const existingPills =
|
||||||
|
this.elements.pillsContainer.querySelectorAll(".badge");
|
||||||
|
existingPills.forEach((pill) => {
|
||||||
|
this.selectedPackages.push({
|
||||||
|
url: pill.dataset.packageUrl,
|
||||||
|
name: pill.dataset.packageName,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// If no pills found, select all reviewed packages by default
|
||||||
|
if (this.selectedPackages.length === 0) {
|
||||||
|
// Iterate through all menu items and collect reviewed packages
|
||||||
|
const menuItems =
|
||||||
|
this.elements.packageDropdown.querySelectorAll("li");
|
||||||
|
|
||||||
|
for (const item of menuItems) {
|
||||||
|
// Check if this is the "Unreviewed Packages" menu title
|
||||||
|
if (
|
||||||
|
item.classList.contains("menu-title") &&
|
||||||
|
item.textContent.trim() === "Unreviewed Packages"
|
||||||
|
) {
|
||||||
|
break; // Stop processing after this point
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for package options (only reviewed packages reach here)
|
||||||
|
const packageOption = item.querySelector(".package-option");
|
||||||
|
if (packageOption) {
|
||||||
|
this.selectedPackages.push({
|
||||||
|
url: packageOption.dataset.packageUrl,
|
||||||
|
name: packageOption.dataset.packageName,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
attachEventListeners() {
|
||||||
|
// Toggle package selection on dropdown item click
|
||||||
|
this.elements.packageOptions.forEach((option) => {
|
||||||
|
option.addEventListener("click", (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation(); // Prevent dropdown from closing
|
||||||
|
const packageUrl = option.dataset.packageUrl;
|
||||||
|
const packageName = option.dataset.packageName;
|
||||||
|
this.togglePackageSelection(packageUrl, packageName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove package when X is clicked (using event delegation)
|
||||||
|
this.elements.pillsContainer.addEventListener("click", (e) => {
|
||||||
|
if (
|
||||||
|
e.target.classList.contains("package-remove-btn") ||
|
||||||
|
e.target.closest(".package-remove-btn")
|
||||||
|
) {
|
||||||
|
const pill = e.target.closest(".badge");
|
||||||
|
if (pill) {
|
||||||
|
const packageUrl = pill.dataset.packageUrl;
|
||||||
|
this.removePackage(packageUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
togglePackageSelection(packageUrl, packageName) {
|
||||||
|
const index = this.selectedPackages.findIndex(
|
||||||
|
(pkg) => pkg.url === packageUrl,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
// Remove from selection
|
||||||
|
this.selectedPackages.splice(index, 1);
|
||||||
|
} else {
|
||||||
|
// Add to selection
|
||||||
|
this.selectedPackages.push({ url: packageUrl, name: packageName });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
},
|
||||||
|
|
||||||
|
removePackage(packageUrl) {
|
||||||
|
const index = this.selectedPackages.findIndex(
|
||||||
|
(pkg) => pkg.url === packageUrl,
|
||||||
|
);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.selectedPackages.splice(index, 1);
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.renderPills();
|
||||||
|
this.renderAddButton();
|
||||||
|
this.renderCheckmarks();
|
||||||
|
},
|
||||||
|
|
||||||
|
renderPills() {
|
||||||
|
// Clear existing pills and button (except placeholder)
|
||||||
|
const pills = this.elements.pillsContainer.querySelectorAll(".badge");
|
||||||
|
pills.forEach((pill) => pill.remove());
|
||||||
|
|
||||||
|
const existingButton = this.elements.pillsContainer.querySelector(
|
||||||
|
"#modal_package_add_button",
|
||||||
|
);
|
||||||
|
if (existingButton) {
|
||||||
|
existingButton.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create pills from data
|
||||||
|
this.selectedPackages.forEach((pkg) => {
|
||||||
|
const pill = this.createPillElement(pkg.url, pkg.name);
|
||||||
|
this.elements.pillsContainer.appendChild(pill);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
renderAddButton() {
|
||||||
|
// Only render button if there are packages available
|
||||||
|
if (this.elements.packageOptions.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.type = "button";
|
||||||
|
button.id = "modal_package_add_button";
|
||||||
|
button.setAttribute("popovertarget", "package_dropdown_menu");
|
||||||
|
button.style.cssText = "anchor-name:--anchor-packages";
|
||||||
|
button.className = "btn btn-sm btn-ghost gap-2 text-base-content/50";
|
||||||
|
|
||||||
|
button.innerHTML = `
|
||||||
|
<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-plus-icon lucide-plus"><path d="M5 12h14"/><path d="M12 5v14"/></svg>
|
||||||
|
Add Package
|
||||||
|
`;
|
||||||
|
|
||||||
|
this.elements.pillsContainer.appendChild(button);
|
||||||
|
},
|
||||||
|
|
||||||
|
createPillElement(packageUrl, packageName) {
|
||||||
|
const pill = document.createElement("span");
|
||||||
|
pill.className = "badge badge-outline gap-2 max-w-xs";
|
||||||
|
pill.dataset.packageUrl = packageUrl;
|
||||||
|
pill.dataset.packageName = packageName;
|
||||||
|
|
||||||
|
pill.innerHTML = `
|
||||||
|
<span class="truncate" title="${packageName}">${packageName}</span>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-4 w-4 cursor-pointer hover:text-error package-remove-btn flex-shrink-0 rotate-45"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none" stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M5 12h14"/><path d="M12 5v14"/>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return pill;
|
||||||
|
},
|
||||||
|
|
||||||
|
renderCheckmarks() {
|
||||||
|
// Update all checkmarks based on selected packages
|
||||||
|
this.elements.packageOptions.forEach((option) => {
|
||||||
|
const packageUrl = option.dataset.packageUrl;
|
||||||
|
const isSelected = this.selectedPackages.some(
|
||||||
|
(pkg) => pkg.url === packageUrl,
|
||||||
|
);
|
||||||
|
const checkmark = option.querySelector(".package-checkmark");
|
||||||
|
|
||||||
|
if (checkmark) {
|
||||||
|
checkmark.classList.toggle("hidden", !isSelected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getSelectedPackages() {
|
||||||
|
return this.selectedPackages.map((pkg) => pkg.url);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Modal and Search Management
|
||||||
|
const modal = document.getElementById("search_modal");
|
||||||
|
const searchbar = document.getElementById("modal_searchbar");
|
||||||
|
const searchButton = document.getElementById("modal_search_button");
|
||||||
|
const modeButton = document.getElementById("modal_mode_button");
|
||||||
|
const resultsDiv = document.getElementById("search_results");
|
||||||
|
const loadingDiv = document.getElementById("search_loading");
|
||||||
|
|
||||||
|
// MutationObserver to detect when modal opens
|
||||||
|
const observer = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
if (mutation.attributeName === "open" && modal.open) {
|
||||||
|
PackageSelector.render();
|
||||||
|
// Delay focus to allow CSS transitions to complete (modal has 0.3s transition)
|
||||||
|
setTimeout(() => {
|
||||||
|
searchbar.focus();
|
||||||
|
}, 320);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(modal, { attributes: true });
|
||||||
|
|
||||||
|
// Close modal when clicking outside (on the backdrop)
|
||||||
|
// According to DaisyUI docs: https://daisyui.com/components/modal/
|
||||||
|
// The backdrop form with method="dialog" should handle closing automatically when its button is clicked.
|
||||||
|
// We also handle clicks directly on the dialog element (backdrop area) or the backdrop form.
|
||||||
|
modal.addEventListener("click", function (event) {
|
||||||
|
const backdrop = modal.querySelector(".modal-backdrop");
|
||||||
|
const modalBox = modal.querySelector(".modal-box");
|
||||||
|
|
||||||
|
// Close if clicking directly on the dialog element (backdrop area)
|
||||||
|
// or on the backdrop form (but ensure we're not clicking on modal-box content)
|
||||||
|
if (
|
||||||
|
event.target === modal ||
|
||||||
|
(backdrop &&
|
||||||
|
(event.target === backdrop || backdrop.contains(event.target)) &&
|
||||||
|
!modalBox.contains(event.target))
|
||||||
|
) {
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear results when modal closes
|
||||||
|
modal.addEventListener("close", function () {
|
||||||
|
resultsDiv.innerHTML = "";
|
||||||
|
loadingDiv.classList.add("hidden");
|
||||||
|
searchbar.value = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mode dropdown handlers
|
||||||
|
const dropdownMenu = document.getElementById("search_dropdown_menu");
|
||||||
|
|
||||||
|
const modeButtons = [
|
||||||
|
{ id: "modal_dropdown_text", text: "Text" },
|
||||||
|
{ id: "modal_dropdown_smiles_default", text: "Default" },
|
||||||
|
{ id: "modal_dropdown_smiles_canonical", text: "Canonical" },
|
||||||
|
{ id: "modal_dropdown_smiles_exact", text: "Exact" },
|
||||||
|
{ id: "modal_dropdown_inchikey", text: "InChIKey" },
|
||||||
|
];
|
||||||
|
|
||||||
|
modeButtons.forEach(({ id, text }) => {
|
||||||
|
document.getElementById(id).addEventListener("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
modeButton.innerHTML =
|
||||||
|
text +
|
||||||
|
` <svg class="w-4 h-4 ml-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
||||||
|
</svg>`;
|
||||||
|
// Close dropdown using popover API
|
||||||
|
if (dropdownMenu && typeof dropdownMenu.hidePopover === "function") {
|
||||||
|
dropdownMenu.hidePopover();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initialize Package Selector
|
||||||
|
PackageSelector.init();
|
||||||
|
|
||||||
|
// Search Response Handler
|
||||||
|
function handleSearchResponse(data) {
|
||||||
|
resultsDiv.innerHTML = "";
|
||||||
|
|
||||||
|
function makeContent(objs) {
|
||||||
|
let links = "";
|
||||||
|
objs.forEach((obj) => {
|
||||||
|
links += `<a href="${obj.url}" class="block px-4 py-2 hover:bg-base-300 rounded-lg transition-colors">${obj.name}</a>`;
|
||||||
|
});
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
let allEmpty = true;
|
||||||
|
let content = "";
|
||||||
|
|
||||||
|
// Category order for better UX
|
||||||
|
const categoryOrder = [
|
||||||
|
"Compounds",
|
||||||
|
"Compound Structures",
|
||||||
|
"Rules",
|
||||||
|
"Reactions",
|
||||||
|
"Pathways",
|
||||||
|
];
|
||||||
|
|
||||||
|
categoryOrder.forEach((key) => {
|
||||||
|
if (!data[key] || data[key].length < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
allEmpty = false;
|
||||||
|
|
||||||
|
content += `
|
||||||
|
<div class="collapse collapse-arrow bg-base-200 mb-2">
|
||||||
|
<input type="checkbox" checked />
|
||||||
|
<div class="collapse-title font-medium">
|
||||||
|
${key} <span class="badge badge-neutral badge-sm ml-2">${data[key].length}</span>
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
${makeContent(data[key])}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allEmpty) {
|
||||||
|
resultsDiv.innerHTML = `
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||||
|
</svg>
|
||||||
|
<span>No results found</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
resultsDiv.innerHTML = `
|
||||||
|
<div class="mb-2">
|
||||||
|
<div class="text-sm font-semibold text-base-content/70 mb-2">Results</div>
|
||||||
|
${content}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search Execution
|
||||||
|
function performSearch(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const query = searchbar.value.trim();
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
console.log("Search phrase empty, won't do search");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selPacks = PackageSelector.getSelectedPackages();
|
||||||
|
|
||||||
|
if (selPacks.length < 1) {
|
||||||
|
console.log("No package selected, won't do search");
|
||||||
|
resultsDiv.innerHTML = `
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||||
|
</svg>
|
||||||
|
<span>Please select at least one package</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mode = modeButton.textContent.trim().toLowerCase();
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
selPacks.forEach((pack) => params.append("packages", pack));
|
||||||
|
params.append("search", query);
|
||||||
|
params.append("mode", mode);
|
||||||
|
|
||||||
|
// Show loading
|
||||||
|
loadingDiv.classList.remove("hidden");
|
||||||
|
resultsDiv.innerHTML = "";
|
||||||
|
|
||||||
|
fetch(`{{ SERVER_BASE }}/search?${params.toString()}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Search request failed");
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
loadingDiv.classList.add("hidden");
|
||||||
|
handleSearchResponse(result);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
loadingDiv.classList.add("hidden");
|
||||||
|
console.error("Search error:", error);
|
||||||
|
resultsDiv.innerHTML = `
|
||||||
|
<div class="alert alert-error">
|
||||||
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||||
|
</svg>
|
||||||
|
<span>Search failed. Please try again.</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Event listeners for search
|
||||||
|
searchButton.addEventListener("click", performSearch);
|
||||||
|
searchbar.addEventListener("keydown", function (e) {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
performSearch(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
@ -1,110 +0,0 @@
|
|||||||
<div class="modal fade bs-modal-sm" id="signupmodal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel"
|
|
||||||
aria-hidden="true">
|
|
||||||
<div class="modal-dialog modal-sm">
|
|
||||||
<div class="modal-content">
|
|
||||||
<br>
|
|
||||||
<div class="bs-example bs-example-tabs">
|
|
||||||
<ul id="myTab" class="nav nav-tabs">
|
|
||||||
<li class="active">
|
|
||||||
<a href="#signin" data-toggle="tab">Sign In</a>
|
|
||||||
</li>
|
|
||||||
<li class="">
|
|
||||||
<a href="#signup" data-toggle="tab">Register</a>
|
|
||||||
</li>
|
|
||||||
<li class="">
|
|
||||||
<a href="#why" data-toggle="tab">Why?</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div id="myTabContent" class="tab-content">
|
|
||||||
<div class="tab-pane fade active in" id="signin">
|
|
||||||
<form class="form-horizontal" method="post" action="{% url 'login' %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<fieldset>
|
|
||||||
<input type="hidden" name="login" id="login" value="true"/>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="username">Username:</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="username" name="username" type="text" class="form-control"
|
|
||||||
placeholder="username" autocomplete="username">
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="passwordinput">Password:</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="passwordinput" name="password" class="form-control"
|
|
||||||
type="password" placeholder="********" autocomplete="current-password">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Button -->
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="signin"></label>
|
|
||||||
<div class="controls">
|
|
||||||
<button id="signin" name="signin" class="btn btn-success">Sign In</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Why tab -->
|
|
||||||
<div class="tab-pane fade in" id="why">
|
|
||||||
<p>After you register, you have more permissions on
|
|
||||||
this site, e.g., can create your own
|
|
||||||
packages, submit data for review, and set access
|
|
||||||
permissions to your data.</p>
|
|
||||||
<p></p>
|
|
||||||
<p>
|
|
||||||
<br> Please
|
|
||||||
contact <a href="mailto:admin@envipath.org">admin@envipath.org</a>
|
|
||||||
if you have any questions.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Register -->
|
|
||||||
<div class="tab-pane fade"
|
|
||||||
id="signup">
|
|
||||||
<div id="passwordGuideline" class="alert alert-info">
|
|
||||||
The password must contain 8 to 30 characters<br>
|
|
||||||
The following characters are allowed:
|
|
||||||
- Upper and lower case characters<br>
|
|
||||||
- Digits<br>
|
|
||||||
- Special characters _, -, +<br>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form id="signup-action" class="form-horizontal" action="{% url 'login' %}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
<input type="hidden" name="register" id="register" value="true"/>
|
|
||||||
|
|
||||||
<label class="control-label" for="userid">Username:</label>
|
|
||||||
<input id="userid" name="username" class="form-control" type="text" placeholder="user" required autocomplete="username">
|
|
||||||
|
|
||||||
<label class="control-label" for="email">Email:</label>
|
|
||||||
<input id="email" name="email" class="form-control" type="email" placeholder="user@envipath.org" required>
|
|
||||||
|
|
||||||
<label class="control-label" for="password">Password:</label>
|
|
||||||
<input id="password" name="password" class="form-control" type="password" placeholder="********" required autocomplete="new-password">
|
|
||||||
|
|
||||||
<label class="control-label" for="rpassword">Repeat Password:</label>
|
|
||||||
<input id="rpassword" name="rpassword" class="form-control" type="password" placeholder="********" required autocomplete="new-password">
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="confirmsignup"></label>
|
|
||||||
<div class="controls">
|
|
||||||
<button id="confirmsignup" name="confirmsignup" class="btn btn-success">Sign Up
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<center>
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
|
||||||
</center>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</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 %}
|
||||||
@ -12,18 +13,34 @@
|
|||||||
<!-- Include required libs -->
|
<!-- Include required libs -->
|
||||||
<script src="https://d3js.org/d3.v5.min.js"></script>
|
<script src="https://d3js.org/d3.v5.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/c3@0.7.20/c3.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/c3@0.7.20/c3.min.js"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/c3@0.7.20/c3.min.css" rel="stylesheet">
|
<link
|
||||||
|
href="https://cdn.jsdelivr.net/npm/c3@0.7.20/c3.min.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
<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|safe }}
|
||||||
<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"
|
||||||
aria-haspopup="true" aria-expanded="false"><span
|
>
|
||||||
class="glyphicon glyphicon-wrench"></span> Actions <span class="caret"></span><span
|
<a
|
||||||
style="padding-right:1em"></span></a>
|
href="#"
|
||||||
|
class="dropdown-toggle"
|
||||||
|
data-toggle="dropdown"
|
||||||
|
role="button"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="false"
|
||||||
|
><span class="glyphicon glyphicon-wrench"></span> Actions
|
||||||
|
<span class="caret"></span><span style="padding-right:1em"></span
|
||||||
|
></a>
|
||||||
<ul id="actionsList" class="dropdown-menu">
|
<ul id="actionsList" class="dropdown-menu">
|
||||||
{% block actions %}
|
{% block actions %}
|
||||||
{% include "actions/objects/model.html" %}
|
{% include "actions/objects/model.html" %}
|
||||||
@ -32,81 +49,135 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<p> {{ model.description|safe }} </p>
|
<p>{{ model.description|safe }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning'%}
|
{% if model|classname == 'MLRelativeReasoning' or model|classname == 'RuleBasedRelativeReasoning' %}
|
||||||
<!-- Rule Packages -->
|
<!-- Rule Packages -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="rule-package-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#rule-package">Rule Packages</a>
|
id="rule-package-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#rule-package"
|
||||||
|
>Rule Packages</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<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|safe }}</a
|
||||||
|
>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Reaction Packages -->
|
<!-- Reaction Packages -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="reaction-package-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#reaction-package">Rule Packages</a>
|
id="reaction-package-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#reaction-package"
|
||||||
|
>Rule Packages</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<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|safe }}</a
|
||||||
|
>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if model.eval_packages.all|length > 0 %}
|
{% if model.eval_packages.all|length > 0 %}
|
||||||
<!-- Eval Packages -->
|
<!-- Eval Packages -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="eval-package-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#eval-package">Rule Packages</a>
|
id="eval-package-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#eval-package"
|
||||||
|
>Rule Packages</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<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|safe }}</a
|
||||||
|
>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<!-- Model Status -->
|
<!-- Model Status -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="model-status-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#model-status">Model Status</a>
|
id="model-status-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#model-status"
|
||||||
|
>Model Status</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="model-status" class="panel-collapse collapse in">
|
<div id="model-status" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">{{ model.status }}</div>
|
||||||
{{ model.status }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if model.ready_for_prediction %}
|
{% if model.ready_for_prediction %}
|
||||||
<!-- Predict Panel -->
|
<!-- Predict Panel -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="predict-smiles-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#predict-smiles">Predict</a>
|
id="predict-smiles-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#predict-smiles"
|
||||||
|
>Predict</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="predict-smiles" class="panel-collapse collapse in">
|
<div id="predict-smiles" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="smiles-to-predict" type="text" class="form-control"
|
<input
|
||||||
placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C">
|
id="smiles-to-predict"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C"
|
||||||
|
/>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button class="btn btn-default" type="submit" id="predict-button">Predict!</button>
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
type="submit"
|
||||||
|
id="predict-button"
|
||||||
|
>
|
||||||
|
Predict!
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="predictLoading"></div>
|
<div id="predictLoading"></div>
|
||||||
@ -118,18 +189,37 @@
|
|||||||
|
|
||||||
{% if model.ready_for_prediction and model.app_domain %}
|
{% if model.ready_for_prediction and model.app_domain %}
|
||||||
<!-- App Domain -->
|
<!-- App Domain -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="app-domain-assessment-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#app-domain-assessment">Applicability Domain Assessment</a>
|
id="app-domain-assessment-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#app-domain-assessment"
|
||||||
|
>Applicability Domain Assessment</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="app-domain-assessment" class="panel-collapse collapse in">
|
<div id="app-domain-assessment" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input id="smiles-to-assess" type="text" class="form-control" placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C">
|
<input
|
||||||
|
id="smiles-to-assess"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="CCN(CC)C(=O)C1=CC(=CC=C1)C"
|
||||||
|
/>
|
||||||
<span class="input-group-btn">
|
<span class="input-group-btn">
|
||||||
<button class="btn btn-default" type="submit" id="assess-button">Assess!</button>
|
<button
|
||||||
|
class="btn btn-default"
|
||||||
|
type="submit"
|
||||||
|
id="assess-button"
|
||||||
|
>
|
||||||
|
Assess!
|
||||||
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="appDomainLoading"></div>
|
<div id="appDomainLoading"></div>
|
||||||
@ -141,23 +231,34 @@
|
|||||||
|
|
||||||
{% if model.model_status == 'FINISHED' %}
|
{% if model.model_status == 'FINISHED' %}
|
||||||
<!-- Single Gen Curve Panel -->
|
<!-- Single Gen Curve Panel -->
|
||||||
<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"
|
||||||
|
>
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<a id="sg-curve-link" data-toggle="collapse" data-parent="#model-detail"
|
<a
|
||||||
href="#sg-curve">Precision Recall Curve</a>
|
id="sg-curve-link"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-parent="#model-detail"
|
||||||
|
href="#sg-curve"
|
||||||
|
>Precision Recall Curve</a
|
||||||
|
>
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div id="sg-curve" class="panel-collapse collapse in">
|
<div id="sg-curve" class="panel-collapse collapse in">
|
||||||
<div class="panel-body list-group-item">
|
<div class="panel-body list-group-item">
|
||||||
<!-- Center container contents -->
|
<!-- Center container contents -->
|
||||||
<div class="container" style="display: flex;justify-content: center;">
|
<div
|
||||||
|
class="container"
|
||||||
|
style="display: flex;justify-content: center;"
|
||||||
|
>
|
||||||
<div id="sg-curve-plotdiv" class="chart">
|
<div id="sg-curve-plotdiv" class="chart">
|
||||||
<div id="sg-chart"></div>
|
<div id="sg-chart"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{# prettier-ignore-start #}
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
if (!($('#sg-chart').length > 0)) {
|
if (!($('#sg-chart').length > 0)) {
|
||||||
@ -264,44 +365,61 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
{# prettier-ignore-end #}
|
||||||
<!-- End Single Gen Curve Panel -->
|
<!-- End Single Gen Curve Panel -->
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function handlePredictionResponse(data) {
|
function handlePredictionResponse(data) {
|
||||||
res = "<table class='table table-striped'>"
|
res = "<table class='table table-striped'>";
|
||||||
res += "<thead>"
|
res += "<thead>";
|
||||||
res += "<th scope='col'>#</th>"
|
res += "<th scope='col'>#</th>";
|
||||||
|
|
||||||
columns = ['products', 'image', 'probability', 'btrule']
|
columns = ["products", "image", "probability", "btrule"];
|
||||||
|
|
||||||
for (col in columns) {
|
for (col in columns) {
|
||||||
res += "<th scope='col'>" + columns[col] + "</th>"
|
res += "<th scope='col'>" + columns[col] + "</th>";
|
||||||
}
|
}
|
||||||
|
|
||||||
res += "</thead>"
|
res += "</thead>";
|
||||||
res += "<tbody>"
|
res += "<tbody>";
|
||||||
var cnt = 1;
|
var cnt = 1;
|
||||||
for (transformation in data) {
|
for (transformation in data) {
|
||||||
res += "<tr>"
|
res += "<tr>";
|
||||||
res += "<th scope='row'>" + cnt + "</th>"
|
res += "<th scope='row'>" + cnt + "</th>";
|
||||||
res += "<th scope='row'>" + data[transformation]['products'][0].join(', ') + "</th>"
|
res +=
|
||||||
res += "<th scope='row'>" + "<img width='400' src='{% url 'depict' %}?smiles=" + encodeURIComponent(data[transformation]['products'][0].join('.')) + "'></th>"
|
"<th scope='row'>" +
|
||||||
res += "<th scope='row'>" + data[transformation]['probability'].toFixed(3) + "</th>"
|
data[transformation]["products"][0].join(", ") +
|
||||||
if (data[transformation]['btrule'] != null) {
|
"</th>";
|
||||||
res += "<th scope='row'>" + "<a href='" + data[transformation]['btrule']['url'] + "'>" + data[transformation]['btrule']['name'] + "</a>" + "</th>"
|
res +=
|
||||||
|
"<th scope='row'>" +
|
||||||
|
"<img width='400' src='{% url 'depict' %}?smiles=" +
|
||||||
|
encodeURIComponent(data[transformation]["products"][0].join(".")) +
|
||||||
|
"'></th>";
|
||||||
|
res +=
|
||||||
|
"<th scope='row'>" +
|
||||||
|
data[transformation]["probability"].toFixed(3) +
|
||||||
|
"</th>";
|
||||||
|
if (data[transformation]["btrule"] != null) {
|
||||||
|
res +=
|
||||||
|
"<th scope='row'>" +
|
||||||
|
"<a href='" +
|
||||||
|
data[transformation]["btrule"]["url"] +
|
||||||
|
"'>" +
|
||||||
|
data[transformation]["btrule"]["name"] +
|
||||||
|
"</a>" +
|
||||||
|
"</th>";
|
||||||
} else {
|
} else {
|
||||||
res += "<th scope='row'>N/A</th>"
|
res += "<th scope='row'>N/A</th>";
|
||||||
}
|
}
|
||||||
res += "</tr>"
|
res += "</tr>";
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
res += "</tbody>"
|
res += "</tbody>";
|
||||||
res += "</table>"
|
res += "</table>";
|
||||||
$("#predictResultTable").append(res);
|
$("#predictResultTable").append(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,37 +428,40 @@
|
|||||||
$("#" + divid).empty();
|
$("#" + divid).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($('#predict-button').length > 0) {
|
if ($("#predict-button").length > 0) {
|
||||||
$("#predict-button").on("click", function (e) {
|
$("#predict-button").on("click", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
clear("predictResultTable");
|
clear("predictResultTable");
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"smiles": $("#smiles-to-predict").val(),
|
smiles: $("#smiles-to-predict").val(),
|
||||||
"classify": "ILikeCats!"
|
classify: "ILikeCats!",
|
||||||
}
|
};
|
||||||
|
|
||||||
if (data["smiles"].trim() === "") {
|
if (data["smiles"].trim() === "") {
|
||||||
$("#predictResultTable").addClass("alert alert-danger");
|
$("#predictResultTable").addClass("alert alert-danger");
|
||||||
$("#predictResultTable").append("Please enter a SMILES string to predict!");
|
$("#predictResultTable").append(
|
||||||
|
"Please enter a SMILES string to predict!",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeLoadingGif("#predictLoading", "{% static '/images/wait.gif' %}");
|
makeLoadingGif("#predictLoading", "{% static '/images/wait.gif' %}");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'get',
|
type: "get",
|
||||||
data: data,
|
data: data,
|
||||||
url: '',
|
url: "",
|
||||||
success: function (data, textStatus) {
|
success: function (data, textStatus) {
|
||||||
try {
|
try {
|
||||||
$("#predictLoading").empty();
|
$("#predictLoading").empty();
|
||||||
handlePredictionResponse(data);
|
handlePredictionResponse(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
||||||
$("#predictLoading").empty();
|
$("#predictLoading").empty();
|
||||||
$("#predictResultTable").addClass("alert alert-danger");
|
$("#predictResultTable").addClass("alert alert-danger");
|
||||||
$("#predictResultTable").append("Error while processing response :/");
|
$("#predictResultTable").append(
|
||||||
|
"Error while processing response :/",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function (jqXHR, textStatus, errorThrown, x) {
|
error: function (jqXHR, textStatus, errorThrown, x) {
|
||||||
@ -352,30 +473,30 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($('#assess-button').length > 0) {
|
if ($("#assess-button").length > 0) {
|
||||||
$("#assess-button").on("click", function (e) {
|
$("#assess-button").on("click", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
clear("appDomainAssessmentResultTable");
|
clear("appDomainAssessmentResultTable");
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"smiles": $("#smiles-to-assess").val(),
|
smiles: $("#smiles-to-assess").val(),
|
||||||
"app-domain-assessment": "ILikeCats!"
|
"app-domain-assessment": "ILikeCats!",
|
||||||
}
|
};
|
||||||
|
|
||||||
if (data["smiles"].trim() === "") {
|
if (data["smiles"].trim() === "") {
|
||||||
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
||||||
$("#appDomainAssessmentResultTable").append("Please enter a SMILES string to predict!");
|
$("#appDomainAssessmentResultTable").append(
|
||||||
|
"Please enter a SMILES string to predict!",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
makeLoadingGif("#appDomainLoading", "{% static '/images/wait.gif' %}");
|
makeLoadingGif("#appDomainLoading", "{% static '/images/wait.gif' %}");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'get',
|
type: "get",
|
||||||
data: data,
|
data: data,
|
||||||
url: '',
|
url: "",
|
||||||
success: function (data, textStatus) {
|
success: function (data, textStatus) {
|
||||||
try {
|
try {
|
||||||
$("#appDomainLoading").empty();
|
$("#appDomainLoading").empty();
|
||||||
@ -383,19 +504,23 @@
|
|||||||
console.log(data);
|
console.log(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
$("#appDomainLoading").empty();
|
$("#appDomainLoading").empty();
|
||||||
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
$("#appDomainAssessmentResultTable").addClass(
|
||||||
$("#appDomainAssessmentResultTable").append("Error while processing response :/");
|
"alert alert-danger",
|
||||||
|
);
|
||||||
|
$("#appDomainAssessmentResultTable").append(
|
||||||
|
"Error while processing response :/",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function (jqXHR, textStatus, errorThrown) {
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
$("#appDomainLoading").empty();
|
$("#appDomainLoading").empty();
|
||||||
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
$("#appDomainAssessmentResultTable").addClass("alert alert-danger");
|
||||||
$("#appDomainAssessmentResultTable").append(jqXHR.responseJSON.error);
|
$("#appDomainAssessmentResultTable").append(
|
||||||
}
|
jqXHR.responseJSON.error,
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|||||||
194
templates/predict_pathway.html
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="mx-auto w-full p-8">
|
||||||
|
<h1 class="h1 mb-4 text-3xl font-bold">
|
||||||
|
Predict a Pathway
|
||||||
|
|
||||||
|
<span class="text-base-content/50 text-xs"
|
||||||
|
>in <strong>{{ meta.current_package.name|safe }}</strong>
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<form
|
||||||
|
id="predict_form"
|
||||||
|
accept-charset="UTF-8"
|
||||||
|
action="{{ meta.current_package.url }}/pathway"
|
||||||
|
method="post"
|
||||||
|
>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="mb-8 flex flex-col gap-8 md:flex-row md:items-end">
|
||||||
|
<fieldset class="flex flex-col gap-4 md:flex-3/4">
|
||||||
|
<label class="floating-label" for="name">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
placeholder="Name"
|
||||||
|
id="name"
|
||||||
|
class="input input-md w-full"
|
||||||
|
/>
|
||||||
|
<span>Name</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label class="floating-label" for="description">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="description"
|
||||||
|
placeholder="Description"
|
||||||
|
id="description"
|
||||||
|
class="input input-md w-full"
|
||||||
|
/>
|
||||||
|
<span>Description</span>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset
|
||||||
|
class="fieldset flex shrink-0 flex-row items-start gap-3 md:flex-1/4 md:flex-col"
|
||||||
|
>
|
||||||
|
<label class="fieldset-label text-base-content/50">Mode</label>
|
||||||
|
<label class="label">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="predict"
|
||||||
|
id="radioPredict"
|
||||||
|
value="predict"
|
||||||
|
checked
|
||||||
|
class="radio radio-neutral"
|
||||||
|
/>
|
||||||
|
Predict
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="predict"
|
||||||
|
id="radioIncremental"
|
||||||
|
value="incremental"
|
||||||
|
class="radio radio-neutral"
|
||||||
|
/>
|
||||||
|
Incremental
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="predict"
|
||||||
|
id="radioBuild"
|
||||||
|
value="build"
|
||||||
|
class="radio radio-neutral"
|
||||||
|
/>
|
||||||
|
Build
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="floating-label" for="predict-smiles">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="smiles"
|
||||||
|
placeholder="SMILES"
|
||||||
|
id="predict-smiles"
|
||||||
|
class="input input-md w-full"
|
||||||
|
/>
|
||||||
|
<span>SMILES</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="divider text-base-content/50">OR</div>
|
||||||
|
|
||||||
|
<div class="mb-8 w-full">
|
||||||
|
<label class="text-base-content/50 mb-4 text-xs font-medium"
|
||||||
|
>Draw Structure</label
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
id="predict-ketcher"
|
||||||
|
src="{% static '/js/ketcher2/ketcher.html' %}"
|
||||||
|
width="100%"
|
||||||
|
height="510"
|
||||||
|
></iframe>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<label class="select mb-8 w-full">
|
||||||
|
<span class="label">Predictor</span>
|
||||||
|
<select id="prediction-setting" name="prediction-setting">
|
||||||
|
<option disabled>Select a Setting</option>
|
||||||
|
{% for s in meta.available_settings %}
|
||||||
|
<option
|
||||||
|
value="{{ s.url }}"
|
||||||
|
{% if s.id == meta.user.default_setting.id %}selected{% endif %}
|
||||||
|
>
|
||||||
|
{{ s.name }}{% if s.id == meta.user.default_setting.id %}
|
||||||
|
(User default)
|
||||||
|
{% endif %}
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="flex justify-end gap-2">
|
||||||
|
<a href="{{ meta.current_package.url }}/pathway" class="btn btn-outline"
|
||||||
|
>Cancel</a
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
id="predict-submit-button"
|
||||||
|
class="btn btn-primary"
|
||||||
|
>
|
||||||
|
Predict
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function predictKetcherToTextInput() {
|
||||||
|
$("#predict-smiles").val(this.ketcher.getSmiles());
|
||||||
|
}
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$("#predict-ketcher").on("load", function () {
|
||||||
|
const checkKetcherReady = () => {
|
||||||
|
const win = this.contentWindow;
|
||||||
|
if (win.ketcher && "editor" in win.ketcher) {
|
||||||
|
window.predictKetcher = win.ketcher;
|
||||||
|
win.ketcher.editor.event.change.handlers.push({
|
||||||
|
once: false,
|
||||||
|
priority: 0,
|
||||||
|
f: predictKetcherToTextInput,
|
||||||
|
ketcher: win.ketcher,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setTimeout(checkKetcherReady, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkKetcherReady();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#predict-submit-button").on("click", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const button = $(this);
|
||||||
|
button.prop("disabled", true);
|
||||||
|
button.text("Predicting...");
|
||||||
|
|
||||||
|
// Get SMILES from either input or Ketcher
|
||||||
|
let smiles = $("#predict-smiles").val().trim();
|
||||||
|
|
||||||
|
// If SMILES input is empty, try to get from Ketcher
|
||||||
|
if (!smiles && window.predictKetcher) {
|
||||||
|
smiles = window.predictKetcher.getSmiles().trim();
|
||||||
|
if (smiles) {
|
||||||
|
$("#predict-smiles").val(smiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Basic validation
|
||||||
|
if (!smiles) {
|
||||||
|
alert("Please enter a SMILES string or draw a structure.");
|
||||||
|
button.prop("disabled", false);
|
||||||
|
button.text("Predict");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Submit form
|
||||||
|
$("#predict_form").submit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock content %}
|
||||||
@ -1,197 +0,0 @@
|
|||||||
{% extends "framework.html" %}
|
|
||||||
{% load static %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div id=searchContent>
|
|
||||||
<div id="packSelector">
|
|
||||||
<label>Select Packages</label><br>
|
|
||||||
<select id="selPackages" name="selPackages" data-actions-box='true' class="selPackages" multiple
|
|
||||||
data-width='100%'>
|
|
||||||
{% if unreviewed_objects %}
|
|
||||||
<option disabled>Reviewed Packages</option>
|
|
||||||
{% endif %}
|
|
||||||
{% for obj in reviewed_objects %}
|
|
||||||
<option value="{{ obj.url }}" selected>{{ obj.name|safe }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
{% if unreviewed_objects %}
|
|
||||||
<option disabled>Unreviewed Packages</option>
|
|
||||||
{% endif %}
|
|
||||||
{% for obj in unreviewed_objects %}
|
|
||||||
<option value="{{ obj.url }}">{{ obj.name|safe }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<p></p>
|
|
||||||
<div>
|
|
||||||
<label>Search Term</label><br>
|
|
||||||
<div class="input-group" id="index-form-bar">
|
|
||||||
<input type="text" class="form-control" id='searchbar' placeholder="Benfuracarb">
|
|
||||||
<div class="input-group-btn">
|
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"
|
|
||||||
id="mode-button"
|
|
||||||
aria-haspopup="true" aria-expanded="false">Text <span class="caret"></span></button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
<li class="dropdown-header">Text</li>
|
|
||||||
<li><a id="dropdown-predict-text-text">Text</a></li>
|
|
||||||
<li class="dropdown-header">SMILES</li>
|
|
||||||
<li><a id="dropdown-search-smiles-default" data-toggle="tooltip">Default</a></li>
|
|
||||||
<li><a id="dropdown-search-smiles-canonical">Canonical</a></li>
|
|
||||||
<li><a id="dropdown-search-smiles-exact">Exact</a></li>
|
|
||||||
<li class="dropdown-header">InChI</li>
|
|
||||||
<li><a id="dropdown-search-inchi-inchikey">InChIKey</a></li>
|
|
||||||
</ul>
|
|
||||||
<button class="btn" style="background-color:#222222;color:#9d9d9d" type="button" id="search-button">
|
|
||||||
Go!
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p></p>
|
|
||||||
<div id="results"></div>
|
|
||||||
<p></p>
|
|
||||||
<div id="loading"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
function modeDropdownClicked() {
|
|
||||||
var suffix = ' <span class="caret"></span>';
|
|
||||||
var dropdownVal = $(this).text();
|
|
||||||
$('#mode-button').html(dropdownVal + suffix);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSearchResponse(id, data) {
|
|
||||||
content = `
|
|
||||||
<div class='panel-group' id='search-accordion'>
|
|
||||||
<div class='panel panel-default'>
|
|
||||||
<div class='panel-heading' id='headingPanel' style='font-size:2rem;height: 46px'>
|
|
||||||
Results
|
|
||||||
</div>
|
|
||||||
<div id='descDiv'></div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
function makeContent(objs) {
|
|
||||||
links = "";
|
|
||||||
for (idx in objs) {
|
|
||||||
obj = objs[idx];
|
|
||||||
links += `<a class='list-group-item' href='${obj.url}'>${obj.name}</a>`
|
|
||||||
}
|
|
||||||
return links;
|
|
||||||
}
|
|
||||||
|
|
||||||
allEmpty = true;
|
|
||||||
for (key in data) {
|
|
||||||
if (key === 'searchterm') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data[key].length < 1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
allEmpty = false;
|
|
||||||
content += `
|
|
||||||
<div class='panel panel-default panel-heading list-group-item' style='background-color:silver'>
|
|
||||||
<h4 class='panel-title'>
|
|
||||||
<a id='${key}_link' data-toggle='collapse' data-parent='#search-accordion' href='#${key}_panel'>
|
|
||||||
${key}
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<div id='${key}_panel' class='panel-collapse collapse in'>
|
|
||||||
<div class='panel-body list-group-item'>
|
|
||||||
${makeContent(data[key])}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
if (allEmpty) {
|
|
||||||
$('#' + id).append('<div class="alert alert-danger" role="alert"><p>' + "No results..." + '</p></div>');
|
|
||||||
} else {
|
|
||||||
$('#' + id).append(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function search(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
query = $("#searchbar").val()
|
|
||||||
|
|
||||||
if (!query) {
|
|
||||||
// Nothing to search...
|
|
||||||
console.log("Search phrase empty, won't do search")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var selPacks = [];
|
|
||||||
$("#selPackages :selected").each(function () {
|
|
||||||
var id = this.value;
|
|
||||||
selPacks.push(id);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (selPacks.length < 1) {
|
|
||||||
console.log("No package selected, won't do search")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mode = $('#mode-button').text().trim().toLowerCase();
|
|
||||||
|
|
||||||
var par = {};
|
|
||||||
par['packages'] = selPacks;
|
|
||||||
par['search'] = query;
|
|
||||||
par['mode'] = mode;
|
|
||||||
|
|
||||||
console.log(par);
|
|
||||||
|
|
||||||
var queryString = $.param(par, true);
|
|
||||||
|
|
||||||
makeLoadingGif("#loading", "{% static '/images/wait.gif' %}");
|
|
||||||
|
|
||||||
$("#results").empty();
|
|
||||||
|
|
||||||
$.getJSON("{{ SERVER_BASE }}/search?" + queryString, function (result) {
|
|
||||||
handleSearchResponse("results", result);
|
|
||||||
$("#loading").empty();
|
|
||||||
}).fail(function (d) {
|
|
||||||
$("#loading").empty();
|
|
||||||
console.log(d.responseText);
|
|
||||||
handleError(JSON.parse(d.responseText));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$(function () {
|
|
||||||
|
|
||||||
tooltips = {
|
|
||||||
'dropdown-predict-text-text': 'The inserted pattern will be searched on all enviPath object names and descriptions',
|
|
||||||
'dropdown-search-smiles-default': 'Search by SMILES, stereochemistry and charge are ignored',
|
|
||||||
'dropdown-search-smiles-canonical': 'Search by SMILES, stereochemistry is ignored but charge is preserved',
|
|
||||||
'dropdown-search-smiles-exact': 'Search by SMILES, exact match for stereochemistry and charge',
|
|
||||||
'dropdown-search-inchi-inchikey': 'Search by InChIKey',
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(tooltips).forEach(key => {
|
|
||||||
$('#' + key).tooltip({
|
|
||||||
placement: "top",
|
|
||||||
title: tooltips[key]
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#' + key).on('click', modeDropdownClicked);
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#selPackages").selectpicker();
|
|
||||||
$("#search-button").on("click", search);
|
|
||||||
|
|
||||||
$("#searchbar").on("keydown", function (e) {
|
|
||||||
if (e.key === "Enter") {
|
|
||||||
e.preventDefault();
|
|
||||||
search(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
{% if search_result %}
|
|
||||||
$('#searchbar').val('{{ search_result.searchterm }}')
|
|
||||||
handleSearchResponse("results", {{ search_result|safe }});
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
||||||
132
templates/static/about_us.html
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>About Us</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">About enviPath</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<!-- Hero Image/Graphic -->
|
||||||
|
<div class="mb-8">
|
||||||
|
<img src="{% static '/images/ep-rule-artwork.png' %}" alt="enviPath System" class="w-full max-w-2xl mx-auto rounded-lg shadow-md" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
enviPath is a comprehensive database and prediction system for the microbial biotransformation of
|
||||||
|
organic environmental contaminants. Since 2015, we have been at the forefront of computational
|
||||||
|
environmental chemistry, helping researchers understand and predict biodegradation pathways.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Our Mission</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Our mission is to advance environmental science through innovative computational tools that predict
|
||||||
|
and analyze the biotransformation of chemical compounds. We strive to provide researchers, regulators,
|
||||||
|
and industry professionals with accurate, accessible tools for understanding environmental fate and behavior.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">What We Offer</h2>
|
||||||
|
<div class="grid md:grid-cols-2 gap-6 mb-6">
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">Pathway Database</h3>
|
||||||
|
<p>Access experimentally observed biotransformation pathways and reactions from curated scientific literature.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">Prediction System</h3>
|
||||||
|
<p>Use our relative reasoning models to predict likely biotransformation pathways and products for new compounds.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">Machine Learning Models</h3>
|
||||||
|
<p>Leverage advanced ML algorithms trained on extensive biodegradation data for accurate predictions.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">Community Platform</h3>
|
||||||
|
<p>Join our active community of researchers to share knowledge, discuss findings, and collaborate.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Our Technology</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
enviPath employs a unique combination of rule-based and machine learning approaches to predict
|
||||||
|
biotransformation pathways:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li><strong>Relative Reasoning:</strong> Uses structural similarity to known biotransformations</li>
|
||||||
|
<li><strong>Rule-Based Systems:</strong> Applies expert-curated transformation rules</li>
|
||||||
|
<li><strong>Machine Learning:</strong> Leverages neural networks for pattern recognition</li>
|
||||||
|
<li><strong>Hybrid Models:</strong> Combines multiple approaches for optimal accuracy</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Our Partners</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
enviPath is backed by leading research institutions and collaborators:
|
||||||
|
</p>
|
||||||
|
<div class="flex flex-wrap justify-center items-center gap-8 my-8">
|
||||||
|
<img src="{% static '/images/uoa-logo-small.png' %}" alt="The University of Auckland" class="h-20 object-contain" />
|
||||||
|
<img src="{% static '/images/logo-eawag.svg' %}" alt="Eawag" class="h-16 object-contain" />
|
||||||
|
<img src="{% static '/images/uzh-logo.svg' %}" alt="University of Zurich" class="h-20 object-contain" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Our Team</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
enviPath is developed and maintained by a dedicated team of computational chemists, environmental
|
||||||
|
scientists, and software engineers. Our interdisciplinary approach ensures that the platform meets
|
||||||
|
the needs of the scientific community while remaining accessible and user-friendly.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Research Impact</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Since its inception, enviPath has contributed to numerous scientific publications and environmental
|
||||||
|
assessments. Our tools are used by:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Academic researchers in environmental chemistry and toxicology</li>
|
||||||
|
<li>Regulatory agencies for chemical risk assessment</li>
|
||||||
|
<li>Chemical manufacturers for product development and safety evaluation</li>
|
||||||
|
<li>Environmental consultants for contamination studies</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Open Science Commitment</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We are committed to open science principles. enviPath provides free access to our database and
|
||||||
|
prediction tools for academic research. We actively contribute to the scientific community through
|
||||||
|
publications, open-source software, and collaboration.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-primary text-primary-content mt-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">Get Involved</h3>
|
||||||
|
<p>Join our community, contribute data, or collaborate on research projects.</p>
|
||||||
|
<div class="card-actions justify-end mt-4">
|
||||||
|
<a href="https://community.envipath.org/" target="_blank" class="btn btn-secondary">Visit Community</a>
|
||||||
|
<a href="/contact" class="btn btn-ghost">Contact Us</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Publications</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
To learn more about the science behind enviPath, please visit our
|
||||||
|
<a href="/cite" class="link link-primary">citations page</a> for key publications and how to cite our work.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
190
templates/static/careers.html
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Jobs & Careers</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Jobs & Careers</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
Join our team of passionate scientists and developers working at the intersection of environmental
|
||||||
|
chemistry, computational science, and machine learning. Help us build the future of biodegradation prediction.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Hero Card -->
|
||||||
|
<div class="card bg-gradient-to-br from-primary to-secondary text-primary-content mb-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title text-2xl">Why Work With Us?</h2>
|
||||||
|
<p>
|
||||||
|
At enviPath, we're committed to advancing environmental science through innovative technology.
|
||||||
|
We offer a collaborative, research-focused environment where your work directly impacts
|
||||||
|
environmental protection and sustainability.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">What We Value</h2>
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 mb-6 not-prose">
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary flex-shrink-0 mt-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold">Scientific Excellence</h3>
|
||||||
|
<p class="text-sm">Rigorous research and peer-reviewed contributions</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary flex-shrink-0 mt-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold">Collaboration</h3>
|
||||||
|
<p class="text-sm">Work with leading institutions worldwide</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary flex-shrink-0 mt-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold">Innovation</h3>
|
||||||
|
<p class="text-sm">Push the boundaries of computational chemistry</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-start gap-3">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-primary flex-shrink-0 mt-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-semibold">Impact</h3>
|
||||||
|
<p class="text-sm">Contribute to environmental protection</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Current Opportunities</h2>
|
||||||
|
|
||||||
|
<div class="alert alert-info mb-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">No Current Openings</h3>
|
||||||
|
<div class="text-sm">We don't have any open positions at the moment, but we're always interested in hearing from talented individuals. Please check back later or reach out with your CV.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Example Job Posting Structure (for when there are openings) -->
|
||||||
|
<!--
|
||||||
|
<div class="card bg-base-200 shadow-md mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="flex justify-between items-start">
|
||||||
|
<div>
|
||||||
|
<h3 class="card-title text-xl">Position Title</h3>
|
||||||
|
<div class="flex gap-2 mt-2">
|
||||||
|
<div class="badge badge-primary">Full-time</div>
|
||||||
|
<div class="badge badge-outline">Remote</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm text-base-content/70">Posted: Date</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-4">Brief description of the role...</p>
|
||||||
|
<div class="card-actions justify-end mt-4">
|
||||||
|
<button class="btn btn-primary">Apply Now</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Types of Roles</h2>
|
||||||
|
<p class="mb-4">We typically hire for the following types of positions:</p>
|
||||||
|
|
||||||
|
<div class="space-y-4 mb-6">
|
||||||
|
<div class="card bg-base-200">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-lg">Computational Chemists</h3>
|
||||||
|
<p>Develop and improve prediction models, curate chemical databases, and validate predictions against experimental data.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card bg-base-200">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-lg">Machine Learning Engineers</h3>
|
||||||
|
<p>Build and optimize ML models for biotransformation prediction, feature engineering, and model deployment.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card bg-base-200">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-lg">Software Developers</h3>
|
||||||
|
<p>Develop and maintain the enviPath platform, API, and user interfaces using Python, Django, and modern web technologies.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card bg-base-200">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-lg">Postdoctoral Researchers</h3>
|
||||||
|
<p>Conduct independent research, publish findings, and contribute to grant proposals in computational environmental chemistry.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Student Opportunities</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We regularly host students for internships, Master's theses, and PhD projects. If you're interested
|
||||||
|
in computational chemistry, machine learning, or environmental science, we'd love to hear from you.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-secondary text-secondary-content mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">Academic Collaborations</h3>
|
||||||
|
<p>
|
||||||
|
We partner with universities including the University of Auckland, Eawag, and University of Zurich.
|
||||||
|
Check with your academic advisor about potential collaboration opportunities.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">How to Apply</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Interested in joining our team? Here's how to get in touch:
|
||||||
|
</p>
|
||||||
|
<ol class="list-decimal list-inside mb-6 space-y-2">
|
||||||
|
<li>Review our <a href="/about" class="link link-primary">about page</a> to understand our mission and work</li>
|
||||||
|
<li>Prepare your CV/resume and a brief cover letter explaining your interest</li>
|
||||||
|
<li>Visit our <a href="https://community.envipath.org/" target="_blank" class="link link-primary">community forums</a> or reach out via <a href="https://www.linkedin.com/company/envipath/" target="_blank" class="link link-primary">LinkedIn</a></li>
|
||||||
|
<li>Include links to your publications, GitHub profile, or portfolio if relevant</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="alert alert-success">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">We Value Diversity</h3>
|
||||||
|
<div class="text-sm">enviPath is an equal opportunity employer. We celebrate diversity and are committed to creating an inclusive environment for all team members.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="divider my-8"></div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Contact</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Have questions about careers at enviPath? Visit our <a href="/contact" class="link link-primary">contact page</a>
|
||||||
|
or join our <a href="https://community.envipath.org/" target="_blank" class="link link-primary">community forums</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
204
templates/static/cite.html
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>How to Cite enviPath</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">How to Cite enviPath</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
If you use enviPath in your research, please cite our work. Citations help us demonstrate the
|
||||||
|
impact of our platform and support continued development and maintenance.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-info mb-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">Quick Reference</h3>
|
||||||
|
<div class="text-sm">The citation depends on which specific tools or models you used. Please cite the relevant publications below.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Main Platform Citation</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you use the enviPath platform in general, please cite:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-base-200 mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="font-semibold mb-2">Advancements in biotransformation pathway prediction: enhancements, datasets, and novel functionalities in enviPath</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
<strong>Authors:</strong> Hafner, J., Lorsbach, T., Schmidt, S., Brydon, L., Dost, K., Zhang, K., Fenner, K., and Wicker, J.<br>
|
||||||
|
<strong>Journal:</strong> Journal of Cheminformatics, 16(1), 93<br>
|
||||||
|
<strong>Year:</strong> 2024<br>
|
||||||
|
<strong>DOI:</strong> <a href="https://doi.org/10.1186/s13321-024-00881-6" target="_blank" class="link link-primary">10.1186/s13321-024-00881-6</a>
|
||||||
|
</p>
|
||||||
|
<div class="collapse collapse-arrow bg-base-300">
|
||||||
|
<input type="checkbox" />
|
||||||
|
<div class="collapse-title font-medium text-sm">
|
||||||
|
Show BibTeX
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<pre class="text-xs overflow-x-auto"><code>@ARTICLE{Hafner2024,
|
||||||
|
title = "Advancements in biotransformation pathway prediction:
|
||||||
|
enhancements, datasets, and novel functionalities in enviPath",
|
||||||
|
author = "Hafner, Jasmin and Lorsbach, Tim and Schmidt, Sebastian and
|
||||||
|
Brydon, Liam and Dost, Katharina and Zhang, Kunyang and Fenner,
|
||||||
|
Kathrin and Wicker, J{\"o}rg",
|
||||||
|
journal = "J. Cheminform.",
|
||||||
|
publisher = "Springer Science and Business Media LLC",
|
||||||
|
volume = 16,
|
||||||
|
number = 1,
|
||||||
|
pages = "93",
|
||||||
|
month = aug,
|
||||||
|
year = 2024,
|
||||||
|
doi = "10.1186/s13321-024-00881-6"
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Pathway Prediction System</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you use the pathway prediction functionality, please also cite:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-base-200 mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="font-semibold mb-2">Predicting Biodegradation Pathways Using a Hybrid Relative Reasoning Model</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
<strong>Authors:</strong> Wicker, J., Fenner, K., Ellis, L., Kramer, S.<br>
|
||||||
|
<strong>Journal:</strong> Biotechnology and Bioengineering, 110(3), 837-846<br>
|
||||||
|
<strong>Year:</strong> 2013<br>
|
||||||
|
<strong>DOI:</strong> <a href="https://doi.org/10.1002/bit.24744" target="_blank" class="link link-primary">10.1002/bit.24744</a>
|
||||||
|
</p>
|
||||||
|
<div class="collapse collapse-arrow bg-base-300">
|
||||||
|
<input type="checkbox" />
|
||||||
|
<div class="collapse-title font-medium text-sm">
|
||||||
|
Show BibTeX
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<pre class="text-xs overflow-x-auto"><code>@article{wicker2013predicting,
|
||||||
|
title={Predicting biodegradation pathways using a hybrid relative reasoning model},
|
||||||
|
author={Wicker, J{\"o}rg and Fenner, Kathrin and Ellis, Lynda and Kramer, Stefan},
|
||||||
|
journal={Biotechnology and Bioengineering},
|
||||||
|
volume={110},
|
||||||
|
number={3},
|
||||||
|
pages={837--846},
|
||||||
|
year={2013},
|
||||||
|
publisher={Wiley Online Library},
|
||||||
|
doi={10.1002/bit.24744}
|
||||||
|
}</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Machine Learning Models</h2>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-semibold mt-6 mb-3">enviPath-Transformer (Latest ML Model)</h3>
|
||||||
|
<div class="card bg-base-200 mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="text-sm mb-2">
|
||||||
|
If you use the Transformer-based prediction model, please cite:
|
||||||
|
</p>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
<strong>Authors:</strong> Brydon, L., Zhang, K., Dobbie, G., Taškova, K., and Wicker, J.<br>
|
||||||
|
<strong>Journal:</strong> Journal of Cheminformatics, 17(1), 21<br>
|
||||||
|
<strong>Year:</strong> 2025<br>
|
||||||
|
<strong>DOI:</strong> <a href="https://doi.org/10.1186/s13321-025-00969-7" target="_blank" class="link link-primary">10.1186/s13321-025-00969-7</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-semibold mt-6 mb-3">Relative Reasoning Models</h3>
|
||||||
|
<div class="card bg-base-200 mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="text-sm mb-2">
|
||||||
|
For relative reasoning and machine learning approaches:
|
||||||
|
</p>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
<strong>Authors:</strong> Fenner, K., Gao, J., Kramer, S., Ellis, L., Wackett, L.<br>
|
||||||
|
<strong>Journal:</strong> Environmental Science & Technology, 42(15), 5761-5767<br>
|
||||||
|
<strong>Year:</strong> 2008<br>
|
||||||
|
<strong>DOI:</strong> <a href="https://doi.org/10.1021/es800408g" target="_blank" class="link link-primary">10.1021/es800408g</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Package-Specific Citations</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you use data from a specific package within enviPath, please also acknowledge the package creators
|
||||||
|
and cite any relevant publications associated with that package. Package-specific citation information
|
||||||
|
is available on each package's detail page.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Example Acknowledgment Text</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
You may use the following text in your acknowledgments section:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-base-200 mb-6">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="italic text-sm">
|
||||||
|
"Biotransformation pathway predictions were performed using enviPath
|
||||||
|
(<a href="https://envipath.org" target="_blank" class="link link-primary">https://envipath.org</a>),
|
||||||
|
a database and prediction system for microbial biotransformation of organic environmental contaminants."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Additional Resources</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
For a complete list of publications related to enviPath, please visit:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-6 space-y-2">
|
||||||
|
<li>
|
||||||
|
<a href="https://community.envipath.org/" target="_blank" class="link link-primary">
|
||||||
|
enviPath Community - Publications Section
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://wiki.envipath.org/" target="_blank" class="link link-primary">
|
||||||
|
enviPath Documentation - References
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="alert alert-success mt-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">Thank You!</h3>
|
||||||
|
<div class="text-sm">
|
||||||
|
Thank you for citing enviPath. Your citations help demonstrate the impact of our work and
|
||||||
|
enable us to continue providing this resource to the scientific community.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="divider my-8"></div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Questions?</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you're unsure which papers to cite or have questions about citations, please
|
||||||
|
<a href="/contact" class="link link-primary">contact us</a> or ask on our
|
||||||
|
<a href="https://community.envipath.org/" target="_blank" class="link link-primary">community forums</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
169
templates/static/contact.html
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Contact & Support</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Contact & Support</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
We're here to help! Whether you have questions about using enviPath, need technical support,
|
||||||
|
or want to discuss collaboration opportunities, we'd love to hear from you.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Contact Methods Grid -->
|
||||||
|
<div class="grid md:grid-cols-2 gap-6 mb-8 not-prose">
|
||||||
|
<!-- Community Support -->
|
||||||
|
<div class="card bg-primary text-primary-content shadow-lg">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z" />
|
||||||
|
</svg>
|
||||||
|
Community Forums
|
||||||
|
</h2>
|
||||||
|
<p>Get help from our active community of users and developers.</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="https://community.envipath.org/" target="_blank" class="btn btn-secondary">Visit Forums</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Documentation -->
|
||||||
|
<div class="card bg-secondary text-secondary-content shadow-lg">
|
||||||
|
<div class="card-body">
|
||||||
|
<h2 class="card-title">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||||
|
</svg>
|
||||||
|
Documentation
|
||||||
|
</h2>
|
||||||
|
<p>Browse our comprehensive documentation and tutorials.</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="https://wiki.envipath.org/" target="_blank" class="btn btn-accent">Read Docs</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Get Support</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
For the fastest response, we recommend using our community forums where you can:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-6 space-y-2">
|
||||||
|
<li>Ask questions and get answers from the community</li>
|
||||||
|
<li>Report bugs or technical issues</li>
|
||||||
|
<li>Request new features</li>
|
||||||
|
<li>Share your research and findings</li>
|
||||||
|
<li>Find tutorials and how-to guides</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="alert alert-info mb-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">Before Contacting Support</h3>
|
||||||
|
<div class="text-sm">Please check our documentation and search the community forums for existing answers.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Business & Collaboration Inquiries</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
For business inquiries, partnership opportunities, or custom development requests, please reach out
|
||||||
|
through our community platform or LinkedIn.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="card bg-base-200 mb-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">enviPath Ltd.</h3>
|
||||||
|
<p>Biodegradation prediction since 2015</p>
|
||||||
|
<div class="flex gap-4 mt-4">
|
||||||
|
<a href="https://www.linkedin.com/company/envipath/" target="_blank" class="btn btn-outline btn-sm">
|
||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 fill-current mr-2">
|
||||||
|
<path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/>
|
||||||
|
</svg>
|
||||||
|
LinkedIn
|
||||||
|
</a>
|
||||||
|
<a href="https://www.youtube.com/@envipath7231" target="_blank" class="btn btn-outline btn-sm">
|
||||||
|
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-4 h-4 fill-current mr-2">
|
||||||
|
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814z"/>
|
||||||
|
</svg>
|
||||||
|
YouTube
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Report Security Issues</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you discover a security vulnerability, please report it responsibly. Do not post security issues
|
||||||
|
publicly. Instead, please contact us directly through the community forums using a private message
|
||||||
|
to the administrators.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Media & Press</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
For media inquiries, press releases, or interview requests, please reach out through our
|
||||||
|
community platform or LinkedIn.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="divider my-8"></div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Frequently Asked Questions</h2>
|
||||||
|
|
||||||
|
<div class="join join-vertical w-full">
|
||||||
|
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||||
|
<input type="radio" name="faq-accordion" />
|
||||||
|
<div class="collapse-title text-lg font-medium">
|
||||||
|
How do I get started with enviPath?
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<p>Simply visit our homepage and try the prediction tool! For full access to all features, create a free account. Check out our <a href="https://wiki.envipath.org/" target="_blank" class="link link-primary">documentation</a> for detailed guides.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||||
|
<input type="radio" name="faq-accordion" />
|
||||||
|
<div class="collapse-title text-lg font-medium">
|
||||||
|
Is enviPath free to use?
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<p>Yes! enviPath is free for academic research and educational purposes. For commercial use or custom solutions, please contact us for licensing options.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||||
|
<input type="radio" name="faq-accordion" />
|
||||||
|
<div class="collapse-title text-lg font-medium">
|
||||||
|
How do I cite enviPath in my research?
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<p>Please visit our <a href="/cite" class="link link-primary">citation page</a> for detailed information on how to properly cite enviPath in your publications.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="collapse collapse-arrow join-item border border-base-300">
|
||||||
|
<input type="radio" name="faq-accordion" />
|
||||||
|
<div class="collapse-title text-lg font-medium">
|
||||||
|
Can I contribute data to enviPath?
|
||||||
|
</div>
|
||||||
|
<div class="collapse-content">
|
||||||
|
<p>Yes! We welcome contributions from the scientific community. Please visit our <a href="https://community.envipath.org/" target="_blank" class="link link-primary">community forums</a> to learn about the contribution process.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
145
templates/static/cookie_policy.html
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Cookie Policy</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Cookie Policy</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
This Cookie Policy explains how enviPath uses cookies and similar technologies to recognize you when
|
||||||
|
you visit our platform. It explains what these technologies are and why we use them.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">1. What Are Cookies?</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Cookies are small data files that are placed on your computer or mobile device when you visit a website.
|
||||||
|
Cookies are widely used by website owners to make their websites work, or to work more efficiently, as
|
||||||
|
well as to provide reporting information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">2. Why We Use Cookies</h2>
|
||||||
|
<p class="mb-4">We use cookies for several reasons:</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li><strong>Essential Cookies:</strong> Required for the platform to function properly</li>
|
||||||
|
<li><strong>Analytics Cookies:</strong> Help us understand how visitors interact with our platform</li>
|
||||||
|
<li><strong>Functional Cookies:</strong> Enable enhanced functionality and personalization</li>
|
||||||
|
<li><strong>Security Cookies:</strong> Authenticate users and prevent fraudulent use</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">3. Types of Cookies We Use</h2>
|
||||||
|
|
||||||
|
<div class="overflow-x-auto mb-6">
|
||||||
|
<table class="table table-zebra w-full">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Cookie Type</th>
|
||||||
|
<th>Purpose</th>
|
||||||
|
<th>Duration</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Session Cookies</strong></td>
|
||||||
|
<td>Maintain your login state and session data</td>
|
||||||
|
<td>Session</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>CSRF Token</strong></td>
|
||||||
|
<td>Security protection against cross-site request forgery</td>
|
||||||
|
<td>Session</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Matomo Analytics</strong></td>
|
||||||
|
<td>Track usage patterns and improve our services</td>
|
||||||
|
<td>13 months</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>OAuth Tokens</strong></td>
|
||||||
|
<td>Authentication and authorization for API access</td>
|
||||||
|
<td>Varies</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">4. Matomo Analytics</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We use Matomo, an open-source web analytics platform, to collect information about how visitors use enviPath.
|
||||||
|
Matomo uses cookies to collect standard internet log information and visitor behavior patterns. The information
|
||||||
|
generated by cookies about your use of the platform is transmitted to our servers.
|
||||||
|
</p>
|
||||||
|
<p class="mb-4">
|
||||||
|
We analyze this information to:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Understand how users interact with our platform</li>
|
||||||
|
<li>Identify popular features and areas for improvement</li>
|
||||||
|
<li>Detect and diagnose technical issues</li>
|
||||||
|
<li>Generate reports on platform usage</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">5. Third-Party Cookies</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
In addition to our own cookies, we may use various third-party cookies to report usage statistics and
|
||||||
|
provide integrated services:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li><strong>Discourse Community:</strong> For our community forums at community.envipath.org</li>
|
||||||
|
<li><strong>External CDNs:</strong> For loading libraries like jQuery and Font Awesome</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">6. Managing Cookies</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Most web browsers allow you to control cookies through their settings. However, if you limit the ability
|
||||||
|
of websites to set cookies, you may worsen your overall user experience, as some features may not function
|
||||||
|
properly.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-warning mb-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
||||||
|
</svg>
|
||||||
|
<span><strong>Note:</strong> Disabling essential cookies will prevent you from using certain features of enviPath.</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-semibold mt-6 mb-3">Browser Settings</h3>
|
||||||
|
<p class="mb-4">You can manage cookies in your browser settings:</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li><strong>Chrome:</strong> Settings → Privacy and security → Cookies and other site data</li>
|
||||||
|
<li><strong>Firefox:</strong> Options → Privacy & Security → Cookies and Site Data</li>
|
||||||
|
<li><strong>Safari:</strong> Preferences → Privacy → Cookies and website data</li>
|
||||||
|
<li><strong>Edge:</strong> Settings → Cookies and site permissions → Cookies and site data</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">7. Updates to This Policy</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We may update this Cookie Policy from time to time to reflect changes in technology, legislation, or our
|
||||||
|
operations. Please check this page regularly for updates.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">8. Contact Us</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you have questions about our use of cookies, please <a href="/contact" class="link link-primary">contact us</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Last updated: 2025</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
139
templates/static/legal.html
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Legal</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Legal Information</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
Welcome to enviPath's legal information center. Here you can find all our legal documents,
|
||||||
|
policies, and terms that govern the use of our platform.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Legal Documents Grid -->
|
||||||
|
<div class="grid md:grid-cols-2 gap-6 mb-8">
|
||||||
|
<!-- Terms of Use -->
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
Terms of Use
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
Our terms and conditions that govern the use of enviPath services, including
|
||||||
|
licensing, user responsibilities, and platform usage guidelines.
|
||||||
|
</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="/terms" class="btn btn-primary btn-sm">Read Terms</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Privacy Policy -->
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" />
|
||||||
|
</svg>
|
||||||
|
Privacy Policy
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
How we collect, use, and protect your personal information when you use
|
||||||
|
enviPath, including data handling practices and your privacy rights.
|
||||||
|
</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="/privacy" class="btn btn-primary btn-sm">Read Policy</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Cookie Policy -->
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||||
|
</svg>
|
||||||
|
Cookie Policy
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
Information about the cookies and tracking technologies we use on enviPath,
|
||||||
|
including analytics and essential functionality cookies.
|
||||||
|
</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="/cookie-policy" class="btn btn-primary btn-sm">Read Policy</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Citation Guidelines -->
|
||||||
|
<div class="card bg-base-200 shadow-md">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title text-primary">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
Citation Guidelines
|
||||||
|
</h3>
|
||||||
|
<p class="text-sm mb-4">
|
||||||
|
How to properly cite enviPath in your research publications and academic work,
|
||||||
|
including recommended citation formats and acknowledgments.
|
||||||
|
</p>
|
||||||
|
<div class="card-actions justify-end">
|
||||||
|
<a href="/cite" class="btn btn-primary btn-sm">View Guidelines</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Quick Access Section -->
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">Quick Access</h2>
|
||||||
|
<div class="grid md:grid-cols-3 gap-4 mb-6">
|
||||||
|
<a href="/terms" class="btn btn-outline btn-sm w-full">Terms of Use</a>
|
||||||
|
<a href="/privacy" class="btn btn-outline btn-sm w-full">Privacy Policy</a>
|
||||||
|
<a href="/cookie-policy" class="btn btn-outline btn-sm w-full">Cookie Policy</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Important Information -->
|
||||||
|
<div class="alert alert-info mt-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<h3 class="font-bold">Important Notice</h3>
|
||||||
|
<p class="text-sm">
|
||||||
|
By using enviPath, you agree to be bound by our Terms of Use and Privacy Policy.
|
||||||
|
We recommend reviewing these documents regularly as they may be updated from time to time.
|
||||||
|
For questions about our legal policies, please <a href="/contact" class="link link-primary">contact us</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Contact Information -->
|
||||||
|
<div class="card bg-primary text-primary-content mt-8">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">Questions About Our Legal Policies?</h3>
|
||||||
|
<p>If you have any questions or concerns about our legal documents, please don't hesitate to reach out to us.</p>
|
||||||
|
<div class="card-actions justify-end mt-4">
|
||||||
|
<a href="/contact" class="btn btn-secondary">Contact Us</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
@ -1,59 +1,236 @@
|
|||||||
{% extends "static/static_base.html" %}
|
{% extends "static/login_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}enviPath - Sign In{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_styles %}
|
||||||
|
/* Tab styling */ .tab-content { display: none; } .tab-content.active {
|
||||||
|
display: block; } input[type="radio"].tab-radio { display: none; } .tab-label
|
||||||
|
{ cursor: pointer; padding: 0.75rem 1.5rem; border-bottom: 2px solid
|
||||||
|
transparent; transition: all 0.3s ease; } .tab-label:hover { background-color:
|
||||||
|
rgba(0, 0, 0, 0.05); } input[type="radio"].tab-radio:checked + .tab-label {
|
||||||
|
border-bottom-color: #3b82f6; font-weight: 600; }
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if message %}
|
<!-- Tab Navigation -->
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="border-b border-base-300 mb-6">
|
||||||
{{ message }}
|
<div class="flex justify-start">
|
||||||
</div>
|
<input
|
||||||
{% elif success_message %}
|
type="radio"
|
||||||
<div class="alert alert-success" role="alert">
|
name="auth-tab"
|
||||||
{{ success_message }}
|
id="tab-signin"
|
||||||
</div>
|
class="tab-radio"
|
||||||
{% else %}
|
checked
|
||||||
<div class="alert alert-success" role="alert">
|
/>
|
||||||
Kia ora! We are running our closed beta tests at the moment. It would be great to get your help as tester,
|
<label for="tab-signin" class="tab-label">Sign In</label>
|
||||||
you
|
|
||||||
can apply to become tester by registering for this page, just hit the button below. More information on the
|
<input type="radio" name="auth-tab" id="tab-signup" class="tab-radio" />
|
||||||
beta
|
<label for="tab-signup" class="tab-label">Register</label>
|
||||||
test is available in our <a href="https://community.envipath.org/t/apply-to-join-our-closed-beta/95">
|
|
||||||
community
|
|
||||||
form</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="modal-dialog" style="margin:30px auto; z-index:9999;">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="form-horizontal" method="post" action="{% url 'login' %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<fieldset>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="username">Username</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="username" name="username" type="text"
|
|
||||||
class="form-control" placeholder="username" autocomplete="username">
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="passwordinput">Password:</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="passwordinput" name="password" class="form-control"
|
|
||||||
type="password" placeholder="********" autocomplete="current-password">
|
|
||||||
</div>
|
|
||||||
<div class="form-group text-center" style="margin-top:15px;">
|
|
||||||
<a href="{% url 'password_reset' %}">Forgot your password?</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<!-- Sign In Tab -->
|
||||||
<label class="control-label" for="signin"></label>
|
<div id="content-signin" class="tab-content active">
|
||||||
<div class="controls">
|
<form method="post" action="{% url 'login' %}" class="space-y-4">
|
||||||
<button id="signin" name="signin" class="btn btn-success pull-right">Sign In
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="login" value="true" />
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="username">
|
||||||
|
<span class="label-text">Username</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="username"
|
||||||
|
name="username"
|
||||||
|
placeholder="username"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="username"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="passwordinput">
|
||||||
|
<span class="label-text">Password</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="passwordinput"
|
||||||
|
name="password"
|
||||||
|
placeholder="••••••••"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="current-password"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
<a href="{% url 'password_reset' %}" class="link link-primary text-sm"
|
||||||
|
>Forgot password?</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden" name="next" value="{{ next }}" />
|
||||||
|
|
||||||
|
<button type="submit" name="signin" class="btn btn-primary w-full">
|
||||||
|
Sign In
|
||||||
</button>
|
</button>
|
||||||
<a class="btn btn-primary" href="{% url 'register' %}">Create an Account</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="next" value="{{ next }}"/>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Register Tab -->
|
||||||
|
<div id="content-signup" class="tab-content">
|
||||||
|
<div class="alert alert-info mb-4 text-sm">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-6 w-6 shrink-0 stroke-current"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<div class="font-bold">Password Requirements</div>
|
||||||
|
<div class="text-xs mt-1">
|
||||||
|
• 8 to 30 characters<br />
|
||||||
|
• Upper and lower case letters<br />
|
||||||
|
• Digits and special characters (_, -, +)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="post" action="{% url 'login' %}" class="space-y-4">
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="register" value="true" />
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="userid">
|
||||||
|
<span class="label-text">Username</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="userid"
|
||||||
|
name="username"
|
||||||
|
placeholder="username"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="username"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="email">
|
||||||
|
<span class="label-text">Email</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
placeholder="user@envipath.org"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="email"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="password">
|
||||||
|
<span class="label-text">Password</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
placeholder="••••••••"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-control">
|
||||||
|
<label class="label" for="rpassword">
|
||||||
|
<span class="label-text">Repeat Password</span>
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="password"
|
||||||
|
id="rpassword"
|
||||||
|
name="rpassword"
|
||||||
|
placeholder="••••••••"
|
||||||
|
class="input input-bordered w-full"
|
||||||
|
required
|
||||||
|
autocomplete="new-password"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input type="hidden" name="next" value="{{ next }}" />
|
||||||
|
|
||||||
|
<button type="submit" name="confirmsignup" class="btn btn-success w-full">
|
||||||
|
Sign Up
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Why Register Section -->
|
||||||
|
<div class="mt-6 p-4 bg-base-200 rounded-lg">
|
||||||
|
<h3 class="font-semibold mb-2">Why register?</h3>
|
||||||
|
<p class="text-sm mb-2">
|
||||||
|
enviPath is free for academic research and educational purposes.
|
||||||
|
However, we require registration to ensure the security of the platform
|
||||||
|
and to prevent abuse.
|
||||||
|
</p>
|
||||||
|
<p class="text-sm mt-3">
|
||||||
|
Questions? Check our
|
||||||
|
<a
|
||||||
|
href="https://wiki.envipath.org/"
|
||||||
|
target="_blank"
|
||||||
|
class="link link-primary"
|
||||||
|
>documentation</a
|
||||||
|
>
|
||||||
|
or the
|
||||||
|
<a
|
||||||
|
href="https://community.envipath.org/"
|
||||||
|
target="_blank"
|
||||||
|
class="link link-primary"
|
||||||
|
>community forums</a
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_scripts %}
|
||||||
|
<script>
|
||||||
|
// Tab switching functionality
|
||||||
|
document.querySelectorAll('input[name="auth-tab"]').forEach((radio) => {
|
||||||
|
radio.addEventListener("change", function () {
|
||||||
|
// Hide all content
|
||||||
|
document.querySelectorAll(".tab-content").forEach((content) => {
|
||||||
|
content.classList.remove("active");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show selected content
|
||||||
|
const contentId = "content-" + this.id.replace("tab-", "");
|
||||||
|
document.getElementById(contentId).classList.add("active");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check for hash in URL to auto-select tab
|
||||||
|
window.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const hash = window.location.hash.substring(1); // Remove the # symbol
|
||||||
|
if (hash === "signup" || hash === "signin") {
|
||||||
|
const tabRadio = document.getElementById("tab-" + hash);
|
||||||
|
if (tabRadio) {
|
||||||
|
tabRadio.checked = true;
|
||||||
|
// Trigger change event to show correct content
|
||||||
|
tabRadio.dispatchEvent(new Event("change"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|||||||
83
templates/static/login_base.html
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
{% load static %}
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-theme="envipath">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>{% block title %}enviPath{% endblock %}</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="shortcut icon" type="image/png" href="{% static 'images/favicon.ico' %}"/>
|
||||||
|
|
||||||
|
<!-- Tailwind CSS Output -->
|
||||||
|
<link href="{% static 'css/output.css' %}" rel="stylesheet" type="text/css"/>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
{% block extra_styles %}{% endblock %}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="bg-base-100">
|
||||||
|
<div class="flex h-screen">
|
||||||
|
<!-- Left side - Hero Image -->
|
||||||
|
<div class="hidden lg:flex lg:w-1/2 bg-cover bg-center bg-no-repeat items-center justify-center p-12"
|
||||||
|
style="background-image: linear-gradient(135deg, color-mix(in oklab, var(--color-primary) 30%, transparent) 0%, color-mix(in oklab, var(--color-primary-600) 40%, transparent) 100%), url('{% static "/images/hero.png" %}');">
|
||||||
|
<div class="text-left text-white space-y-6">
|
||||||
|
<svg class="h-16 w-auto fill-white" viewBox="0 0 104 26" role="img">
|
||||||
|
<use href='{% static "/images/logo-name.svg" %}#ep-logo-name' />
|
||||||
|
</svg>
|
||||||
|
<p class="text-lg max-w-md mx-auto">
|
||||||
|
Predict and explore microbial biotransformation pathways for environmental contaminants
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right side - Content -->
|
||||||
|
<div class="w-full lg:w-1/2 flex flex-col items-center justify-center p-8 overflow-y-auto">
|
||||||
|
<div class="w-full max-w-md flex-1 flex flex-col justify-center">
|
||||||
|
<!-- Logo for mobile -->
|
||||||
|
<div class="lg:hidden text-center mb-8">
|
||||||
|
<svg class="h-12 w-auto mx-auto fill-current" viewBox="0 0 104 26" role="img">
|
||||||
|
<use href='{% static "/images/logo-name.svg" %}#ep-logo-name' />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Messages -->
|
||||||
|
{% if message %}
|
||||||
|
<div class="alert alert-error mb-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<span>{{ message }}</span>
|
||||||
|
</div>
|
||||||
|
{% elif success_message %}
|
||||||
|
<div class="alert alert-success mb-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<span>{{ success_message }}</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer with legal links - positioned at bottom of right column -->
|
||||||
|
<div class="w-full mt-auto pt-4">
|
||||||
|
<div class="flex justify-center items-center space-x-6 text-sm text-base-content/50">
|
||||||
|
<a href="/legal" class="link link-hover">Legal</a>
|
||||||
|
<span class="text-base-content/30">•</span>
|
||||||
|
<a href="/terms" class="link link-hover">Terms of Use</a>
|
||||||
|
<span class="text-base-content/30">•</span>
|
||||||
|
<a href="/privacy" class="link link-hover">Privacy Policy</a>
|
||||||
|
<span class="text-base-content/30">•</span>
|
||||||
|
<a href="/cookie-policy" class="link link-hover">Cookie Policy</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% block extra_scripts %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -1,5 +1,30 @@
|
|||||||
{% extends "static/static_base.html" %}
|
{% extends "static/login_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}enviPath - Password Reset Complete{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<p>Your password has been reset successfully. <a href="{% url 'login' %}">Login</a></p>
|
<!-- Success Icon -->
|
||||||
|
<div class="flex justify-center mb-6">
|
||||||
|
<div class="rounded-full bg-success/20 p-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 stroke-success" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h2 class="text-3xl font-bold mb-4">Password Reset Complete!</h2>
|
||||||
|
<p class="text-base-content/70 mb-4">
|
||||||
|
Your password has been successfully reset.
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-base-content/60">
|
||||||
|
You can now sign in with your new password.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="space-y-4">
|
||||||
|
<a href="{% url 'login' %}" class="btn btn-primary w-full">Sign In</a>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@ -1,31 +1,94 @@
|
|||||||
{% extends "static/static_base.html" %}
|
{% extends "static/login_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}enviPath - Set New Password{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="modal-dialog" style="margin:30px auto; z-index:9999;">
|
<!-- Title -->
|
||||||
<div class="modal-content">
|
<div class="mb-8">
|
||||||
<div class="modal-body">
|
<h2 class="text-3xl font-bold mb-2">Set New Password</h2>
|
||||||
<h2>Enter new password</h2>
|
<p class="text-base-content/70">Please enter your new password below.</p>
|
||||||
<form method="post">
|
</div>
|
||||||
|
|
||||||
|
<!-- Messages -->
|
||||||
|
{% if validlink %}
|
||||||
|
<!-- Password Requirements Info -->
|
||||||
|
<div class="alert alert-info mb-4 text-sm">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="h-6 w-6 shrink-0 stroke-current">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<div class="font-bold">Password Requirements</div>
|
||||||
|
<div class="text-xs mt-1">
|
||||||
|
• 8 to 30 characters<br>
|
||||||
|
• Upper and lower case letters<br>
|
||||||
|
• Digits and special characters (_, -, +)
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Reset Password Form -->
|
||||||
|
<form method="post" class="space-y-4">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<p>
|
|
||||||
<label for="id_new_password1">New password:</label>
|
|
||||||
<input type="password" class="form-control" name="new_password1" autocomplete="new-password"
|
|
||||||
required=""
|
|
||||||
aria-describedby="id_new_password1_helptext" id="id_new_password1">
|
|
||||||
<span class="helptext" id="id_new_password1_helptext"></span></p>
|
|
||||||
|
|
||||||
{{ form.new_password1.help_text|safe }}
|
<div class="form-control">
|
||||||
|
<label class="label" for="id_new_password1">
|
||||||
|
<span class="label-text">New Password</span>
|
||||||
|
</label>
|
||||||
|
<input type="password" id="id_new_password1" name="new_password1" placeholder="••••••••"
|
||||||
|
class="input input-bordered w-full" required autocomplete="new-password">
|
||||||
|
{% if form.new_password1.help_text %}
|
||||||
|
<label class="label">
|
||||||
|
<span class="label-text-alt text-base-content/60">{{ form.new_password1.help_text }}</span>
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
{% if form.new_password1.errors %}
|
||||||
|
<label class="label">
|
||||||
|
<span class="label-text-alt text-error">{{ form.new_password1.errors|join:", " }}</span>
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<p>
|
<div class="form-control">
|
||||||
<label for="id_new_password2">New password confirmation:</label>
|
<label class="label" for="id_new_password2">
|
||||||
<input type="password" class="form-control" name="new_password2" autocomplete="new-password"
|
<span class="label-text">Confirm New Password</span>
|
||||||
required=""
|
</label>
|
||||||
aria-describedby="id_new_password2_helptext" id="id_new_password2">
|
<input type="password" id="id_new_password2" name="new_password2" placeholder="••••••••"
|
||||||
{{ form.new_password2.help_text|safe }}
|
class="input input-bordered w-full" required autocomplete="new-password">
|
||||||
</p>
|
{% if form.new_password2.help_text %}
|
||||||
<button class="btn btn-primary" type="submit">Reset Password</button>
|
<label class="label">
|
||||||
|
<span class="label-text-alt text-base-content/60">{{ form.new_password2.help_text }}</span>
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
{% if form.new_password2.errors %}
|
||||||
|
<label class="label">
|
||||||
|
<span class="label-text-alt text-error">{{ form.new_password2.errors|join:", " }}</span>
|
||||||
|
</label>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-full">Reset Password</button>
|
||||||
</form>
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<!-- Invalid Link -->
|
||||||
|
<div class="alert alert-error mb-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 shrink-0 stroke-current" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||||
|
</svg>
|
||||||
|
<div>
|
||||||
|
<div class="font-bold">Invalid Reset Link</div>
|
||||||
|
<div class="text-sm">This password reset link is invalid or has expired.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="space-y-4">
|
||||||
|
<a href="{% url 'password_reset' %}" class="btn btn-primary w-full">Request New Reset Link</a>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Back to Sign In -->
|
||||||
|
<div class="mt-6 text-center text-sm text-base-content/70">
|
||||||
|
<p>Remember your password?
|
||||||
|
<a href="{% url 'login' %}" class="link link-primary">Sign in</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -1,7 +1,30 @@
|
|||||||
{% extends "static/static_base.html" %}
|
{% extends "static/login_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}enviPath - Reset Email Sent{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="alert alert-success" role="alert">
|
<!-- Success Icon -->
|
||||||
An email has been sent with instructions to reset your password.
|
<div class="flex justify-center mb-6">
|
||||||
|
<div class="rounded-full bg-success/20 p-6">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-16 w-16 stroke-success" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 19v-8.93a2 2 0 01.89-1.664l7-4.666a2 2 0 012.22 0l7 4.666A2 2 0 0121 10.07V19M3 19a2 2 0 002 2h14a2 2 0 002-2M3 19l6.75-4.5M21 19l-6.75-4.5M3 10l6.75 4.5M21 10l-6.75 4.5m0 0l-1.14.76a2 2 0 01-2.22 0l-1.14-.76" />
|
||||||
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
<h2 class="text-3xl font-bold mb-4">Check Your Email</h2>
|
||||||
|
<p class="text-base-content/70 mb-4">
|
||||||
|
We've sent an email with instructions to reset your password.
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-base-content/60">
|
||||||
|
If you don't see it in your inbox, please check your spam folder.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="space-y-4">
|
||||||
|
<a href="{% url 'login' %}" class="btn btn-primary w-full">Back to Sign In</a>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -1,23 +1,33 @@
|
|||||||
{% extends "static/static_base.html" %}
|
{% extends "static/login_base.html" %}
|
||||||
|
|
||||||
|
{% block title %}enviPath - Reset Password{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="modal-dialog" style="margin:30px auto; z-index:9999;">
|
<!-- Title -->
|
||||||
<div class="modal-content">
|
<div class="mb-8">
|
||||||
<div class="modal-body">
|
<h2 class="text-3xl font-bold mb-2">Reset Password</h2>
|
||||||
<form method="post">
|
<p class="text-base-content/70">Enter your email address and we'll send you a link to reset your password.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Reset Password Form -->
|
||||||
|
<form method="post" class="space-y-4">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<label class="control-label" for="username">Email:</label>
|
|
||||||
<input type="email" name="email" class="form-control" maxlength="254"
|
<div class="form-control">
|
||||||
required="" id="id_email">
|
<label class="label" for="id_email">
|
||||||
<div class="control-group">
|
<span class="label-text">Email</span>
|
||||||
<label class="control-label" for="signin"></label>
|
</label>
|
||||||
<div class="controls">
|
<input type="email" id="id_email" name="email" placeholder="user@envipath.org"
|
||||||
<button id="signin" name="signin" type="submit" class="btn btn-success">Send
|
class="input input-bordered w-full" required autocomplete="email">
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary w-full">Send Reset Link</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Back to Sign In -->
|
||||||
|
<div class="mt-6 text-center text-sm text-base-content/70">
|
||||||
|
<p>Remember your password?
|
||||||
|
<a href="{% url 'login' %}" class="link link-primary">Sign in</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
138
templates/static/privacy_policy.html
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Privacy Policy</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Privacy Policy</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
enviPath is committed to protecting your privacy. This Privacy Policy explains how we collect, use,
|
||||||
|
disclose, and safeguard your information when you use our platform.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">1. Information We Collect</h2>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-semibold mt-6 mb-3">Personal Information</h3>
|
||||||
|
<p class="mb-4">
|
||||||
|
We may collect personal information that you voluntarily provide when you:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Register for an account</li>
|
||||||
|
<li>Use our prediction services</li>
|
||||||
|
<li>Submit data or pathways</li>
|
||||||
|
<li>Contact our support team</li>
|
||||||
|
<li>Participate in our community forums</li>
|
||||||
|
</ul>
|
||||||
|
<p class="mb-4">
|
||||||
|
This information may include: name, email address, institution affiliation, and research interests.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 class="text-xl font-semibold mt-6 mb-3">Usage Data</h3>
|
||||||
|
<p class="mb-4">
|
||||||
|
We automatically collect certain information when you visit, use, or navigate the platform. This includes:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>IP address and browser type</li>
|
||||||
|
<li>Pages visited and time spent</li>
|
||||||
|
<li>Referring/exit pages</li>
|
||||||
|
<li>Prediction queries and results</li>
|
||||||
|
<li>Operating system and device information</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">2. How We Use Your Information</h2>
|
||||||
|
<p class="mb-4">We use the information we collect to:</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Provide, operate, and maintain our services</li>
|
||||||
|
<li>Improve and personalize user experience</li>
|
||||||
|
<li>Understand and analyze usage patterns</li>
|
||||||
|
<li>Develop new features and services</li>
|
||||||
|
<li>Communicate with you about updates and support</li>
|
||||||
|
<li>Prevent fraudulent activities and ensure security</li>
|
||||||
|
<li>Conduct research and analysis for scientific advancement</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">3. Data Sharing and Disclosure</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We do not sell your personal information. We may share your information in the following situations:
|
||||||
|
</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li><strong>Academic Research:</strong> Anonymized usage data may be used for research purposes</li>
|
||||||
|
<li><strong>Legal Requirements:</strong> When required by law or to protect our rights</li>
|
||||||
|
<li><strong>Service Providers:</strong> With trusted third parties who assist in operating our platform</li>
|
||||||
|
<li><strong>Public Data:</strong> Data you explicitly mark as public will be accessible to other users</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">4. Data Retention</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We retain your personal information for as long as necessary to provide our services and fulfill the
|
||||||
|
purposes outlined in this policy. You may request deletion of your account and associated data at any time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">5. Analytics and Cookies</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We use Matomo analytics to understand how users interact with our platform. This helps us improve our
|
||||||
|
services. For more details, see our <a href="/cookie-policy" class="link link-primary">Cookie Policy</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">6. Data Security</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We implement appropriate technical and organizational security measures to protect your personal information.
|
||||||
|
However, no electronic transmission or storage is 100% secure, and we cannot guarantee absolute security.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">7. Your Rights</h2>
|
||||||
|
<p class="mb-4">Depending on your location, you may have the following rights:</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Access to your personal data</li>
|
||||||
|
<li>Correction of inaccurate data</li>
|
||||||
|
<li>Deletion of your data</li>
|
||||||
|
<li>Restriction of processing</li>
|
||||||
|
<li>Data portability</li>
|
||||||
|
<li>Objection to processing</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">8. Third-Party Services</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Our platform may contain links to third-party websites or integrate with external services
|
||||||
|
(e.g., Discourse community forums). We are not responsible for the privacy practices of these third parties.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">9. Children's Privacy</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
enviPath is not intended for users under the age of 16. We do not knowingly collect personal information
|
||||||
|
from children. If you believe we have collected information from a child, please contact us.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">10. Changes to This Policy</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
We may update this Privacy Policy from time to time. We will notify you of any changes by posting the
|
||||||
|
new policy on this page and updating the "Last updated" date.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">11. Contact Us</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you have questions or concerns about this Privacy Policy, please
|
||||||
|
<a href="/contact" class="link link-primary">contact us</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Last updated: 2025</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
@ -1,65 +0,0 @@
|
|||||||
{% extends "static/static_base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% if message %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
{{ message }}
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<div class="alert alert-success" role="alert">
|
|
||||||
Kia ora! We are running our closed beta tests at the moment. It would be great to get your help as tester,
|
|
||||||
you
|
|
||||||
can apply to become tester by registering for this page, just hit the button below. More information on the
|
|
||||||
beta
|
|
||||||
test is available in our <a href="https://community.envipath.org/t/apply-to-join-our-closed-beta/95">
|
|
||||||
community
|
|
||||||
form</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="modal-dialog" style="margin:30px auto; z-index:9999;">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-body">
|
|
||||||
<form class="form-horizontal" method="post" action="{% url 'register' %}">
|
|
||||||
{% csrf_token %}
|
|
||||||
<fieldset>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="username">Username</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="username" name="username" type="text"
|
|
||||||
class="form-control" placeholder="username" autocomplete="username">
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="email">Email</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="email" name="email" type="text"
|
|
||||||
class="form-control" placeholder="email" autocomplete="email">
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="passwordinput">Password:</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="passwordinput" name="password" class="form-control"
|
|
||||||
type="password" placeholder="********" autocomplete="current-password">
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="passwordinput2">Password:</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input required id="passwordinput2" name="rpassword" class="form-control"
|
|
||||||
type="password" placeholder="********" autocomplete="current-password">
|
|
||||||
</div>
|
|
||||||
<div class="form-group text-center" style="margin-top:15px;">
|
|
||||||
<a href="{% url 'password_reset' %}">Forgot your password?</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="signin"></label>
|
|
||||||
<div class="controls">
|
|
||||||
<button id="signin" name="signin" class="btn btn-success pull-right">Sign Up
|
|
||||||
</button>
|
|
||||||
<a class="btn btn-primary" href="{% url 'login' %}">Already have an Account?</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input type="hidden" name="next" value="{{ next }}"/>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
96
templates/static/terms_of_use.html
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{% extends "framework_modern.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block main_content %}
|
||||||
|
<div class="max-w-4xl mx-auto px-4 py-8">
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
<div class="text-sm breadcrumbs mb-4">
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Home</a></li>
|
||||||
|
<li>Terms of Use</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="bg-base-100 shadow-xl rounded-lg p-8">
|
||||||
|
<h1 class="text-4xl font-bold mb-6">Terms of Use</h1>
|
||||||
|
|
||||||
|
<div class="prose max-w-none">
|
||||||
|
<p class="text-lg mb-6">
|
||||||
|
Welcome to enviPath. By accessing and using this platform, you agree to be bound by these terms of use.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">1. Acceptance of Terms</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
By accessing and using enviPath, you accept and agree to be bound by the terms and provision of this agreement.
|
||||||
|
If you do not agree to these terms, please do not use our services.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">2. Use License</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Permission is granted to temporarily access the materials (information or software) on enviPath for personal,
|
||||||
|
non-commercial research and educational use only. This is the grant of a license, not a transfer of title.
|
||||||
|
</p>
|
||||||
|
<p class="mb-4">Under this license you may not:</p>
|
||||||
|
<ul class="list-disc list-inside mb-4 space-y-2">
|
||||||
|
<li>Modify or copy the materials</li>
|
||||||
|
<li>Use the materials for any commercial purpose</li>
|
||||||
|
<li>Attempt to decompile or reverse engineer any software contained on enviPath</li>
|
||||||
|
<li>Remove any copyright or other proprietary notations from the materials</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">3. Data and Content</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
Users may submit, upload, or otherwise make available data and content to enviPath. By doing so, you grant
|
||||||
|
enviPath a license to use, modify, publicly perform, publicly display, reproduce, and distribute such content.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">4. Disclaimer</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
The materials on enviPath are provided on an 'as is' basis. enviPath makes no warranties, expressed or implied,
|
||||||
|
and hereby disclaims and negates all other warranties including, without limitation, implied warranties or
|
||||||
|
conditions of merchantability, fitness for a particular purpose, or non-infringement of intellectual property.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">5. Limitations</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
In no event shall enviPath or its suppliers be liable for any damages (including, without limitation, damages
|
||||||
|
for loss of data or profit, or due to business interruption) arising out of the use or inability to use the
|
||||||
|
materials on enviPath.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">6. Academic Use and Citations</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you use enviPath in your research, we request that you cite our work appropriately. Please visit our
|
||||||
|
<a href="/cite" class="link link-primary">citation page</a> for details.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">7. License Information</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
For detailed license information about enviPath data and software, please refer to the
|
||||||
|
<a href="https://community.envipath.org/t/envipath-license/109" target="_blank" class="link link-primary">
|
||||||
|
enviPath License documentation
|
||||||
|
</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">8. Modifications</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
enviPath may revise these terms of use at any time without notice. By using this platform, you are agreeing
|
||||||
|
to be bound by the then current version of these terms of use.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 class="text-2xl font-semibold mt-8 mb-4">9. Contact Information</h2>
|
||||||
|
<p class="mb-4">
|
||||||
|
If you have any questions about these Terms of Use, please <a href="/contact" class="link link-primary">contact us</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="alert alert-info mt-8">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="stroke-current shrink-0 w-6 h-6">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||||
|
</svg>
|
||||||
|
<span>Last updated: 2025</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock main_content %}
|
||||||
@ -4,7 +4,14 @@ from django.test import TestCase, tag
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from epdb.logic import UserManager
|
from epdb.logic import UserManager
|
||||||
from epdb.models import Package, UserPackagePermission, Permission, GroupPackagePermission, Group
|
from epdb.models import (
|
||||||
|
Package,
|
||||||
|
UserPackagePermission,
|
||||||
|
Permission,
|
||||||
|
GroupPackagePermission,
|
||||||
|
Group,
|
||||||
|
License,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class PackageViewTest(TestCase):
|
class PackageViewTest(TestCase):
|
||||||
@ -29,6 +36,15 @@ class PackageViewTest(TestCase):
|
|||||||
add_to_group=True,
|
add_to_group=True,
|
||||||
is_active=True,
|
is_active=True,
|
||||||
)
|
)
|
||||||
|
# Create the default license set.
|
||||||
|
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
|
||||||
|
for cc_string in cc_strings:
|
||||||
|
if not License.objects.filter(cc_string=cc_string).exists():
|
||||||
|
new_license = License()
|
||||||
|
new_license.cc_string = cc_string
|
||||||
|
new_license.link = f"https://creativecommons.org/licenses/{cc_string}/4.0/"
|
||||||
|
new_license.image_link = f"https://licensebuttons.net/l/{cc_string}/4.0/88x31.png"
|
||||||
|
new_license.save()
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.client.force_login(self.user1)
|
self.client.force_login(self.user1)
|
||||||
@ -188,7 +204,28 @@ class PackageViewTest(TestCase):
|
|||||||
self.client.post(package_url, {"license": "no-license"})
|
self.client.post(package_url, {"license": "no-license"})
|
||||||
|
|
||||||
self.assertIsNone(p.license)
|
self.assertIsNone(p.license)
|
||||||
# TODO test others
|
|
||||||
|
# Test other possible licenses
|
||||||
|
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
|
||||||
|
for cc_string in cc_strings:
|
||||||
|
self.client.post(package_url, {"license": cc_string})
|
||||||
|
# Without this, the instance of p doesn't have the license. However, the one retrieved with get does
|
||||||
|
p = Package.objects.get(url=package_url)
|
||||||
|
self.assertEqual(
|
||||||
|
p.license.link, f"https://creativecommons.org/licenses/{cc_string}/4.0/"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test again to ensure that Licenses are reused
|
||||||
|
cc_strings = ["by", "by-nc", "by-nc-nd", "by-nc-sa", "by-nd", "by-sa"]
|
||||||
|
for cc_string in cc_strings:
|
||||||
|
self.client.post(package_url, {"license": cc_string})
|
||||||
|
# Without this, the instance of p doesn't have the license. However, the one retrieved with get does
|
||||||
|
p = Package.objects.get(url=package_url)
|
||||||
|
self.assertEqual(
|
||||||
|
p.license.link, f"https://creativecommons.org/licenses/{cc_string}/4.0/"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(License.objects.count(), len(cc_strings))
|
||||||
|
|
||||||
def test_delete_package(self):
|
def test_delete_package(self):
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
|
|||||||
@ -714,6 +714,7 @@ class PackageImporter:
|
|||||||
license_obj, _ = License.objects.get_or_create(
|
license_obj, _ = License.objects.get_or_create(
|
||||||
name=license_data["name"],
|
name=license_data["name"],
|
||||||
defaults={
|
defaults={
|
||||||
|
"cc_string": license_data.get("cc_string", ""),
|
||||||
"link": license_data.get("link", ""),
|
"link": license_data.get("link", ""),
|
||||||
"image_link": license_data.get("image_link", ""),
|
"image_link": license_data.get("image_link", ""),
|
||||||
},
|
},
|
||||||
|
|||||||
302
uv.lock
generated
@ -17,7 +17,7 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aiohttp"
|
name = "aiohttp"
|
||||||
version = "3.13.0"
|
version = "3.13.2"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "aiohappyeyeballs" },
|
{ name = "aiohappyeyeballs" },
|
||||||
@ -28,76 +28,76 @@ dependencies = [
|
|||||||
{ name = "propcache" },
|
{ name = "propcache" },
|
||||||
{ name = "yarl" },
|
{ name = "yarl" },
|
||||||
]
|
]
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/62/f1/8515650ac3121a9e55c7b217c60e7fae3e0134b5acfe65691781b5356929/aiohttp-3.13.0.tar.gz", hash = "sha256:378dbc57dd8cf341ce243f13fa1fa5394d68e2e02c15cd5f28eae35a70ec7f67", size = 7832348, upload-time = "2025-10-06T19:58:48.089Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/1c/ce/3b83ebba6b3207a7135e5fcaba49706f8a4b6008153b4e30540c982fae26/aiohttp-3.13.2.tar.gz", hash = "sha256:40176a52c186aefef6eb3cad2cdd30cd06e3afbe88fe8ab2af9c0b90f228daca", size = 7837994, upload-time = "2025-10-28T20:59:39.937Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/95/7e8bdfa6e79099a086d59d42589492f1fe9d29aae3cefb58b676015ce278/aiohttp-3.13.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1c272a9a18a5ecc48a7101882230046b83023bb2a662050ecb9bfcb28d9ab53a", size = 735585, upload-time = "2025-10-06T19:55:43.401Z" },
|
{ url = "https://files.pythonhosted.org/packages/29/9b/01f00e9856d0a73260e86dd8ed0c2234a466c5c1712ce1c281548df39777/aiohttp-3.13.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b1e56bab2e12b2b9ed300218c351ee2a3d8c8fdab5b1ec6193e11a817767e47b", size = 737623, upload-time = "2025-10-28T20:56:30.797Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/20/2f1d3ee06ee94eafe516810705219bff234d09f135d6951661661d5595ae/aiohttp-3.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:97891a23d7fd4e1afe9c2f4473e04595e4acb18e4733b910b6577b74e7e21985", size = 490613, upload-time = "2025-10-06T19:55:45.237Z" },
|
{ url = "https://files.pythonhosted.org/packages/5a/1b/4be39c445e2b2bd0aab4ba736deb649fabf14f6757f405f0c9685019b9e9/aiohttp-3.13.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:364e25edaabd3d37b1db1f0cbcee8c73c9a3727bfa262b83e5e4cf3489a2a9dc", size = 492664, upload-time = "2025-10-28T20:56:32.708Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/74/15/ab8600ef6dc1dcd599009a81acfed2ea407037e654d32e47e344e0b08c34/aiohttp-3.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:475bd56492ce5f4cffe32b5533c6533ee0c406d1d0e6924879f83adcf51da0ae", size = 489750, upload-time = "2025-10-06T19:55:46.937Z" },
|
{ url = "https://files.pythonhosted.org/packages/28/66/d35dcfea8050e131cdd731dff36434390479b4045a8d0b9d7111b0a968f1/aiohttp-3.13.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c5c94825f744694c4b8db20b71dba9a257cd2ba8e010a803042123f3a25d50d7", size = 491808, upload-time = "2025-10-28T20:56:34.57Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/59/752640c2b86ca987fe5703a01733b00d375e6cd2392bc7574489934e64e5/aiohttp-3.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c32ada0abb4bc94c30be2b681c42f058ab104d048da6f0148280a51ce98add8c", size = 1736812, upload-time = "2025-10-06T19:55:48.917Z" },
|
{ url = "https://files.pythonhosted.org/packages/00/29/8e4609b93e10a853b65f8291e64985de66d4f5848c5637cddc70e98f01f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba2715d842ffa787be87cbfce150d5e88c87a98e0b62e0f5aa489169a393dbbb", size = 1738863, upload-time = "2025-10-28T20:56:36.377Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/c6/dd6b86ddb852a7fdbcdc7a45b6bdc80178aef713c08279afcaee7a5a9f07/aiohttp-3.13.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4af1f8877ca46ecdd0bc0d4a6b66d4b2bddc84a79e2e8366bc0d5308e76bceb8", size = 1698535, upload-time = "2025-10-06T19:55:50.75Z" },
|
{ url = "https://files.pythonhosted.org/packages/9d/fa/4ebdf4adcc0def75ced1a0d2d227577cd7b1b85beb7edad85fcc87693c75/aiohttp-3.13.2-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:585542825c4bc662221fb257889e011a5aa00f1ae4d75d1d246a5225289183e3", size = 1700586, upload-time = "2025-10-28T20:56:38.034Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/e2/27c92d205b9e8cee7661670e8e9f187931b71e26d42796b153d2a0ba6949/aiohttp-3.13.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e04ab827ec4f775817736b20cdc8350f40327f9b598dec4e18c9ffdcbea88a93", size = 1766573, upload-time = "2025-10-06T19:55:53.106Z" },
|
{ url = "https://files.pythonhosted.org/packages/da/04/73f5f02ff348a3558763ff6abe99c223381b0bace05cd4530a0258e52597/aiohttp-3.13.2-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:39d02cb6025fe1aabca329c5632f48c9532a3dabccd859e7e2f110668972331f", size = 1768625, upload-time = "2025-10-28T20:56:39.75Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/6a/1fc1ad71d130a30f7a207d8d958a41224c29b834463b5185efb2dbff6ad4/aiohttp-3.13.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a6d9487b9471ec36b0faedf52228cd732e89be0a2bbd649af890b5e2ce422353", size = 1865229, upload-time = "2025-10-06T19:55:55.01Z" },
|
{ url = "https://files.pythonhosted.org/packages/f8/49/a825b79ffec124317265ca7d2344a86bcffeb960743487cb11988ffb3494/aiohttp-3.13.2-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e67446b19e014d37342f7195f592a2a948141d15a312fe0e700c2fd2f03124f6", size = 1867281, upload-time = "2025-10-28T20:56:41.471Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/14/51/d0c1701a79fcb0109cff5304da16226581569b89a282d8e7f1549a7e3ec0/aiohttp-3.13.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e66c57416352f36bf98f6641ddadd47c93740a22af7150d3e9a1ef6e983f9a8", size = 1750379, upload-time = "2025-10-06T19:55:57.219Z" },
|
{ url = "https://files.pythonhosted.org/packages/b9/48/adf56e05f81eac31edcfae45c90928f4ad50ef2e3ea72cb8376162a368f8/aiohttp-3.13.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4356474ad6333e41ccefd39eae869ba15a6c5299c9c01dfdcfdd5c107be4363e", size = 1752431, upload-time = "2025-10-28T20:56:43.162Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/3d/2ec4b934f85856de1c0c18e90adc8902adadbfac2b3c0b831bfeb7214fc8/aiohttp-3.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:469167d5372f5bb3aedff4fc53035d593884fff2617a75317740e885acd48b04", size = 1560798, upload-time = "2025-10-06T19:55:58.888Z" },
|
{ url = "https://files.pythonhosted.org/packages/30/ab/593855356eead019a74e862f21523db09c27f12fd24af72dbc3555b9bfd9/aiohttp-3.13.2-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:eeacf451c99b4525f700f078becff32c32ec327b10dcf31306a8a52d78166de7", size = 1562846, upload-time = "2025-10-28T20:56:44.85Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/38/56/e23d9c3e13006e599fdce3851517c70279e177871e3e567d22cf3baf5d6c/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a9f3546b503975a69b547c9fd1582cad10ede1ce6f3e313a2f547c73a3d7814f", size = 1697552, upload-time = "2025-10-06T19:56:01.172Z" },
|
{ url = "https://files.pythonhosted.org/packages/39/0f/9f3d32271aa8dc35036e9668e31870a9d3b9542dd6b3e2c8a30931cb27ae/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d8a9b889aeabd7a4e9af0b7f4ab5ad94d42e7ff679aaec6d0db21e3b639ad58d", size = 1699606, upload-time = "2025-10-28T20:56:46.519Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/56/cb/caa32c2ccaeca0a3dc39129079fd2ad02f9406c3a5f7924340435b87d4cd/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:6b4174fcec98601f0cfdf308ee29a6ae53c55f14359e848dab4e94009112ee7d", size = 1718609, upload-time = "2025-10-06T19:56:03.102Z" },
|
{ url = "https://files.pythonhosted.org/packages/2c/3c/52d2658c5699b6ef7692a3f7128b2d2d4d9775f2a68093f74bca06cf01e1/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:fa89cb11bc71a63b69568d5b8a25c3ca25b6d54c15f907ca1c130d72f320b76b", size = 1720663, upload-time = "2025-10-28T20:56:48.528Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/c0/5911856fef9e40fd1ccbb8c54a90116875d5753a92c1cac66ce2059b390d/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a533873a7a4ec2270fb362ee5a0d3b98752e4e1dc9042b257cd54545a96bd8ed", size = 1735887, upload-time = "2025-10-06T19:56:04.841Z" },
|
{ url = "https://files.pythonhosted.org/packages/9b/d4/8f8f3ff1fb7fb9e3f04fcad4e89d8a1cd8fc7d05de67e3de5b15b33008ff/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8aa7c807df234f693fed0ecd507192fc97692e61fee5702cdc11155d2e5cadc8", size = 1737939, upload-time = "2025-10-28T20:56:50.77Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0e/48/8d6f4757a24c02f0a454c043556593a00645d10583859f7156db44d8b7d3/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:ce887c5e54411d607ee0959cac15bb31d506d86a9bcaddf0b7e9d63325a7a802", size = 1553079, upload-time = "2025-10-06T19:56:07.197Z" },
|
{ url = "https://files.pythonhosted.org/packages/03/d3/ddd348f8a27a634daae39a1b8e291ff19c77867af438af844bf8b7e3231b/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:9eb3e33fdbe43f88c3c75fa608c25e7c47bbd80f48d012763cb67c47f39a7e16", size = 1555132, upload-time = "2025-10-28T20:56:52.568Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/39/fa/e82c9445e40b50e46770702b5b6ca2f767966d53e1a5eef03583ceac6df6/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d871f6a30d43e32fc9252dc7b9febe1a042b3ff3908aa83868d7cf7c9579a59b", size = 1762750, upload-time = "2025-10-06T19:56:09.376Z" },
|
{ url = "https://files.pythonhosted.org/packages/39/b8/46790692dc46218406f94374903ba47552f2f9f90dad554eed61bfb7b64c/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9434bc0d80076138ea986833156c5a48c9c7a8abb0c96039ddbb4afc93184169", size = 1764802, upload-time = "2025-10-28T20:56:54.292Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3d/e6/9d30554e7f1e700bfeae4ab6b153d5dc7441606a9ec5e929288fa93a1477/aiohttp-3.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:222c828243b4789d79a706a876910f656fad4381661691220ba57b2ab4547865", size = 1717461, upload-time = "2025-10-06T19:56:11.551Z" },
|
{ url = "https://files.pythonhosted.org/packages/ba/e4/19ce547b58ab2a385e5f0b8aa3db38674785085abcf79b6e0edd1632b12f/aiohttp-3.13.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ff15c147b2ad66da1f2cbb0622313f2242d8e6e8f9b79b5206c84523a4473248", size = 1719512, upload-time = "2025-10-28T20:56:56.428Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1f/e5/29cca547990a59ea54f0674fc01de98519fc628cfceeab6175711750eca7/aiohttp-3.13.0-cp312-cp312-win32.whl", hash = "sha256:682d2e434ff2f1108314ff7f056ce44e457f12dbed0249b24e106e385cf154b9", size = 424633, upload-time = "2025-10-06T19:56:13.316Z" },
|
{ url = "https://files.pythonhosted.org/packages/70/30/6355a737fed29dcb6dfdd48682d5790cb5eab050f7b4e01f49b121d3acad/aiohttp-3.13.2-cp312-cp312-win32.whl", hash = "sha256:27e569eb9d9e95dbd55c0fc3ec3a9335defbf1d8bc1d20171a49f3c4c607b93e", size = 426690, upload-time = "2025-10-28T20:56:58.736Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/68/46dd042d7bc62eab30bafdb8569f55ef125c3a88bb174270324224f8df56/aiohttp-3.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:0a2be20eb23888df130214b91c262a90e2de1553d6fb7de9e9010cec994c0ff2", size = 451401, upload-time = "2025-10-06T19:56:15.188Z" },
|
{ url = "https://files.pythonhosted.org/packages/0a/0d/b10ac09069973d112de6ef980c1f6bb31cb7dcd0bc363acbdad58f927873/aiohttp-3.13.2-cp312-cp312-win_amd64.whl", hash = "sha256:8709a0f05d59a71f33fd05c17fc11fcb8c30140506e13c2f5e8ee1b8964e1b45", size = 453465, upload-time = "2025-10-28T20:57:00.795Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/2c/ac53efdc9c10e41399acc2395af98f835b86d0141d5c3820857eb9f6a14a/aiohttp-3.13.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:00243e51f16f6ec0fb021659d4af92f675f3cf9f9b39efd142aa3ad641d8d1e6", size = 730090, upload-time = "2025-10-06T19:56:16.858Z" },
|
{ url = "https://files.pythonhosted.org/packages/bf/78/7e90ca79e5aa39f9694dcfd74f4720782d3c6828113bb1f3197f7e7c4a56/aiohttp-3.13.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7519bdc7dfc1940d201651b52bf5e03f5503bda45ad6eacf64dda98be5b2b6be", size = 732139, upload-time = "2025-10-28T20:57:02.455Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/13/18/1ac95683e1c1d48ef4503965c96f5401618a04c139edae12e200392daae8/aiohttp-3.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:059978d2fddc462e9211362cbc8446747ecd930537fa559d3d25c256f032ff54", size = 488041, upload-time = "2025-10-06T19:56:18.659Z" },
|
{ url = "https://files.pythonhosted.org/packages/db/ed/1f59215ab6853fbaa5c8495fa6cbc39edfc93553426152b75d82a5f32b76/aiohttp-3.13.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:088912a78b4d4f547a1f19c099d5a506df17eacec3c6f4375e2831ec1d995742", size = 490082, upload-time = "2025-10-28T20:57:04.784Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/79/ef0d477c771a642d1a881b92d226314c43d3c74bc674c93e12e679397a97/aiohttp-3.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:564b36512a7da3b386143c611867e3f7cfb249300a1bf60889bd9985da67ab77", size = 486989, upload-time = "2025-10-06T19:56:20.371Z" },
|
{ url = "https://files.pythonhosted.org/packages/68/7b/fe0fe0f5e05e13629d893c760465173a15ad0039c0a5b0d0040995c8075e/aiohttp-3.13.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5276807b9de9092af38ed23ce120539ab0ac955547b38563a9ba4f5b07b95293", size = 489035, upload-time = "2025-10-28T20:57:06.894Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/37/b4/0e440481a0e77a551d6c5dcab5d11f1ff6b2b2ddb8dedc24f54f5caad732/aiohttp-3.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4aa995b9156ae499393d949a456a7ab0b994a8241a96db73a3b73c7a090eff6a", size = 1718331, upload-time = "2025-10-06T19:56:22.188Z" },
|
{ url = "https://files.pythonhosted.org/packages/d2/04/db5279e38471b7ac801d7d36a57d1230feeee130bbe2a74f72731b23c2b1/aiohttp-3.13.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1237c1375eaef0db4dcd7c2559f42e8af7b87ea7d295b118c60c36a6e61cb811", size = 1720387, upload-time = "2025-10-28T20:57:08.685Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e6/59/76c421cc4a75bb1aceadb92f20ee6f05a990aa6960c64b59e8e0d340e3f5/aiohttp-3.13.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:55ca0e95a3905f62f00900255ed807c580775174252999286f283e646d675a49", size = 1686263, upload-time = "2025-10-06T19:56:24.393Z" },
|
{ url = "https://files.pythonhosted.org/packages/31/07/8ea4326bd7dae2bd59828f69d7fdc6e04523caa55e4a70f4a8725a7e4ed2/aiohttp-3.13.2-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:96581619c57419c3d7d78703d5b78c1e5e5fc0172d60f555bdebaced82ded19a", size = 1688314, upload-time = "2025-10-28T20:57:10.693Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/ac/5095f12a79c7775f402cfc3e83651b6e0a92ade10ddf7f2c78c4fed79f71/aiohttp-3.13.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:49ce7525853a981fc35d380aa2353536a01a9ec1b30979ea4e35966316cace7e", size = 1754265, upload-time = "2025-10-06T19:56:26.365Z" },
|
{ url = "https://files.pythonhosted.org/packages/48/ab/3d98007b5b87ffd519d065225438cc3b668b2f245572a8cb53da5dd2b1bc/aiohttp-3.13.2-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2713a95b47374169409d18103366de1050fe0ea73db358fc7a7acb2880422d4", size = 1756317, upload-time = "2025-10-28T20:57:12.563Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/d7/a48e4989bd76cc70600c505bbdd0d90ca1ad7f9053eceeb9dbcf9345a9ec/aiohttp-3.13.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2117be9883501eaf95503bd313eb4c7a23d567edd44014ba15835a1e9ec6d852", size = 1856486, upload-time = "2025-10-06T19:56:28.438Z" },
|
{ url = "https://files.pythonhosted.org/packages/97/3d/801ca172b3d857fafb7b50c7c03f91b72b867a13abca982ed6b3081774ef/aiohttp-3.13.2-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:228a1cd556b3caca590e9511a89444925da87d35219a49ab5da0c36d2d943a6a", size = 1858539, upload-time = "2025-10-28T20:57:14.623Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1e/02/45b388b49e37933f316e1fb39c0de6fb1d77384b0c8f4cf6af5f2cbe3ea6/aiohttp-3.13.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d169c47e40c911f728439da853b6fd06da83761012e6e76f11cb62cddae7282b", size = 1737545, upload-time = "2025-10-06T19:56:30.688Z" },
|
{ url = "https://files.pythonhosted.org/packages/f7/0d/4764669bdf47bd472899b3d3db91fffbe925c8e3038ec591a2fd2ad6a14d/aiohttp-3.13.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ac6cde5fba8d7d8c6ac963dbb0256a9854e9fafff52fbcc58fdf819357892c3e", size = 1739597, upload-time = "2025-10-28T20:57:16.399Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6c/a7/4fde058f1605c34a219348a83a99f14724cc64e68a42480fc03cf40f9ea3/aiohttp-3.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:703ad3f742fc81e543638a7bebddd35acadaa0004a5e00535e795f4b6f2c25ca", size = 1552958, upload-time = "2025-10-06T19:56:32.528Z" },
|
{ url = "https://files.pythonhosted.org/packages/c4/52/7bd3c6693da58ba16e657eb904a5b6decfc48ecd06e9ac098591653b1566/aiohttp-3.13.2-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f2bef8237544f4e42878c61cef4e2839fee6346dc60f5739f876a9c50be7fcdb", size = 1555006, upload-time = "2025-10-28T20:57:18.288Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/12/0bac4d29231981e3aa234e88d1931f6ba38135ff4c2cf3afbb7895527630/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5bf635c3476f4119b940cc8d94ad454cbe0c377e61b4527f0192aabeac1e9370", size = 1681166, upload-time = "2025-10-06T19:56:34.81Z" },
|
{ url = "https://files.pythonhosted.org/packages/48/30/9586667acec5993b6f41d2ebcf96e97a1255a85f62f3c653110a5de4d346/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:16f15a4eac3bc2d76c45f7ebdd48a65d41b242eb6c31c2245463b40b34584ded", size = 1683220, upload-time = "2025-10-28T20:57:20.241Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/95/b829eb5f8ac1ca1d8085bb8df614c8acf3ff32e23ad5ad1173c7c9761daa/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:cfe6285ef99e7ee51cef20609be2bc1dd0e8446462b71c9db8bb296ba632810a", size = 1710516, upload-time = "2025-10-06T19:56:36.787Z" },
|
{ url = "https://files.pythonhosted.org/packages/71/01/3afe4c96854cfd7b30d78333852e8e851dceaec1c40fd00fec90c6402dd2/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:bb7fb776645af5cc58ab804c58d7eba545a97e047254a52ce89c157b5af6cd0b", size = 1712570, upload-time = "2025-10-28T20:57:22.253Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/47/6d/15ccf4ef3c254d899f62580e0c7fc717014f4d14a3ac31771e505d2c736c/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:34d8af6391c5f2e69749d7f037b614b8c5c42093c251f336bdbfa4b03c57d6c4", size = 1731354, upload-time = "2025-10-06T19:56:38.659Z" },
|
{ url = "https://files.pythonhosted.org/packages/11/2c/22799d8e720f4697a9e66fd9c02479e40a49de3de2f0bbe7f9f78a987808/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e1b4951125ec10c70802f2cb09736c895861cd39fd9dcb35107b4dc8ae6220b8", size = 1733407, upload-time = "2025-10-28T20:57:24.37Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/6a/8acf6c57e03b6fdcc8b4c06392e66abaff3213ea275e41db3edb20738d91/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:12f5d820fadc5848d4559ea838aef733cf37ed2a1103bba148ac2f5547c14c29", size = 1548040, upload-time = "2025-10-06T19:56:40.578Z" },
|
{ url = "https://files.pythonhosted.org/packages/34/cb/90f15dd029f07cebbd91f8238a8b363978b530cd128488085b5703683594/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:550bf765101ae721ee1d37d8095f47b1f220650f85fe1af37a90ce75bab89d04", size = 1550093, upload-time = "2025-10-28T20:57:26.257Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/75/7d/fbfd59ab2a83fe2578ce79ac3db49727b81e9f4c3376217ad09c03c6d279/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f1338b61ea66f4757a0544ed8a02ccbf60e38d9cfb3225888888dd4475ebb96", size = 1756031, upload-time = "2025-10-06T19:56:42.492Z" },
|
{ url = "https://files.pythonhosted.org/packages/69/46/12dce9be9d3303ecbf4d30ad45a7683dc63d90733c2d9fe512be6716cd40/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fe91b87fc295973096251e2d25a811388e7d8adf3bd2b97ef6ae78bc4ac6c476", size = 1758084, upload-time = "2025-10-28T20:57:28.349Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/e7/cc9f0fdf06cab3ca61e6b62bff9a4b978b8ca736e9d76ddf54365673ab19/aiohttp-3.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:582770f82513419512da096e8df21ca44f86a2e56e25dc93c5ab4df0fe065bf0", size = 1714933, upload-time = "2025-10-06T19:56:45.542Z" },
|
{ url = "https://files.pythonhosted.org/packages/f9/c8/0932b558da0c302ffd639fc6362a313b98fdf235dc417bc2493da8394df7/aiohttp-3.13.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0c8e31cfcc4592cb200160344b2fb6ae0f9e4effe06c644b5a125d4ae5ebe23", size = 1716987, upload-time = "2025-10-28T20:57:30.233Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/db/43/7abbe1de94748a58a71881163ee280fd3217db36e8344d109f63638fe16a/aiohttp-3.13.0-cp313-cp313-win32.whl", hash = "sha256:3194b8cab8dbc882f37c13ef1262e0a3d62064fa97533d3aa124771f7bf1ecee", size = 423799, upload-time = "2025-10-06T19:56:47.779Z" },
|
{ url = "https://files.pythonhosted.org/packages/5d/8b/f5bd1a75003daed099baec373aed678f2e9b34f2ad40d85baa1368556396/aiohttp-3.13.2-cp313-cp313-win32.whl", hash = "sha256:0740f31a60848d6edb296a0df827473eede90c689b8f9f2a4cdde74889eb2254", size = 425859, upload-time = "2025-10-28T20:57:32.105Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c9/58/afab7f2b9e7df88c995995172eb78cae8a3d5a62d5681abaade86b3f0089/aiohttp-3.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:7897298b3eedc790257fef8a6ec582ca04e9dbe568ba4a9a890913b925b8ea21", size = 450138, upload-time = "2025-10-06T19:56:49.49Z" },
|
{ url = "https://files.pythonhosted.org/packages/5d/28/a8a9fc6957b2cee8902414e41816b5ab5536ecf43c3b1843c10e82c559b2/aiohttp-3.13.2-cp313-cp313-win_amd64.whl", hash = "sha256:a88d13e7ca367394908f8a276b89d04a3652044612b9a408a0bb22a5ed976a1a", size = 452192, upload-time = "2025-10-28T20:57:34.166Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fe/c1/93bb1e35cd0c4665bb422b1ca3d87b588f4bca2656bbe9292b963d5b76a9/aiohttp-3.13.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c417f8c2e1137775569297c584a8a7144e5d1237789eae56af4faf1894a0b861", size = 733187, upload-time = "2025-10-06T19:56:51.385Z" },
|
{ url = "https://files.pythonhosted.org/packages/9b/36/e2abae1bd815f01c957cbf7be817b3043304e1c87bad526292a0410fdcf9/aiohttp-3.13.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:2475391c29230e063ef53a66669b7b691c9bfc3f1426a0f7bcdf1216bdbac38b", size = 735234, upload-time = "2025-10-28T20:57:36.415Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5e/36/2d50eba91992d3fe7a6452506ccdab45d03685ee8d8acaa5b289384a7d4c/aiohttp-3.13.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f84b53326abf8e56ebc28a35cebf4a0f396a13a76300f500ab11fe0573bf0b52", size = 488684, upload-time = "2025-10-06T19:56:53.25Z" },
|
{ url = "https://files.pythonhosted.org/packages/ca/e3/1ee62dde9b335e4ed41db6bba02613295a0d5b41f74a783c142745a12763/aiohttp-3.13.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:f33c8748abef4d8717bb20e8fb1b3e07c6adacb7fd6beaae971a764cf5f30d61", size = 490733, upload-time = "2025-10-28T20:57:38.205Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/82/93/fa4b1d5ecdc7805bdf0815ef00257db4632ccf0a8bffd44f9fc4657b1677/aiohttp-3.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:990a53b9d6a30b2878789e490758e568b12b4a7fb2527d0c89deb9650b0e5813", size = 489255, upload-time = "2025-10-06T19:56:55.136Z" },
|
{ url = "https://files.pythonhosted.org/packages/1a/aa/7a451b1d6a04e8d15a362af3e9b897de71d86feac3babf8894545d08d537/aiohttp-3.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ae32f24bbfb7dbb485a24b30b1149e2f200be94777232aeadba3eecece4d0aa4", size = 491303, upload-time = "2025-10-28T20:57:40.122Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/0f/85241f0d158da5e24e8ac9d50c0849ed24f882cafc53dc95749ef85eef09/aiohttp-3.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c811612711e01b901e18964b3e5dec0d35525150f5f3f85d0aee2935f059910a", size = 1715914, upload-time = "2025-10-06T19:56:57.286Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/1e/209958dbb9b01174870f6a7538cd1f3f28274fdbc88a750c238e2c456295/aiohttp-3.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d7f02042c1f009ffb70067326ef183a047425bb2ff3bc434ead4dd4a4a66a2b", size = 1717965, upload-time = "2025-10-28T20:57:42.28Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ab/fc/c755590d6f6d2b5d1565c72d6ee658d3c30ec61acb18964d1e9bf991d9b5/aiohttp-3.13.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:ee433e594d7948e760b5c2a78cc06ac219df33b0848793cf9513d486a9f90a52", size = 1665171, upload-time = "2025-10-06T19:56:59.688Z" },
|
{ url = "https://files.pythonhosted.org/packages/08/aa/6a01848d6432f241416bc4866cae8dc03f05a5a884d2311280f6a09c73d6/aiohttp-3.13.2-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:93655083005d71cd6c072cdab54c886e6570ad2c4592139c3fb967bfc19e4694", size = 1667221, upload-time = "2025-10-28T20:57:44.869Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/de/caa61e213ff546b8815aef5e931d7eae1dbe8c840a3f11ec5aa41c5ae462/aiohttp-3.13.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:19bb08e56f57c215e9572cd65cb6f8097804412c54081d933997ddde3e5ac579", size = 1755124, upload-time = "2025-10-06T19:57:02.69Z" },
|
{ url = "https://files.pythonhosted.org/packages/87/4f/36c1992432d31bbc789fa0b93c768d2e9047ec8c7177e5cd84ea85155f36/aiohttp-3.13.2-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:0db1e24b852f5f664cd728db140cf11ea0e82450471232a394b3d1a540b0f906", size = 1757178, upload-time = "2025-10-28T20:57:47.216Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/b7/40c3219dd2691aa35cf889b4fbb0c00e48a19092928707044bfe92068e01/aiohttp-3.13.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f27b7488144eb5dd9151cf839b195edd1569629d90ace4c5b6b18e4e75d1e63a", size = 1835949, upload-time = "2025-10-06T19:57:05.251Z" },
|
{ url = "https://files.pythonhosted.org/packages/ac/b4/8e940dfb03b7e0f68a82b88fd182b9be0a65cb3f35612fe38c038c3112cf/aiohttp-3.13.2-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b009194665bcd128e23eaddef362e745601afa4641930848af4c8559e88f18f9", size = 1838001, upload-time = "2025-10-28T20:57:49.337Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/57/e8/66e3c32841fc0e26a09539c377aa0f3bbf6deac1957ac5182cf276c5719c/aiohttp-3.13.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d812838c109757a11354a161c95708ae4199c4fd4d82b90959b20914c1d097f6", size = 1714276, upload-time = "2025-10-06T19:57:07.41Z" },
|
{ url = "https://files.pythonhosted.org/packages/d7/ef/39f3448795499c440ab66084a9db7d20ca7662e94305f175a80f5b7e0072/aiohttp-3.13.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c038a8fdc8103cd51dbd986ecdce141473ffd9775a7a8057a6ed9c3653478011", size = 1716325, upload-time = "2025-10-28T20:57:51.327Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6b/a5/c68e5b46ff0410fe3abfa508651b09372428f27036138beacf4ff6b7cb8c/aiohttp-3.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7c20db99da682f9180fa5195c90b80b159632fb611e8dbccdd99ba0be0970620", size = 1545929, upload-time = "2025-10-06T19:57:09.336Z" },
|
{ url = "https://files.pythonhosted.org/packages/d7/51/b311500ffc860b181c05d91c59a1313bdd05c82960fdd4035a15740d431e/aiohttp-3.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66bac29b95a00db411cd758fea0e4b9bdba6d549dfe333f9a945430f5f2cc5a6", size = 1547978, upload-time = "2025-10-28T20:57:53.554Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7a/a6/4c97dc27f9935c0c0aa6e3e10e5b4548823ab5d056636bde374fcd297256/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:cf8b0870047900eb1f17f453b4b3953b8ffbf203ef56c2f346780ff930a4d430", size = 1679988, upload-time = "2025-10-06T19:57:11.367Z" },
|
{ url = "https://files.pythonhosted.org/packages/31/64/b9d733296ef79815226dab8c586ff9e3df41c6aff2e16c06697b2d2e6775/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4ebf9cfc9ba24a74cf0718f04aac2a3bbe745902cc7c5ebc55c0f3b5777ef213", size = 1682042, upload-time = "2025-10-28T20:57:55.617Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/1b/11f9c52fd72b786a47e796e6794883417280cdca8eb1032d8d0939928dfa/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:5b8a5557d5af3f4e3add52a58c4cf2b8e6e59fc56b261768866f5337872d596d", size = 1678031, upload-time = "2025-10-06T19:57:13.357Z" },
|
{ url = "https://files.pythonhosted.org/packages/3f/30/43d3e0f9d6473a6db7d472104c4eff4417b1e9df01774cb930338806d36b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:a4b88ebe35ce54205c7074f7302bd08a4cb83256a3e0870c72d6f68a3aaf8e49", size = 1680085, upload-time = "2025-10-28T20:57:57.59Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ea/eb/948903d40505f3a25e53e051488d2714ded3afac1f961df135f2936680f9/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:052bcdd80c1c54b8a18a9ea0cd5e36f473dc8e38d51b804cea34841f677a9971", size = 1726184, upload-time = "2025-10-06T19:57:15.478Z" },
|
{ url = "https://files.pythonhosted.org/packages/16/51/c709f352c911b1864cfd1087577760ced64b3e5bee2aa88b8c0c8e2e4972/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:98c4fb90bb82b70a4ed79ca35f656f4281885be076f3f970ce315402b53099ae", size = 1728238, upload-time = "2025-10-28T20:57:59.525Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/44/14/c8ced38c7dfe80804dec17a671963ccf3cb282f12700ec70b1f689d8de7d/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:76484ba17b2832776581b7ab466d094e48eba74cb65a60aea20154dae485e8bd", size = 1542344, upload-time = "2025-10-06T19:57:17.611Z" },
|
{ url = "https://files.pythonhosted.org/packages/19/e2/19bd4c547092b773caeb48ff5ae4b1ae86756a0ee76c16727fcfd281404b/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:ec7534e63ae0f3759df3a1ed4fa6bc8f75082a924b590619c0dd2f76d7043caa", size = 1544395, upload-time = "2025-10-28T20:58:01.914Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a4/6e/f2e6bff550a51fd7c45fdab116a1dab7cc502e5d942956f10fc5c626bb15/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:62d8a0adcdaf62ee56bfb37737153251ac8e4b27845b3ca065862fb01d99e247", size = 1740913, upload-time = "2025-10-06T19:57:19.821Z" },
|
{ url = "https://files.pythonhosted.org/packages/cf/87/860f2803b27dfc5ed7be532832a3498e4919da61299b4a1f8eb89b8ff44d/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5b927cf9b935a13e33644cbed6c8c4b2d0f25b713d838743f8fe7191b33829c4", size = 1742965, upload-time = "2025-10-28T20:58:03.972Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/00/8f057300d9b598a706348abb375b3de9a253195fb615f17c0b2be2a72836/aiohttp-3.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5004d727499ecb95f7c9147dd0bfc5b5670f71d355f0bd26d7af2d3af8e07d2f", size = 1695535, upload-time = "2025-10-06T19:57:21.856Z" },
|
{ url = "https://files.pythonhosted.org/packages/67/7f/db2fc7618925e8c7a601094d5cbe539f732df4fb570740be88ed9e40e99a/aiohttp-3.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:88d6c017966a78c5265d996c19cdb79235be5e6412268d7e2ce7dee339471b7a", size = 1697585, upload-time = "2025-10-28T20:58:06.189Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8a/ab/6919d584d8f053a14b15f0bfa3f315b3f548435c2142145459da2efa8673/aiohttp-3.13.0-cp314-cp314-win32.whl", hash = "sha256:a1c20c26af48aea984f63f96e5d7af7567c32cb527e33b60a0ef0a6313cf8b03", size = 429548, upload-time = "2025-10-06T19:57:24.285Z" },
|
{ url = "https://files.pythonhosted.org/packages/0c/07/9127916cb09bb38284db5036036042b7b2c514c8ebaeee79da550c43a6d6/aiohttp-3.13.2-cp314-cp314-win32.whl", hash = "sha256:f7c183e786e299b5d6c49fb43a769f8eb8e04a2726a2bd5887b98b5cc2d67940", size = 431621, upload-time = "2025-10-28T20:58:08.636Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c5/59/5d9e78de6132079066f5077d9687bf524f764a2f8207e04d8d68790060c6/aiohttp-3.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:56f7d230ec66e799fbfd8350e9544f8a45a4353f1cf40c1fea74c1780f555b8f", size = 455548, upload-time = "2025-10-06T19:57:26.136Z" },
|
{ url = "https://files.pythonhosted.org/packages/fb/41/554a8a380df6d3a2bba8a7726429a23f4ac62aaf38de43bb6d6cde7b4d4d/aiohttp-3.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:fe242cd381e0fb65758faf5ad96c2e460df6ee5b2de1072fe97e4127927e00b4", size = 457627, upload-time = "2025-10-28T20:58:11Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/ea/7d98da03d1e9798bb99c3ca4963229150d45c9b7a3a16210c5b4a5f89e07/aiohttp-3.13.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:2fd35177dc483ae702f07b86c782f4f4b100a8ce4e7c5778cea016979023d9fd", size = 765319, upload-time = "2025-10-06T19:57:28.278Z" },
|
{ url = "https://files.pythonhosted.org/packages/c7/8e/3824ef98c039d3951cb65b9205a96dd2b20f22241ee17d89c5701557c826/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:f10d9c0b0188fe85398c61147bbd2a657d616c876863bfeff43376e0e3134673", size = 767360, upload-time = "2025-10-28T20:58:13.358Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5c/02/37f29beced8213bb467c52ad509a5e3b41e6e967de2f6eaf7f8db63bea54/aiohttp-3.13.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4df1984c8804ed336089e88ac81a9417b1fd0db7c6f867c50a9264488797e778", size = 502567, upload-time = "2025-10-06T19:57:30.273Z" },
|
{ url = "https://files.pythonhosted.org/packages/a4/0f/6a03e3fc7595421274fa34122c973bde2d89344f8a881b728fa8c774e4f1/aiohttp-3.13.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:e7c952aefdf2460f4ae55c5e9c3e80aa72f706a6317e06020f80e96253b1accd", size = 504616, upload-time = "2025-10-28T20:58:15.339Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e7/22/b0afcafcfe3637bc8d7992abf08ee9452018366c0801e4e7d4efda2ed839/aiohttp-3.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e68c0076052dd911a81d3acc4ef2911cc4ef65bf7cadbfbc8ae762da24da858f", size = 507078, upload-time = "2025-10-06T19:57:32.619Z" },
|
{ url = "https://files.pythonhosted.org/packages/c6/aa/ed341b670f1bc8a6f2c6a718353d13b9546e2cef3544f573c6a1ff0da711/aiohttp-3.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c20423ce14771d98353d2e25e83591fa75dfa90a3c1848f3d7c68243b4fbded3", size = 509131, upload-time = "2025-10-28T20:58:17.693Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/49/4c/046c847b7a1993b49f3855cc3b97872d5df193d9240de835d0dc6a97b164/aiohttp-3.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc95c49853cd29613e4fe4ff96d73068ff89b89d61e53988442e127e8da8e7ba", size = 1862115, upload-time = "2025-10-06T19:57:34.758Z" },
|
{ url = "https://files.pythonhosted.org/packages/7f/f0/c68dac234189dae5c4bbccc0f96ce0cc16b76632cfc3a08fff180045cfa4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e96eb1a34396e9430c19d8338d2ec33015e4a87ef2b4449db94c22412e25ccdf", size = 1864168, upload-time = "2025-10-28T20:58:20.113Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/1a/25/1449a59e3c6405da5e47b0138ee0855414dc12a8c306685d7fc3dd300e1f/aiohttp-3.13.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3b3bdc89413117b40cc39baae08fd09cbdeb839d421c4e7dce6a34f6b54b3ac1", size = 1717147, upload-time = "2025-10-06T19:57:36.938Z" },
|
{ url = "https://files.pythonhosted.org/packages/8f/65/75a9a76db8364b5d0e52a0c20eabc5d52297385d9af9c35335b924fafdee/aiohttp-3.13.2-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:23fb0783bc1a33640036465019d3bba069942616a6a2353c6907d7fe1ccdaf4e", size = 1719200, upload-time = "2025-10-28T20:58:22.583Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/23/8f/50cc34ad267b38608f21c6a74327015dd08a66f1dd8e7ceac954d0953191/aiohttp-3.13.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3e77a729df23be2116acc4e9de2767d8e92445fbca68886dd991dc912f473755", size = 1841443, upload-time = "2025-10-06T19:57:39.708Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/55/8df2ed78d7f41d232f6bd3ff866b6f617026551aa1d07e2f03458f964575/aiohttp-3.13.2-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2e1a9bea6244a1d05a4e57c295d69e159a5c50d8ef16aa390948ee873478d9a5", size = 1843497, upload-time = "2025-10-28T20:58:24.672Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/df/b9/b3ab1278faa0d1b8f434c85f9cf34eeb0a25016ffe1ee6bc361d09fef0ec/aiohttp-3.13.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e88ab34826d6eeb6c67e6e92400b9ec653faf5092a35f07465f44c9f1c429f82", size = 1933652, upload-time = "2025-10-06T19:57:42.33Z" },
|
{ url = "https://files.pythonhosted.org/packages/e9/e0/94d7215e405c5a02ccb6a35c7a3a6cfff242f457a00196496935f700cde5/aiohttp-3.13.2-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0a3d54e822688b56e9f6b5816fb3de3a3a64660efac64e4c2dc435230ad23bad", size = 1935703, upload-time = "2025-10-28T20:58:26.758Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/88/e2/86050aaa3bd7021b115cdfc88477b754e8cf93ef0079867840eee22d3c34/aiohttp-3.13.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:019dbef24fe28ce2301419dd63a2b97250d9760ca63ee2976c2da2e3f182f82e", size = 1790682, upload-time = "2025-10-06T19:57:44.851Z" },
|
{ url = "https://files.pythonhosted.org/packages/0b/78/1eeb63c3f9b2d1015a4c02788fb543141aad0a03ae3f7a7b669b2483f8d4/aiohttp-3.13.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7a653d872afe9f33497215745da7a943d1dc15b728a9c8da1c3ac423af35178e", size = 1792738, upload-time = "2025-10-28T20:58:29.787Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/78/8d/9af903324c2ba24a0c4778e9bcc738b773c98dded3a4fcf8041d5211769f/aiohttp-3.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:2c4aeaedd20771b7b4bcdf0ae791904445df6d856c02fc51d809d12d17cffdc7", size = 1622011, upload-time = "2025-10-06T19:57:47.025Z" },
|
{ url = "https://files.pythonhosted.org/packages/41/75/aaf1eea4c188e51538c04cc568040e3082db263a57086ea74a7d38c39e42/aiohttp-3.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:56d36e80d2003fa3fc0207fac644216d8532e9504a785ef9a8fd013f84a42c61", size = 1624061, upload-time = "2025-10-28T20:58:32.529Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/97/5174971ba4986d913554ceb248b0401eb5358cb60672ea0166f9f596cd08/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:b3a8e6a2058a0240cfde542b641d0e78b594311bc1a710cbcb2e1841417d5cb3", size = 1787148, upload-time = "2025-10-06T19:57:49.149Z" },
|
{ url = "https://files.pythonhosted.org/packages/9b/c2/3b6034de81fbcc43de8aeb209073a2286dfb50b86e927b4efd81cf848197/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:78cd586d8331fb8e241c2dd6b2f4061778cc69e150514b39a9e28dd050475661", size = 1789201, upload-time = "2025-10-28T20:58:34.618Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/dd/ae/8b397e980ac613ef3ddd8e996aa7a40a1828df958257800d4bb325657db3/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:f8e38d55ca36c15f36d814ea414ecb2401d860de177c49f84a327a25b3ee752b", size = 1774816, upload-time = "2025-10-06T19:57:51.523Z" },
|
{ url = "https://files.pythonhosted.org/packages/c9/38/c15dcf6d4d890217dae79d7213988f4e5fe6183d43893a9cf2fe9e84ca8d/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:20b10bbfbff766294fe99987f7bb3b74fdd2f1a2905f2562132641ad434dcf98", size = 1776868, upload-time = "2025-10-28T20:58:38.835Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c7/54/0e8e2111dd92051c787e934b6bbf30c213daaa5e7ee5f51bca8913607492/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a921edbe971aade1bf45bcbb3494e30ba6863a5c78f28be992c42de980fd9108", size = 1788610, upload-time = "2025-10-06T19:57:54.337Z" },
|
{ url = "https://files.pythonhosted.org/packages/04/75/f74fd178ac81adf4f283a74847807ade5150e48feda6aef024403716c30c/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9ec49dff7e2b3c85cdeaa412e9d438f0ecd71676fde61ec57027dd392f00c693", size = 1790660, upload-time = "2025-10-28T20:58:41.507Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/dd/c9283dbfd9325ed6fa6c91f009db6344d8d370a7bcf09f36e7b2fcbfae02/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:474cade59a447cb4019c0dce9f0434bf835fb558ea932f62c686fe07fe6db6a1", size = 1615498, upload-time = "2025-10-06T19:57:56.604Z" },
|
{ url = "https://files.pythonhosted.org/packages/e7/80/7368bd0d06b16b3aba358c16b919e9c46cf11587dc572091031b0e9e3ef0/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:94f05348c4406450f9d73d38efb41d669ad6cd90c7ee194810d0eefbfa875a7a", size = 1617548, upload-time = "2025-10-28T20:58:43.674Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8c/f6/da76230679bd9ef175d876093f89e7fd6d6476c18505e115e3026fe5ef95/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:99a303ad960747c33b65b1cb65d01a62ac73fa39b72f08a2e1efa832529b01ed", size = 1815187, upload-time = "2025-10-06T19:57:59.036Z" },
|
{ url = "https://files.pythonhosted.org/packages/7d/4b/a6212790c50483cb3212e507378fbe26b5086d73941e1ec4b56a30439688/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:fa4dcb605c6f82a80c7f95713c2b11c3b8e9893b3ebd2bc9bde93165ed6107be", size = 1817240, upload-time = "2025-10-28T20:58:45.787Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/78/394003ac738703822616f4f922705b54e5b3d8e7185831ecc1c97904174d/aiohttp-3.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:bb34001fc1f05f6b323e02c278090c07a47645caae3aa77ed7ed8a3ce6abcce9", size = 1760281, upload-time = "2025-10-06T19:58:01.585Z" },
|
{ url = "https://files.pythonhosted.org/packages/ff/f7/ba5f0ba4ea8d8f3c32850912944532b933acbf0f3a75546b89269b9b7dde/aiohttp-3.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf00e5db968c3f67eccd2778574cf64d8b27d95b237770aa32400bd7a1ca4f6c", size = 1762334, upload-time = "2025-10-28T20:58:47.936Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bd/b0/4bad0a9dd5910bd01c3119f8bd3d71887cd412d4105e4acddcdacf3cfa76/aiohttp-3.13.0-cp314-cp314t-win32.whl", hash = "sha256:dea698b64235d053def7d2f08af9302a69fcd760d1c7bd9988fd5d3b6157e657", size = 462608, upload-time = "2025-10-06T19:58:03.674Z" },
|
{ url = "https://files.pythonhosted.org/packages/7e/83/1a5a1856574588b1cad63609ea9ad75b32a8353ac995d830bf5da9357364/aiohttp-3.13.2-cp314-cp314t-win32.whl", hash = "sha256:d23b5fe492b0805a50d3371e8a728a9134d8de5447dce4c885f5587294750734", size = 464685, upload-time = "2025-10-28T20:58:50.642Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/bd/af/ad12d592f623aae2bd1d3463201dc39c201ea362f9ddee0d03efd9e83720/aiohttp-3.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1f164699a060c0b3616459d13c1464a981fddf36f892f0a5027cbd45121fb14b", size = 496010, upload-time = "2025-10-06T19:58:05.589Z" },
|
{ url = "https://files.pythonhosted.org/packages/9f/4d/d22668674122c08f4d56972297c51a624e64b3ed1efaa40187607a7cb66e/aiohttp-3.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:ff0a7b0a82a7ab905cbda74006318d1b12e37c797eb1b0d4eb3e316cf47f658f", size = 498093, upload-time = "2025-10-28T20:58:52.782Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -764,11 +764,11 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fsspec"
|
name = "fsspec"
|
||||||
version = "2025.9.0"
|
version = "2025.10.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/de/e0/bab50af11c2d75c9c4a2a26a5254573c0bd97cea152254401510950486fa/fsspec-2025.9.0.tar.gz", hash = "sha256:19fd429483d25d28b65ec68f9f4adc16c17ea2c7c7bf54ec61360d478fb19c19", size = 304847, upload-time = "2025-09-02T19:10:49.215Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/24/7f/2747c0d332b9acfa75dc84447a066fdf812b5a6b8d30472b74d309bfe8cb/fsspec-2025.10.0.tar.gz", hash = "sha256:b6789427626f068f9a83ca4e8a3cc050850b6c0f71f99ddb4f542b8266a26a59", size = 309285, upload-time = "2025-10-30T14:58:44.036Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/47/71/70db47e4f6ce3e5c37a607355f80da8860a33226be640226ac52cb05ef2e/fsspec-2025.9.0-py3-none-any.whl", hash = "sha256:530dc2a2af60a414a832059574df4a6e10cce927f6f4a78209390fe38955cfb7", size = 199289, upload-time = "2025-09-02T19:10:47.708Z" },
|
{ url = "https://files.pythonhosted.org/packages/eb/02/a6b21098b1d5d6249b7c5ab69dde30108a71e4e819d4a9778f1de1d5b70d/fsspec-2025.10.0-py3-none-any.whl", hash = "sha256:7c7712353ae7d875407f97715f0e1ffcc21e33d5b24556cb1e090ae9409ec61d", size = 200966, upload-time = "2025-10-30T14:58:42.53Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.optional-dependencies]
|
[package.optional-dependencies]
|
||||||
@ -1560,86 +1560,86 @@ wheels = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "propcache"
|
name = "propcache"
|
||||||
version = "0.4.0"
|
version = "0.4.1"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/ea/c8/d70cd26d845c6d85479d8f5a11a0fd7151e9bc4794cc5e6eb5a790f12df8/propcache-0.4.0.tar.gz", hash = "sha256:c1ad731253eb738f9cadd9fa1844e019576c70bca6a534252e97cf33a57da529", size = 45187, upload-time = "2025-10-04T21:57:39.546Z" }
|
sdist = { url = "https://files.pythonhosted.org/packages/9e/da/e9fc233cf63743258bff22b3dfa7ea5baef7b5bc324af47a0ad89b8ffc6f/propcache-0.4.1.tar.gz", hash = "sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d", size = 46442, upload-time = "2025-10-08T19:49:02.291Z" }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/b3/cf/3f88344261d69f8021256f20e82e820c5df3aba96e5ba9b5fdd3685d3a9f/propcache-0.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:381c84a445efb8c9168f1393a5a7c566de22edc42bfe207a142fff919b37f5d9", size = 79846, upload-time = "2025-10-04T21:55:31.447Z" },
|
{ url = "https://files.pythonhosted.org/packages/a2/0f/f17b1b2b221d5ca28b4b876e8bb046ac40466513960646bda8e1853cdfa2/propcache-0.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e153e9cd40cc8945138822807139367f256f89c6810c2634a4f6902b52d3b4e2", size = 80061, upload-time = "2025-10-08T19:46:46.075Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/be/fa/0286fc92764eead9dcfee639b67828daa32e61dd0f1618831547141eb28b/propcache-0.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5a531d29d7b873b12730972237c48b1a4e5980b98cf21b3f09fa4710abd3a8c3", size = 45850, upload-time = "2025-10-04T21:55:32.637Z" },
|
{ url = "https://files.pythonhosted.org/packages/76/47/8ccf75935f51448ba9a16a71b783eb7ef6b9ee60f5d14c7f8a8a79fbeed7/propcache-0.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cd547953428f7abb73c5ad82cbb32109566204260d98e41e5dfdc682eb7f8403", size = 46037, upload-time = "2025-10-08T19:46:47.23Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c7/83/57840656f972f8a67992eee40781e4066657776dcb889f49df0e8eecb112/propcache-0.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cd6e22255ed73efeaaeb1765505a66a48a9ec9ebc919fce5ad490fe5e33b1555", size = 47171, upload-time = "2025-10-04T21:55:33.819Z" },
|
{ url = "https://files.pythonhosted.org/packages/0a/b6/5c9a0e42df4d00bfb4a3cbbe5cf9f54260300c88a0e9af1f47ca5ce17ac0/propcache-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f048da1b4f243fc44f205dfd320933a951b8d89e0afd4c7cacc762a8b9165207", size = 47324, upload-time = "2025-10-08T19:46:48.384Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/8e/e0a0bd376c3440476b924eca517589ee535bb4520420d178268bf88558ba/propcache-0.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9a8d277dc218ddf04ec243a53ac309b1afcebe297c0526a8f82320139b56289", size = 225306, upload-time = "2025-10-04T21:55:35.312Z" },
|
{ url = "https://files.pythonhosted.org/packages/9e/d3/6c7ee328b39a81ee877c962469f1e795f9db87f925251efeb0545e0020d0/propcache-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec17c65562a827bba85e3872ead335f95405ea1674860d96483a02f5c698fa72", size = 225505, upload-time = "2025-10-08T19:46:50.055Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/fe/76884442da1bab6d4353ba1c43fdc4a770c3b3973f3ac7620a7205402fdd/propcache-0.4.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:399c73201d88c856a994916200d7cba41d7687096f8eb5139eb68f02785dc3f7", size = 230013, upload-time = "2025-10-04T21:55:37.005Z" },
|
{ url = "https://files.pythonhosted.org/packages/01/5d/1c53f4563490b1d06a684742cc6076ef944bc6457df6051b7d1a877c057b/propcache-0.4.1-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:405aac25c6394ef275dee4c709be43745d36674b223ba4eb7144bf4d691b7367", size = 230242, upload-time = "2025-10-08T19:46:51.815Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/b7/322af273bd1136bb7e13628821fb855c9f61d64651c73fea71dded68dda5/propcache-0.4.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a1d5e474d43c238035b74ecf997f655afa67f979bae591ac838bb3fbe3076392", size = 238331, upload-time = "2025-10-04T21:55:38.713Z" },
|
{ url = "https://files.pythonhosted.org/packages/20/e1/ce4620633b0e2422207c3cb774a0ee61cac13abc6217763a7b9e2e3f4a12/propcache-0.4.1-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0013cb6f8dde4b2a2f66903b8ba740bdfe378c943c4377a200551ceb27f379e4", size = 238474, upload-time = "2025-10-08T19:46:53.208Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/84/5e/036d2b105927ae7f179346c9911d16c345f4dba5a19a063f23a8d28acfbd/propcache-0.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:22f589652ee38de96aa58dd219335604e09666092bc250c1d9c26a55bcef9932", size = 221461, upload-time = "2025-10-04T21:55:40.034Z" },
|
{ url = "https://files.pythonhosted.org/packages/46/4b/3aae6835b8e5f44ea6a68348ad90f78134047b503765087be2f9912140ea/propcache-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15932ab57837c3368b024473a525e25d316d8353016e7cc0e5ba9eb343fbb1cf", size = 221575, upload-time = "2025-10-08T19:46:54.511Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/0d/babd038efb12a87a46ab070438c52daeac6bed0a930693a418feef8cb8a6/propcache-0.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e5227da556b2939da6125cda1d5eecf9e412e58bc97b41e2f192605c3ccbb7c2", size = 216707, upload-time = "2025-10-04T21:55:41.455Z" },
|
{ url = "https://files.pythonhosted.org/packages/6e/a5/8a5e8678bcc9d3a1a15b9a29165640d64762d424a16af543f00629c87338/propcache-0.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:031dce78b9dc099f4c29785d9cf5577a3faf9ebf74ecbd3c856a7b92768c3df3", size = 216736, upload-time = "2025-10-08T19:46:56.212Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ab/68/dd075a037381581f16e7e504a6da9c1d7e415e945dd8ed67905d608f0687/propcache-0.4.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:92bc43a1ab852310721ce856f40a3a352254aa6f5e26f0fad870b31be45bba2e", size = 212591, upload-time = "2025-10-04T21:55:42.938Z" },
|
{ url = "https://files.pythonhosted.org/packages/f1/63/b7b215eddeac83ca1c6b934f89d09a625aa9ee4ba158338854c87210cc36/propcache-0.4.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ab08df6c9a035bee56e31af99be621526bd237bea9f32def431c656b29e41778", size = 213019, upload-time = "2025-10-08T19:46:57.595Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/43/22698f28fc8e04c32b109cb9cb81305a4873b77c907b17484566b6133aef/propcache-0.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:83ae2f5343f6f06f4c91ae530d95f56b415f768f9c401a5ee2a10459cf74370b", size = 220188, upload-time = "2025-10-04T21:55:44.53Z" },
|
{ url = "https://files.pythonhosted.org/packages/57/74/f580099a58c8af587cac7ba19ee7cb418506342fbbe2d4a4401661cca886/propcache-0.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4d7af63f9f93fe593afbf104c21b3b15868efb2c21d07d8732c0c4287e66b6a6", size = 220376, upload-time = "2025-10-08T19:46:59.067Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/96/7a/27886e4a4c69598a38fbeeed64f9b8ddfa6f08fe3452035845a1fe90336f/propcache-0.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:077a32977399dc05299b16e793210341a0b511eb0a86d1796873e83ce47334cc", size = 226736, upload-time = "2025-10-04T21:55:46.348Z" },
|
{ url = "https://files.pythonhosted.org/packages/c4/ee/542f1313aff7eaf19c2bb758c5d0560d2683dac001a1c96d0774af799843/propcache-0.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cfc27c945f422e8b5071b6e93169679e4eb5bf73bbcbf1ba3ae3a83d2f78ebd9", size = 226988, upload-time = "2025-10-08T19:47:00.544Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5b/c7/313c632b5888db3c9f4cb262420dcd5e57cf858d939d6ad9c3b1b90c12af/propcache-0.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:94a278c45e6463031b5a8278e40a07edf2bcc3b5379510e22b6c1a6e6498c194", size = 216363, upload-time = "2025-10-04T21:55:47.768Z" },
|
{ url = "https://files.pythonhosted.org/packages/8f/18/9c6b015dd9c6930f6ce2229e1f02fb35298b847f2087ea2b436a5bfa7287/propcache-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:35c3277624a080cc6ec6f847cbbbb5b49affa3598c4535a0a4682a697aaa5c75", size = 215615, upload-time = "2025-10-08T19:47:01.968Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7a/5d/5aaf82bd1542aedb47d10483b84f49ee8f00d970a58e27534cd241e9c5ac/propcache-0.4.0-cp312-cp312-win32.whl", hash = "sha256:4c491462e1dc80f9deb93f428aad8d83bb286de212837f58eb48e75606e7726c", size = 37945, upload-time = "2025-10-04T21:55:49.104Z" },
|
{ url = "https://files.pythonhosted.org/packages/80/9e/e7b85720b98c45a45e1fca6a177024934dc9bc5f4d5dd04207f216fc33ed/propcache-0.4.1-cp312-cp312-win32.whl", hash = "sha256:671538c2262dadb5ba6395e26c1731e1d52534bfe9ae56d0b5573ce539266aa8", size = 38066, upload-time = "2025-10-08T19:47:03.503Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/67/47ffff6eb176f383f56319f31c0e1bcf7500cb94ffb7582efc600c6b3c73/propcache-0.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cdb0cecafb528ab15ed89cdfed183074d15912d046d3e304955513b50a34b907", size = 41530, upload-time = "2025-10-04T21:55:50.261Z" },
|
{ url = "https://files.pythonhosted.org/packages/54/09/d19cff2a5aaac632ec8fc03737b223597b1e347416934c1b3a7df079784c/propcache-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:cb2d222e72399fcf5890d1d5cc1060857b9b236adff2792ff48ca2dfd46c81db", size = 41655, upload-time = "2025-10-08T19:47:04.973Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f3/7e/61b70306b9d7527286ce887a8ff28c304ab2514e5893eea36b5bdf7a21af/propcache-0.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:b2f29697d1110e8cdf7a39cc630498df0082d7898b79b731c1c863f77c6e8cfc", size = 37662, upload-time = "2025-10-04T21:55:51.35Z" },
|
{ url = "https://files.pythonhosted.org/packages/68/ab/6b5c191bb5de08036a8c697b265d4ca76148efb10fa162f14af14fb5f076/propcache-0.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:204483131fb222bdaaeeea9f9e6c6ed0cac32731f75dfc1d4a567fc1926477c1", size = 37789, upload-time = "2025-10-08T19:47:06.077Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cd/dd/f405b0fe84d29d356895bc048404d3321a2df849281cf3f932158c9346ac/propcache-0.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e2d01fd53e89cb3d71d20b8c225a8c70d84660f2d223afc7ed7851a4086afe6d", size = 77565, upload-time = "2025-10-04T21:55:52.907Z" },
|
{ url = "https://files.pythonhosted.org/packages/bf/df/6d9c1b6ac12b003837dde8a10231a7344512186e87b36e855bef32241942/propcache-0.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:43eedf29202c08550aac1d14e0ee619b0430aaef78f85864c1a892294fbc28cf", size = 77750, upload-time = "2025-10-08T19:47:07.648Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c0/48/dfb2c45e1b0d92228c9c66fa929af7316c15cbe69a7e438786aaa60c1b3c/propcache-0.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7dfa60953169d2531dd8ae306e9c27c5d4e5efe7a2ba77049e8afdaece062937", size = 44602, upload-time = "2025-10-04T21:55:54.406Z" },
|
{ url = "https://files.pythonhosted.org/packages/8b/e8/677a0025e8a2acf07d3418a2e7ba529c9c33caf09d3c1f25513023c1db56/propcache-0.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d62cdfcfd89ccb8de04e0eda998535c406bf5e060ffd56be6c586cbcc05b3311", size = 44780, upload-time = "2025-10-08T19:47:08.851Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d0/d9/b15e88b4463df45a7793fb04e2b5497334f8fcc24e281c221150a0af9aff/propcache-0.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:227892597953611fce2601d49f1d1f39786a6aebc2f253c2de775407f725a3f6", size = 46168, upload-time = "2025-10-04T21:55:55.537Z" },
|
{ url = "https://files.pythonhosted.org/packages/89/a4/92380f7ca60f99ebae761936bc48a72a639e8a47b29050615eef757cb2a7/propcache-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cae65ad55793da34db5f54e4029b89d3b9b9490d8abe1b4c7ab5d4b8ec7ebf74", size = 46308, upload-time = "2025-10-08T19:47:09.982Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/40/ac/983e69cce8800251aab85858069cf9359b22222a9cda47591e03e2f24eec/propcache-0.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e0a5bc019014531308fb67d86066d235daa7551baf2e00e1ea7b00531f6ea85", size = 207997, upload-time = "2025-10-04T21:55:57.022Z" },
|
{ url = "https://files.pythonhosted.org/packages/2d/48/c5ac64dee5262044348d1d78a5f85dd1a57464a60d30daee946699963eb3/propcache-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:333ddb9031d2704a301ee3e506dc46b1fe5f294ec198ed6435ad5b6a085facfe", size = 208182, upload-time = "2025-10-08T19:47:11.319Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/9c/5586a7a54e7e0b9a87fdd8ba935961f398c0e6eaecd57baaa8eca468a236/propcache-0.4.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6ebc6e2e65c31356310ddb6519420eaa6bb8c30fbd809d0919129c89dcd70f4c", size = 210948, upload-time = "2025-10-04T21:55:58.397Z" },
|
{ url = "https://files.pythonhosted.org/packages/c6/0c/cd762dd011a9287389a6a3eb43aa30207bde253610cca06824aeabfe9653/propcache-0.4.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:fd0858c20f078a32cf55f7e81473d96dcf3b93fd2ccdb3d40fdf54b8573df3af", size = 211215, upload-time = "2025-10-08T19:47:13.146Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/5f/ba/644e367f8a86461d45bd023ace521180938e76515040550af9b44085e99a/propcache-0.4.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1927b78dd75fc31a7fdc76cc7039e39f3170cb1d0d9a271e60f0566ecb25211a", size = 217988, upload-time = "2025-10-04T21:56:00.251Z" },
|
{ url = "https://files.pythonhosted.org/packages/30/3e/49861e90233ba36890ae0ca4c660e95df565b2cd15d4a68556ab5865974e/propcache-0.4.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:678ae89ebc632c5c204c794f8dab2837c5f159aeb59e6ed0539500400577298c", size = 218112, upload-time = "2025-10-08T19:47:14.913Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/0e/1e21af74b4732d002b0452605bdf31d6bf990fd8b720cb44e27a97d80db5/propcache-0.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5b113feeda47f908562d9a6d0e05798ad2f83d4473c0777dafa2bc7756473218", size = 204442, upload-time = "2025-10-04T21:56:01.93Z" },
|
{ url = "https://files.pythonhosted.org/packages/f1/8b/544bc867e24e1bd48f3118cecd3b05c694e160a168478fa28770f22fd094/propcache-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d472aeb4fbf9865e0c6d622d7f4d54a4e101a89715d8904282bb5f9a2f476c3f", size = 204442, upload-time = "2025-10-08T19:47:16.277Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/30/ae2eec96995a8a760acb9a0b6c92b9815f1fc885c7d8481237ccb554eab0/propcache-0.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4596c12aa7e3bb2abf158ea8f79eb0fb4851606695d04ab846b2bb386f5690a1", size = 199371, upload-time = "2025-10-04T21:56:03.25Z" },
|
{ url = "https://files.pythonhosted.org/packages/50/a6/4282772fd016a76d3e5c0df58380a5ea64900afd836cec2c2f662d1b9bb3/propcache-0.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4d3df5fa7e36b3225954fba85589da77a0fe6a53e3976de39caf04a0db4c36f1", size = 199398, upload-time = "2025-10-08T19:47:17.962Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/45/1d/a18fac8cb04f8379ccb79cf15aac31f4167a270d1cd1111f33c0d38ce4fb/propcache-0.4.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6d1f67dad8cc36e8abc2207a77f3f952ac80be7404177830a7af4635a34cbc16", size = 196638, upload-time = "2025-10-04T21:56:04.619Z" },
|
{ url = "https://files.pythonhosted.org/packages/3e/ec/d8a7cd406ee1ddb705db2139f8a10a8a427100347bd698e7014351c7af09/propcache-0.4.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:ee17f18d2498f2673e432faaa71698032b0127ebf23ae5974eeaf806c279df24", size = 196920, upload-time = "2025-10-08T19:47:19.355Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/48/45/3549a2b6f74dce6f21b2664d078bd26ceb876aae9c58f3c017cf590f0ee3/propcache-0.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:e6229ad15366cd8b6d6b4185c55dd48debf9ca546f91416ba2e5921ad6e210a6", size = 203651, upload-time = "2025-10-04T21:56:06.153Z" },
|
{ url = "https://files.pythonhosted.org/packages/f6/6c/f38ab64af3764f431e359f8baf9e0a21013e24329e8b85d2da32e8ed07ca/propcache-0.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:580e97762b950f993ae618e167e7be9256b8353c2dcd8b99ec100eb50f5286aa", size = 203748, upload-time = "2025-10-08T19:47:21.338Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7d/f0/90ea14d518c919fc154332742a9302db3004af4f1d3df688676959733283/propcache-0.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2a4bf309d057327f1f227a22ac6baf34a66f9af75e08c613e47c4d775b06d6c7", size = 205726, upload-time = "2025-10-04T21:56:07.955Z" },
|
{ url = "https://files.pythonhosted.org/packages/d6/e3/fa846bd70f6534d647886621388f0a265254d30e3ce47e5c8e6e27dbf153/propcache-0.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:501d20b891688eb8e7aa903021f0b72d5a55db40ffaab27edefd1027caaafa61", size = 205877, upload-time = "2025-10-08T19:47:23.059Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f6/de/8efc1dbafeb42108e7af744822cdca944b990869e9da70e79efb21569d6b/propcache-0.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c2e274f3d1cbb2ddcc7a55ce3739af0f8510edc68a7f37981b2258fa1eedc833", size = 199576, upload-time = "2025-10-04T21:56:09.43Z" },
|
{ url = "https://files.pythonhosted.org/packages/e2/39/8163fc6f3133fea7b5f2827e8eba2029a0277ab2c5beee6c1db7b10fc23d/propcache-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a0bd56e5b100aef69bd8562b74b46254e7c8812918d3baa700c8a8009b0af66", size = 199437, upload-time = "2025-10-08T19:47:24.445Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d7/38/4d79fe3477b050398fb8d8f59301ed116d8c6ea3c4dbf09498c679103f90/propcache-0.4.0-cp313-cp313-win32.whl", hash = "sha256:f114a3e1f8034e2957d34043b7a317a8a05d97dfe8fddb36d9a2252c0117dbbc", size = 37474, upload-time = "2025-10-04T21:56:10.74Z" },
|
{ url = "https://files.pythonhosted.org/packages/93/89/caa9089970ca49c7c01662bd0eeedfe85494e863e8043565aeb6472ce8fe/propcache-0.4.1-cp313-cp313-win32.whl", hash = "sha256:bcc9aaa5d80322bc2fb24bb7accb4a30f81e90ab8d6ba187aec0744bc302ad81", size = 37586, upload-time = "2025-10-08T19:47:25.736Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/36/9b/a283daf665a1945cff1b03d1104e7c9ee92bb7b6bbcc6518b24fcdac8bd0/propcache-0.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ba68c57cde9c667f6b65b98bc342dfa7240b1272ffb2c24b32172ee61b6d281", size = 40685, upload-time = "2025-10-04T21:56:11.896Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/ab/f76ec3c3627c883215b5c8080debb4394ef5a7a29be811f786415fc1e6fd/propcache-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:381914df18634f5494334d201e98245c0596067504b9372d8cf93f4bb23e025e", size = 40790, upload-time = "2025-10-08T19:47:26.847Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e9/f7/def8fc0b4d7a89f1628f337cb122bb9a946c5ed97760f2442b27b7fa5a69/propcache-0.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb77a85253174bf73e52c968b689d64be62d71e8ac33cabef4ca77b03fb4ef92", size = 37046, upload-time = "2025-10-04T21:56:13.021Z" },
|
{ url = "https://files.pythonhosted.org/packages/59/1b/e71ae98235f8e2ba5004d8cb19765a74877abf189bc53fc0c80d799e56c3/propcache-0.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:8873eb4460fd55333ea49b7d189749ecf6e55bf85080f11b1c4530ed3034cba1", size = 37158, upload-time = "2025-10-08T19:47:27.961Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ca/6b/f6e8b36b58d17dfb6c505b9ae1163fcf7a4cf98825032fdc77bba4ab5c4a/propcache-0.4.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:c0e1c218fff95a66ad9f2f83ad41a67cf4d0a3f527efe820f57bde5fda616de4", size = 81274, upload-time = "2025-10-04T21:56:14.206Z" },
|
{ url = "https://files.pythonhosted.org/packages/83/ce/a31bbdfc24ee0dcbba458c8175ed26089cf109a55bbe7b7640ed2470cfe9/propcache-0.4.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:92d1935ee1f8d7442da9c0c4fa7ac20d07e94064184811b685f5c4fada64553b", size = 81451, upload-time = "2025-10-08T19:47:29.445Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/8e/c5/1fd0baa222b8faf53ba04dd4f34de33ea820b80e34f87c7960666bae5f4f/propcache-0.4.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:5710b1c01472542bb024366803812ca13e8774d21381bcfc1f7ae738eeb38acc", size = 46232, upload-time = "2025-10-04T21:56:15.337Z" },
|
{ url = "https://files.pythonhosted.org/packages/25/9c/442a45a470a68456e710d96cacd3573ef26a1d0a60067e6a7d5e655621ed/propcache-0.4.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:473c61b39e1460d386479b9b2f337da492042447c9b685f28be4f74d3529e566", size = 46374, upload-time = "2025-10-08T19:47:30.579Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/cb/6b/7aa5324983cab7666ed58fc32c68a0430468a18e02e3f04e7a879c002414/propcache-0.4.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d7f008799682e8826ce98f25e8bc43532d2cd26c187a1462499fa8d123ae054f", size = 48239, upload-time = "2025-10-04T21:56:16.768Z" },
|
{ url = "https://files.pythonhosted.org/packages/f4/bf/b1d5e21dbc3b2e889ea4327044fb16312a736d97640fb8b6aa3f9c7b3b65/propcache-0.4.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:c0ef0aaafc66fbd87842a3fe3902fd889825646bc21149eafe47be6072725835", size = 48396, upload-time = "2025-10-08T19:47:31.79Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/24/0f/58c192301c0436762ed5fed5a3edadb0ae399cb73528fb9c1b5cb8e53523/propcache-0.4.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0596d2ae99d74ca436553eb9ce11fe4163dc742fcf8724ebe07d7cb0db679bb1", size = 275804, upload-time = "2025-10-04T21:56:18.066Z" },
|
{ url = "https://files.pythonhosted.org/packages/f4/04/5b4c54a103d480e978d3c8a76073502b18db0c4bc17ab91b3cb5092ad949/propcache-0.4.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f95393b4d66bfae908c3ca8d169d5f79cd65636ae15b5e7a4f6e67af675adb0e", size = 275950, upload-time = "2025-10-08T19:47:33.481Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f7/b9/092ee32064ebfabedae4251952787e63e551075af1a1205e8061b3ed5838/propcache-0.4.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ab9c1bd95ebd1689f0e24f2946c495808777e9e8df7bb3c1dfe3e9eb7f47fe0d", size = 273996, upload-time = "2025-10-04T21:56:19.801Z" },
|
{ url = "https://files.pythonhosted.org/packages/b4/c1/86f846827fb969c4b78b0af79bba1d1ea2156492e1b83dea8b8a6ae27395/propcache-0.4.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c07fda85708bc48578467e85099645167a955ba093be0a2dcba962195676e859", size = 273856, upload-time = "2025-10-08T19:47:34.906Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/43/82/becf618ed28e732f3bba3df172cd290a1afbd99f291074f747fd5bd031bb/propcache-0.4.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a8ef2ea819549ae2e8698d2ec229ae948d7272feea1cb2878289f767b6c585a4", size = 280266, upload-time = "2025-10-04T21:56:21.136Z" },
|
{ url = "https://files.pythonhosted.org/packages/36/1d/fc272a63c8d3bbad6878c336c7a7dea15e8f2d23a544bda43205dfa83ada/propcache-0.4.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:af223b406d6d000830c6f65f1e6431783fc3f713ba3e6cc8c024d5ee96170a4b", size = 280420, upload-time = "2025-10-08T19:47:36.338Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/51/be/b370930249a9332a81b5c4c550dac614b7e11b6c160080777e903d57e197/propcache-0.4.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:71a400b2f0b079438cc24f9a27f02eff24d8ef78f2943f949abc518b844ade3d", size = 263186, upload-time = "2025-10-04T21:56:22.787Z" },
|
{ url = "https://files.pythonhosted.org/packages/07/0c/01f2219d39f7e53d52e5173bcb09c976609ba30209912a0680adfb8c593a/propcache-0.4.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a78372c932c90ee474559c5ddfffd718238e8673c340dc21fe45c5b8b54559a0", size = 263254, upload-time = "2025-10-08T19:47:37.692Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/33/b6/546fd3e31770aed3aed1c01b120944c689edb510aeb7a25472edc472ce23/propcache-0.4.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4c2735d3305e6cecab6e53546909edf407ad3da5b9eeaf483f4cf80142bb21be", size = 260721, upload-time = "2025-10-04T21:56:24.22Z" },
|
{ url = "https://files.pythonhosted.org/packages/2d/18/cd28081658ce597898f0c4d174d4d0f3c5b6d4dc27ffafeef835c95eb359/propcache-0.4.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:564d9f0d4d9509e1a870c920a89b2fec951b44bf5ba7d537a9e7c1ccec2c18af", size = 261205, upload-time = "2025-10-08T19:47:39.659Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/80/70/3751930d16e5984490c73ca65b80777e4b26e7a0015f2d41f31d75959a71/propcache-0.4.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:72b51340047ac43b3cf388eebd362d052632260c9f73a50882edbb66e589fd44", size = 247516, upload-time = "2025-10-04T21:56:25.577Z" },
|
{ url = "https://files.pythonhosted.org/packages/7a/71/1f9e22eb8b8316701c2a19fa1f388c8a3185082607da8e406a803c9b954e/propcache-0.4.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:17612831fda0138059cc5546f4d12a2aacfb9e47068c06af35c400ba58ba7393", size = 247873, upload-time = "2025-10-08T19:47:41.084Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/90/4bc96ce6476f67e2e6b72469f328c92b53259a0e4d1d5386d71a36e9258c/propcache-0.4.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:184c779363740d6664982ad05699f378f7694220e2041996f12b7c2a4acdcad0", size = 262675, upload-time = "2025-10-04T21:56:27.065Z" },
|
{ url = "https://files.pythonhosted.org/packages/4a/65/3d4b61f36af2b4eddba9def857959f1016a51066b4f1ce348e0cf7881f58/propcache-0.4.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:41a89040cb10bd345b3c1a873b2bf36413d48da1def52f268a055f7398514874", size = 262739, upload-time = "2025-10-08T19:47:42.51Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/d1/f16d096869c5f1c93d67fc37488c0c814add0560574f6877653a10239cde/propcache-0.4.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:a60634a9de41f363923c6adfb83105d39e49f7a3058511563ed3de6748661af6", size = 263379, upload-time = "2025-10-04T21:56:28.517Z" },
|
{ url = "https://files.pythonhosted.org/packages/2a/42/26746ab087faa77c1c68079b228810436ccd9a5ce9ac85e2b7307195fd06/propcache-0.4.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e35b88984e7fa64aacecea39236cee32dd9bd8c55f57ba8a75cf2399553f9bd7", size = 263514, upload-time = "2025-10-08T19:47:43.927Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ab/2a/da5cd1bc1c6412939c457ea65bbe7e034045c395d98ff8ff880d06ec4553/propcache-0.4.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8119244d122241a9c4566bce49bb20408a6827044155856735cf14189a7da", size = 257694, upload-time = "2025-10-04T21:56:30.051Z" },
|
{ url = "https://files.pythonhosted.org/packages/94/13/630690fe201f5502d2403dd3cfd451ed8858fe3c738ee88d095ad2ff407b/propcache-0.4.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f8b465489f927b0df505cbe26ffbeed4d6d8a2bbc61ce90eb074ff129ef0ab1", size = 257781, upload-time = "2025-10-08T19:47:45.448Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/a5/11/938e67c07189b662a6c72551d48285a02496de885408392447c25657dd47/propcache-0.4.0-cp313-cp313t-win32.whl", hash = "sha256:515b610a364c8cdd2b72c734cc97dece85c416892ea8d5c305624ac8734e81db", size = 41321, upload-time = "2025-10-04T21:56:31.406Z" },
|
{ url = "https://files.pythonhosted.org/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717", size = 41396, upload-time = "2025-10-08T19:47:47.202Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/6e/72b11a4dcae68c728b15126cc5bc830bf275c84836da2633412b768d07e0/propcache-0.4.0-cp313-cp313t-win_amd64.whl", hash = "sha256:7ea86eb32e74f9902df57e8608e8ac66f1e1e1d24d1ed2ddeb849888413b924d", size = 44846, upload-time = "2025-10-04T21:56:32.5Z" },
|
{ url = "https://files.pythonhosted.org/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37", size = 44897, upload-time = "2025-10-08T19:47:48.336Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/94/09/0ef3c025e0621e703ef71b69e0085181a3124bcc1beef29e0ffef59ed7f4/propcache-0.4.0-cp313-cp313t-win_arm64.whl", hash = "sha256:c1443fa4bb306461a3a8a52b7de0932a2515b100ecb0ebc630cc3f87d451e0a9", size = 39689, upload-time = "2025-10-04T21:56:33.686Z" },
|
{ url = "https://files.pythonhosted.org/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a", size = 39789, upload-time = "2025-10-08T19:47:49.876Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/60/89/7699d8e9f8c222bbef1fae26afd72d448353f164a52125d5f87dd9fec2c7/propcache-0.4.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:de8e310d24b5a61de08812dd70d5234da1458d41b059038ee7895a9e4c8cae79", size = 77977, upload-time = "2025-10-04T21:56:34.836Z" },
|
{ url = "https://files.pythonhosted.org/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12", size = 78152, upload-time = "2025-10-08T19:47:51.051Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/77/c5/2758a498199ce46d6d500ba4391a8594df35400cc85738aa9f0c9b8366db/propcache-0.4.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:55a54de5266bc44aa274915cdf388584fa052db8748a869e5500ab5993bac3f4", size = 44715, upload-time = "2025-10-04T21:56:36.075Z" },
|
{ url = "https://files.pythonhosted.org/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c", size = 44869, upload-time = "2025-10-08T19:47:52.594Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0d/da/5a44e10282a28c2dd576e5e1a2c7bb8145587070ddab7375fb643f7129d7/propcache-0.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:88d50d662c917ec2c9d3858920aa7b9d5bfb74ab9c51424b775ccbe683cb1b4e", size = 46463, upload-time = "2025-10-04T21:56:37.227Z" },
|
{ url = "https://files.pythonhosted.org/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded", size = 46596, upload-time = "2025-10-08T19:47:54.073Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d5/5a/b2c314f655f46c10c204dc0d69e19fadfb1cc4d40ab33f403698a35c3281/propcache-0.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae3adf88a66f5863cf79394bc359da523bb27a2ed6ba9898525a6a02b723bfc5", size = 206980, upload-time = "2025-10-04T21:56:38.828Z" },
|
{ url = "https://files.pythonhosted.org/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641", size = 206981, upload-time = "2025-10-08T19:47:55.715Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7c/4e/f6643ec2cd5527b92c93488f9b67a170494736bb1c5460136399d709ce5a/propcache-0.4.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7f088e21d15b3abdb9047e4b7b7a0acd79bf166893ac2b34a72ab1062feb219e", size = 211385, upload-time = "2025-10-04T21:56:40.2Z" },
|
{ url = "https://files.pythonhosted.org/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4", size = 211490, upload-time = "2025-10-08T19:47:57.499Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/71/41/362766a346c3f8d3bbeb7899e1ff40f18844e0fe37e9f6f536553cf6b6be/propcache-0.4.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a4efbaf10793fd574c76a5732c75452f19d93df6e0f758c67dd60552ebd8614b", size = 215315, upload-time = "2025-10-04T21:56:41.574Z" },
|
{ url = "https://files.pythonhosted.org/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44", size = 215371, upload-time = "2025-10-08T19:47:59.317Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ff/98/17385d51816d56fa6acc035d8625fbf833b6a795d7ef7fb37ea3f62db6c9/propcache-0.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:681a168d06284602d56e97f09978057aa88bcc4177352b875b3d781df4efd4cb", size = 201416, upload-time = "2025-10-04T21:56:42.947Z" },
|
{ url = "https://files.pythonhosted.org/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d", size = 201424, upload-time = "2025-10-08T19:48:00.67Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/7a/83/801178ca1c29e217564ee507ff2a49d3f24a4dd85c9b9d681fd1d62b15f2/propcache-0.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a7f06f077fc4ef37e8a37ca6bbb491b29e29db9fb28e29cf3896aad10dbd4137", size = 197726, upload-time = "2025-10-04T21:56:44.313Z" },
|
{ url = "https://files.pythonhosted.org/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b", size = 197566, upload-time = "2025-10-08T19:48:02.604Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/d2/38/c8743917bca92b7e5474366b6b04c7b3982deac32a0fe4b705f2e92c09bb/propcache-0.4.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:082a643479f49a6778dcd68a80262fc324b14fd8e9b1a5380331fe41adde1738", size = 192819, upload-time = "2025-10-04T21:56:45.702Z" },
|
{ url = "https://files.pythonhosted.org/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e", size = 193130, upload-time = "2025-10-08T19:48:04.499Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0b/74/3de3ef483e8615aaaf62026fcdcb20cbfc4535ea14871b12f72d52c1d6dc/propcache-0.4.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:26692850120241a99bb4a4eec675cd7b4fdc431144f0d15ef69f7f8599f6165f", size = 202492, upload-time = "2025-10-04T21:56:47.388Z" },
|
{ url = "https://files.pythonhosted.org/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f", size = 202625, upload-time = "2025-10-08T19:48:06.213Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/86/a130dd85199d651a6986ba6bf1ce297b7bbcafc01c8e139e6ba2b8218a20/propcache-0.4.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:33ad7d37b9a386f97582f5d042cc7b8d4b3591bb384cf50866b749a17e4dba90", size = 204106, upload-time = "2025-10-04T21:56:49.139Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49", size = 204209, upload-time = "2025-10-08T19:48:08.432Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b2/f7/44eab58659d71d21995146c94139e63882bac280065b3a9ed10376897bcc/propcache-0.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e7fd82d4a5b7583588f103b0771e43948532f1292105f13ee6f3b300933c4ca", size = 198043, upload-time = "2025-10-04T21:56:50.561Z" },
|
{ url = "https://files.pythonhosted.org/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144", size = 197797, upload-time = "2025-10-08T19:48:09.968Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/96/14/df37be1bf1423d2dda201a4cdb1c5cb44048d34e31a97df227cc25b0a55c/propcache-0.4.0-cp314-cp314-win32.whl", hash = "sha256:213eb0d3bc695a70cffffe11a1c2e1c2698d89ffd8dba35a49bc44a035d45c93", size = 38036, upload-time = "2025-10-04T21:56:51.868Z" },
|
{ url = "https://files.pythonhosted.org/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f", size = 38140, upload-time = "2025-10-08T19:48:11.232Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/99/96/9cea65d6c50224737e80c57a3f3db4ca81bc7b1b52bc73346df8c50db400/propcache-0.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:087e2d3d7613e1b59b2ffca0daabd500c1a032d189c65625ee05ea114afcad0b", size = 41156, upload-time = "2025-10-04T21:56:53.242Z" },
|
{ url = "https://files.pythonhosted.org/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153", size = 41257, upload-time = "2025-10-08T19:48:12.707Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/52/4d/91523dcbe23cc127b097623a6ba177da51fca6b7c979082aa49745b527b7/propcache-0.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:94b0f7407d18001dbdcbb239512e753b1b36725a6e08a4983be1c948f5435f79", size = 37976, upload-time = "2025-10-04T21:56:54.351Z" },
|
{ url = "https://files.pythonhosted.org/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992", size = 38097, upload-time = "2025-10-08T19:48:13.923Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/f7/7118a944cb6cdb548c9333cf311bda120f9793ecca54b2ca4a3f7e58723e/propcache-0.4.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b730048ae8b875e2c0af1a09ca31b303fc7b5ed27652beec03fa22b29545aec9", size = 81270, upload-time = "2025-10-04T21:56:55.516Z" },
|
{ url = "https://files.pythonhosted.org/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f", size = 81455, upload-time = "2025-10-08T19:48:15.16Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ab/f9/04a8bc9977ea201783f3ccb04106f44697f635f70439a208852d4d08554d/propcache-0.4.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:f495007ada16a4e16312b502636fafff42a9003adf1d4fb7541e0a0870bc056f", size = 46224, upload-time = "2025-10-04T21:56:56.695Z" },
|
{ url = "https://files.pythonhosted.org/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393", size = 46372, upload-time = "2025-10-08T19:48:16.424Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/0f/3d/808b074034156f130a0047304d811a5a5df3bb0976c9adfb9383718fd888/propcache-0.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:659a0ea6d9017558ed7af00fb4028186f64d0ba9adfc70a4d2c85fcd3d026321", size = 48246, upload-time = "2025-10-04T21:56:57.926Z" },
|
{ url = "https://files.pythonhosted.org/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0", size = 48411, upload-time = "2025-10-08T19:48:17.577Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/66/eb/e311f3a59ddc93078cb079b12699af9fd844142c4b4d382b386ee071d921/propcache-0.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d74aa60b1ec076d4d5dcde27c9a535fc0ebb12613f599681c438ca3daa68acac", size = 275562, upload-time = "2025-10-04T21:56:59.221Z" },
|
{ url = "https://files.pythonhosted.org/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a", size = 275712, upload-time = "2025-10-08T19:48:18.901Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/f4/05/a146094d6a00bb2f2036dd2a2f4c2b2733ff9574b59ce53bd8513edfca5d/propcache-0.4.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34000e31795bdcda9826e0e70e783847a42e3dcd0d6416c5d3cb717905ebaec0", size = 273627, upload-time = "2025-10-04T21:57:00.582Z" },
|
{ url = "https://files.pythonhosted.org/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be", size = 273557, upload-time = "2025-10-08T19:48:20.762Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/91/95/a6d138f6e3d5f6c9b34dbd336b964a1293f2f1a79cafbe70ae3403d7cc46/propcache-0.4.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:bcb5bfac5b9635e6fc520c8af6efc7a0a56f12a1fe9e9d3eb4328537e316dd6a", size = 279778, upload-time = "2025-10-04T21:57:01.944Z" },
|
{ url = "https://files.pythonhosted.org/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc", size = 280015, upload-time = "2025-10-08T19:48:22.592Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ac/09/19594a20da0519bfa00deef8cf35dda6c9a5b51bba947f366e85ea59b3de/propcache-0.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ea11fceb31fa95b0fa2007037f19e922e2caceb7dc6c6cac4cb56e2d291f1a2", size = 262833, upload-time = "2025-10-04T21:57:03.326Z" },
|
{ url = "https://files.pythonhosted.org/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a", size = 262880, upload-time = "2025-10-08T19:48:23.947Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/b5/92/60d2ddc7662f7b2720d3b628ad8ce888015f4ab5c335b7b1b50183194e68/propcache-0.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:cd8684f628fe285ea5c86f88e1c30716239dc9d6ac55e7851a4b7f555b628da3", size = 260456, upload-time = "2025-10-04T21:57:05.159Z" },
|
{ url = "https://files.pythonhosted.org/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89", size = 260938, upload-time = "2025-10-08T19:48:25.656Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/6f/e2/4c2e25c77cf43add2e05a86c4fcf51107edc4d92318e5c593bbdc2515d57/propcache-0.4.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:790286d3d542c0ef9f6d0280d1049378e5e776dcba780d169298f664c39394db", size = 247284, upload-time = "2025-10-04T21:57:06.566Z" },
|
{ url = "https://files.pythonhosted.org/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726", size = 247641, upload-time = "2025-10-08T19:48:27.207Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/3e/c273ab8edc80683ec8b15b486e95c03096ef875d99e4b0ab0a36c1e42c94/propcache-0.4.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:009093c9b5dbae114a5958e6a649f8a5d94dd6866b0f82b60395eb92c58002d4", size = 262368, upload-time = "2025-10-04T21:57:08.231Z" },
|
{ url = "https://files.pythonhosted.org/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367", size = 262510, upload-time = "2025-10-08T19:48:28.65Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/ac/a9/3fa231f65a9f78614c5aafa9cee788d7f55c22187cc2f33e86c7c16d0262/propcache-0.4.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:728d98179e92d77096937fdfecd2c555a3d613abe56c9909165c24196a3b5012", size = 263010, upload-time = "2025-10-04T21:57:09.641Z" },
|
{ url = "https://files.pythonhosted.org/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36", size = 263161, upload-time = "2025-10-08T19:48:30.133Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/38/a0/f4f5d368e60c9dc04d3158eaf1ca0ad899b40ac3d29c015bf62735225a6f/propcache-0.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a9725d96a81e17e48a0fe82d0c3de2f5e623d7163fec70a6c7df90753edd1bec", size = 257298, upload-time = "2025-10-04T21:57:11.125Z" },
|
{ url = "https://files.pythonhosted.org/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455", size = 257393, upload-time = "2025-10-08T19:48:31.567Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c7/30/f78d6758dc36a98f1cddc39b3185cefde616cc58248715b7c65495491cb1/propcache-0.4.0-cp314-cp314t-win32.whl", hash = "sha256:0964c55c95625193defeb4fd85f8f28a9a754ed012cab71127d10e3dc66b1373", size = 42484, upload-time = "2025-10-04T21:57:12.652Z" },
|
{ url = "https://files.pythonhosted.org/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85", size = 42546, upload-time = "2025-10-08T19:48:32.872Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/4e/ad/de0640e9b56d2caa796c4266d7d1e6cc4544cc327c25b7ced5c59893b625/propcache-0.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:24403152e41abf09488d3ae9c0c3bf7ff93e2fb12b435390718f21810353db28", size = 46229, upload-time = "2025-10-04T21:57:14.034Z" },
|
{ url = "https://files.pythonhosted.org/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1", size = 46259, upload-time = "2025-10-08T19:48:34.226Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/da/bf/5aed62dddbf2bbe62a3564677436261909c9dd63a0fa1fb6cf0629daa13c/propcache-0.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0363a696a9f24b37a04ed5e34c2e07ccbe92798c998d37729551120a1bb744c4", size = 40329, upload-time = "2025-10-04T21:57:15.198Z" },
|
{ url = "https://files.pythonhosted.org/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9", size = 40428, upload-time = "2025-10-08T19:48:35.441Z" },
|
||||||
{ url = "https://files.pythonhosted.org/packages/c7/16/794c114f6041bbe2de23eb418ef58a0f45de27224d5540f5dbb266a73d72/propcache-0.4.0-py3-none-any.whl", hash = "sha256:015b2ca2f98ea9e08ac06eecc409d5d988f78c5fd5821b2ad42bc9afcd6b1557", size = 13183, upload-time = "2025-10-04T21:57:38.054Z" },
|
{ url = "https://files.pythonhosted.org/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237", size = 13305, upload-time = "2025-10-08T19:49:00.792Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||