Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ test: ## Run tests with coverage
# Dashboard commands

serve-dev: ## Serve Panel dashboard - Dev mode
panel serve panel/app.py \
panel serve panel/simdec.py panel/sampling.py \
--index panel/index.html \
--show --autoreload \
--static-dirs _static=docs/_static \
--reuse-sessions --warm

serve-oauth: ## Serve Panel dashboard - Prod mode with OAuth2. Needs: PANEL_OAUTH_REDIRECT_URI, PANEL_OAUTH_KEY, PANEL_OAUTH_SECRET, PANEL_OAUTH_ENCRYPTION
PANEL_OAUTH_SCOPE=email panel serve panel/app.py \
PANEL_OAUTH_SCOPE=email panel serve panel/simdec.py panel/sampling.py \
--index panel/index.html \
--show \
--cookie-secret panel_cookie_secret_oauth \
--basic-login-template panel/login.html \
Expand Down
3 changes: 2 additions & 1 deletion panel/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ USER app
WORKDIR /app

# Run the web service on container startup.
CMD ["panel", "serve", "panel/app.py", \
CMD ["panel", "serve", "panel/simdec.py", "panel/sampling.py", \
"--address", "0.0.0.0", "--port", "8080", \
"--num-procs", "2", \
"--allow-websocket-origin", "simdec.io", \
Expand All @@ -72,6 +72,7 @@ CMD ["panel", "serve", "panel/app.py", \
"--basic-login-template", "panel/login.html", \
"--logout-template", "panel/logout.html", \
"--oauth-provider", "custom_google", \
"--index", "panel/index.html", \
"--static-dirs", "_static=_static", \
"--reuse-sessions", "--warm", \
"--global-loading-spinner"]
302 changes: 302 additions & 0 deletions panel/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,302 @@
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Basic Page Needs
-------------------------------------------------- -->
<meta charset="utf-8">
<title>Sensitivity Analysis Applications</title>

<!-- Mobile Specific Metas
-------------------------------------------------- -->
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- FONT
-------------------------------------------------- -->
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600&Lato|Work+Sans:400,700&display=swap" rel="stylesheet" type='text/css'>

<!-- CSS
-------------------------------------------------- -->
<style>*:not(:defined){visibility:hidden}</style>

<!-- Favicon
-------------------------------------------------- -->
<link rel="icon" type="image/x-icon" href="_static/icon.png">
<link rel="manifest" href="{{ PANEL_CDN }}images/site.webmanifest">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="theme-color" content="#ffffff">
<script type="module" src="{{ PANEL_CDN }}bundled/@microsoft/fast-components@2.30.6/dist/fast-components.js"></script>
<script type="module" src="{{ PANEL_CDN }}bundled/fast/js/fast_design.js"></script>
<script type="text/javascript">
function setParamsFromSearch(text){
const params = new URLSearchParams(location.search);
if (text===""){
params.delete("search")
} else {
params.set('search', text);
}
window.history.replaceState({}, '', `${location.pathname}?${params}`);
}
function hideCards(text) {
text=text.toLowerCase();
const cards = document.getElementsByTagName("li")
for (const card of cards){
if (text==="" || card.innerHTML.toLowerCase().includes(text)){
card.style.display=""
} else {card.style.display="none"}
}

setParamsFromSearch(text)
}
function toggleLightDarkTheme(update) {
const switchEl = document.getElementById("theme-switch")
const params = new URLSearchParams(location.search);
if (switchEl.checked) {
window.bodyDesign.setLuminance(1)
window.bodyDesign.setBackgroundColor("#ffffff")
params.set('theme', "default");
} else {
window.bodyDesign.setLuminance(0.1)
window.bodyDesign.setBackgroundColor("#000000")
params.set('theme', "dark");
}
if (update) {
window.history.replaceState({}, '', `${location.pathname}?${params}`);
}
}
function setSwitchFromParams(){
const params = new URLSearchParams(window.location.search)
if (params.has('theme')){
const theme = params.get('theme')
const switchEl = document.getElementById("theme-switch")
if (theme==='dark'){
switchEl.checked = false
} else {
switchEl.checked = true
}
toggleLightDarkTheme(true)
} else {
toggleLightDarkTheme(false)
}
}
function setSearchFromParams(){
const params = new URLSearchParams(window.location.search)
if (params.has('search')){
const search = params.get('search')
const searchEl = document.getElementById("search-input")
searchEl.value = search
hideCards(search)
}
}
</script>

<style>
:root {
--background-color: #ffffff;
--header-background: #000000;
}
html {
height:100%;
}
html, #body-design-provider {
min-height: 100vh;
}
body {
margin: 0px;
padding: 0;
font-style: normal;
font-variant-ligatures: normal;
font-variant-caps: normal;
font-variant-numeric: normal;
font-variant-east-asian: normal;
font-weight: normal;
font-stretch: normal;
font-size: 16px;
line-height: normal;
font-family: aktiv-grotesk, "Segoe UI", Arial, Helvetica, sans-serif;
overflow-y: auto;
}
.gallery-item:hover {
box-shadow: 0 1px 5px var(--neutral-fill-strong-focus);
}
.gallery-item {
cursor: pointer;
text-align: center;
}
.header {
/*background-image: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0) ),url('{{ PANEL_CDN }}images/index_background.png');*/
background-size: cover;
background-repeat: space;
background-position: center;
}
.header-content {
display: flex;
flex-direction: column;
padding: 2rem;
}
#header-design-provider {
background-color: var(--header-background);
}
#body-design-provider {
color: var(--neutral-foreground-rest);
}
#title {
background: transparent;
}
#subtitle {
color: black;
font-size: 2em;
font-weight: bold;
margin: 1em 0 0 1em;
}
#search-input {
margin-top: 1em;
margin-left:2em;
margin-bottom:0em;
width: calc(100% - 4em);
}
.theme-toggle-icon {
height: 25px;
width: 25px;
margin-top: 5px;
fill: #bababa;
}
/* The grid layout is inspired by
https://css-tricks.com/look-ma-no-media-queries-responsive-layouts-using-css-grid/
https://codepen.io/andybelldesign/pen/vMMYKJ */
/*
AUTO GRID
Set the minimum item size with `--cards-grid-min-size` and you'll
get a fully responsive grid with no media queries.
*/
.cards-grid {
--cards-grid-min-size: 16rem;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--cards-grid-min-size), 1fr));
grid-gap: 2rem;
list-style: none;
}
/* Presentational styles */
.card {
padding: 0px;
}
.cards-grid {
margin: 2rem;
padding: 0px;
}
.avatar {
vertical-align: middle;
float: right;
width: 30px;
height: 30px;
margin-top: 5px;
border-radius: 50%;
}
.card-action svg {
vertical-align: middle;
float: right;
height: 20px;
color: white;
margin-top: 10px;
margin-right: 10px;
fill: var(--neutral-foreground-rest);
}
.card-image {
height: 175px;
width: 100%;
margin-top: 25px;
}
object {
height: 175px;
max-width: calc(100% - 50px);
margin-top: 25px;
border-radius: calc(var(--control-corner-radius) * 1px);
}
.card-content {
padding: 10px 10px 10px;
color: var(--neutral-foreground-rest);
}
.card-text {
height: 100px;
}
.card-header {
height: 2em;
text-align: center;
}
footer {
padding: .50rem;
text-align: center;
font-size: .75rem;
}
#panel-logo {
width: 300px;
}
.card-link {
text-decoration: none;
color: var(--neutral-foreground-rest);
}
</style>
</head>
<body>
<fast-design-system-provider id="body-design-provider" use-defaults>
<fast-design-system-provider id="header-design-provider" use-defaults>
<section class="header">
<fast-switch id="theme-switch" style="float: right; padding-top: 1em; padding-right: 2em;" onChange="toggleLightDarkTheme()" checked>
<span slot="checked-message">
<svg class="theme-toggle-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25"><path d="M0 0h24v24H0z" fill="none"/><path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/></svg>
</span>
<span slot="unchecked-message">
<svg class="theme-toggle-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25 25"><path d="M0 0h24v24H0z" fill="none"/><path d="M10 2c-1.82 0-3.53.5-5 1.35C7.99 5.08 10 8.3 10 12s-2.01 6.92-5 8.65C6.47 21.5 8.18 22 10 22c5.52 0 10-4.48 10-10S15.52 2 10 2z"/></svg>
</span>
</fast-switch>
<fast-tooltip anchor="theme-switch">Click to toggle the Theme</fast-tooltip>
<div class="header-content">
<div>
<fast-anchor id="title" href="https://simdec.fi" appearance="neutral" target="_self">
<img id="logo" src="_static/logo.gif" width="150" height="150">
</fast-anchor>
<fast-tooltip anchor="title">Click to visit the SimDec web site</fast-tooltip>
</div>
</div>
</section>
</fast-design-system-provider>
<section class="search">
<fast-text-field id="search-input" placeholder="search" onInput="hideCards(event.target.value)"></fast-text-field>
</section>
<section id="cards">
<ul class="cards-grid">
{% for item in sorted(items, key=lambda item: item[1:].replace("_", " ").title()) %}
<li class="card">
<a class="card-link" href=".{{ item }}" id="{{ item }}">
<fast-card class="gallery-item">
<object data="thumbnails{{ item }}.png" type="image/png">
<svg class="card-image" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-window" viewBox="0 0 16 16">
<path d="M2.5 4a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1zm2-.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0zm1 .5a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1z"/>
<path d="M2 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H2zm13 2v2H1V3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1zM2 14a1 1 0 0 1-1-1V6h14v7a1 1 0 0 1-1 1H2z"/>
</svg>
</object>
<div class="card-content">
<h2 class="card-header">{{ item[1:].replace("_", " ").title() }}</h2>
</div>
</fast-card>
</a>
</li>
{% end %}
</ul>
</section>
<section>
<fast-divider></fast-divider>
<footer></footer>
</section>
</fast-design-system-provider>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', (event) => {
const header_design = new window.fastDesignProvider("#header-design-provider");
header_design.setBackgroundColor('#ffffff')
const body_design = window.bodyDesign = new window.fastDesignProvider("#body-design-provider");
body_design.setAccentColor("#0072B5")
setSwitchFromParams()
setSearchFromParams()
})
</script>
</body>
</html>
Loading