diff --git a/uhepp-js/package-lock.json b/uhepp-js/package-lock.json index 090b075fb8974bacce977aa207e24e2d5a82e2b7..a54299391f815ed02553f256836207d61b6a3fdb 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 b13cf473c6d9e0de95bf3a7dbbb6624711ab3044..21a10c78ae27becb204995f8b53bd18b4532fa7f 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 a5dd86711160c9c4002bc40834f5e61d73ef83a1..5313f3082cdd371e177cf2921d676ceec543ef6e 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 110e05ddc350196a549b319705527e5c1bb94389..725bae53e671cd6510db76ab672615397a61e84a 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 3e8abd10af0fa99c01353d96f77521811a77c691..5e8da88bc3f05b88bc6c084ad040ff4bd7f50ebf 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 cbe31222fe0f7b4b0b301ecc910fe2db68cc07e9..ca69151470b2ba67de630cb740c5fe936fc6823c 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 c206f861c484da6af79c21e269193ed5086a3feb..db67857f04aaac5dd5c881d28a5ec88172213e10 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 12df3923187cfbd3ef697d54d5b7e427684d3bae..4e6789cd4edddac206dbab6007119e41c53055f3 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 dc83f97b9cf12c7e46a9108f564eccaa775868bd..0eda2f50de9fac66506076d6661c1f8e41b135a5 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 068e808f1ffb0219da467fc4635d2283b300fa3f..77d2ccec8c57265cf37570a2bb09b87a69ddf7d3 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 d5353f9f4282d653fdafb8b645ebe70356063d51..d24d9fe009235b233500c637ee5dbb3c872fce38 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 cee6cea51850d43b6b38fea11b345298e20a1923..d11a8fba3f20325674d1f76134cdf6e4c8fe26a9 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 366866e9cb0206204a67ffd5bf9f4732ba0fce87..fda74198967b61b32bdc3ee3f8d2b02315eea0d6 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 245f247aa9d2534b5af23699ae739b3ef42ffb7d..9fc3ab3ebd55f6601071b6bb263c7566f2284bde 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 f3e8e2070706647088d646f77250cf7b1c334fe7..802463177096dfba85d544e888eb44b697b6565f 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 aa396a966f1e5326e19a64ccd5353f5cadbdcfcb..b43000564fcbbaaf1596c6d08d1643b7baf00bef 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):