Split jinja template in views
This commit is contained in:
parent
b0f8e336bc
commit
b26425d4cf
9 changed files with 163 additions and 61 deletions
|
@ -6,22 +6,24 @@ Usage: `python -m render`
|
||||||
from traceback import format_exc
|
from traceback import format_exc
|
||||||
|
|
||||||
from flask import Flask, render_template, request
|
from flask import Flask, render_template, request
|
||||||
from glicid_spawner.form import TEMPLATE_FORM, options_from_form
|
from glicid_spawner.form import TEMPLATES, options_from_form
|
||||||
from glicid_spawner.micromamba import MicromambaEnv
|
from glicid_spawner.micromamba import MicromambaEnv
|
||||||
from glicid_spawner.resources import CPU, GPU, RAM
|
from glicid_spawner.resources import CPU, GPU, RAM
|
||||||
from livereload import Server
|
from livereload import Server
|
||||||
|
|
||||||
# Monkeypatch
|
# Dummy username and python environments
|
||||||
|
USERNAME = 'john-doe'
|
||||||
|
ENVS = [
|
||||||
|
MicromambaEnv('USER', 'foo', f'/{USERNAME}/envs/foo'),
|
||||||
|
MicromambaEnv('USER', 'bar', f'/{USERNAME}/envs/bar'),
|
||||||
|
MicromambaEnv('GLOBAL', 'baz', '/global/envs/baz'),
|
||||||
|
]
|
||||||
OPTIONS = {
|
OPTIONS = {
|
||||||
'username': 'john-doe',
|
'username': USERNAME,
|
||||||
'python_envs': [
|
'envs': ENVS,
|
||||||
MicromambaEnv('USER', 'foo', '/john-doe/envs/foo'),
|
'cpus': CPU,
|
||||||
MicromambaEnv('USER', 'bar', '/john-doe/envs/bar'),
|
'rams': RAM,
|
||||||
MicromambaEnv('GLOBAL', 'baz', '/global/envs/baz'),
|
'gpus': GPU,
|
||||||
],
|
|
||||||
'cpu_available': CPU,
|
|
||||||
'ram_available': RAM,
|
|
||||||
'gpu_available': GPU,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +36,9 @@ app.debug = True
|
||||||
def home():
|
def home():
|
||||||
"""Form spawner home page."""
|
"""Form spawner home page."""
|
||||||
return render_template(
|
return render_template(
|
||||||
'form.html', spawner_options_form=TEMPLATE_FORM.render(**OPTIONS), options=OPTIONS
|
'form.html',
|
||||||
|
spawner_options_form=TEMPLATES.get_template('spawner_form.jinja').render(**OPTIONS),
|
||||||
|
options=OPTIONS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,23 +9,23 @@ TEMPLATES = Environment(
|
||||||
loader=PackageLoader('glicid_spawner'),
|
loader=PackageLoader('glicid_spawner'),
|
||||||
autoescape=select_autoescape(),
|
autoescape=select_autoescape(),
|
||||||
)
|
)
|
||||||
TEMPLATE_FORM = TEMPLATES.get_template('spawner_form.html')
|
|
||||||
|
|
||||||
|
|
||||||
def options_attrs(username: str) -> dict:
|
def options_attrs(username: str) -> dict:
|
||||||
"""Form options attributes."""
|
"""Form options attributes."""
|
||||||
return {
|
return {
|
||||||
'username': username,
|
'username': username,
|
||||||
'python_envs': get_envs(username),
|
'envs': get_envs(username),
|
||||||
'cpu_available': CPU,
|
'cpus': CPU,
|
||||||
'ram_available': RAM,
|
'rams': RAM,
|
||||||
'gpu_available': GPU,
|
'gpus': GPU,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def options_form(username: str) -> str:
|
def options_form(username: str) -> str:
|
||||||
"""Render default spawner form."""
|
"""Render default spawner form."""
|
||||||
return TEMPLATE_FORM.render(**options_attrs(username))
|
template = TEMPLATES.get_template('spawner_form.jinja')
|
||||||
|
return template.render(**options_attrs(username))
|
||||||
|
|
||||||
|
|
||||||
def options_from_form(formdata) -> dict:
|
def options_from_form(formdata) -> dict:
|
||||||
|
|
12
src/glicid_spawner/templates/spawner_form.jinja
Normal file
12
src/glicid_spawner/templates/spawner_form.jinja
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<style type="text/css">
|
||||||
|
{% include "static/style.css" %}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="form-horizontal">
|
||||||
|
|
||||||
|
{% include "views/username.jinja" %}
|
||||||
|
{% include "views/envs.jinja" %}
|
||||||
|
{% include "views/resources.jinja" %}
|
||||||
|
{% include "views/slurm.jinja" %}
|
||||||
|
|
||||||
|
</div>
|
24
src/glicid_spawner/templates/static/style.css
Normal file
24
src/glicid_spawner/templates/static/style.css
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
/* Spawner form addition style */
|
||||||
|
input[type=radio] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=radio]:checked+label {
|
||||||
|
background-color: #f37524;
|
||||||
|
border-color: #e34f21;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading .panel-title-toggle {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading .panel-title-toggle:before {
|
||||||
|
font-family: 'FontAwesome';
|
||||||
|
content: "\\f078";
|
||||||
|
color: lightgrey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-heading .panel-title-toggle.collapsed:before {
|
||||||
|
content: "\\f054";
|
||||||
|
}
|
10
src/glicid_spawner/templates/views/envs.jinja
Normal file
10
src/glicid_spawner/templates/views/envs.jinja
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="python-env" class="col-sm-3 control-label">Python environment:</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select class="form-control" name="python-env">
|
||||||
|
{%- for pyenv in envs -%}
|
||||||
|
<option value="{{ pyenv.path }}">{{ pyenv.name }} ({{ pyenv.scope | upper }})</option>
|
||||||
|
{% endfor -%}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,24 +1,9 @@
|
||||||
<div class="form-horizontal">
|
<div class="resources">
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-3 control-label">Username:</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<div class="form-control-static">{{ username }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="python-env" class="col-sm-3 control-label">Python environment:</label>
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<select class="form-control" name="python-env">
|
|
||||||
{%- for pyenv in python_envs -%}
|
|
||||||
<option value="{{ pyenv.path }}">{{ pyenv.name }} ({{ pyenv.scope | upper }})</option>
|
|
||||||
{% endfor -%}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="cpu" class="col-sm-3 control-label">CPU:</label>
|
<label for="cpu" class="col-sm-3 control-label">CPU:</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
{%- for cpu in cpu_available -%}
|
{%- for cpu in cpus -%}
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<input type="radio" name="cpu" id="cpu_{{loop.index0}}" value="{{loop.index0}}"
|
<input type="radio" name="cpu" id="cpu_{{loop.index0}}" value="{{loop.index0}}"
|
||||||
data-max-duration="{{cpu.max_duration}}"{% if loop.first %} checked{% endif %}>
|
data-max-duration="{{cpu.max_duration}}"{% if loop.first %} checked{% endif %}>
|
||||||
|
@ -29,10 +14,11 @@
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="ram" class="col-sm-3 control-label">Memory:</label>
|
<label for="ram" class="col-sm-3 control-label">Memory:</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
{%- for ram in ram_available -%}
|
{%- for ram in rams -%}
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<input type="radio" name="ram" id="ram_{{loop.index0}}" value="{{loop.index0}}"
|
<input type="radio" name="ram" id="ram_{{loop.index0}}" value="{{loop.index0}}"
|
||||||
data-max-duration="{{ram.max_duration}}"{% if loop.first %} checked{% endif %}>
|
data-max-duration="{{ram.max_duration}}"{% if loop.first %} checked{% endif %}>
|
||||||
|
@ -43,10 +29,11 @@
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="gpu" class="col-sm-3 control-label">GPU:</label>
|
<label for="gpu" class="col-sm-3 control-label">GPU:</label>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
{%- for gpu in gpu_available -%}
|
{%- for gpu in gpus -%}
|
||||||
<div class="col-sm-2">
|
<div class="col-sm-2">
|
||||||
<input type="radio" name="gpu" id="gpu_{{loop.index0}}" value="{{loop.index0}}"
|
<input type="radio" name="gpu" id="gpu_{{loop.index0}}" value="{{loop.index0}}"
|
||||||
data-max-duration="{{gpu.max_duration}}"{% if loop.first %} checked{% endif %}>
|
data-max-duration="{{gpu.max_duration}}"{% if loop.first %} checked{% endif %}>
|
||||||
|
@ -57,32 +44,20 @@
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label class="col-sm-3 control-label">Session duration:</label>
|
|
||||||
<div class="col-sm-9">
|
<div class="form-group">
|
||||||
<div class="form-control-static"><span id="time-max-duration">24</span> h</div>
|
<label class="col-sm-3 control-label">Session duration:</label>
|
||||||
</div>
|
<div class="col-sm-9">
|
||||||
|
<div class="form-control-static"><span id="time-max-duration">24</span> h</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Append button style
|
|
||||||
var $style = $(`<style>
|
|
||||||
input[type=radio] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
input[type=radio]:checked + label {
|
|
||||||
background-color: #f37524;
|
|
||||||
border-color: #e34f21;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
</style>`)
|
|
||||||
$('html > head').append($style);
|
|
||||||
|
|
||||||
// Adjust time duration
|
// Adjust time duration
|
||||||
var $reservations_dropdown = $("#time-max-duration");
|
var $reservations_dropdown = $("#time-max-duration");
|
||||||
|
|
||||||
$('input[type=radio]').change(function () {
|
$('.resources input[type=radio]').change(function () {
|
||||||
var cpu = $('input[name=cpu]:checked').data('max-duration');
|
var cpu = $('input[name=cpu]:checked').data('max-duration');
|
||||||
var ram = $('input[name=ram]:checked').data('max-duration');
|
var ram = $('input[name=ram]:checked').data('max-duration');
|
||||||
var gpu = $('input[name=gpu]:checked').data('max-duration');
|
var gpu = $('input[name=gpu]:checked').data('max-duration');
|
70
src/glicid_spawner/templates/views/slurm.jinja
Normal file
70
src/glicid_spawner/templates/views/slurm.jinja
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<div class="panel-group" id="advanced-config" role="tablist" aria-multiselectable="true">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading" role="tab" id="heading">
|
||||||
|
<h4 class="panel-title">
|
||||||
|
<a class="panel-title-toggle collapsed" role="button" data-toggle="collapse"
|
||||||
|
data-parent="#advanced-config" href="#advanced-config-collapse" aria-expanded="true" aria-controls="advanced-config-collapse">
|
||||||
|
Advanced configuration
|
||||||
|
</a>
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div id="advanced-config-collapse" class="panel-collapse {# collapse #}" role="tabpanel" aria-labelledby="heading">
|
||||||
|
<div class="panel-body">
|
||||||
|
<p>You can specify on which cluster/partion/node you want to start your Jupyter server:</p>
|
||||||
|
|
||||||
|
{# {% if slurm is not 'None' %} #}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="cluster" class="col-sm-3 control-label">Clusters:</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
{%- for cluster in slurm -%}
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input type="radio" name="cluster" id="cluster_{{cluster}}" class="slurm_cluster"
|
||||||
|
value="{{cluster}}">
|
||||||
|
<label for="cluster_{{cluster}}" class="btn btn-default btn-block">
|
||||||
|
{{ cluster | capitalize }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{% endfor -%}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{# {% endif %} #}
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="partition" class="col-sm-3 control-label">Partitions:</label>
|
||||||
|
<div class="col-sm-9" id="partitions-list"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="node" class="col-sm-3 control-label">Nodes:</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="radio" name="node" id="node_0" value="0" checked>
|
||||||
|
<label for="node_0" class="btn btn-default btn-block">
|
||||||
|
cribbar033
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="radio" name="node" id="node_1" value="1">
|
||||||
|
<label for="node_1" class="btn btn-default btn-block">
|
||||||
|
cribbar034
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="radio" name="node" id="node_2" value="2">
|
||||||
|
<label for="node_2" class="btn btn-default btn-block">
|
||||||
|
cribbar035
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3">
|
||||||
|
<input type="radio" name="node" id="node_3" value="3">
|
||||||
|
<label for="node_3" class="btn btn-default btn-block">
|
||||||
|
cribbar036
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
6
src/glicid_spawner/templates/views/username.jinja
Normal file
6
src/glicid_spawner/templates/views/username.jinja
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-3 control-label">Username:</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<div class="form-control-static">{{ username }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from glicid_spawner import form, micromamba
|
from glicid_spawner import form
|
||||||
from glicid_spawner.form import options_form, options_from_form
|
from glicid_spawner.form import options_form, options_from_form
|
||||||
|
from glicid_spawner.micromamba import MicromambaEnv
|
||||||
|
|
||||||
|
|
||||||
def test_options_form(monkeypatch):
|
def test_options_form(monkeypatch):
|
||||||
|
@ -12,9 +13,9 @@ def test_options_form(monkeypatch):
|
||||||
form,
|
form,
|
||||||
'get_envs',
|
'get_envs',
|
||||||
lambda username: [
|
lambda username: [
|
||||||
micromamba.MicromambaEnv('USER', 'foo', f'/{username}/envs/foo'),
|
MicromambaEnv('USER', 'foo', f'/{username}/envs/foo'),
|
||||||
micromamba.MicromambaEnv('USER', 'bar', f'/{username}/envs/bar'),
|
MicromambaEnv('USER', 'bar', f'/{username}/envs/bar'),
|
||||||
micromamba.MicromambaEnv('GLOBAL', 'baz', '/global/envs/baz'),
|
MicromambaEnv('GLOBAL', 'baz', '/global/envs/baz'),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue