Compare commits
8 Commits
d9e0052003
...
2b50c686d0
| Author | SHA1 | Date | |
|---|---|---|---|
| 2b50c686d0 | |||
| 57e69390b2 | |||
| 23d354bc12 | |||
| cad9849019 | |||
| b4c395f0da | |||
| d55c699549 | |||
| 05775a2e1e | |||
| 9b0588679f |
@ -1,60 +1,6 @@
|
||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
||||
<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"
|
||||
>
|
||||
<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-800 dark:text-white"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 8h6m-6 4h6m-6 4h6M6 3v18l2-2 2 2 2-2 2 2 2-2 2 2V3l-2 2-2-2-2 2-2-2-2 2-2-2Z"
|
||||
/>
|
||||
|
||||
<span class="ml-1 text-gray-400 md:ml-2 dark:text-gray-500" aria-current="page">Audit Log</span>
|
||||
</svg>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Audit Log</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% extends "/base/page.html.j2" %}
|
||||
{% block title %}Audit{% endblock %}
|
||||
{% block page_content %}
|
||||
<div id="auditContent">
|
||||
{% include 'audit/inner.html.j2' %}
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="en" class="dark">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
@ -9,25 +9,21 @@
|
||||
{% include 'base/partials/stylesheets.html.j2' %}
|
||||
{% endblock %}
|
||||
</head>
|
||||
<body class="bg-gray-50 text-gray-900 min-h-screen flex flex-col">
|
||||
|
||||
<!-- Optional: Shoelace modals, toasts -->
|
||||
<sl-alert id="global-alert" variant="primary" duration="4000" closable></sl-alert>
|
||||
<sl-dialog id="global-dialog" label="Dialog"></sl-dialog>
|
||||
<body class="bg-gray-50 text-gray-900 dark:bg-gray-900 min-h-screen flex flex-col">
|
||||
|
||||
<!-- Layout Container -->
|
||||
<div class="flex flex-1 h-full overflow-hidden">
|
||||
|
||||
<!-- Sidebar -->
|
||||
|
||||
<aside class="hidden md:flex md:w-64 flex-col h-full min-h-screen bg-white border-r border-gray-300" id="sidebar" aria-label="sidebar">
|
||||
<aside class="hidden md:flex md:w-64 flex-col h-full min-h-screen bg-white border-r border-gray-300 dark:bg-gray-800 dark:border-gray-700" id="sidebar" aria-label="sidebar">
|
||||
{% include "base/partials/sidebar.html.j2" %}
|
||||
</aside>
|
||||
<!-- Main Panel -->
|
||||
<div class="flex-1 flex flex-col overflow-hidden">
|
||||
|
||||
<!-- Topbar -->
|
||||
<header class="bg-white border-b px-4 py-3 border-gray-300">
|
||||
<header class="bg-white border-b px-4 py-3 border-gray-300 dark:bg-gray-800 dark:border-gray-700">
|
||||
{% include "base/partials/navbar.html.j2" %}
|
||||
</header>
|
||||
|
||||
@ -35,7 +31,7 @@
|
||||
<main id="content" class="flex-1 overflow-y-auto" hx-target="this" hx-swap="innerHTML">
|
||||
{% block breadcrumbs %}
|
||||
{% endblock %}
|
||||
<div class="p-4" id="maincontent">
|
||||
<div class="" id="maincontent">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</main>
|
||||
@ -43,8 +39,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% block scripts %}
|
||||
{% include 'base/partials/scripts.html.j2' %}
|
||||
{% endblock %}
|
||||
{% block local_scripts %}
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -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 dark:bg-gray-800 dark:border-gray-700">
|
||||
{% 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 dark:bg-gray-800">
|
||||
{% block detail %}
|
||||
<p class="p-4 text-gray-500 dark:text-gray-200">Select an item to view details</p>
|
||||
{% endblock %}
|
||||
</section>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@ -1,20 +1,19 @@
|
||||
{% extends "/base/base.html.j2" %}
|
||||
|
||||
{% block title %}{{ title or "Page" }}{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
|
||||
<div class="p-4 bg-white block sm:flex items-center justify-between border-b border-gray-200">
|
||||
<div class="p-4 bg-white block sm:flex items-center justify-between border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700">
|
||||
<nav class="text-sm text-gray-500" aria-label="Breadcrumb">
|
||||
|
||||
<sl-breadcrumb>
|
||||
<sl-breadcrumb id="breadcrumbs">
|
||||
<sl-breadcrumb-item>
|
||||
<sl-icon slot="prefix" name="house"></sl-icon>
|
||||
<a href="/">Home</a>
|
||||
</sl-breadcrumb-item>
|
||||
{% if breadcrumbs %}
|
||||
{% for label, url in breadcrumbs %}
|
||||
<sl-breadcrumb-item>
|
||||
<sl-breadcrumb-item class="page-breadcrumb">
|
||||
{% if url %}
|
||||
<a href="{{url}}">{{label}}</a>
|
||||
{% else %}
|
||||
@ -32,7 +31,7 @@
|
||||
<!-- Breadcrumbs -->
|
||||
|
||||
<!-- Page Content -->
|
||||
<section>
|
||||
<section class="bg-white dark:bg-gray-800">
|
||||
{% block page_content %}
|
||||
<p>This is a generic page.</p>
|
||||
{% endblock %}
|
||||
|
||||
@ -15,18 +15,9 @@
|
||||
</button>
|
||||
|
||||
<!-- Page title or logo -->
|
||||
<a href="/" class="flex ml-2 md:mr-24">
|
||||
<img
|
||||
src="{{ url_for('static', path='logo.svg') }}"
|
||||
class="h-11 mr-3"
|
||||
alt="Sshecret Logo"
|
||||
/>
|
||||
<span
|
||||
class="self-center text-xl font-semibold sm:text-2xl whitespace-nowrap dark:text-white"
|
||||
>Sshecret</span
|
||||
>
|
||||
</a>
|
||||
|
||||
{% if page_title %}
|
||||
<h1 class="text-xl flex ml-2 md:mr-24 font-semibold text-gray-900 sm:text-2xl dark:text-white">{{page_title}}</h1>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Right: User menu -->
|
||||
|
||||
@ -3,8 +3,9 @@
|
||||
<!-- Top: Brand -->
|
||||
<div class="px-4 py-6">
|
||||
|
||||
<a href="/" class="text-xl font-semibold text-gray-800">
|
||||
🐚 Sshecret
|
||||
<a href="/" class="text-xl font-semibold text-gray-800 dark:text-gray-100">
|
||||
<sl-icon src="{{ url_for('static', path='logo.svg') }}"></sl-icon>
|
||||
Sshecret
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@ -12,28 +13,28 @@
|
||||
<ul class="space-y-">
|
||||
|
||||
<li>
|
||||
<a href="/" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100">
|
||||
<a href="/" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
<sl-icon name="house"></sl-icon>
|
||||
Dashboard
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/clients/" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100">
|
||||
<a href="/clients/" class="flex items-center px-3 py-2 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
<sl-icon name="person-fill-lock"> </sl-icon>
|
||||
Clients
|
||||
</a>
|
||||
</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 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
<sl-icon name="database-lock"></sl-icon>
|
||||
Secrets
|
||||
</a>
|
||||
</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 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||
<sl-icon name="card-list"></sl-icon>
|
||||
Audit Log
|
||||
</a>
|
||||
|
||||
@ -35,3 +35,16 @@
|
||||
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/dark.css"
|
||||
onload="document.documentElement.classList.add('sl-theme-dark');"
|
||||
/>
|
||||
|
||||
<script>
|
||||
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
|
||||
if (
|
||||
localStorage.getItem("color-theme") === "dark" ||
|
||||
(!("color-theme" in localStorage) &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
||||
) {
|
||||
document.documentElement.classList.add("dark");
|
||||
} else {
|
||||
document.documentElement.classList.remove("dark");
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
||||
<div class="min-h-screen bg-gray-100 flex items-center justify-center p-4">
|
||||
{% extends "/base/page.html.j2" %}
|
||||
{% block title %}Change Password{% endblock %}
|
||||
|
||||
{% block page_content %}
|
||||
|
||||
<div class="h-[calc(100vh-8rem)] bg-gray-100 flex items-center justify-center p-4">
|
||||
<div class="w-full max-w-xl p-6 space-y-8 bg-white rounded-lg shadow sm:p-8 dark:bg-gray-800">
|
||||
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||
Change Password
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
||||
<div class="min-h-screen bg-gray-100 flex items-center justify-center p-4">
|
||||
|
||||
{% extends "/base/page.html.j2" %}
|
||||
|
||||
{% block page_content %}
|
||||
<div class="h-[calc(100vh-8rem)] bg-gray-100 flex items-center justify-center p-4">
|
||||
<div class="text-center xl:max-w-4xl">
|
||||
<h1 class="mb-3 text-2xl font-bold leading-tight text-gray-900 sm:text-4xl lg:text-5xl dark:text-white">Password Changed</h1>
|
||||
<p class="mb-5 text-base font-normal text-gray-500 md:text-lg dark:text-gray-400">Your password was changed sucessfully. Next time you log in, use your new password.</p>
|
||||
@ -9,4 +12,4 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% endblock %}
|
||||
|
||||
@ -1,46 +1,24 @@
|
||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
||||
<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">
|
||||
<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>
|
||||
|
||||
|
||||
</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' %}
|
||||
</div>
|
||||
<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">
|
||||
{% include '/clients/partials/client_details.html.j2' %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% include '/clients/partials/drawer_create.html.j2' %}
|
||||
{% extends 'base/master-detail-email.html.j2' %}
|
||||
{% block title %}Client {{ client.name }}{% endblock %}
|
||||
|
||||
{% block master %}
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block detail %}
|
||||
|
||||
<div id="clientdetails" class="w-full">
|
||||
{% include '/clients/partials/client_details.html.j2' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% include '/clients/partials/drawer_create.html.j2' %}
|
||||
{% block local_scripts %}
|
||||
<script>
|
||||
{% include '/clients/partials/tree_event.js' %}
|
||||
</script>
|
||||
{% endblock local_scripts %}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,41 +1,21 @@
|
||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
||||
<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">
|
||||
<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>
|
||||
</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' %}
|
||||
</div>
|
||||
<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">
|
||||
<h3 class="mb-4 text-sm italic text-gray-400 dark:text-white">Click an item to view details</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% include '/clients/partials/drawer_create.html.j2' %}
|
||||
{% extends 'base/master-detail-email.html.j2' %}
|
||||
{% block title %}Clients{% endblock %}
|
||||
|
||||
{% block master %}
|
||||
{% include '/clients/partials/tree.html.j2' %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block detail %}
|
||||
|
||||
<div id="clientdetails" class="w-full bg-white dark:bg-gray-800">
|
||||
<h3 class="mb-4 text-sm italic text-gray-400 dark:text-white">Click an item to view details</h3>
|
||||
</div>
|
||||
{% include '/clients/partials/drawer_create.html.j2' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block local_scripts %}
|
||||
<script>
|
||||
{% include '/clients/partials/tree_event.js' %}
|
||||
</script>
|
||||
{% endblock local_scripts %}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<sl-tab-group placement="end">
|
||||
<sl-tab-group >
|
||||
<sl-tab slot="nav" panel="client_data">Client Data</sl-tab>
|
||||
<sl-tab slot="nav" panel="events">Events</sl-tab>
|
||||
|
||||
@ -47,37 +47,37 @@
|
||||
<div id="client_details">
|
||||
<div class="w-full p-2">
|
||||
<div class="px-4 sm:px-0">
|
||||
<h3 class="text-base/7 font-semibold text-gray-900">{{client.name}}</h3>
|
||||
<h3 class="text-base/7 font-semibold text-gray-900 dark:text-gray-50">{{client.name}}</h3>
|
||||
{% if client.description %}
|
||||
<p class="mt-1 max-w-2xl text-sm/6 text-gray-500">{{ client.description }}</p>
|
||||
<p class="mt-1 max-w-2xl text-sm/6 text-gray-500 dark:text-gray-100">{{ client.description }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="mt-6 border-t border-gray-100">
|
||||
<dl class="divide-y divide-gray-100">
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Client ID</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">{{client.id}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Client ID</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300">{{client.id}}</dd>
|
||||
</div>
|
||||
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Client Description</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">{{client.description}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Client Description</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300">{{client.description}}</dd>
|
||||
</div>
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Client Version</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">{{client.version}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Client Version</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300">{{client.version}}</dd>
|
||||
</div>
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Public Key</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 truncate">{{client.public_key}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Public Key</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300 truncate">{{client.public_key}}</dd>
|
||||
</div>
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Assigned Secrets</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">{{client.secrets|length}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Assigned Secrets</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300">{{client.secrets|length}}</dd>
|
||||
</div>
|
||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
||||
<dt class="text-sm/6 font-medium text-gray-900">Allowed sources</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">{{client.policies|join(', ')}}</dd>
|
||||
<dt class="text-sm/6 font-medium text-gray-900 dark:text-gray-200">Allowed sources</dt>
|
||||
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0 dark:text-gray-300">{{client.policies|join(', ')}}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
@ -86,7 +86,7 @@
|
||||
</sl-tab-panel>
|
||||
<sl-tab-panel name="events">
|
||||
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-600" id="last-audit-events">
|
||||
<table class="min-w-full lg:table-fixed divide-y divide-gray-200 dark:divide-gray-600" id="last-audit-events">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Timestamp</th>
|
||||
|
||||
@ -1,67 +1,64 @@
|
||||
<div class="flex flex-1 flex-col justify-between h-full flowbite-init-target">
|
||||
<div class="grid grid-cols-2 place-content-between mb-6">
|
||||
<div>
|
||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Clients</h1>
|
||||
<div class="flex">
|
||||
<div
|
||||
class="htmx-indicator mt-2"
|
||||
id="client-spinner">
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" class="inline w-6 h-6 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
{# This is the master block #}
|
||||
|
||||
<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">Client List</h1>
|
||||
<div class="flex">
|
||||
<div
|
||||
class="htmx-indicator mt-2"
|
||||
id="client-spinner">
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" class="inline w-6 h-6 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex w-full justify-end"
|
||||
>
|
||||
<sl-icon-button
|
||||
name="plus-square"
|
||||
label="Add Client"
|
||||
data-drawer-target="drawer-create-client-default"
|
||||
data-drawer-show="drawer-create-client-default"
|
||||
aria-controls="drawer-create-client-default"
|
||||
data-drawer-placement="right"
|
||||
|
||||
|
||||
></sl-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-full">
|
||||
<div class="relative">
|
||||
<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>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
||||
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="search"
|
||||
id="client-search"
|
||||
name="query"
|
||||
class="block w-full p-2.5 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-gray-900 focus:border-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-gray-900 dark:focus:border-gray-900"
|
||||
placeholder="Search..."
|
||||
required
|
||||
hx-post="/clients/query"
|
||||
hx-trigger="input changed delay:500ms, keyup[key=='Enter']"
|
||||
hx-target="#client-tree-items"
|
||||
hx-indicator="#client-spinner"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="flex justify-end px-4"
|
||||
>
|
||||
<sl-icon-button
|
||||
name="plus-square"
|
||||
label="Add Client"
|
||||
data-drawer-target="drawer-create-client-default"
|
||||
data-drawer-show="drawer-create-client-default"
|
||||
aria-controls="drawer-create-client-default"
|
||||
data-drawer-placement="right"
|
||||
|
||||
|
||||
></sl-icon-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-1 overflow-auto">
|
||||
<div class="relative w-full ">
|
||||
<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>
|
||||
<div class="relative">
|
||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
||||
<svg class="w-4 h-4 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<input
|
||||
type="search"
|
||||
id="client-search"
|
||||
name="query"
|
||||
class="block w-full p-2.5 ps-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-gray-900 focus:border-gray-900 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-gray-900 dark:focus:border-gray-900"
|
||||
placeholder="Search..."
|
||||
required
|
||||
hx-post="/clients/query"
|
||||
hx-trigger="input changed delay:500ms, keyup[key=='Enter']"
|
||||
hx-target="#client-tree-items"
|
||||
hx-indicator="#client-spinner"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="client-tree-items">
|
||||
{% include '/clients/partials/tree_items.html.j2' %}
|
||||
</div>
|
||||
<div id="client-tree-items">
|
||||
{% include '/clients/partials/tree_items.html.j2' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
{% include '/clients/partials/tree_event.js' %}
|
||||
</script>
|
||||
|
||||
@ -1,3 +1,16 @@
|
||||
function setBreadcrumb(name) {
|
||||
// Set the current client name as the final breadcrumb
|
||||
const breadcrumbs = document.getElementById("breadcrumbs");
|
||||
const existingNode = document.getElementById("bc-dynamic-client");
|
||||
if (existingNode) {
|
||||
breadcrumbs.removeChild(existingNode);
|
||||
}
|
||||
const newCrumb = document.createElement("sl-breadcrumb-item");
|
||||
newCrumb.setAttribute("id", "bc-dynamic-client");
|
||||
const bcTitle = document.createTextNode(name);
|
||||
newCrumb.appendChild(bcTitle);
|
||||
breadcrumbs.appendChild(newCrumb);
|
||||
}
|
||||
function addTreeListener() {
|
||||
const tree = document.querySelector("sl-tree");
|
||||
|
||||
@ -8,6 +21,8 @@ function addTreeListener() {
|
||||
|
||||
if (!selectedEl) return;
|
||||
|
||||
const masterPane = document.getElementById("master-pane");
|
||||
const detailPane = document.getElementById("detail-pane");
|
||||
const type = selectedEl.dataset.nodeType;
|
||||
const clientId = selectedEl.dataset.clientId;
|
||||
const name = selectedEl.dataset.clientName;
|
||||
@ -17,11 +32,17 @@ function addTreeListener() {
|
||||
|
||||
let url = `/clients/client/${encodeURIComponent(clientId)}`;
|
||||
if (url) {
|
||||
htmx.ajax("GET", url, {
|
||||
target: "#clientdetails",
|
||||
//swap: 'OuterHTML',
|
||||
indicator: "#client-spinner",
|
||||
});
|
||||
htmx
|
||||
.ajax("GET", url, {
|
||||
target: "#clientdetails",
|
||||
//swap: 'OuterHTML',
|
||||
indicator: "#client-spinner",
|
||||
})
|
||||
.then(() => {
|
||||
masterPane.classList.add("hidden");
|
||||
detailPane.classList.remove("hidden");
|
||||
setBreadcrumb(name);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -38,5 +38,4 @@
|
||||
{% include 'clients/partials/pagination.html.j2' %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends "/shared/_base.html" %} {% block content %} {% if login_error %}
|
||||
{% extends "/base/bare.html.j2" %} {% block content %} {% if login_error %}
|
||||
|
||||
<div class="flex bg-gray-100">
|
||||
<div
|
||||
@ -88,7 +88,5 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
{% endif %} {% endblock %}
|
||||
</div>
|
||||
|
||||
@ -47,85 +47,67 @@
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{% 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">
|
||||
<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">Secrets</span>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Secrets</h1>
|
||||
</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" id="secret-tree">
|
||||
{% block title %}Secrets{% endblock %}
|
||||
|
||||
|
||||
<div class="flex flex-1 flex-col">
|
||||
<div class="h-full w-full">
|
||||
<sl-tree class="tree-with-icons">
|
||||
<sl-tree-item
|
||||
id="secret-group-root-item"
|
||||
data-type="root"
|
||||
data-name="root"
|
||||
{% block master %}
|
||||
|
||||
{% if "/" in group_path_nodes %}
|
||||
expanded=""
|
||||
{% endif %}
|
||||
{% if selected_group == "/"%}
|
||||
selected=""
|
||||
{% endif %}
|
||||
>
|
||||
<sl-icon name="folder"> </sl-icon>
|
||||
<span class="px-2">Ungrouped</span>
|
||||
{% for entry in groups.ungrouped %}
|
||||
{{ display_entry(entry) }}
|
||||
{% endfor %}
|
||||
</sl-tree-item>
|
||||
{% for child in groups.groups %}
|
||||
{{ display_group(child) }}
|
||||
{% endfor %}
|
||||
</sl-tree>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flowbite-init-target">
|
||||
<div id="secret-tree">
|
||||
<sl-tree class="tree-with-icons">
|
||||
<sl-tree-item
|
||||
id="secret-group-root-item"
|
||||
data-type="root"
|
||||
data-name="root"
|
||||
|
||||
</div>
|
||||
<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">
|
||||
{% if group_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/group_detail.html.j2' %}
|
||||
</div>
|
||||
{% elif root_group_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/edit_root.html.j2' %}
|
||||
</div>
|
||||
{% elif secret_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/tree_detail.html.j2' %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% include '/secrets/partials/default_detail.html.j2' %}
|
||||
{% if "/" in group_path_nodes %}
|
||||
expanded=""
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% if selected_group == "/"%}
|
||||
selected=""
|
||||
{% endif %}
|
||||
>
|
||||
<sl-icon name="folder"> </sl-icon>
|
||||
<span class="px-2">Ungrouped</span>
|
||||
{% for entry in groups.ungrouped %}
|
||||
{{ display_entry(entry) }}
|
||||
{% endfor %}
|
||||
</sl-tree-item>
|
||||
{% for child in groups.groups %}
|
||||
{{ display_group(child) }}
|
||||
{% endfor %}
|
||||
</sl-tree>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block detail %}
|
||||
{% if group_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/group_detail.html.j2' %}
|
||||
</div>
|
||||
{% elif root_group_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/edit_root.html.j2' %}
|
||||
</div>
|
||||
{% elif secret_page | default(false) %}
|
||||
<div class="w-full" id="secretdetails">
|
||||
{% include '/secrets/partials/tree_detail.html.j2' %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% include '/secrets/partials/default_detail.html.j2' %}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block local_scripts %}
|
||||
<script>
|
||||
{% include '/secrets/partials/tree_event.js' %}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="w-full my-2">
|
||||
<div class="w-full my-2 dark:text-white">
|
||||
<ul class="w-48 text-sm font-medium text-gray-900 bg-white dark:bg-gray-700 dark:text-white" id="secretclientlist">
|
||||
{% include '/secrets/partials/client_list_inner.html.j2' %}
|
||||
</ul>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="w-full">
|
||||
<div class="w-full dark:text-white">
|
||||
<sl-details summary="Create secret">
|
||||
<form
|
||||
hx-post="/secrets/create/root"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="w-full">
|
||||
<div class="w-full dark:text-white">
|
||||
<div class="mb-4">
|
||||
<h3 class="text-xl font-semibold dark:text-white">Group {{group.group_name}}</h3>
|
||||
{% if description %}
|
||||
|
||||
@ -1,33 +1,33 @@
|
||||
<div class="w-full flowbite-init-target" id="secretdetails">
|
||||
<div class="w-full flowbite-init-target dark:text-white" id="secretdetails">
|
||||
|
||||
<!-- menu -->
|
||||
<!-- menu -->
|
||||
|
||||
<div class="flex justify-end px-4">
|
||||
<button id="secret-menu-button" data-dropdown-toggle="secret-edit-menu" class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5" type="button">
|
||||
<span class="sr-only">Open dropdown</span>
|
||||
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 3">
|
||||
<path d="M2 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm6.041 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM14 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Dropdown menu -->
|
||||
<div id="secret-edit-menu" class="z-10 hidden text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
|
||||
<ul class="py-2" aria-labelledby="secret-menu-button">
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="block px-4 py-2 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
|
||||
hx-delete="/secrets/{{secret.name}}"
|
||||
hx-target="#secretdetails"
|
||||
hx-swap="OuterHTML"
|
||||
hx-indicator=".secret-spinner"
|
||||
hx-confirm="Really delete this secret?"
|
||||
>
|
||||
Delete
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="flex justify-end px-4">
|
||||
<button id="secret-menu-button" data-dropdown-toggle="secret-edit-menu" class="inline-block text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:ring-4 focus:outline-none focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-1.5" type="button">
|
||||
<span class="sr-only">Open dropdown</span>
|
||||
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 3">
|
||||
<path d="M2 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Zm6.041 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM14 0a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3Z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Dropdown menu -->
|
||||
<div id="secret-edit-menu" class="z-10 hidden text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow-sm w-44 dark:bg-gray-700">
|
||||
<ul class="py-2" aria-labelledby="secret-menu-button">
|
||||
<li>
|
||||
<a
|
||||
href="#"
|
||||
class="block px-4 py-2 text-sm text-red-600 hover:bg-gray-100 dark:hover:bg-gray-600 dark:text-gray-200 dark:hover:text-white"
|
||||
hx-delete="/secrets/{{secret.name}}"
|
||||
hx-target="#secretdetails"
|
||||
hx-swap="OuterHTML"
|
||||
hx-indicator=".secret-spinner"
|
||||
hx-confirm="Really delete this secret?"
|
||||
>
|
||||
Delete
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h3 class="mb-4 text-xl font-semibold dark:text-white">{{secret.name}}</h3>
|
||||
@ -53,65 +53,65 @@
|
||||
</div>
|
||||
</sl-details>
|
||||
{% if secret.secret %}
|
||||
<sl-details summary="Read/Update Secret">
|
||||
<div id="secretvalue">
|
||||
<div class="mb-6">
|
||||
<label for="secret-value" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Value</label>
|
||||
</div>
|
||||
<div class="flex w-full">
|
||||
<div class="relative w-full">
|
||||
<input type="text" id="disabled-input" aria-label="disabled input" class="mb-6 bg-gray-100 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 cursor-not-allowed dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="••••••••" disabled>
|
||||
</div>
|
||||
<div class="px-2.5 mb-2">
|
||||
<button
|
||||
type="button"
|
||||
class="text-gray-900 hover:text-blue-700 border border-gray-200 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 dark:focus:ring-blue-800"
|
||||
hx-get="/secrets/partial/{{ secret.name }}/viewsecret"
|
||||
hx-target="#secretvalue"
|
||||
hx-trigger="click"
|
||||
hx-indicator="#secretupdatespinner"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="htmx-indicator" id="secretupdatespinner">
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" class="inline w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</sl-details>
|
||||
{% if groups.groups %}
|
||||
<sl-details summary="Group">
|
||||
<form
|
||||
hx-put="/secrets/set-group/{{ secret.name }}"
|
||||
hx-target="#secretdetails"
|
||||
hx-swap="OuterHTML"
|
||||
hx-indicator=".secret-spinner"
|
||||
>
|
||||
<sl-details summary="Read/Update Secret">
|
||||
<div id="secretvalue">
|
||||
<div class="mb-6">
|
||||
<label for="secret-value" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Value</label>
|
||||
</div>
|
||||
<div class="flex w-full">
|
||||
<div class="relative w-full">
|
||||
<select id="group_name" name="group_name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<option value="__ROOT">Ungrouped</option>
|
||||
{% for group in groups.groups %}
|
||||
<option value="{{ group.group_name }}" {% if group.name == secret.group -%}selected{% endif %}>{{ group.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<input type="text" id="disabled-input" aria-label="disabled input" class="mb-6 bg-gray-100 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 cursor-not-allowed dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-gray-400 dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="••••••••" disabled>
|
||||
</div>
|
||||
<div class="px-2.5 mb-2">
|
||||
<button type="Submit" class="text-gray-900 hover:text-blue-700 border border-gray-200 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 dark:focus:ring-blue-800">Update</button>
|
||||
<button
|
||||
type="button"
|
||||
class="text-gray-900 hover:text-blue-700 border border-gray-200 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 dark:focus:ring-blue-800"
|
||||
hx-get="/secrets/partial/{{ secret.name }}/viewsecret"
|
||||
hx-target="#secretvalue"
|
||||
hx-trigger="click"
|
||||
hx-indicator="#secretupdatespinner"
|
||||
>
|
||||
View
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="htmx-indicator" id="secretupdatespinner">
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" class="inline w-4 h-4 text-gray-200 animate-spin dark:text-gray-600 fill-blue-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
<path d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z" fill="currentFill"/>
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</sl-details>
|
||||
{% if groups.groups %}
|
||||
<sl-details summary="Group">
|
||||
<form
|
||||
hx-put="/secrets/set-group/{{ secret.name }}"
|
||||
hx-target="#secretdetails"
|
||||
hx-swap="OuterHTML"
|
||||
hx-indicator=".secret-spinner"
|
||||
>
|
||||
<div class="flex w-full">
|
||||
<div class="relative w-full">
|
||||
<select id="group_name" name="group_name" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<option value="__ROOT">Ungrouped</option>
|
||||
{% for group in groups.groups %}
|
||||
<option value="{{ group.group_name }}" {% if group.name == secret.group -%}selected{% endif %}>{{ group.path }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="px-2.5 mb-2">
|
||||
<button type="Submit" class="text-gray-900 hover:text-blue-700 border border-gray-200 hover:bg-gray-100 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 mb-2 dark:border-blue-500 dark:text-blue-500 dark:hover:text-white dark:hover:bg-blue-500 dark:focus:ring-blue-800">Update</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</sl-details>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<sl-details summary="Events">
|
||||
<sl-details summary="Events" class="dark:text-white">
|
||||
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-600" id="last-audit-events">
|
||||
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||
<tr>
|
||||
|
||||
@ -1,4 +1,61 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
function createCrumb(name, url = null) {
|
||||
// Create a breadcrumb
|
||||
const crumb = document.createElement("sl-breadcrumb-item");
|
||||
crumb.classList.add("page-breadcrumb");
|
||||
|
||||
if (url) {
|
||||
var crumbChild = document.createElement("a");
|
||||
crumbChild.setAttribute("href", url);
|
||||
const crumbChildText = document.createTextNode(name);
|
||||
crumbChild.appendChild(crumbChildText);
|
||||
} else {
|
||||
var crumbChild = document.createTextNode(name);
|
||||
}
|
||||
|
||||
crumb.appendChild(crumbChild);
|
||||
|
||||
return crumb;
|
||||
}
|
||||
|
||||
function setGroupBreadcrumbs(name, path, secret = null) {
|
||||
// Set breadcrumbs for a whole group.
|
||||
const breadcrumbs = document.getElementById("breadcrumbs");
|
||||
// First, remove all existing page breadcrumbs
|
||||
console.log(`setGroupBreadcrumbs: ${name} ${path}`);
|
||||
let pageCrumbs = document.getElementsByClassName("page-breadcrumb");
|
||||
for (let i = 0; i < pageCrumbs.length; i++) {
|
||||
breadcrumbs.removeChild(pageCrumbs[i]);
|
||||
}
|
||||
// Re-create the breadcrumbs
|
||||
const newcrumbs = [
|
||||
["Secrets", "/secrets/"],
|
||||
["Groups", "/secrets/groups/"],
|
||||
];
|
||||
if (path) {
|
||||
const pathnodes = path.split("/");
|
||||
for (let i = 0; i < pathnodes.length; i++) {
|
||||
let pathnode = pathnodes[i];
|
||||
let nextnode = i + 1;
|
||||
let groupPathNodes = pathnodes.slice(0, nextnode);
|
||||
let groupPath = groupPathNodes.join("/");
|
||||
newcrumbs.push([pathnode, `/secrets/groups/${groupPath}`]);
|
||||
}
|
||||
} else {
|
||||
newcrumbs.push(["Ungrouped", "/secrets/groups/"]);
|
||||
}
|
||||
|
||||
if (secret) {
|
||||
newcrumbs.push([secret, `/secrets/secret/${secret}`]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < newcrumbs.length; i++) {
|
||||
let crumbParam = newcrumbs[i];
|
||||
let newcrumb = createCrumb(crumbParam[0], crumbParam[1]);
|
||||
breadcrumbs.appendChild(newcrumb);
|
||||
}
|
||||
}
|
||||
|
||||
function addTreeListener() {
|
||||
const tree = document.querySelector("sl-tree");
|
||||
|
||||
if (!tree) return;
|
||||
@ -33,4 +90,12 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
addTreeListener();
|
||||
});
|
||||
|
||||
document.addEventListener("htmx:afterSwap", () => {
|
||||
addTreeListener();
|
||||
});
|
||||
|
||||
@ -42,6 +42,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
page=page, limit=per_page, total=audit_log.total, offset=offset
|
||||
)
|
||||
operations = list(Operation)
|
||||
breadcrumbs = [("Audit", "/audit/")]
|
||||
if request.headers.get("HX-Request"):
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
@ -56,7 +57,8 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
request,
|
||||
"audit/index.html.j2",
|
||||
{
|
||||
"page_title": "Audit",
|
||||
"page_title": "Audit Log",
|
||||
"breadcrumbs": breadcrumbs,
|
||||
"entries": audit_log.results,
|
||||
"user": current_user,
|
||||
"page_info": page_info,
|
||||
|
||||
@ -93,42 +93,14 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
page=page, limit=per_page, total=results.total_results, offset=offset
|
||||
)
|
||||
|
||||
breadcrumbs = [("clients", "/clients/")]
|
||||
|
||||
LOG.info("Results %r", results)
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"clients/index.html.j2",
|
||||
{
|
||||
"page_title": "Clients",
|
||||
"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",
|
||||
{
|
||||
"breadcrumbs": breadcrumbs,
|
||||
"page_title": "Clients",
|
||||
"offset": offset,
|
||||
"pages": paginate,
|
||||
@ -197,6 +169,11 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
)
|
||||
template = "clients/client.html.j2"
|
||||
|
||||
breadcrumbs = [
|
||||
("clients", "/clients/"),
|
||||
(results.client.name, request.url.path),
|
||||
]
|
||||
|
||||
headers: dict[str, str] = {}
|
||||
if request.headers.get("HX-Request"):
|
||||
headers["HX-Push-Url"] = request.url.path
|
||||
@ -207,6 +184,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
template,
|
||||
{
|
||||
"page_title": f"Client {results.client.name}",
|
||||
"breadcrumbs": breadcrumbs,
|
||||
"pages": results.pages,
|
||||
"clients": results.results.clients,
|
||||
"client": results.client,
|
||||
|
||||
@ -81,7 +81,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
request,
|
||||
"dashboard.html",
|
||||
{
|
||||
"page_title": "sshecret",
|
||||
"page_title": "Dashboard",
|
||||
"user": current_user,
|
||||
"stats": stats,
|
||||
"last_login_events": last_login_events,
|
||||
|
||||
@ -63,12 +63,15 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
|
||||
current_user: Annotated[LocalUserInfo, Depends(dependencies.get_user_info)],
|
||||
):
|
||||
breadcrumbs = [("secrets", "/secrets/")]
|
||||
groups = await admin.get_secret_groups()
|
||||
return templates.TemplateResponse(
|
||||
request,
|
||||
"secrets/index.html.j2",
|
||||
{
|
||||
"page_title": "Secrets",
|
||||
"groups": groups,
|
||||
"breadcrumbs": breadcrumbs,
|
||||
"user": current_user,
|
||||
"selected_group": None,
|
||||
"group_path_nodes": ["/"],
|
||||
@ -83,8 +86,15 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
):
|
||||
"""Show the root path."""
|
||||
clients = await admin.get_clients()
|
||||
|
||||
breadcrumbs = [
|
||||
("secrets", "/secrets/"),
|
||||
("groups", "/secrets/groups/"),
|
||||
("Ungrouped", "/secrets/groups/"),
|
||||
]
|
||||
context: dict[str, Any] = {
|
||||
"clients": clients,
|
||||
"breadcrumbs": breadcrumbs,
|
||||
"root_group_page": True,
|
||||
}
|
||||
headers: dict[str, str] = {}
|
||||
@ -95,6 +105,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
else:
|
||||
groups = await admin.get_secret_groups()
|
||||
template_name = "secrets/index.html.j2"
|
||||
context["page_title"] = "Secrets"
|
||||
context["user"] = current_user
|
||||
context["groups"] = groups
|
||||
context["group_path_nodes"] = ["/"]
|
||||
@ -119,11 +130,20 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
)
|
||||
clients = await admin.get_clients()
|
||||
|
||||
breadcrumbs = [("secrets", "/secrets/"), ("groups", "/secrets/groups/")]
|
||||
path_nodes = group.path.split("/")
|
||||
for x in range(len(path_nodes)):
|
||||
next_node = x + 1
|
||||
group_path = "/".join(path_nodes[:next_node])
|
||||
crumb_path = os.path.join("/secrets", group_path)
|
||||
breadcrumbs.append((path_nodes[x], crumb_path))
|
||||
|
||||
headers: dict[str, str] = {}
|
||||
context: dict[str, Any] = {
|
||||
"group_page": True,
|
||||
"group": group,
|
||||
"clients": clients,
|
||||
"breadcrumbs": breadcrumbs,
|
||||
}
|
||||
if request.headers.get("HX-Request"):
|
||||
# This is a HTMX request.
|
||||
@ -133,6 +153,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
template_name = "secrets/index.html.j2"
|
||||
|
||||
groups = await admin.get_secret_groups()
|
||||
context["page_title"] = "Secrets"
|
||||
context["user"] = current_user
|
||||
context["groups"] = groups
|
||||
context["group_path_nodes"] = group.path.split("/")
|
||||
@ -180,6 +201,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
||||
group_path = group.path.split("/")
|
||||
|
||||
template_name = "secrets/index.html.j2"
|
||||
context["page_title"] = "Secrets"
|
||||
context["user"] = current_user
|
||||
context["groups"] = groups
|
||||
context["group_path_nodes"] = group_path
|
||||
|
||||
@ -382,9 +382,6 @@
|
||||
.order-1 {
|
||||
order: 1;
|
||||
}
|
||||
.order-2 {
|
||||
order: 2;
|
||||
}
|
||||
.col-span-2 {
|
||||
grid-column: span 2 / span 2;
|
||||
}
|
||||
@ -457,9 +454,6 @@
|
||||
.ms-3 {
|
||||
margin-inline-start: calc(var(--spacing) * 3);
|
||||
}
|
||||
.ms-auto {
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
.me-2 {
|
||||
margin-inline-end: calc(var(--spacing) * 2);
|
||||
}
|
||||
@ -682,15 +676,18 @@
|
||||
.h-\[12px\] {
|
||||
height: 12px;
|
||||
}
|
||||
.h-\[16px\] {
|
||||
height: 16px;
|
||||
}
|
||||
.h-\[32px\] {
|
||||
height: 32px;
|
||||
}
|
||||
.h-\[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 {
|
||||
height: 100%;
|
||||
}
|
||||
@ -1245,9 +1242,6 @@
|
||||
.border-blue-300 {
|
||||
border-color: var(--color-blue-300);
|
||||
}
|
||||
.border-blue-700 {
|
||||
border-color: var(--color-blue-700);
|
||||
}
|
||||
.border-gray-100 {
|
||||
border-color: var(--color-gray-100);
|
||||
}
|
||||
@ -1332,9 +1326,6 @@
|
||||
.bg-blue-600 {
|
||||
background-color: var(--color-blue-600);
|
||||
}
|
||||
.bg-blue-700 {
|
||||
background-color: var(--color-blue-700);
|
||||
}
|
||||
.bg-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 {
|
||||
@media (hover: hover) {
|
||||
@ -2774,11 +2758,6 @@
|
||||
inset: calc(var(--spacing) * 0);
|
||||
}
|
||||
}
|
||||
.md\:order-1 {
|
||||
@media (width >= 48rem) {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
.md\:order-2 {
|
||||
@media (width >= 48rem) {
|
||||
order: 2;
|
||||
@ -2859,6 +2838,16 @@
|
||||
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\)\] {
|
||||
@media (width >= 48rem) {
|
||||
width: calc(100% - 256px);
|
||||
@ -3114,6 +3103,11 @@
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
.lg\:table-fixed {
|
||||
@media (width >= 64rem) {
|
||||
table-layout: fixed;
|
||||
}
|
||||
}
|
||||
.lg\:grid-cols-2 {
|
||||
@media (width >= 64rem) {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
@ -3469,11 +3463,6 @@
|
||||
border-color: var(--color-red-800);
|
||||
}
|
||||
}
|
||||
.dark\:bg-blue-600 {
|
||||
&:where(.dark, .dark *) {
|
||||
background-color: var(--color-blue-600);
|
||||
}
|
||||
}
|
||||
.dark\:bg-blue-900 {
|
||||
&:where(.dark, .dark *) {
|
||||
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 {
|
||||
&:where(.dark, .dark *) {
|
||||
&:hover {
|
||||
|
||||
@ -19,3 +19,11 @@ sl-details.small-details::part(header) {
|
||||
sl-details.small-details::part(base) {
|
||||
font-size: var(--sl-input-font-size-small);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
sl-details::part(base) {
|
||||
background-color: var(--color-gray-700);
|
||||
border: solid 1px var(--color-gray-500);
|
||||
color: var(--color-gray-50);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user