Add initial design suggestion index page

This commit is contained in:
2025-10-21 17:09:40 +13:00
parent de1dc75a12
commit 9ca94eeb42
10 changed files with 194 additions and 108 deletions

View File

@ -1,5 +1,26 @@
@import "tailwindcss"; @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 */ /* Tell Tailwind where to find Django templates and Python files */
@source "../../templates"; @source "../../templates";

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 21 KiB

BIN
static/images/uoa-logo-small.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -4,7 +4,7 @@
<head> <head>
<title>{{ title }}</title> <title>{{ title }}</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="csrf-token" content="{{ csrf_token }}"> <meta name="csrf-token" content="{{ csrf_token }}">
{# Favicon #} {# Favicon #}

View File

@ -1,17 +1,18 @@
{% load static %} {% load static %}
<div class="lg:max-w-2/3 mx-auto bg-base-200 text-base-content"> <div class="lg:max-w-5xl mt-10 mx-auto bg-base-300 text-base-content">
<footer class="footer sm:footer-horizontal p-10"> <footer class="footer sm:footer-horizontal p-10">
<nav> <nav>
<h6 class="footer-title">Predict</h6> <h6 class="footer-title">Services</h6>
<a class="link link-hover">Predict</a>
<a class="link link-hover">Search</a> <a class="link link-hover">Search</a>
<a class="link link-hover">Design</a> <a class="link link-hover">Browse</a>
<a class="link link-hover">Marketing</a> <a class="link link-hover">Modelling</a>
<a class="link link-hover">Advertisement</a>
</nav> </nav>
<nav> <nav>
<h6 class="footer-title">Company</h6> <h6 class="footer-title">Company</h6>
<a class="link link-hover">About us</a> <a class="link link-hover">About us</a>
<a class="link link-hover">Support</a>
<a class="link link-hover">Contact</a> <a class="link link-hover">Contact</a>
<a class="link link-hover">Jobs</a> <a class="link link-hover">Jobs</a>
</nav> </nav>
@ -23,7 +24,7 @@
<a class="link link-hover">Cite enviPath</a> <a class="link link-hover">Cite enviPath</a>
</nav> </nav>
</footer> </footer>
<footer class="footer border-neutral-200 border-t-2 px-10 py-4"> <footer class="footer border-neutral-300 border-t-2 px-10 py-4">
<aside class="grid-flow-col items-center"> <aside class="grid-flow-col items-center">
<svg class="fill-neutral-content flex-shrink-0 h-14 m-2" viewbox="0 0 65 65" > <svg class="fill-neutral-content flex-shrink-0 h-14 m-2" viewbox="0 0 65 65" >
<use <use

View File

@ -1,9 +1,11 @@
{% load static %} {% load static %}
{# Modern DaisyUI Navbar #} {# Modern DaisyUI Navbar #}
<div class="navbar bg-neutral-50 text-neutral-950 shadow-lg"> <div class="navbar bg-neutral-50 text-neutral-950 shadow-lg x-50">
<div class="navbar-start"> <div class="navbar-start">
<a href="{{ meta.server_url }}" class="btn btn-ghost normal-case text-xl"> <a href="{{ meta.server_url }}" class="btn btn-ghost normal-case text-xl">
<img src='{% static "/images/logo-short-white.svg" %}' width="100" class="fill-neutral-950" alt="enviPath"> <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> </a>
</div> </div>

View File

@ -3,18 +3,29 @@
{% block main_content %} {% block main_content %}
<!-- Hero Section with Logo and Search --> <!-- Hero Section with Logo and Search -->
<section class="hero min-h-[calc(100vh*0.7)] w-full shadow-none" <section class="hero h-fit max-w-5xl w-full shadow-none mx-auto relative">
<div class="hero min-h-[calc(100vh*0.4)]"
style="background-image: url('{% static "/images/hero.png" %}'); background-size: cover; background-position: center;"> style="background-image: url('{% static "/images/hero.png" %}'); background-size: cover; background-position: center;">
<div class="hero-overlay"></div>
<!-- Predict Pathway text over the image -->
<div class="absolute bottom-40 left-1/8 -translate-x-8 z-10">
<h2 class="text-3xl text-base-100 text-shadow-lg text-left">Predict Your Pathway</h2>
</div>
</div>
</section>
<div class="hero-overlay blur-xs"></div> <div class="shadow-md max-w-5xl mx-auto bg-base-200">
<div class="hero-content flex-col lg:flex-row-reverse w-full h-fit"> <!-- Predict Pathway Section -->
<div class="card bg-base-100 shrink-0 shadow-2xl p-8 w-3/4"> <div class="flex-col lg:flex-row-reverse w-full mx-auto -mt-32 relative z-20 mb-10 ">
<div class="card bg-base-100 shrink-0 shadow-xl w-3/4 mx-auto transition-all duration-300 ease-in-out">
<div class="card-body"> <div class="card-body">
<fieldset class="fieldset"> <!-- Input Mode Toggle - Fixed position outside fieldset -->
<div class="flex flex-row justify-between items-center h-fit"> <div class="flex flex-row justify-start items-center h-fit ml-8 my-4">
<h2 class="card-title text-xl text-neutral-600">Predict Pathway</h2> <div class="flex items-center gap-2">
<label class="toggle text-base-content toggle-xl justify-self-end mb-6 align-baseline"> <!-- <span class="text-sm text-neutral-500">Input Mode:</span> -->
<label class="toggle text-base-content toggle-md">
<input type="checkbox" /> <input type="checkbox" />
<svg aria-label="smiles mode" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="size-5"> <svg aria-label="smiles mode" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="size-5">
<g <g
@ -40,23 +51,29 @@
</svg> </svg>
</label> </label>
</div> </div>
</div>
<fieldset class="fieldset transition-all duration-300 ease-in-out overflow-hidden">
<form id="index-form" action="{{ meta.current_package.url }}/pathway" method="POST"> <form id="index-form" action="{{ meta.current_package.url }}/pathway" method="POST">
{% csrf_token %} {% csrf_token %}
<div id="text-input-container" class="transition-all duration-300 ease-in-out opacity-100 transform scale-100"> <div id="text-input-container" class="transition-all duration-300 ease-in-out opacity-100 transform scale-100">
<div class="join w-full mx-auto"> <div class="join w-full mx-auto">
<input type="text" id="index-form-text-input" placeholder="cannonical SMILES string" class="input grow input-lg join-item" /> <input type="text" id="index-form-text-input" placeholder="cannonical SMILES string" class="input grow input-md join-item" />
<button class="btn btn-lg bg-primary-950 text-primary-50 join-item">Predict!</button> <button class="btn btn-neutral join-item">Predict!</button>
</div> </div>
<div class="label flex flex-row gap-2 w-full mt-1" > <div class="label relative w-full mt-1" >
<div class="flex gap-2">
<a href="#">Example 1</a> <a href="#">Example 1</a>
<a href="#">Example 2</a> <a href="#">Example 2</a>
<a class="ml-auto w-[9em]" href="#">Advanced </a> <!-- TODO: positioning a bit sloppy. Better reference button? --> </div>
<a class="absolute top-0 left-[calc(100%-5.4rem)]" href="#">Advanced</a>
</div> </div>
</div> </div>
<div id="ketcher-container" class="hidden w-full transition-all duration-300 ease-in-out opacity-0 transform scale-95"> <div id="ketcher-container" class="hidden w-full transition-all duration-300 ease-in-out opacity-0 transform scale-95">
<iframe id="index-ketcher" src="{% static '/js/ketcher2/ketcher.html' %}" <iframe id="index-ketcher" src="{% static '/js/ketcher2/ketcher.html' %}"
width="100%" height="510"></iframe> width="100%" height="400" class="rounded-lg"></iframe>
<button class="btn btn-lg bg-primary-950 text-primary-50 join-item w-full mt-2">Predict!</button> <button class="btn btn-lg bg-primary-950 text-primary-50 join-item w-full mt-2">Predict!</button>
<a class="label mx-auto w-full mt-1" href="#">Advanced</a>
</div> </div>
<input type="hidden" id="index-form-smiles" name="smiles" value="smiles"> <input 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="index-form-predict" name="predict" value="predict">
@ -67,19 +84,11 @@
</div> </div>
</div> </div>
<div class="hero-overlay"></div>
<div class="hero-content text-neutral-content text-center">
<div class="max-w-md">
</div>
</div>
</div>
</section>
<!-- Community News Section --> <!-- Community News Section -->
<section class="py-16 bg-base-200"> <section class="py-16 bg-base-200 z-10 mx-8">
<div class="max-w-7xl mx-auto px-4"> <div class="max-w-7xl mx-auto px-4">
<h2 class="text-3xl font-bold text-center mb-8">Community Updates</h2> <h2 class="h2 font-bold text-left mb-8">Community Updates</h2>
<div id="community-news-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div id="community-news-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- News cards will be populated here --> <!-- News cards will be populated here -->
@ -100,31 +109,54 @@
</div> </div>
</section> </section>
<!-- Partners Section -->
<section class="py-14 sm:py-12 from-base-200 to-base-100 bg-gradient-to-b">
<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>
<!-- Mission Statement Section --> <!-- Mission Statement Section -->
<section class="py-16 bg-base-100"> <section class="py-16 bg-base-100">
<div class="max-w-4xl mx-auto px-4"> <div class="mx-auto px-8 md:px-12">
<h2 class="text-3xl font-bold text-center mb-8">About enviPath</h2> <div class="flex flex-row gap-4">
<div class="space-y-4 text-center"> <div class="w-1/3">
<p class="text-lg"> <img src="{% static "/images/ep-rule-artwork.png" %}" alt="rule-based iterative tree greneration" class="w-full h-full object-contain" />
</div>
<div class="space-y-4 text-left w-2/3 mr-8">
<h2 class="h2 font-bold mb-8">About enviPath</h2>
<p class="">
enviPath is a database and prediction system for the microbial enviPath is a database and prediction system for the microbial
biotransformation of organic environmental contaminants. The biotransformation of organic environmental contaminants. The
database provides the possibility to store and view experimentally database provides the possibility to store and view experimentally
observed biotransformation pathways. observed biotransformation pathways.
</p> </p>
<p class="text-lg"> <p class="">
The pathway prediction system provides different relative reasoning models The pathway prediction system provides different relative reasoning models
to predict likely biotransformation pathways and products. Explore our tools to predict likely biotransformation pathways and products. Explore our tools
and contribute to advancing environmental biotransformation research. and contribute to advancing environmental biotransformation research.
</p> </p>
<a href="/about" class="float-right btn btn-ghost-neutral">Read More</a>
</div> </div>
</div> </div>
</div>
</section> </section>
</div>
<script language="javascript"> <script language="javascript">
var currentPackage = "{{ meta.current_package.url }}"; var currentPackage = "{{ meta.current_package.url }}";
// Process discourse topics into individual cards // Process discourse topics into individual cards
function processDiscourseTopics() { function processDiscourseTopics(retryCount = 0) {
setTimeout(function() { setTimeout(function() {
const topicsList = $('#discourse-topics'); const topicsList = $('#discourse-topics');
if (topicsList.length && topicsList.find('li').length > 0) { if (topicsList.length && topicsList.find('li').length > 0) {
@ -161,10 +193,10 @@
}); });
} else { } else {
// Retry if not loaded yet // Retry if not loaded yet
if (index < 10) { if (retryCount < 10) {
processDiscourseTopics(); processDiscourseTopics(retryCount + 1);
} else { } else {
$('#loading').html('<p class="text-gray-500">Unable to load community updates</p>'); $('#loading').html('<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>');
} }
} }
}, 500); }, 500);
@ -175,27 +207,45 @@
const toggle = $('input[type="checkbox"]'); const toggle = $('input[type="checkbox"]');
const textContainer = $('#text-input-container'); const textContainer = $('#text-input-container');
const ketcherContainer = $('#ketcher-container'); const ketcherContainer = $('#ketcher-container');
const formCard = $('.card');
const fieldset = $('.fieldset');
if (toggle.is(':checked')) { if (toggle.is(':checked')) {
// Draw mode - show Ketcher, hide text input // Draw mode - show Ketcher, hide text input
textContainer.addClass('hidden opacity-0 transform scale-95'); textContainer.addClass('opacity-0 transform scale-95');
textContainer.removeClass('opacity-100 transform scale-100'); textContainer.removeClass('opacity-100 transform scale-100');
// Small delay to allow text container to fade out first // 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(() => { setTimeout(() => {
textContainer.addClass('hidden');
ketcherContainer.removeClass('hidden opacity-0 transform scale-95'); ketcherContainer.removeClass('hidden opacity-0 transform scale-95');
ketcherContainer.addClass('opacity-100 transform scale-100'); ketcherContainer.addClass('opacity-100 transform scale-100');
}, 150);
// Force re-evaluation of iframe size
const iframe = document.getElementById('index-ketcher');
if (iframe) {
iframe.style.height = '400px';
}
}, 300);
} else { } else {
// SMILES mode - show text input, hide Ketcher // SMILES mode - show text input, hide Ketcher
ketcherContainer.addClass('opacity-0 transform scale-95'); ketcherContainer.addClass('opacity-0 transform scale-95');
ketcherContainer.removeClass('opacity-100 transform scale-100'); ketcherContainer.removeClass('opacity-100 transform scale-100');
// Small delay to allow ketcher container to fade out first // 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(() => { setTimeout(() => {
ketcherContainer.addClass('hidden');
textContainer.removeClass('hidden opacity-0 transform scale-95'); textContainer.removeClass('hidden opacity-0 transform scale-95');
textContainer.addClass('opacity-100 transform scale-100'); textContainer.addClass('opacity-100 transform scale-100');
}, 150); }, 300);
// Transfer SMILES from Ketcher to text input if available // Transfer SMILES from Ketcher to text input if available
if (window.indexKetcher && window.indexKetcher.getSmiles) { if (window.indexKetcher && window.indexKetcher.getSmiles) {
@ -213,6 +263,9 @@
} }
$(function () { $(function () {
// Initialize fieldset with proper padding
$('.fieldset').addClass('p-8');
// Toggle event listener // Toggle event listener
$('input[type="checkbox"]').on('change', toggleInputMode); $('input[type="checkbox"]').on('change', toggleInputMode);