progress toward bootstrap 5

This commit is contained in:
Min RK
2024-04-04 16:10:15 +02:00
parent cca49486e3
commit 2fe060861a
11 changed files with 106 additions and 83 deletions

2
.gitignore vendored
View File

@@ -22,6 +22,8 @@ jupyterhub_cookie_secret
jupyterhub.sqlite jupyterhub.sqlite
jupyterhub.sqlite* jupyterhub.sqlite*
share/jupyterhub/static/components share/jupyterhub/static/components
share/jupyterhub/static/css/style.css
share/jupyterhub/static/css/style.css.map
share/jupyterhub/static/css/style.min.css share/jupyterhub/static/css/style.min.css
share/jupyterhub/static/css/style.min.css.map share/jupyterhub/static/css/style.min.css.map
share/jupyterhub/static/js/admin-react.js* share/jupyterhub/static/js/admin-react.js*

1
jsx/.gitignore vendored
View File

@@ -1,2 +1,3 @@
node_modules node_modules
build/admin-react.js build/admin-react.js
.yarn

View File

@@ -342,7 +342,7 @@ const ServerDashboard = (props) => {
variant={open ? "secondary" : "primary"} variant={open ? "secondary" : "primary"}
size="sm" size="sm"
> >
<span className="caret"></span> <span className="fa fa-caret-down"></span>
</Button>{" "} </Button>{" "}
</span> </span>
<span data-testid={`user-name-div-${userServerName}`}> <span data-testid={`user-name-div-${userServerName}`}>
@@ -565,7 +565,7 @@ const ServerDashboard = (props) => {
Stop All Stop All
</Button> </Button>
{/* spacing between start/stop and Shutdown */} {/* spacing between start/stop and Shutdown */}
<span style={{ marginLeft: "56px" }}> </span> <span style={{ marginLeft: "30px" }}> </span>
{/* Shutdown Jupyterhub */} {/* Shutdown Jupyterhub */}
<Button <Button
variant="danger" variant="danger"

View File

@@ -7,13 +7,6 @@
margin-left: auto; margin-left: auto;
} }
.btn-light {
/* backport bs5 btn-light colors */
background-color: #f9fafb;
border-color: #f9fafb;
color: #000;
}
.server-dashboard-container .btn-light { .server-dashboard-container .btn-light {
border: 1px solid #ddd; border: 1px solid #ddd;
} }

View File

