Skip to content
Snippets Groups Projects
Commit 0e558c44 authored by Jaromír Hradil's avatar Jaromír Hradil
Browse files

Merge branch 'new-style' into 'master'

Adapt to new Jupyterhub

See merge request !49
parents 6cfe9617 6c98aae1
Branches
No related tags found
1 merge request!49Adapt to new Jupyterhub
......@@ -149,7 +149,7 @@ hub:
image:
name: eginotebooks/hub
# k8s-hub 4.2.0
tag: "sha-bd95b14"
tag: "sha-cc2f20b"
config:
Authenticator:
enable_auth_state: true
......@@ -218,6 +218,7 @@ hub:
admin_access: true
authenticate_prometheus: false
authenticator_class: egi_notebooks_hub.onedata.OnedataAuthenticator
logo_file: "/egi-notebooks-hub/static/images/egi-notebooks.png"
# spawner_class: (in egi-notebooks-b2drop)
extraConfig:
egi-notebooks-welcome: |-
......@@ -312,84 +313,100 @@ hub:
c.JupyterHub.spawner_class = B2DropSpawner
c.B2DropSpawner.http_timeout = 90
c.B2DropSpawner.args = ["--FileCheckpoints.checkpoint_dir='/home/jovyan/.notebookCheckpoints'"]
c.B2DropSpawner.profile_form_template = """
c.B2DropSpanwer.additional_profile_form_template_paths = "/egi-notebooks-hub/templates"
{% endraw %}
templatePaths:
- /egi-notebooks-hub/templates
extraFiles:
login.html:
mountPath: /egi-notebooks-hub/templates/login.html
stringData: |-
{%- raw %}
{% extends "egi-login.html" %}
{% block main_resources %}
<p>
Default environment provides 4 vCPU cores, 6 GB RAM and 10GB of personal storage space per user.
</p>
{% endblock main_resources %}
{% endraw %}
extraFiles:
form.html:
mountPath: /egi-notebooks-hub/templates/form.html
stringData: |-
{%- raw %}
<style>
/*
.profile divs holds two div tags: one for a radio button, and one
for the profile's content.
*/
#kubespawner-profiles-list .profile {
display: flex;
flex-direction: row;
font-weight: normal;
border-bottom: 1px solid #ccc;
padding-bottom: 12px;
}
{% include 'style.css' %}
#kubespawner-profiles-list .profile .radio {
padding: 12px;
#kubespawner-profiles-list h4 {
margin-top: 10px;
}
/* .option divs holds a label and a select tag */
#kubespawner-profiles-list .profile .option {
display: flex;
flex-direction: row;
align-items: center;
padding-bottom: 12px;
}
#kubespawner-profiles-list .profile .option label {
font-weight: normal;
margin-right: 8px;
min-width: 96px;
.accordion {
margin-top: 10px;
}
</style>
<div class='form-group' id='kubespawner-profiles-list'>
<div class="form-group" id="kubespawner-profiles-list">
{%- for profile in profile_list %}
{#- Wrap everything in a <label> so clicking anywhere selects the option #}
<label for='profile-item-{{ profile.slug }}' class='profile'>
<div class='radio'>
<input type='radio' name='profile' id='profile-item-{{ profile.slug }}'
value='{{ profile.slug }}' {% if profile.default %}checked{% endif %} />
{#- Wrap everything in a label tag so clicking anywhere selects the option #}
<label for="profile-item-{{ profile.slug }}"
class="profile js-profile-label">
<div class="radio">
<input type="radio"
name="profile"
id="profile-item-{{ profile.slug }}"
value="{{ profile.slug }}"
{% if profile.default %}checked{% endif %} />
</div>
<div>
<h3>{{ profile.display_name }}</h3>
{%- if profile.description %}
<p>{{ profile.description }}</p>
{%- endif %}
<h4>{{ profile.display_name }}</h4>
{%- if profile.description %}<p>{{ profile.description }}</p>{%- endif %}
{%- if profile.profile_options %}
<div>
{%- for k, option in profile.profile_options.items() %}
<div class='option'>
<label for='profile-option-{{profile.slug}}-{{k}}'>{{option.display_name}}</label>
<select name="profile-option-{{profile.slug}}-{{k}}" class="form-control">
<div class="js-options-container">
<div class="option">
<label for="profile-option-{{ profile.slug }}--{{ k }}"
class="js-profile-option-label">{{ option.display_name }}</label>
<select name="profile-option-{{ profile.slug }}--{{ k }}"
class="form-control js-profile-option-select">
{%- for k, choice in option['choices'].items() %}
<option value="{{ k }}" {% if choice.default %}selected{% endif %}>{{ choice.display_name }}</option>
{%- endfor %}
{%- if option['unlisted_choice']['enabled'] %}
<option value="unlisted-choice">{{ option['unlisted_choice']['display_name_in_choices'] }}</option>
{%- endif %}
</select>
</div>
{%- if option['unlisted_choice']['enabled'] %}
<div class="option hidden js-other-input-container">
<label for="profile-option-{{ profile.slug }}--{{ k }}--unlisted-choice">
{{ option['unlisted_choice']['display_name'] }}
</label>
<input data-name="profile-option-{{ profile.slug }}--{{ k }}--unlisted-choice"
{%- if option['unlisted_choice']['validation_regex'] %}
pattern="{{ option['unlisted_choice']['validation_regex'] }}"
{%- endif %}
title="{{ option['unlisted_choice']['validation_message'] }}"
class="form-control js-other-input" />
</div>
{%- endif %}
</div>
{%- endfor %}
</div>
{%- endif %}
</div>
</label>
{%- endfor %}
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="headingOne">
<h4 class="panel-title">
<a class="collapsed" role="button" data-bs-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="false"
aria-controls="collapseOne">
<div class="accordion" id="b2drop-accordion">
<div class="accordion-item">
<h2 class="accordion-header id="headingOne">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne">
B2DROP connection
</a>
{%if b2drop_ready %}<span class="label label-success">Already configured!</span>{% endif %}
</h4>
</div>
<div id="collapseOne" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingOne">
<div class="panel-body">
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#b2drop-accordion">
<div class="accordion-body">
<div class='form-group'>
<label for="b2drop-user" class="form-label">B2DROP app Username</label>
<input type="text" class="form-control" name="b2drop-user" id="b2drop-user" aria-describedby="b2drop-user-help" value="{{ b2drop_user }}">
......@@ -405,36 +422,51 @@ hub:
<label class="form-check-label" for="from-check-input">Remember B2DROP credentials</label>
</div>
</div>
<div>
</div>
</div>
</div>
"""
{% endraw %}
templatePaths:
- /egi-notebooks-hub/templates
extraFiles:
login.html:
mountPath: /egi-notebooks-hub/templates/login.html
stringData: |-
{%- raw %}
{% extends "egi-login.html" %}
{% block main_intro %}
<h1><img alt="Notebooks Logo" src="{{ static_url('images/egi-icon-notebooks.svg') }}"
height="100">Notebooks</h1>
<p>
Notebooks is an environment based on <a href="http://jupyter.org/">Jupyter</a> and
the <a href="https://www.egi.eu/services/cloud-compute/">EGI cloud service</a> that
offers a browser-based, scalable tool for interactive data analysis. The Notebooks
environment provides users with notebooks where they can combine text, mathematics,
computations and rich media output.
</p>
<p>
Access requires a valid <a href="https://docs.egi.eu/users/check-in/signup">EGI account</a>
and <a href="https://docs.egi.eu/users/dev-env/notebooks/#notebooks-for-researchers">
enrolling to one of the supported VOs</a>.
</p>
<p>
Default environment provides 4 vCPU cores, 6 GB RAM and 10GB of personal storage space per user.
</p>
{% endblock main_intro %}
<script>
$('.js-profile-option-select, .js-profile-option-label').click(function() {
// we need this bit of JS to select the profile when a <select> inside is clicked.
$(this).parents('.js-profile-label')
.find('input[type=radio]')
.prop('checked', true);
});
// If the user selects "Other" in the dropdown, show the free text field
$('.js-profile-option-select').change(function() {
const selectionValue = $(this).val();
const $otherInputContainer = $(this).parents('.js-options-container').find('.js-other-input-container');
const $otherInput = $(this).parents('.js-options-container').find('.js-other-input');
if (selectionValue === 'unlisted-choice') {
// if the Select box is selected with a value that is not 'unlisted-choice',
// we remove the "name" attribute for the unlisted-choice input
// and vice-versa, so that we only submit valid form values
// and don't leave the complexity of figuring out which value
// to use to the back-end.
// This can probably be done cleaner by completely refactoring
// how we send values from the frontend.
$(this).data('name', $(this).attr('name'));
$(this).removeAttr('name');
$otherInput.attr('name', $otherInput.data('name'));
$otherInputContainer.removeClass('hidden');
} else {
$otherInput.removeAttr('name');
$(this).attr('name', $(this).data('name'));
$otherInputContainer.addClass('hidden');
}
});
// wrapping in a document.ready to make clear this is executed once
// on page load
$(document).ready(() => {
// trigger the `change` event on the select inputs,
// so that if "Other" is selected on page load, the corresponding
// free-text input shows
$('.js-profile-option-select').trigger('change');
});
</script>
{% endraw %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment