admin-redesign #26

Merged
eising merged 9 commits from admin-redesign into main 2025-06-19 05:24:06 +00:00
18 changed files with 483 additions and 190 deletions
Showing only changes of commit 05775a2e1e - Show all commits

View File

@ -35,7 +35,7 @@
<main id="content" class="flex-1 overflow-y-auto" hx-target="this" hx-swap="innerHTML"> <main id="content" class="flex-1 overflow-y-auto" hx-target="this" hx-swap="innerHTML">
{% block breadcrumbs %} {% block breadcrumbs %}
{% endblock %} {% endblock %}
<div class="p-4" id="maincontent"> <div class="" id="maincontent">
{% block content %}{% endblock %} {% block content %}{% endblock %}
</div> </div>
</main> </main>
@ -43,8 +43,12 @@
</div> </div>
</div> </div>
{% block scripts %} {% block scripts %}
{% include 'base/partials/scripts.html.j2' %} {% include 'base/partials/scripts.html.j2' %}
{% endblock %} {% endblock %}
{% block local_scripts %}
{% endblock %}
</body> </body>
</html> </html>

View File

@ -0,0 +1,26 @@
{% extends 'base/page.html.j2' %}
{% block page_content %}
<!-- Master-Detail Split View -->
<div class="flex h-[calc(100vh-8rem)] overflow-hidden">
<!-- Master Pane -->
<aside id="master-pane"
class="md:w-80 w-full shrink-0 border-r overflow-y-auto bg-white md:block border-gray-200 p-4">
{% block master %}
<p class="p-4 text-gray-500">Master view (e.g. list/tree)</p>
{% endblock %}
</aside>
<!-- Detail Pane -->
<section id="detail-pane"
class="flex-1 flex overflow-y-auto bg-white p-4 hidden md:block">
{% block detail %}
<p class="p-4 text-gray-500">Select an item to view details</p>
{% endblock %}
</section>
</div>
{% endblock %}

View File

@ -26,14 +26,14 @@
</li> </li>
<li> <li>
<a href="/admin/secrets" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100"> <a href="/secrets" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100">
<sl-icon name="database-lock"></sl-icon> <sl-icon name="database-lock"></sl-icon>
Secrets Secrets
</a> </a>
</li> </li>
<li> <li>
<a href="/admin/audit" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100"> <a href="/audit" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100">
<sl-icon name="card-list"></sl-icon> <sl-icon name="card-list"></sl-icon>
Audit Log Audit Log
</a> </a>

View File

@ -1,46 +1,24 @@
{% extends "/dashboard/_base.html" %} {% block content %} {% extends 'base/master-detail-email.html.j2' %}
<div class="p-4 bg-white block sm:flex items-center justify-between border-b border-gray-200 lg:mt-1.5 dark:bg-gray-800 dark:border-gray-700"> {% block title %}Client {{ client.name }}{% endblock %}
<div class="w-full mb-1">
<div class="mb-4">
<nav class="flex mb-5" aria-label="Breadcrumb">
<ol class="inline-flex items-center space-x-1 text-sm font-medium md:space-x-2">
<li class="inline-flex items-center">
<a href="/" class="inline-flex items-center text-gray-700 hover:text-primary-600 dark:text-gray-300 dark:hover:text-white">
<svg class="w-5 h-5 mr-2.5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg>
Home
</a>
</li>
<li>
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
<span class="ml-1 text-gray-400 md:ml-2 dark:text-gray-500" aria-current="page">Clients</span>
</div>
</li>
<li>
<div class="flex items-center">
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
<span class="ml-1 text-gray-400 md:ml-2 dark:text-gray-500" aria-current="page">View</span>
</div>
</li>
</ol>
</nav>
{% block master %}
</div>
<div class="grid w-full grid-cols-1 gap-4 mt-4 xl:grid-cols-3">
<div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm sm:flex dark:border-gray-700 sm:p-6 dark:bg-gray-800 h-full" id="client-tree">
{% include '/clients/partials/tree.html.j2' %} {% include '/clients/partials/tree.html.j2' %}
</div> {% endblock %}
<div class="2xl:col-span-2 xl:col-span-2 p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<div class="w-full" id="clientdetails">
{% block detail %}
<div id="clientdetails" class="w-full">
{% include '/clients/partials/client_details.html.j2' %} {% include '/clients/partials/client_details.html.j2' %}
</div> </div>
</div>
</div>
</div>
</div>
{% include '/clients/partials/drawer_create.html.j2' %}
{% endblock %} {% endblock %}
{% include '/clients/partials/drawer_create.html.j2' %}
{% block local_scripts %}
<script>
{% include '/clients/partials/tree_event.js' %}
</script>
{% endblock local_scripts %}

