admin-redesign #26
@ -1,60 +1,6 @@
|
|||||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
{% extends "/base/page.html.j2" %}
|
||||||
<div
|
{% block title %}Audit{% endblock %}
|
||||||
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 page_content %}
|
||||||
>
|
|
||||||
<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>
|
|
||||||
<div id="auditContent">
|
<div id="auditContent">
|
||||||
{% include 'audit/inner.html.j2' %}
|
{% include 'audit/inner.html.j2' %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>{% block title %}Sshecret Admin{% endblock %}</title>
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{% include 'base/partials/stylesheets.html.j2' %}
|
||||||
|
{% endblock %}
|
||||||
|
</head>
|
||||||
|
<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 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 dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
{% include "base/partials/navbar.html.j2" %}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Main Content Area -->
|
||||||
|
<main id="content" class="flex-1 overflow-y-auto" hx-target="this" hx-swap="innerHTML">
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{% endblock %}
|
||||||
|
<div class="" id="maincontent">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
</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 %}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
{% extends 'base/page.html.j2' %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block title %}Clients{% endblock %}
|
||||||
|
|
||||||
|
{% block page_content %}
|
||||||
|
|
||||||
|
<!-- Master-Detail Layout -->
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-[300px_1fr] gap-4">
|
||||||
|
|
||||||
|
<!-- Master (e.g., tree or list) -->
|
||||||
|
<div id="master-pane">
|
||||||
|
{% block master %}
|
||||||
|
<p>Master list goes here</p>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Detail (loaded by HTMX or inline) -->
|
||||||
|
<div id="detail-pane" class="bg-white rounded shadow p-4">
|
||||||
|
{% block detail %}
|
||||||
|
<p>Select an item from the list to view details.</p>
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
{% extends "/base/base.html.j2" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
|
||||||
|
<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 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 class="page-breadcrumb">
|
||||||
|
{% if url %}
|
||||||
|
<a href="{{url}}">{{label}}</a>
|
||||||
|
{% else %}
|
||||||
|
{{ label }}
|
||||||
|
{% endif %}
|
||||||
|
</sl-breadcrumb-item>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</sl-breadcrumb>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<!-- Breadcrumbs -->
|
||||||
|
|
||||||
|
<!-- Page Content -->
|
||||||
|
<section class="bg-white dark:bg-gray-800">
|
||||||
|
{% block page_content %}
|
||||||
|
<p>This is a generic page.</p>
|
||||||
|
{% endblock %}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
<header class="flex items-center justify-between">
|
||||||
|
|
||||||
|
<!-- Left: Sidebar toggle (for mobile) + Title -->
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
|
||||||
|
<!-- Mobile sidebar toggle -->
|
||||||
|
<button
|
||||||
|
id="sidebar-toggle"
|
||||||
|
aria-expanded="true"
|
||||||
|
aria-controls="mobile-sidebar"
|
||||||
|
class="md:hidden text-gray-600 hover:text-gray-900 focus:outline-none"
|
||||||
|
aria-label="Toggle sidebar"
|
||||||
|
>
|
||||||
|
<sl-icon name="list" class="text-xl"></sl-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Page title or logo -->
|
||||||
|
{% 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 -->
|
||||||
|
<div class="relative">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
|
||||||
|
id="user-menu-button-2"
|
||||||
|
aria-expanded="false"
|
||||||
|
data-dropdown-toggle="dropdown-2"
|
||||||
|
>
|
||||||
|
<span class="sr-only">Open user menu</span>
|
||||||
|
<sl-avatar label="User avatar"></sl-avatar>
|
||||||
|
</button>
|
||||||
|
<!-- Dropdown placeholder -->
|
||||||
|
<div
|
||||||
|
class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded shadow dark:bg-gray-700 dark:divide-gray-600"
|
||||||
|
id="dropdown-2"
|
||||||
|
>
|
||||||
|
<div class="px-4 py-3" role="none">
|
||||||
|
<p class="text-sm text-gray-900 dark:text-white" role="none">
|
||||||
|
{{ user.display_name }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ul class="py-1" role="none">
|
||||||
|
{% if user.local %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/password"
|
||||||
|
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
|
||||||
|
role="menuitem"
|
||||||
|
>Change Password</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/logout"
|
||||||
|
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-600 dark:hover:text-white"
|
||||||
|
role="menuitem"
|
||||||
|
>Logout</a
|
||||||
|
>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!-- You can later replace this with a Flowbite dropdown or Shoelace menu -->
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
{# <script src="{{ url_for('static', path='js/sidebar.js') }}"></script> #}
|
||||||
|
<script async defer src="https://buttons.github.io/buttons.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@9.0.3"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
||||||
|
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||||
|
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/shoelace-autoloader.js"></script>
|
||||||
|
<script type="text/javascript" src="{{ url_for('static', path="js/prism.js") }}"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const sidebarToggle = document.getElementById('sidebar-toggle');
|
||||||
|
const sidebarDrawer = document.getElementById('sidebar');
|
||||||
|
|
||||||
|
sidebarToggle?.addEventListener('click', () => {
|
||||||
|
sidebarDrawer.classList.toggle("hidden");
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.addEventListener("htmx:afterSwap", (e) => {
|
||||||
|
const swappedEl = e.target;
|
||||||
|
|
||||||
|
const initTargets = swappedEl.querySelectorAll(".flowbite-init-target");
|
||||||
|
if (initTargets.length > 0 && typeof window.initFlowbite === "function") {
|
||||||
|
window.initFlowbite();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
<!-- Sidebar Container -->
|
||||||
|
|
||||||
|
<!-- Top: Brand -->
|
||||||
|
<div class="px-4 py-6">
|
||||||
|
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<nav class="flex-1 overflow-y-auto px-4" aria-label="navigation">
|
||||||
|
<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 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 dark:text-gray-200 dark:hover:bg-gray-700">
|
||||||
|
<sl-icon name="person-fill-lock"> </sl-icon>
|
||||||
|
Clients
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<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="/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>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="{{ url_for('static', path='css/main.css') }}"
|
||||||
|
type="text/css"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="{{ url_for('static', path='css/prism.css') }}"
|
||||||
|
type="text/css"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
href="{{ url_for('static', path='css/style.css') }}"
|
||||||
|
type="text/css"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<link
|
||||||
|
href="https://cdn.jsdelivr.net/npm/remixicon@3.5.0/fonts/remixicon.css"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
media="(prefers-color-scheme:light)"
|
||||||
|
href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.20.1/cdn/themes/light.css"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
media="(prefers-color-scheme:dark)"
|
||||||
|
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 %}
|
{% extends "/base/page.html.j2" %}
|
||||||
<div class="min-h-screen bg-gray-100 flex items-center justify-center p-4">
|
{% 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">
|
<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">
|
<h2 class="text-2xl font-bold text-gray-900 dark:text-white">
|
||||||
Change Password
|
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">
|
<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>
|
<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>
|
<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>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock %}
|
||||||
|
|||||||
@ -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 %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,41 +1,21 @@
|
|||||||
{% 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 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>
|
<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>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% include '/clients/partials/drawer_create.html.j2' %}
|
{% include '/clients/partials/drawer_create.html.j2' %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block local_scripts %}
|
||||||
|
<script>
|
||||||
|
{% include '/clients/partials/tree_event.js' %}
|
||||||
|
</script>
|
||||||
|
{% endblock local_scripts %}
|
||||||
|
|||||||
@ -38,7 +38,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</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="client_data">Client Data</sl-tab>
|
||||||
<sl-tab slot="nav" panel="events">Events</sl-tab>
|
<sl-tab slot="nav" panel="events">Events</sl-tab>
|
||||||
|
|
||||||
@ -47,37 +47,37 @@
|
|||||||
<div id="client_details">
|
<div id="client_details">
|
||||||
<div class="w-full p-2">
|
<div class="w-full p-2">
|
||||||
<div class="px-4 sm:px-0">
|
<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 %}
|
{% 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 %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-6 border-t border-gray-100">
|
<div class="mt-6 border-t border-gray-100">
|
||||||
<dl class="divide-y divide-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">
|
<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>
|
<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">{{client.id}}</dd>
|
<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>
|
||||||
|
|
||||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
<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>
|
<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">{{client.description}}</dd>
|
<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>
|
||||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
<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>
|
<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">{{client.version}}</dd>
|
<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>
|
||||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
<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>
|
<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 truncate">{{client.public_key}}</dd>
|
<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>
|
||||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
<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>
|
<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">{{client.secrets|length}}</dd>
|
<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>
|
||||||
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
|
<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>
|
<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">{{client.policies|join(', ')}}</dd>
|
<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>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
@ -86,7 +86,7 @@
|
|||||||
</sl-tab-panel>
|
</sl-tab-panel>
|
||||||
<sl-tab-panel name="events">
|
<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">
|
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Timestamp</th>
|
<th scope="col" class="p-4 text-xs font-medium tracking-wider text-left text-gray-500 uppercase dark:text-white">Timestamp</th>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
<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">
|
||||||
<h1 class="text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white">Clients</h1>
|
<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="flex">
|
||||||
<div
|
<div
|
||||||
class="htmx-indicator mt-2"
|
class="htmx-indicator mt-2"
|
||||||
@ -14,10 +15,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 +30,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 +55,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>
|
|
||||||
|
|||||||
@ -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() {
|
function addTreeListener() {
|
||||||
const tree = document.querySelector("sl-tree");
|
const tree = document.querySelector("sl-tree");
|
||||||
|
|
||||||
@ -8,6 +21,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 +32,16 @@ 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");
|
||||||
|
setBreadcrumb(name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -38,5 +38,4 @@
|
|||||||
{% include 'clients/partials/pagination.html.j2' %}
|
{% include 'clients/partials/pagination.html.j2' %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
{% extends "/dashboard/_base.html" %} {% block content %}
|
{% extends "/base/base.html.j2" %} {% block content %}
|
||||||
|
|
||||||
<div class="px-4 pt-6">
|
<div class="px-4 pt-6">
|
||||||
<div class="py-8 px-4 mt-4 mx-auto max-w-screen-xl text-center lg:py-16">
|
<div class="py-8 px-4 mt-4 mx-auto max-w-screen-xl text-center lg:py-16">
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div id="main-content" class="relative w-full h-full overflow-y-auto bg-gray-50 lg:ml-64 dark:bg-gray-900 flex flex-col md:flex-row flex-grow">
|
<div id="main-content" class="relative w-full h-full overflow-y-auto bg-gray-50 lg:ml-64 dark:bg-gray-900 flex flex-col md:flex-row flex-grow">
|
||||||
<main class="flex-grow p-4 order-2 md:order-1">
|
<main>
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@ -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 class="flex bg-gray-100">
|
||||||
<div
|
<div
|
||||||
@ -88,7 +88,5 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %} {% endblock %}
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -47,36 +47,15 @@
|
|||||||
{% endmacro %}
|
{% 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">
|
{% block title %}Secrets{% 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">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">
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-1 flex-col">
|
{% block master %}
|
||||||
<div class="h-full w-full">
|
|
||||||
|
<div class="flowbite-init-target">
|
||||||
|
<div id="secret-tree">
|
||||||
<sl-tree class="tree-with-icons">
|
<sl-tree class="tree-with-icons">
|
||||||
<sl-tree-item
|
<sl-tree-item
|
||||||
id="secret-group-root-item"
|
id="secret-group-root-item"
|
||||||
@ -103,8 +82,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</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">
|
|
||||||
|
{% block detail %}
|
||||||
{% if group_page | default(false) %}
|
{% if group_page | default(false) %}
|
||||||
<div class="w-full" id="secretdetails">
|
<div class="w-full" id="secretdetails">
|
||||||
{% include '/secrets/partials/group_detail.html.j2' %}
|
{% include '/secrets/partials/group_detail.html.j2' %}
|
||||||
@ -121,11 +101,13 @@
|
|||||||
{% include '/secrets/partials/default_detail.html.j2' %}
|
{% include '/secrets/partials/default_detail.html.j2' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
{% endblock %}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
{% block local_scripts %}
|
||||||
<script>
|
<script>
|
||||||
{% include '/secrets/partials/tree_event.js' %}
|
{% include '/secrets/partials/tree_event.js' %}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% 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">
|
<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' %}
|
{% include '/secrets/partials/client_list_inner.html.j2' %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="w-full">
|
<div class="w-full dark:text-white">
|
||||||
<sl-details summary="Create secret">
|
<sl-details summary="Create secret">
|
||||||
<form
|
<form
|
||||||
hx-post="/secrets/create/root"
|
hx-post="/secrets/create/root"
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="w-full">
|
<div class="w-full dark:text-white">
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h3 class="text-xl font-semibold dark:text-white">Group {{group.group_name}}</h3>
|
<h3 class="text-xl font-semibold dark:text-white">Group {{group.group_name}}</h3>
|
||||||
{% if description %}
|
{% if description %}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div class="w-full flowbite-init-target" id="secretdetails">
|
<div class="w-full flowbite-init-target dark:text-white" id="secretdetails">
|
||||||
|
|
||||||
<!-- menu -->
|
<!-- menu -->
|
||||||
|
|
||||||
@ -111,7 +111,7 @@
|
|||||||
</sl-details>
|
</sl-details>
|
||||||
{% endif %}
|
{% 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">
|
<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">
|
<thead class="bg-gray-50 dark:bg-gray-700">
|
||||||
<tr>
|
<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");
|
const tree = document.querySelector("sl-tree");
|
||||||
|
|
||||||
if (!tree) return;
|
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
|
page=page, limit=per_page, total=audit_log.total, offset=offset
|
||||||
)
|
)
|
||||||
operations = list(Operation)
|
operations = list(Operation)
|
||||||
|
breadcrumbs = [("Audit", "/audit/")]
|
||||||
if request.headers.get("HX-Request"):
|
if request.headers.get("HX-Request"):
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
request,
|
request,
|
||||||
@ -56,7 +57,8 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
request,
|
request,
|
||||||
"audit/index.html.j2",
|
"audit/index.html.j2",
|
||||||
{
|
{
|
||||||
"page_title": "Audit",
|
"page_title": "Audit Log",
|
||||||
|
"breadcrumbs": breadcrumbs,
|
||||||
"entries": audit_log.results,
|
"entries": audit_log.results,
|
||||||
"user": current_user,
|
"user": current_user,
|
||||||
"page_info": page_info,
|
"page_info": page_info,
|
||||||
|
|||||||
@ -93,11 +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",
|
||||||
{
|
{
|
||||||
|
"breadcrumbs": breadcrumbs,
|
||||||
"page_title": "Clients",
|
"page_title": "Clients",
|
||||||
"offset": offset,
|
"offset": offset,
|
||||||
"pages": paginate,
|
"pages": paginate,
|
||||||
@ -166,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
|
||||||
@ -176,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,
|
||||||
|
|||||||
@ -81,7 +81,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
request,
|
request,
|
||||||
"dashboard.html",
|
"dashboard.html",
|
||||||
{
|
{
|
||||||
"page_title": "sshecret",
|
"page_title": "Dashboard",
|
||||||
"user": current_user,
|
"user": current_user,
|
||||||
"stats": stats,
|
"stats": stats,
|
||||||
"last_login_events": last_login_events,
|
"last_login_events": last_login_events,
|
||||||
|
|||||||
@ -63,12 +63,15 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
|
admin: Annotated[AdminBackend, Depends(dependencies.get_admin_backend)],
|
||||||
current_user: Annotated[LocalUserInfo, Depends(dependencies.get_user_info)],
|
current_user: Annotated[LocalUserInfo, Depends(dependencies.get_user_info)],
|
||||||
):
|
):
|
||||||
|
breadcrumbs = [("secrets", "/secrets/")]
|
||||||
groups = await admin.get_secret_groups()
|
groups = await admin.get_secret_groups()
|
||||||
return templates.TemplateResponse(
|
return templates.TemplateResponse(
|
||||||
request,
|
request,
|
||||||
"secrets/index.html.j2",
|
"secrets/index.html.j2",
|
||||||
{
|
{
|
||||||
|
"page_title": "Secrets",
|
||||||
"groups": groups,
|
"groups": groups,
|
||||||
|
"breadcrumbs": breadcrumbs,
|
||||||
"user": current_user,
|
"user": current_user,
|
||||||
"selected_group": None,
|
"selected_group": None,
|
||||||
"group_path_nodes": ["/"],
|
"group_path_nodes": ["/"],
|
||||||
@ -83,8 +86,15 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
):
|
):
|
||||||
"""Show the root path."""
|
"""Show the root path."""
|
||||||
clients = await admin.get_clients()
|
clients = await admin.get_clients()
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
("secrets", "/secrets/"),
|
||||||
|
("groups", "/secrets/groups/"),
|
||||||
|
("Ungrouped", "/secrets/groups/"),
|
||||||
|
]
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"clients": clients,
|
"clients": clients,
|
||||||
|
"breadcrumbs": breadcrumbs,
|
||||||
"root_group_page": True,
|
"root_group_page": True,
|
||||||
}
|
}
|
||||||
headers: dict[str, str] = {}
|
headers: dict[str, str] = {}
|
||||||
@ -95,6 +105,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
else:
|
else:
|
||||||
groups = await admin.get_secret_groups()
|
groups = await admin.get_secret_groups()
|
||||||
template_name = "secrets/index.html.j2"
|
template_name = "secrets/index.html.j2"
|
||||||
|
context["page_title"] = "Secrets"
|
||||||
context["user"] = current_user
|
context["user"] = current_user
|
||||||
context["groups"] = groups
|
context["groups"] = groups
|
||||||
context["group_path_nodes"] = ["/"]
|
context["group_path_nodes"] = ["/"]
|
||||||
@ -119,11 +130,20 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
)
|
)
|
||||||
clients = await admin.get_clients()
|
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] = {}
|
headers: dict[str, str] = {}
|
||||||
context: dict[str, Any] = {
|
context: dict[str, Any] = {
|
||||||
"group_page": True,
|
"group_page": True,
|
||||||
"group": group,
|
"group": group,
|
||||||
"clients": clients,
|
"clients": clients,
|
||||||
|
"breadcrumbs": breadcrumbs,
|
||||||
}
|
}
|
||||||
if request.headers.get("HX-Request"):
|
if request.headers.get("HX-Request"):
|
||||||
# This is a HTMX request.
|
# This is a HTMX request.
|
||||||
@ -133,6 +153,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
template_name = "secrets/index.html.j2"
|
template_name = "secrets/index.html.j2"
|
||||||
|
|
||||||
groups = await admin.get_secret_groups()
|
groups = await admin.get_secret_groups()
|
||||||
|
context["page_title"] = "Secrets"
|
||||||
context["user"] = current_user
|
context["user"] = current_user
|
||||||
context["groups"] = groups
|
context["groups"] = groups
|
||||||
context["group_path_nodes"] = group.path.split("/")
|
context["group_path_nodes"] = group.path.split("/")
|
||||||
@ -180,6 +201,7 @@ def create_router(dependencies: FrontendDependencies) -> APIRouter:
|
|||||||
group_path = group.path.split("/")
|
group_path = group.path.split("/")
|
||||||
|
|
||||||
template_name = "secrets/index.html.j2"
|
template_name = "secrets/index.html.j2"
|
||||||
|
context["page_title"] = "Secrets"
|
||||||
context["user"] = current_user
|
context["user"] = current_user
|
||||||
context["groups"] = groups
|
context["groups"] = groups
|
||||||
context["group_path_nodes"] = group_path
|
context["group_path_nodes"] = group_path
|
||||||
|
|||||||
@ -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;
|
||||||
@ -2854,6 +2833,21 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.md\:w-64 {
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
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);
|
||||||
@ -2879,6 +2873,11 @@
|
|||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.md\:grid-cols-\[300px_1fr\] {
|
||||||
|
@media (width >= 48rem) {
|
||||||
|
grid-template-columns: 300px 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
.md\:flex-row {
|
.md\:flex-row {
|
||||||
@media (width >= 48rem) {
|
@media (width >= 48rem) {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -3104,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));
|
||||||
@ -3459,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);
|
||||||
@ -3718,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 {
|
||||||
|
|||||||
@ -19,3 +19,11 @@ sl-details.small-details::part(header) {
|
|||||||
sl-details.small-details::part(base) {
|
sl-details.small-details::part(base) {
|
||||||
font-size: var(--sl-input-font-size-small);
|
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