mirror of
https://github.com/retspen/webvirtcloud
synced 2026-11-08 19:26:48 +00:00
The Users, Groups and Removed VMs pages were bare tables: rows of coloured icon buttons without words, five columns of small checks for a user's role and permissions, dates broken over three lines and a lone "+" for a new entry. The owner chose a directory layout from three rendered options; it follows the host pages' cards: - Each list is a card with its count and search in the header and one list-group item per entry, which stacks on a phone without scrolling. - A user shows their role as a badge (Superuser, Template editor) or "User", Blocked as a red badge, their groups, a granted clone permission and live API tokens, and the last login on one line; role and status are searchable. Edit is the visible action, the menu holds View profile, Block or Unblock and Delete; Block and Delete are disabled on one's own account, which the server refuses anyway. - A group shows its member and permission counts; its name opens it. The page's title said "Users". - A removed VM shows its UUID, the host it left, its owners and when the record was made and expires. - Logs keep their table in a card, the server search in its header, the count of matching rows, Done and Failed as badges, and a message column wide enough to read on a phone. The user form was one long column of horizontal fields. The owner rejected three boxed layouts and chose one led by what the user may do: the Active switch, Template editor and Superuser as two cards, groups as chips, the user's own permissions as switches each saying what it allows, then the name and password and the quota folded into details whose summaries tell their values (-1 as "any"); they open on a new user and on an error inside them. A refused group or permission is said beside its field. The group form follows it: the name, what its members may do, its members as chips. Cancel goes back to the list instead of the browser history.
61 lines
3.2 KiB
HTML
61 lines
3.2 KiB
HTML
{% extends "base.html" %}
|
|
{% load i18n %}
|
|
{% load static %}
|
|
{% load bootstrap_icons %}
|
|
|
|
{% block title %}{% trans "Groups" %}{% endblock %}
|
|
|
|
{% block page_heading %}{% trans "Groups" %}{% endblock page_heading %}
|
|
|
|
{% block page_heading_extra %}
|
|
<a href="{% url 'admin:group_create' %}" class="btn btn-primary">
|
|
<span aria-hidden="true">{% bs_icon 'plus-lg' %}</span> {% trans "New group" %}
|
|
</a>
|
|
{% endblock page_heading_extra %}
|
|
|
|
{% block content %}
|
|
{% if not groups %}
|
|
<div class="alert alert-warning shadow-sm">
|
|
{% bs_icon 'exclamation-triangle' %} {% trans "There are no groups yet." %}
|
|
</div>
|
|
{% else %}
|
|
<div class="card mb-3">
|
|
<div class="card-header d-flex flex-wrap align-items-center gap-2">
|
|
<span class="me-auto">{% trans "Groups" %} <span class="badge text-bg-light border">{{ groups|length }}</span></span>
|
|
<input id="filter" class="form-control form-control-sm w-auto" type="search" placeholder="{% trans "Search" %}" aria-label="{% trans "Search groups" %}">
|
|
</div>
|
|
<div class="list-group list-group-flush searchable">
|
|
{% for group in groups %}
|
|
<div class="list-group-item py-3" data-search="{{ group.name }}">
|
|
<div class="row g-2 align-items-center">
|
|
<div class="col-12 col-md-4">
|
|
<a href="{% url 'admin:group_update' group.id %}" class="fw-semibold text-break">{{ group.name }}</a>
|
|
</div>
|
|
<div class="col-12 col-md-5 small text-body-secondary">
|
|
{% blocktrans count count=group.members %}{{ count }} member{% plural %}{{ count }} members{% endblocktrans %}
|
|
· {% blocktrans count count=group.perms %}{{ count }} permission{% plural %}{{ count }} permissions{% endblocktrans %}
|
|
</div>
|
|
<div class="col-12 col-md-3 text-md-end">
|
|
<div class="btn-group">
|
|
<a href="{% url 'admin:group_update' group.id %}" class="btn btn-sm btn-outline-secondary">{% trans "Edit" %}</a>
|
|
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-toggle="dropdown" aria-expanded="false"
|
|
data-bs-popper-config='{"strategy": "fixed"}' aria-label="{% blocktrans with name=group.name %}More actions for {{ name }}{% endblocktrans %}">{% bs_icon 'three-dots' %}</button>
|
|
<ul class="dropdown-menu dropdown-menu-end shadow">
|
|
<li><a class="dropdown-item text-danger" href="{% url 'admin:group_delete' group.id %}">{% bs_icon 'trash' %} {% trans "Delete" %}</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
<div role="status">
|
|
<div id="no-match" class="text-center text-body-secondary py-3" hidden>{% trans "No group matches the search." %}</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% endblock content %}
|
|
|
|
{% block script %}
|
|
{% if groups %}<script src="{% static 'js/table_filter.js' %}"></script>{% endif %}
|
|
{% endblock script %}
|