View File

@ -1,41 +1,22 @@
{% extends "/dashboard/_base.html" %} {% block content %} {% extends 'base/master-detail-email.html.j2' %}
<div class="p-4 bg-white block sm:flex items-center justify-between border-b border-gray-200 lg:mt-1.5 dark:bg-gray-800 dark:border-gray-700"> {% block title %}Clients{% endblock %}
<div class="w-full mb-1">
<div class="mb-4">
<nav class="flex mb-5" aria-label="Breadcrumb">
<ol class="inline-flex items-center space-x-1 text-sm font-medium md:space-x-2">
<li class="inline-flex items-center">
<a href="/" class="inline-flex items-center text-gray-700 hover:text-primary-600 dark:text-gray-300 dark:hover:text-white">
<svg class="w-5 h-5 mr-2.5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path></svg>
Home
</a>
</li>
<li>
<div class="flex items-center"> {% block master %}
<svg class="w-6 h-6 text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>
<span class="ml-1 text-gray-400 md:ml-2 dark:text-gray-500" aria-current="page">Clients</span>
</div>
</li>
</ol>
</nav>
</div>
<div class="grid w-full grid-cols-1 gap-4 mt-4 xl:grid-cols-3">
<div class="p-4 bg-white border border-gray-200 rounded-lg shadow-sm sm:flex dark:border-gray-700 sm:p-6 dark:bg-gray-800 h-full" id="client-tree">
{% include '/clients/partials/tree.html.j2' %} {% include '/clients/partials/tree.html.j2' %}
</div> {% endblock %}
<div class="2xl:col-span-2 xl:col-span-2 p-4 mb-4 bg-white border border-gray-200 rounded-lg shadow-sm 2xl:col-span-2 dark:border-gray-700 sm:p-6 dark:bg-gray-800">
<div class="w-full" id="clientdetails">
{% block detail %}
<div id="clientdetails" class="w-full">
<h3 class="mb-4 text-sm italic text-gray-400 dark:text-white">Click an item to view details</h3> <h3 class="mb-4 text-sm italic text-gray-400 dark:text-white">Click an item to view details</h3>
</div> </div>
</div> {% endblock %}
</div>
</div>
</div>
{% include '/clients/partials/drawer_create.html.j2' %} {% include '/clients/partials/drawer_create.html.j2' %}
{% endblock %} {% block local_scripts %}
<script>
{% include '/clients/partials/tree_event.js' %}
</script>
{% endblock local_scripts %}

View File

