1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2026-11-09 03:36:48 +00:00
webvirtcloud/accounts/templates/account.html
catborise 0044359202 feat(accounts): the administrator's view of a user as an identity strip and cards
A superuser's page of a user was a heading, two unlabelled icon buttons
and three tabs: the VMs a table of check columns, the SSH keys a table
that pushed the page sideways on a phone.

Now a card at the top shows the user's name, role, Blocked when they
are, username, email, groups, last login and joining date, with Edit
user and Email OTP QR code as labelled buttons and links to the sections
below with their counts. The VMs card shows each VM with its host and
what the user may do beyond power and console as badges in the VM Users
tab's words (Change settings, Delete the VM, Change console settings),
with Change access and Remove from user in a menu, and Add VM in its
header. The SSH keys and the API tokens are cards; the key rows are now
one include with the user's own Profile, and both lists say when they
are empty. The full key shows over its fingerprint.

The tab script had no page left and goes.
2026-10-31 18:10:05 +03:00

97 lines
6.6 KiB
HTML

{% extends "base.html" %}
{% load i18n %}
{% load bootstrap_icons %}
{% block title %}{% trans "User Profile" %} - {{ user }}{% endblock %}
{% block page_heading %}{% trans "User Profile" %}{% endblock page_heading %}
{% block content %}
<section class="card mb-4" aria-labelledby="identity-title">
<div class="card-body">
<div class="row g-3 align-items-start">
<div class="col-lg-8">
<div class="d-flex flex-wrap align-items-center gap-2">
<h2 class="h4 mb-0 text-break" id="identity-title">{{ user.get_full_name|default:user.username }}</h2>
{% if user.is_superuser %}
<span class="badge text-bg-secondary">{% trans "Superuser" %}</span>
{% elif user.is_staff %}
<span class="badge text-bg-secondary">{% trans "Template editor" %}</span>
{% endif %}
{% if not user.is_active %}<span class="badge text-bg-danger">{% trans "Blocked" %}</span>{% endif %}
</div>
<div class="d-flex flex-wrap align-items-center gap-2 small mt-2">
<span class="text-body-secondary text-break">{{ user.username }}</span>
{% if user.email %}<span class="text-break">{{ user.email }}</span>{% endif %}
{% for group in user.groups.all %}<span class="badge text-bg-light border mw-100 text-wrap text-break">{{ group.name }}</span>{% endfor %}
</div>
<div class="d-flex flex-wrap gap-2 gap-md-4 small text-body-secondary mt-3">
<span>{% trans "Last login" %} {{ user.last_login|date:"Y-m-d H:i"|default:_("never") }}</span>
<span>{% trans "Joined" %} {{ user.date_joined|date:"Y-m-d" }}</span>
</div>
</div>
<div class="col-lg-4 d-flex flex-wrap justify-content-lg-end gap-2">
<a href="{% url 'admin:user_update' user.id %}?next={% url 'accounts:account' user.id %}" class="btn btn-primary">{% bs_icon 'pencil' %} {% trans "Edit user" %}</a>
{% if otp_enabled %}
<form method="post" action="{% url 'accounts:admin_email_otp' user.id %}">{% csrf_token %}
<button type="submit" class="btn btn-outline-secondary">{% bs_icon 'qr-code' %} {% trans "Email OTP QR code" %}</button>
</form>
{% endif %}
</div>
</div>
</div>
<nav class="card-footer d-flex flex-wrap gap-3 small" aria-label="{% trans 'User sections' %}">
<a href="#instances">{% trans "VMs" %} <span class="badge text-bg-light border">{{ user_insts|length }}</span></a>
<a href="#public-keys">{% trans "SSH Keys" %} <span class="badge text-bg-light border">{{ publickeys|length }}</span></a>
<a href="#apitokens">{% trans "API Tokens" %} <span class="badge text-bg-light border">{{ api_tokens|length }}</span></a>
</nav>
</section>
<section class="card mb-4" id="instances" aria-labelledby="instances-title">
<div class="card-header d-flex flex-wrap align-items-center justify-content-between gap-2">
<h2 class="h5 mb-0" id="instances-title">{% trans "VMs" %} <span class="badge text-bg-light border">{{ user_insts|length }}</span></h2>
<a href="{% url 'accounts:user_instance_create' user.id %}" class="btn btn-sm btn-primary">{% bs_icon 'plus-lg' %} {% trans "Add VM" %}</a>
</div>
<div class="list-group list-group-flush">
{% for inst in user_insts %}
<div class="list-group-item py-3">
<div class="d-flex align-items-start align-items-md-center gap-3">
<div class="row g-2 align-items-center flex-grow-1" style="min-width: 0;">
<div class="col-12 col-md-6">
<a class="fw-semibold text-break" href="{% url 'instances:instance' inst.instance.id %}">{{ inst.instance.name }}</a>
<div class="small text-body-secondary text-break">{% trans "Host" %}: {{ inst.instance.compute.name }}</div>
</div>
<div class="col-12 col-md-6 d-flex flex-wrap gap-1">
{# the rights as the VM's Users tab names them: every owner powers the VM and opens its console #}
{% if inst.is_change %}<span class="badge text-bg-light border">{% trans "Change settings" %}</span>{% endif %}
{% if inst.is_delete %}<span class="badge text-bg-light border">{% trans "Delete the VM" %}</span>{% endif %}
{% if inst.is_change and inst.is_vnc %}<span class="badge text-bg-light border">{% trans "Change console settings" %}</span>{% endif %}
{% if not inst.is_change and not inst.is_delete %}<span class="small text-body-secondary">{% trans "Power and console only" %}</span>{% endif %}
</div>
</div>
<div class="dropdown flex-shrink-0">
<button class="btn btn-sm btn-outline-secondary" type="button" data-bs-toggle="dropdown" aria-expanded="false"
aria-label="{% blocktrans with name=inst.instance.name %}Actions for {{ name }}{% endblocktrans %}">{% bs_icon 'three-dots' %}</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="{% url 'accounts:user_instance_update' inst.id %}">{% trans "Change access" %}</a></li>
<li><a class="dropdown-item text-danger" href="{% url 'accounts:user_instance_delete' inst.id %}">{% trans "Remove from user" %}</a></li>
</ul>
</div>
</div>
</div>
{% empty %}
<div class="list-group-item text-body-secondary">{% trans "No VMs." %}</div>
{% endfor %}
</div>
</section>
<section class="card mb-4" id="public-keys" aria-labelledby="public-keys-title">
<div class="card-header"><h2 class="h5 mb-0" id="public-keys-title">{% trans "SSH Keys" %} <span class="badge text-bg-light border">{{ publickeys|length }}</span></h2></div>
<div class="list-group list-group-flush">{% include "ssh_key_list.html" with owner=user %}</div>
</section>
<section class="card" id="apitokens" aria-labelledby="apitokens-title">
<div class="card-header"><h2 class="h5 mb-0" id="apitokens-title">{% trans "API Tokens" %} <span class="badge text-bg-light border">{{ api_tokens|length }}</span></h2></div>
<div class="list-group list-group-flush">{% include "api_token_list.html" with owner=user %}</div>
</section>
{% endblock content %}