@@ -3,21 +3,19 @@
height: 80vh; height: 80vh;
& #insecure-login-warning { & #insecure-login-warning {
// @include bg-warning(); background-color: $warning-bg-subtle;
padding: 10px; padding: 10px;
} }
.service-login { .service-login {
text-align: center; text-align: center;
display: table-cell;
vertical-align: middle; vertical-align: middle;
margin: auto auto 20% auto; margin: auto;
} }
form { form {
display: table-cell;
vertical-align: middle; vertical-align: middle;
margin: auto auto 20% auto; margin: auto;
width: 350px; width: 350px;
} }
@@ -31,8 +29,8 @@
padding: 10px 20px; padding: 10px 20px;
color: #fff; color: #fff;
background: $jupyter-orange; background: $jupyter-orange;
border-radius: $border-radius-large $border-radius-large 0 0;
font-size: large; font-size: large;
border-radius: $border-radius-large $border-radius-large 0 0;
} }
.auth-form-header > h1 { .auth-form-header > h1 {

View File

@@ -1,6 +1,5 @@
@import "./variables.scss";
$logo-height: 28px; $logo-height: 28px;
$grid-float-breakpoint: map-get($grid-breakpoints, "sm");
#jupyterhub-logo { #jupyterhub-logo {
@media (max-width: $grid-float-breakpoint) { @media (max-width: $grid-float-breakpoint) {
@@ -9,7 +8,18 @@ $logo-height: 28px;
} }
.jpy-logo { .jpy-logo {
height: $logo-height; height: $logo-height;
margin-top: ($navbar-height - $logo-height) / 2; margin-top: calc($navbar-brand-height - $logo-height) / 2;
}
}
.navbar-nav {
.nav-link {
&:hover,
&:focus {
// no color change
color: var(--#{$prefix}navbar-color);
background-color: darken($body-tertiary-bg, 10%);
}
} }
} }
@@ -71,6 +81,7 @@ $logo-height: 28px;
0 0 8px $jupyter-orange; 0 0 8px $jupyter-orange;
border-color: $jupyter-orange; border-color: $jupyter-orange;
outline-color: $jupyter-orange; outline-color: $jupyter-orange;
}
.btn-jupyter { .btn-jupyter {
@include button-variant(#fff, $jupyter-orange, $jupyter-red); @include button-variant(#fff, $jupyter-orange, $jupyter-red);

View File

@@ -1,31 +1,60 @@
/*! variables */
@import "./variables.scss";
/*! /*!
* *
* Twitter Bootstrap * Bootstrap
* *
*/ */
// 1. Include functions first (so you can manipulate colors, SVGs, calc, etc)
@import "../components/bootstrap/scss/functions"; // Required @import "../components/bootstrap/scss/functions"; // Required
@import "../components/bootstrap/scss/variables"; // Required
@import "../components/bootstrap/scss/mixins"; // Required
@import "../components/bootstrap/scss/root"; // Required // 2. Include any default variable overrides here
@import "../components/bootstrap/scss/reboot"; // Required @import "./variables.scss";
@import "../components/bootstrap/scss/alert"; @import "../components/bootstrap/scss/bootstrap"; // Full bootstrap (maybe wasteful?)
@import "../components/bootstrap/scss/buttons";
@import "../components/bootstrap/scss/containers"; // // 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets)
@import "../components/bootstrap/scss/grid"; // @import "../components/bootstrap/scss/variables"; // Required
@import "../components/bootstrap/scss/utilities"; // @import "../components/bootstrap/scss/variables-dark"; // Required
//
//
// // 4. Include any default map overrides here
//
// // 5. Include remainder of required parts
// @import "../components/bootstrap/scss/maps"; // Required
// @import "../components/bootstrap/scss/mixins"; // Required
// @import "../components/bootstrap/scss/root"; // Required
//
// // 6. Optionally include any other parts as needed
// @import "../components/bootstrap/scss/utilities";
// @import "../components/bootstrap/scss/reboot";
// @import "../components/bootstrap/scss/type";
// @import "../components/bootstrap/scss/images";
// @import "../components/bootstrap/scss/navbar";
// @import "../components/bootstrap/scss/alert";
// @import "../components/bootstrap/scss/buttons";
// @import "../components/bootstrap/scss/containers";
// @import "../components/bootstrap/scss/grid";
// @import "../components/bootstrap/scss/modal";
// 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss`
// @import "../components/bootstrap/scss/utilities/api";
// redefine .btn-xs, removed in bootstrap 4
.btn-xs {
// $padding-y, $padding-x, $font-size, $border-radius
@include button-size(1px, 5px, 14px, 3px);
}
/*! /*!
* *
* Font Awesome * Font Awesome
* *
*/ */
// $fa-font-path: "../components/font-awesome/fonts"; $fa-font-path: "../components/@fortawesome/fontawesome-free/webfonts";
// @import "../components/font-awesome/scss/font-awesome.scss"; @import "../components/@fortawesome/fontawesome-free/scss/fontawesome";
// You can include all the other styles the same as before
@import "../components/@fortawesome/fontawesome-free/scss/regular.scss";
@import "../components/@fortawesome/fontawesome-free/scss/solid.scss";
/*! /*!
* *

View File

@@ -1,23 +1,17 @@
$border-radius-small: 2px; $border-radius-large: 5px;
$border-radius-base: 2px;
$border-radius-large: 3px;
$navbar-height: 40px; $navbar-height: 40px;
$grid-float-breakpoint: $screen-xs-min;
$navbar-default-color: #222;
$navbar-default-link-color: $navbar-default-color;
// darken background on hover, no change to text // darken background on hover, no change to text
$navbar-default-link-hover-color: $navbar-default-color; // background part is in page.scss
$navbar-default-link-hover-bg: darken($navbar-default-bg, 10%); $nav-link-color: var(--bs-navbar-color);
$nav-link-hover-color: $nav-link-color;
$jupyter-orange: #f37524; $jupyter-orange: #f37524;
$jupyter-red: #e34f21; $jupyter-red: #e34f21;
// color blind-friendly alternative to red/green
// accessible alternative to red/green
// from 5-class RdYlBu via colorbrewer.org // from 5-class RdYlBu via colorbrewer.org
// eliminate distinction between 'primary' and 'success' // eliminate distinction between 'primary' and 'success'
$brand-primary: #2c7bb6; $primary: #2c7bb6;
$brand-success: $brand-primary; $success: $primary;
$brand-danger: #d7191c; $danger: #d7191c;
$text-muted: #222;

View File

@@ -29,7 +29,7 @@
<div class="auth-form-header"> <div class="auth-form-header">
<h1>Sign in</h1> <h1>Sign in</h1>
</div> </div>
<div class='auth-form-body'> <div class='auth-form-body m-auto'>
<p id='insecure-login-warning' class='hidden'> <p id='insecure-login-warning' class='hidden'>
Warning: JupyterHub seems to be served over an unsecured HTTP connection. Warning: JupyterHub seems to be served over an unsecured HTTP connection.

View File

@@ -40,7 +40,7 @@
{% block scripts %} {% block scripts %}
<script src="{{static_url("components/requirejs/require.js") }}" type="text/javascript" charset="utf-8"></script> <script src="{{static_url("components/requirejs/require.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("components/jquery/dist/jquery.min.js") }}" type="text/javascript" charset="utf-8"></script> <script src="{{static_url("components/jquery/dist/jquery.min.js") }}" type="text/javascript" charset="utf-8"></script>
<script src="{{static_url("components/bootstrap/dist/js/bootstrap.min.js") }}" type="text/javascript" charset="utf-8"></script> <!-- <script src="{{static_url("components/bootstrap/dist/js/bootstrap.min.js") }}" type="text/javascript" charset="utf-8"></script> -->
{% endblock %} {% endblock %}
<script> <script>
require.config({ require.config({
@@ -104,35 +104,30 @@
</noscript> </noscript>
{% block nav_bar %} {% block nav_bar %}
<nav class="navbar navbar-default"> <nav class="navbar navbar-expand-lg bg-body-tertiary mb-4">
<div class="container-fluid"> <div class="container-fluid">
<div class="navbar-header">
{% block logo %} {% block logo %}
<span id="jupyterhub-logo" class="pull-left"> <span id="jupyterhub-logo" class="navbar-brand">
<a href="{{logo_url or base_url}}"><img src='{{base_url}}logo' alt='JupyterHub logo' class='jpy-logo' title='Home'/></a> <a href="{{logo_url or base_url}}"><img src='{{base_url}}logo' alt='JupyterHub logo' class='jpy-logo' title='Home'/></a>
</span> </span>
{% endblock %} {% endblock %}
{% if user %} {% if user %}
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#thenavbar" aria-expanded="false"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#thenavbar" aria-controls="thenavbar" aria-expanded="false" aria-label="Toggle navigation">
<span class="sr-only">Toggle navigation</span> <span class="navbar-toggler-icon"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button> </button>
{% endif %} {% endif %}
</div>
<div class="collapse navbar-collapse" id="thenavbar"> <div class="collapse navbar-collapse" id="thenavbar">
{% if user %} {% if user %}
<ul class="nav navbar-nav"> <ul class="nav navbar-nav me-auto mb-2 mb-lg-0">
{% block nav_bar_left_items %} {% block nav_bar_left_items %}
<li><a href="{{base_url}}home">Home</a></li> <li class="nav-item"><a class="nav-link" href="{{base_url}}home">Home</a></li>
<li><a href="{{base_url}}token">Token</a></li> <li class="nav-item"><a class="nav-link" href="{{base_url}}token">Token</a></li>
{% if 'admin-ui' in parsed_scopes %} {% if 'admin-ui' in parsed_scopes %}
<li><a href="{{base_url}}admin">Admin</a></li> <li class="nav-item"><a class="nav-link" href="{{base_url}}admin">Admin</a></li>
{% endif %} {% endif %}
{% if services %} {% if services %}
<li class="dropdown"> <li class="nav-item dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Services<span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Services<span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% for service in services %} {% for service in services %}
@@ -146,16 +141,16 @@
{% endblock %} {% endblock %}
</ul> </ul>
{% endif %} {% endif %}
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav me-2">
{% block nav_bar_right_items %} {% block nav_bar_right_items %}
<li> <li class="nav-item">
{% block login_widget %} {% block login_widget %}
<span id="login_widget"> <span id="login_widget">
{% if user %} {% if user %}
<p class="navbar-text">{{user.name}}</p> <span class="navbar-text">{{user.name}}</span>
<a id="logout" role="button" class="navbar-btn btn-sm btn btn-default" href="{{logout_url}}"> <i aria-hidden="true" class="fa fa-sign-out"></i> Logout</a> <a id="logout" role="button" class="btn btn-sm btn-outline-dark" href="{{logout_url}}"> <i aria-hidden="true" class="fa fa-sign-out"></i> Logout</a>
{% else %} {% else %}
<a id="login" role="button" class="btn-sm btn navbar-btn btn-default" href="{{login_url}}">Login</a> <a id="login" role="button" class="btn btn-sm btn-outline-dark" href="{{login_url}}">Login</a>
{% endif %} {% endif %}
</span> </span>
{% endblock %} {% endblock %}

View File

@@ -5,7 +5,7 @@
<div class="container"> <div class="container">
<h1 class="sr-only">Manage JupyterHub Tokens</h1> <h1 class="sr-only">Manage JupyterHub Tokens</h1>
<div class="row"> <div class="row">
<form id="request-token-form" class="col-md-offset-3 col-md-6"> <form id="request-token-form" class="m-auto col-lg-6">
<div class="text-center"> <div class="text-center">
<button type="submit" class="btn btn-lg btn-jupyter"> <button type="submit" class="btn btn-lg btn-jupyter">
Request new API token Request new API token
@@ -48,16 +48,16 @@
</div> </div>
<div class="row"> <div class="row">
<div id="token-area" class="col-md-6 col-md-offset-3" style="display: none;"> <div id="token-area" class="col-lg-6 m-auto" style="display: none;">
<div class="panel panel-default"> <div class="card">
<div class="panel-heading"> <div class="card-header">
Your new API Token Your new API Token
</div> </div>
<div class="panel-body"> <div class="card-body">
<p class="lead text-center"> <p class="card-title text-center">
<span id="token-result"></span> <span id="token-result"></span>
</p> </p>
<p> <p class="card-text">
Copy this token. You won't be able to see it again, Copy this token. You won't be able to see it again,
but you can always come back here to get a new one. but you can always come back here to get a new one.
</p> </p>
@@ -86,10 +86,10 @@
</thead> </thead>
<tbody> <tbody>
{% for token in api_tokens %} {% for token in api_tokens %}
<tr class="token-row" data-token-id="{{token.api_id}}"> <tr class="token-row container" data-token-id="{{token.api_id}}">
{% block token_row scoped %} {% block token_row scoped %}
<td class="note-col col-sm-4">{{token.note}}</td> <td class="note-col col">{{token.note}}</td>
<td class="scope-col col-sm-1"> <td class="scope-col col">
<details> <details>
<summary>scopes</summary> <summary>scopes</summary>
{% for scope in token.scopes %} {% for scope in token.scopes %}
@@ -97,28 +97,28 @@
{% endfor %} {% endfor %}
</details> </details>
</td> </td>
<td class="time-col col-sm-3"> <td class="time-col col">
{%- if token.last_activity -%} {%- if token.last_activity -%}
{{ token.last_activity.isoformat() + 'Z' }} {{ token.last_activity.isoformat() + 'Z' }}
{%- else -%} {%- else -%}
Never Never
{%- endif -%} {%- endif -%}
</td> </td>
<td class="time-col col-sm-3"> <td class="time-col col">
{%- if token.created -%} {%- if token.created -%}
{{ token.created.isoformat() + 'Z' }} {{ token.created.isoformat() + 'Z' }}
{%- else -%} {%- else -%}
N/A N/A
{%- endif -%} {%- endif -%}
</td> </td>
<td class="time-col col-sm-3"> <td class="time-col col">
{%- if token.expires_at -%} {%- if token.expires_at -%}
{{ token.expires_at.isoformat() + 'Z' }} {{ token.expires_at.isoformat() + 'Z' }}
{%- else -%} {%- else -%}
Never Never
{%- endif -%} {%- endif -%}
</td> </td>
<td class="col-sm-1 text-center"> <td class="col text-center">
<button class="revoke-token-btn btn btn-xs btn-danger">revoke</button> <button class="revoke-token-btn btn btn-xs btn-danger">revoke</button>
</td> </td>
{% endblock token_row %} {% endblock token_row %}