@ -1,7 +1,9 @@
<div class="flex flex-1 flex-col justify-between h-full flowbite-init-target"> {# This is the master block #}
<div class="grid grid-cols-2 place-content-between mb-6">
<div> <div class="flowbite-init-target">
<div class="tree-header grid grid-cols-2 place-content-between mb-6">
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Clients</h1> <h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Clients</h1>
<div class="flex"> <div class="flex">
<div <div
class="htmx-indicator mt-2" class="htmx-indicator mt-2"
@ -14,10 +16,8 @@
<span class="sr-only">Loading...</span> <span class="sr-only">Loading...</span>
</div> </div>
</div> </div>
</div>
</div>
<div <div
class="flex justify-end px-4" class="flex w-full justify-end"
> >
<sl-icon-button <sl-icon-button
name="plus-square" name="plus-square"
@ -31,8 +31,8 @@
></sl-icon-button> ></sl-icon-button>
</div> </div>
</div> </div>
<div class="flex-1 overflow-auto"> <div class="col-span-full">
<div class="relative w-full "> <div class="relative">
<div class="border-b border-gray-200 py-2 mb-6"> <div class="border-b border-gray-200 py-2 mb-6">
<label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label> <label for="default-search" class="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
<div class="relative"> <div class="relative">
@ -56,12 +56,10 @@
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<div id="client-tree-items"> <div id="client-tree-items">
{% include '/clients/partials/tree_items.html.j2' %} {% include '/clients/partials/tree_items.html.j2' %}
</div> </div>
</div> </div>
</div>
<script>
{% include '/clients/partials/tree_event.js' %}
</script>

View File

@ -8,6 +8,8 @@ function addTreeListener() {
if (!selectedEl) return; if (!selectedEl) return;
const masterPane = document.getElementById("master-pane");
const detailPane = document.getElementById("detail-pane");
const type = selectedEl.dataset.nodeType; const type = selectedEl.dataset.nodeType;
const clientId = selectedEl.dataset.clientId; const clientId = selectedEl.dataset.clientId;
const name = selectedEl.dataset.clientName; const name = selectedEl.dataset.clientName;
@ -17,10 +19,15 @@ function addTreeListener() {
let url = `/clients/client/${encodeURIComponent(clientId)}`; let url = `/clients/client/${encodeURIComponent(clientId)}`;
if (url) { if (url) {
htmx.ajax("GET", url, { htmx
.ajax("GET", url, {
target: "#clientdetails", target: "#clientdetails",
//swap: 'OuterHTML', //swap: 'OuterHTML',
indicator: "#client-spinner", indicator: "#client-spinner",
})
.then(() => {
masterPane.classList.add("hidden");
detailPane.classList.remove("hidden");
}); });
} }
}); });

View File

@ -38,5 +38,4 @@
{% include 'clients/partials/pagination.html.j2' %} {% include 'clients/partials/pagination.html.j2' %}
</div> </div>
{% endif %} {% endif %}
</div> </div>

View File

