From 3135b8954f4b6c68f5f7f523e5eb1ee163ce322a Mon Sep 17 00:00:00 2001 From: Frank Sauerburger <frank@sauerburger.com> Date: Tue, 5 Jan 2021 18:58:58 +0100 Subject: [PATCH] Various frontend improvements --- uhepp-js/package-lock.json | 5 ++ uhepp-js/package.json | 1 + uhepp-js/src/common.scss | 24 +++++++++- uhepp-js/src/index.js | 2 + uhepp_org/requirements.txt | 1 + uhepp_org/uhepp_org/settings.py | 3 ++ .../templates/registration/login.html | 29 ++++++++---- .../uhepp_vault/collection_detail.html | 29 ++++++++---- .../uhepp_vault/collection_form.html | 25 ++++++++-- .../uhepp_vault/collection_list.html | 18 +++++-- .../templates/uhepp_vault/plot_detail.html | 7 ++- .../templates/uhepp_vault/plot_list.html | 7 +++ .../templates/uhepp_vault/profile_detail.html | 47 +++++++++++-------- .../templates/uhepp_vault/profile_form.html | 11 ++++- .../templates/uhepp_vault/profile_list.html | 16 +++++-- uhepp_org/uhepp_vault/views.py | 27 ++++++++++- 16 files changed, 193 insertions(+), 59 deletions(-) diff --git a/uhepp-js/package-lock.json b/uhepp-js/package-lock.json index 090b075..a542993 100644 --- a/uhepp-js/package-lock.json +++ b/uhepp-js/package-lock.json @@ -1173,6 +1173,11 @@ "to-fast-properties": "^2.0.0" } }, + "@fortawesome/fontawesome-free": { + "version": "5.15.1", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.1.tgz", + "integrity": "sha512-OEdH7SyC1suTdhBGW91/zBfR6qaIhThbcN8PUXtXilY4GYnSBbVqOntdHbC1vXwsDnX0Qix2m2+DSU1J51ybOQ==" + }, "@popperjs/core": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.6.0.tgz", diff --git a/uhepp-js/package.json b/uhepp-js/package.json index b13cf47..21a10c7 100644 --- a/uhepp-js/package.json +++ b/uhepp-js/package.json @@ -9,6 +9,7 @@ "build": "webpack --mode production" }, "dependencies": { + "@fortawesome/fontawesome-free": "^5.15.1", "@vx/axis": "0.0.199", "@vx/grid": "0.0.199", "@vx/group": "0.0.199", diff --git a/uhepp-js/src/common.scss b/uhepp-js/src/common.scss index a5dd867..5313f30 100644 --- a/uhepp-js/src/common.scss +++ b/uhepp-js/src/common.scss @@ -21,9 +21,10 @@ a:hover { margin-bottom: 0; } + .access-menu { .dropdown-menu { - width: 399px; + width: 350; } .highlight pre { overflow-x: auto; @@ -33,6 +34,22 @@ a:hover { } } +@include media-breakpoint-up(md) { + .access-menu { + .dropdown-menu { + width: 500px; + } + } +} +@include media-breakpoint-up(lg) { + .access-menu { + .dropdown-menu { + width: auto; + min-width: 500px; + } + } +} + dd { margin-left: 1rem; } @@ -51,3 +68,8 @@ dd { } } } + +.controls-head { + display: flex; + justify-content: space-between; +} diff --git a/uhepp-js/src/index.js b/uhepp-js/src/index.js index 110e05d..725bae5 100644 --- a/uhepp-js/src/index.js +++ b/uhepp-js/src/index.js @@ -10,6 +10,8 @@ import React from "react"; import ReactDOM from "react-dom"; import { HashRouter as Router, Route, Link } from "react-router-dom"; +import '@fortawesome/fontawesome-free/js/fontawesome' +import '@fortawesome/fontawesome-free/js/solid' export const fe = { React: React, diff --git a/uhepp_org/requirements.txt b/uhepp_org/requirements.txt index 3e8abd1..5e8da88 100644 --- a/uhepp_org/requirements.txt +++ b/uhepp_org/requirements.txt @@ -4,3 +4,4 @@ mozilla-django-oidc django-pygmentify django-inline-svg psycopg2 +django-crispy-forms diff --git a/uhepp_org/uhepp_org/settings.py b/uhepp_org/uhepp_org/settings.py index cbe3122..ca69151 100644 --- a/uhepp_org/uhepp_org/settings.py +++ b/uhepp_org/uhepp_org/settings.py @@ -108,8 +108,11 @@ INSTALLED_APPS = [ 'rest_framework.authtoken', 'pygmentify', 'svg', + 'crispy_forms', ] +CRISPY_TEMPLATE_PACK = 'bootstrap4' + PYGMENTIFY = { 'style': 'default', 'cssclass': 'highlight border rounded bg-light px-2 m-2' diff --git a/uhepp_org/uhepp_vault/templates/registration/login.html b/uhepp_org/uhepp_vault/templates/registration/login.html index c206f86..db67857 100644 --- a/uhepp_org/uhepp_vault/templates/registration/login.html +++ b/uhepp_org/uhepp_vault/templates/registration/login.html @@ -1,17 +1,26 @@ {% extends 'uhepp_vault/base.html' %} +{% load crispy_forms_tags %} {% block content %} <h1>Login</h1> -<h2>CERN Single Sign-On (preferred)</h2> -<a href="{% url 'oidc_authentication_init' %}">Login via CERN SSO</a> - -<hr /> - -<h2>uhepp.org account</h2> -<form method="post">{% csrf_token %} -{{ form }} -<button type="submit">Log in</button> - +<div class="row"> + <div class="col-md-6 p-4 card bg-light border-primary"> + <h2 class="mt-2"> + CERN Single Sign-On + <small class="text-muted">preferred</small> + </h2> + <p>Use your CERN account to sign in or create a new account.</p> + <p><a tabindex="0" class="btn btn-primary" href="{% url 'oidc_authentication_init' %}">Sign in with CERN SSO</a></p> + </div> + <div class="col-md-6 px-4"> + <h2 class="mt-2">Uhepp hub account</h2> + <p>You can only use this option if you have received a special + account.</p> + <form method="post">{% csrf_token %} + {{ form|crispy }} + <button type="submit" class="btn btn-outline-primary">Sign in</button> + </div> +</div> {% endblock %} diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_detail.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_detail.html index 12df392..4e6789c 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_detail.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_detail.html @@ -10,17 +10,25 @@ </ol> </nav> -<h1>{{ collection.title }}</h1> -{% if collection.owner.pk == user.pk %} -<p> - <a href="{% url 'uhepp_vault:collection-update' collection.pk %}"> - edit +<h1 class="controls-head"> + <span> + {{ collection.title }} + <i class="text-muted fas {% if collection.visibility >= 30 %} fa-globe-europe + {% elif collection.visibility >= 20 %} fa-shield-alt + {% elif collection.visibility >= 10 %} fa-lock + {% endif %}"></i> + </span> + {% if collection.owner.pk == user.pk %} + <span> + <a class="btn btn-outline-secondary" href="{% url 'uhepp_vault:collection-update' collection.pk %}"> + <i class="fas fa-pen"></i> </a> - <a href="{% url 'uhepp_vault:collection-delete' collection.pk %}"> - delete + <a class="btn btn-outline-danger" href="{% url 'uhepp_vault:collection-delete' collection.pk %}"> + <i class="fas fa-trash"></i> </a> -</p> -{% endif %} + </span> + {% endif %} +</h1> <div class="d-flex"> <span>Collection ID: {{ collection.id }}</span> @@ -61,6 +69,9 @@ hist.push({{ collection.pk }}) </button> <div class="dropdown-menu dropdown-menu-right p-4 shadow"> <form> + <p class="alert alert-info m-2"> + Make sure you've set up an <a class="alert-link" href="{% url 'uhepp_vault:token-list' %}">API access token</a>. + </p> <h5>Pull collection</h5> {% pygmentify %} <pre class="bash"> diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_form.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_form.html index dc83f97..0eda2f5 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_form.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_form.html @@ -1,17 +1,34 @@ {% extends 'uhepp_vault/base.html' %} +{% load crispy_forms_tags %} {% block content %} +<nav aria-label="breadcrumb"> + <ol class="breadcrumb my-2"> + <li class="breadcrumb-item"><a href="/">Home</a></li> + <li class="breadcrumb-item"><a href="{% url 'uhepp_vault:user-detail' user.username %}">{{ user.username }}</a></li> +{% if view.edit %} + <li class="breadcrumb-item"><a href="{% url 'uhepp_vault:collection-detail' collection.pk %}">{{ collection.title }}</a></li> +{% else %} + <li class="breadcrumb-item"><a class="active" href="{% url 'uhepp_vault:collection-create' %}">New collection</a></li> +{% endif %} + </ol> +</nav> + {% if view.edit %} <h2>Edit collection</h2> {% else %} <h2>New collection</h2> {% endif %} -<a href="{% url 'uhepp_vault:user-detail' request.user.username %}">Back to profile</a> - <form method="post">{% csrf_token %} - {{ form.as_p }} - <input type="submit" value="Create"> + {{ form|crispy }} + <button type="submit" class="btn btn-primary"> +{% if view.edit %} +Save +{% else %} +Create +{% endif %} + </button> </form> {% endblock %} diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_list.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_list.html index 068e808..77d2cce 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_list.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/collection_list.html @@ -1,6 +1,14 @@ {% extends 'uhepp_vault/base.html' %} {% block content %} +<nav aria-label="breadcrumb"> + <ol class="breadcrumb my-2"> + <li class="breadcrumb-item"><a href="/">Home</a></li> + <li class="breadcrumb-item">Explore</li> + <li class="breadcrumb-item active"><a class="active" href="{% url 'uhepp_vault:collection-list' %}">Collections</a></li> + </ol> +</nav> + <h1>Collections</h1> @@ -11,11 +19,11 @@ <div class="d-flex justify-content-between align-items-center"> <span> {{ collection.title }} - <small class="text-muted">{% if collection.visibility >= 30 %}(public) - {% elif collection.visibility >= 20 %}(internal) - {% elif collection.visibility >= 10 %}(private) - {% endif %} - by <span class="text-body">{{ collection.owner.username}}</span> + <i class="text-muted fas {% if collection.visibility >= 30 %} fa-globe-europe + {% elif collection.visibility >= 20 %} fa-shield-alt + {% elif collection.visibility >= 10 %} fa-lock + {% endif %}"></i> + <small class="text-muted">by <span class="text-body">{{ collection.owner.username}}</span></small> </small> </span> diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_detail.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_detail.html index d5353f9..d24d9fe 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_detail.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_detail.html @@ -11,8 +11,11 @@ </ol> </nav> -<h1>{{ plot }}</h1> - +<h1>{{ plot }} +<i class="text-muted fas {% if plot.collection.visibility >= 30 %} fa-globe-europe +{% elif plot.collection.visibility >= 20 %} fa-shield-alt +{% elif plot.collection.visibility >= 10 %} fa-lock +{% endif %}"></i></h1> <div class="d-flex"> <span class="d-none d-md-inline">UUID: {{ plot.uuid }}</span> diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_list.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_list.html index cee6cea..d11a8fb 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_list.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/plot_list.html @@ -1,6 +1,13 @@ {% extends 'uhepp_vault/base.html' %} {% block content %} +<nav aria-label="breadcrumb"> + <ol class="breadcrumb my-2"> + <li class="breadcrumb-item"><a href="/">Home</a></li> + <li class="breadcrumb-item">Explore</li> + <li class="breadcrumb-item active"><a class="active" href="{% url 'uhepp_vault:plot-list' %}">Plots</a></li> + </ol> +</nav> <h1>Plots</h1> {% if plot_list %} <ul> diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_detail.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_detail.html index 366866e..fda7419 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_detail.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_detail.html @@ -7,25 +7,33 @@ <li class="breadcrumb-item"><a class="active" href="{% url 'uhepp_vault:user-detail' user.username %}">{{ user.username }}</a></li> </ol> </nav> -<h1>{{ user.first_name }} {{ user.last_name }}</h1> -<p>Visibility: -{% if user.profile.visibility >= 30 %} public -{% elif user.profile.visibility >= 20 %} internal -{% elif user.profile.visibility >= 10 %} private) -{% endif %}</p> - -{% if user.username == request.user.username %} -<p><a href="{% url 'uhepp_vault:account-detail' %}">Edit profile</a></p> -{% endif %} - -<p>Home institute: {{ user.profile.home_institute }}</p> - -<h2>Collection</h2> +<h1 class="controls-head" style="margin-bottom: -0.5rem"> + <span> + {{ user.first_name }} {{ user.last_name }} + <i class="text-muted fas {% if user.profile.visibility >= 30 %} fa-user + {% elif user.profile.visibility >= 20 %} fa-user-shield + {% elif user.profile.visibility >= 10 %} fa-user-lock + {% endif %}"></i> + </span> {% if user.username == request.user.username %} -<p><a href="{% url 'uhepp_vault:collection-create' %}">New collection</a></p> + <span> + <a class="btn btn-outline-secondary" href="{% url 'uhepp_vault:account-detail' %}"> + <i class="fas fa-pen"></i> + </a> + </span> {% endif %} +</h1> +<p><small class="text-muted">{{ user.profile.home_institute }}</small></p> +<h2 class="controls-head"> + Collection + {% if user.username == request.user.username %} + <a class="btn btn-outline-primary" href="{% url 'uhepp_vault:collection-create' %}"> + <i class="fas fa-plus"></i> + </a> + {% endif %} +</h2> {% if user.collections %} <div class="list-group"> @@ -34,11 +42,10 @@ <div class="d-flex justify-content-between align-items-center"> <span> {{ collection.title }} - <small class="text-muted">{% if collection.visibility >= 30 %}(public) - {% elif collection.visibility >= 20 %}(internal) - {% elif collection.visibility >= 10 %}(private) - {% endif %} - </small> + <i class="text-muted fas {% if collection.visibility >= 30 %} fa-globe-europe + {% elif collection.visibility >= 20 %} fa-shield-alt + {% elif collection.visibility >= 10 %} fa-lock + {% endif %}"></i> </span> diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_form.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_form.html index 245f247..9fc3ab3 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_form.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_form.html @@ -1,6 +1,13 @@ {% extends 'uhepp_vault/base.html' %} +{% load crispy_forms_tags %} {% block content %} +<nav aria-label="breadcrumb"> + <ol class="breadcrumb my-2"> + <li class="breadcrumb-item"><a href="/">Home</a></li> + <li class="breadcrumb-item"><a class="active" href="{% url 'uhepp_vault:user-detail' user.username %}">{{ user.username }}</a></li> + </ol> +</nav> <h1>Your account</h1> <p>You are logged in as {{ profile.user.username }}</p> @@ -30,8 +37,8 @@ <dt>Email<dt> <dd>{{ profile.user.email}}</dd> </dl> - {{ form }} + {{ form|crispy }} - <input type="submit" value="Update"> + <button type="submit" class="btn btn-primary">Save</button </form> {% endblock %} diff --git a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_list.html b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_list.html index f3e8e20..8024631 100644 --- a/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_list.html +++ b/uhepp_org/uhepp_vault/templates/uhepp_vault/profile_list.html @@ -1,6 +1,13 @@ {% extends 'uhepp_vault/base.html' %} {% block content %} +<nav aria-label="breadcrumb"> + <ol class="breadcrumb my-2"> + <li class="breadcrumb-item"><a href="/">Home</a></li> + <li class="breadcrumb-item">Explore</li> + <li class="breadcrumb-item active"><a class="active" href="{% url 'uhepp_vault:user-list' %}">Users</a></li> + </ol> +</nav> <h1>Users</h1> {% if profile_list %} <ul> @@ -8,11 +15,10 @@ <li> <a href="{% url 'uhepp_vault:user-detail' profile.user.username %}"> {{ profile.user.first_name }} {{ profile.user.last_name }} - </a> - {% if profile.visibility >= 30 %}(public) - {% elif profile.visibility >= 20 %}(internal) - {% elif profile.visibility >= 10 %}(private) - {% endif %} +<i class="text-muted fas {% if profile.visibility >= 30 %} fa-user +{% elif profile.visibility >= 20 %} fa-user-shield +{% elif profile.visibility >= 10 %} fa-user-lock +{% endif %}"></i></a> </li> {% endfor %} </ul> diff --git a/uhepp_org/uhepp_vault/views.py b/uhepp_org/uhepp_vault/views.py index aa396a9..b430005 100644 --- a/uhepp_org/uhepp_vault/views.py +++ b/uhepp_org/uhepp_vault/views.py @@ -3,9 +3,11 @@ from django.views import generic from django.db.models import Q from django.contrib.auth.mixins import LoginRequiredMixin from django.http import JsonResponse, HttpResponseRedirect, \ - HttpResponseForbidden + HttpResponseForbidden, Http404 from django.urls import reverse, reverse_lazy from django.shortcuts import get_object_or_404, redirect, render +from django.conf import settings + from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User, Group from django.utils.translation import gettext_lazy as _ @@ -91,6 +93,14 @@ class UserDetailView(MaskedRelatedMixin, generic.DetailView): ) return queryset + def get(self, request, *args, **kwargs): + try: + return super().get(request, *args, **kwargs) + except Http404 as original: + if not request.user.is_anonymous: + raise original + return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path)) + class CollectionListView(generic.ListView): model = Collection @@ -117,6 +127,14 @@ class CollectionDetailView(generic.DetailView): ) return queryset + def get(self, request, *args, **kwargs): + try: + return super().get(request, *args, **kwargs) + except Http404 as original: + if not request.user.is_anonymous: + raise original + return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path)) + class CollectionCreateView(LoginRequiredMixin, generic.CreateView): model = Collection template_name = 'uhepp_vault/collection_form.html' @@ -190,6 +208,13 @@ class PlotDetail(generic.DetailView): ) return queryset + def get(self, request, *args, **kwargs): + try: + return super().get(request, *args, **kwargs) + except Http404 as original: + if not request.user.is_anonymous: + raise original + return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path)) def plot_download(request, uuid): -- GitLab