@ -93,42 +93,14 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
page=page, limit=per_page, total=results.total_results, offset=offset page=page, limit=per_page, total=results.total_results, offset=offset
) )
breadcrumbs = [("clients", "/clients/")]
LOG.info("Results %r", results) LOG.info("Results %r", results)
return templates.TemplateResponse( return templates.TemplateResponse(
request, request,
"clients/index.html.j2", "clients/index.html.j2",
{ {
"page_title": "Clients", "breadcrumbs": breadcrumbs,
"offset": offset,
"pages": paginate,
"clients": results.clients,
"user": current_user,
"results": results,
},
)
@app.get("/clients/new/")
async def get_new_client_tree(
request: Request,
current_user: Annotated[LocalUserInfo, Depends(dependencies.get_user_info)],
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
) -> Response:
"""Get client tree view."""
page = 1
per_page = CLIENTS_PER_PAGE
offset = 0
client_filter = ClientFilter(offset=offset, limit=per_page)
results = await admin.query_clients(client_filter)
paginate = PagingInfo(
page=page, limit=per_page, total=results.total_results, offset=offset
)
LOG.info("Results %r", results)
return templates.TemplateResponse(
request,
"clients/redesign.html.j2",
{
"page_title": "Clients", "page_title": "Clients",
"offset": offset, "offset": offset,
"pages": paginate, "pages": paginate,
@ -197,6 +169,11 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
) )
template = "clients/client.html.j2" template = "clients/client.html.j2"
breadcrumbs = [
("clients", "/clients/"),
(results.client.name, request.url.path),
]
headers: dict[str, str] = {} headers: dict[str, str] = {}
if request.headers.get("HX-Request"): if request.headers.get("HX-Request"):
headers["HX-Push-Url"] = request.url.path headers["HX-Push-Url"] = request.url.path
@ -207,6 +184,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
template, template,
{ {
"page_title": f"Client {results.client.name}", "page_title": f"Client {results.client.name}",
"breadcrumbs": breadcrumbs,
"pages": results.pages, "pages": results.pages,
"clients": results.results.clients, "clients": results.results.clients,
"client": results.client, "client": results.client,

View File

@ -382,9 +382,6 @@
.order-1 { .order-1 {
order: 1; order: 1;
} }
.order-2 {
order: 2;
}
.col-span-2 { .col-span-2 {
grid-column: span 2 / span 2; grid-column: span 2 / span 2;
} }
@ -457,9 +454,6 @@
.ms-3 { .ms-3 {
margin-inline-start: calc(var(--spacing) * 3); margin-inline-start: calc(var(--spacing) * 3);
} }
.ms-auto {
margin-inline-start: auto;
}
.me-2 { .me-2 {
margin-inline-end: calc(var(--spacing) * 2); margin-inline-end: calc(var(--spacing) * 2);
} }
@ -682,15 +676,18 @@
.h-\[12px\] { .h-\[12px\] {
height: 12px; height: 12px;
} }
.h-\[16px\] {
height: 16px;
}
.h-\[32px\] {
height: 32px;
}
.h-\[36rem\] { .h-\[36rem\] {
height: 36rem; height: 36rem;
} }
.h-\[calc\(100vh-4rem\)\] {
height: calc(100vh - 4rem);
}
.h-\[calc\(100vh-8rem\)\] {
height: calc(100vh - 8rem);
}
.h-\[calc\(100vh-10rem\)\] {
height: calc(100vh - 10rem);
}
.h-full { .h-full {
height: 100%; height: 100%;
} }
@ -1245,9 +1242,6 @@
.border-blue-300 { .border-blue-300 {
border-color: var(--color-blue-300); border-color: var(--color-blue-300);
} }
.border-blue-700 {
border-color: var(--color-blue-700);
}
.border-gray-100 { .border-gray-100 {
border-color: var(--color-gray-100); border-color: var(--color-gray-100);
} }
@ -1332,9 +1326,6 @@
.bg-blue-600 { .bg-blue-600 {
background-color: var(--color-blue-600); background-color: var(--color-blue-600);
} }
.bg-blue-700 {
background-color: var(--color-blue-700);
}
.bg-emerald-500 { .bg-emerald-500 {
background-color: var(--color-emerald-500); background-color: var(--color-emerald-500);
} }
@ -2175,13 +2166,6 @@
} }
} }
} }
.hover\:bg-blue-800 {
&:hover {
@media (hover: hover) {
background-color: var(--color-blue-800);
}
}
}
.hover\:bg-gray-50 { .hover\:bg-gray-50 {
&:hover { &:hover {
@media (hover: hover) { @media (hover: hover) {
@ -2774,11 +2758,6 @@
inset: calc(var(--spacing) * 0); inset: calc(var(--spacing) * 0);
} }
} }
.md\:order-1 {
@media (width >= 48rem) {
order: 1;
}
}
.md\:order-2 { .md\:order-2 {
@media (width >= 48rem) { @media (width >= 48rem) {
order: 2; order: 2;
@ -2859,6 +2838,16 @@
width: calc(var(--spacing) * 64); width: calc(var(--spacing) * 64);
} }
} }
.md\:w-72 {
@media (width >= 48rem) {
width: calc(var(--spacing) * 72);
}
}
.md\:w-80 {
@media (width >= 48rem) {
width: calc(var(--spacing) * 80);
}
}
.md\:w-\[calc\(100\%-256px\)\] { .md\:w-\[calc\(100\%-256px\)\] {
@media (width >= 48rem) { @media (width >= 48rem) {
width: calc(100% - 256px); width: calc(100% - 256px);
@ -3114,6 +3103,11 @@
width: auto; width: auto;
} }
} }
.lg\:table-fixed {
@media (width >= 64rem) {
table-layout: fixed;
}
}
.lg\:grid-cols-2 { .lg\:grid-cols-2 {
@media (width >= 64rem) { @media (width >= 64rem) {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
@ -3469,11 +3463,6 @@
border-color: var(--color-red-800); border-color: var(--color-red-800);
} }
} }
.dark\:bg-blue-600 {
&:where(.dark, .dark *) {
background-color: var(--color-blue-600);
}
}
.dark\:bg-blue-900 { .dark\:bg-blue-900 {
&:where(.dark, .dark *) { &:where(.dark, .dark *) {
background-color: var(--color-blue-900); background-color: var(--color-blue-900);
@ -3728,15 +3717,6 @@
} }
} }
} }
.dark\:hover\:bg-blue-700 {
&:where(.dark, .dark *) {
&:hover {
@media (hover: hover) {
background-color: var(--color-blue-700);
}
}
}
}
.dark\:hover\:bg-blue-800 { .dark\:hover\:bg-blue-800 {
&:where(.dark, .dark *) { &:where(.dark, .dark *) {
&:hover { &:hover {