aggiunto le due sezioni quasar private e admin
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
:root{--ui-bg: #ffffff;--ui-fg: #111827;--ui-muted: #6b7280;--ui-border: #d1d5db;--ui-overlay: rgba(17, 24, 39, .56);--ui-panel: #ffffff;--ui-radius: 10px;--ui-shadow: 0 10px 35px rgba(15, 23, 42, .2);--ui-primary: #111827;--ui-primary-contrast: #ffffff}ui-modal,ui-drop-down,ui-data-table-shell{font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:var(--ui-fg)}
|
||||
File diff suppressed because it is too large
Load Diff
0
web/static/vendor/.gitkeep
vendored
0
web/static/vendor/.gitkeep
vendored
5
web/static/vendor/flags/ch.svg
vendored
5
web/static/vendor/flags/ch.svg
vendored
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true">
|
||||
<rect width="24" height="24" fill="#d52b1e"/>
|
||||
<rect x="10" y="5" width="4" height="14" fill="#ffffff"/>
|
||||
<rect x="5" y="10" width="14" height="4" fill="#ffffff"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 255 B |
5
web/static/vendor/flags/de.svg
vendored
5
web/static/vendor/flags/de.svg
vendored
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 2" aria-hidden="true">
|
||||
<rect width="3" height="0.6667" x="0" y="0" fill="#000000"/>
|
||||
<rect width="3" height="0.6667" x="0" y="0.6667" fill="#dd0000"/>
|
||||
<rect width="3" height="0.6667" x="0" y="1.3333" fill="#ffce00"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 284 B |
11
web/static/vendor/flags/en.svg
vendored
11
web/static/vendor/flags/en.svg
vendored
@@ -1,11 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 60 30" aria-hidden="true">
|
||||
<clipPath id="s"><path d="M0,0 v30 h60 v-30 z"/></clipPath>
|
||||
<clipPath id="t"><path d="M30,15 h30 v15 z v-30 h-30 z h-30 v15 z v15 h30 z"/></clipPath>
|
||||
<g clip-path="url(#s)">
|
||||
<path d="M0,0 v30 h60 v-30 z" fill="#012169"/>
|
||||
<path d="M0,0 L60,30 M60,0 L0,30" stroke="#fff" stroke-width="6"/>
|
||||
<path d="M0,0 L60,30 M60,0 L0,30" clip-path="url(#t)" stroke="#C8102E" stroke-width="4"/>
|
||||
<path d="M30,0 v30 M0,15 h60" stroke="#fff" stroke-width="10"/>
|
||||
<path d="M30,0 v30 M0,15 h60" stroke="#C8102E" stroke-width="6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 628 B |
12
web/static/vendor/flags/en_us.svg
vendored
12
web/static/vendor/flags/en_us.svg
vendored
@@ -1,12 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 190 100" aria-hidden="true">
|
||||
<rect width="190" height="100" fill="#b22234"/>
|
||||
<g fill="#fff">
|
||||
<rect y="7.69" width="190" height="7.69"/>
|
||||
<rect y="23.08" width="190" height="7.69"/>
|
||||
<rect y="38.46" width="190" height="7.69"/>
|
||||
<rect y="53.85" width="190" height="7.69"/>
|
||||
<rect y="69.23" width="190" height="7.69"/>
|
||||
<rect y="84.62" width="190" height="7.69"/>
|
||||
</g>
|
||||
<rect width="76" height="53.85" fill="#3c3b6e"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 502 B |
5
web/static/vendor/flags/fr.svg
vendored
5
web/static/vendor/flags/fr.svg
vendored
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 2" aria-hidden="true">
|
||||
<rect width="1" height="2" x="0" y="0" fill="#0055a4"/>
|
||||
<rect width="1" height="2" x="1" y="0" fill="#ffffff"/>
|
||||
<rect width="1" height="2" x="2" y="0" fill="#ef4135"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 259 B |
5
web/static/vendor/flags/it.svg
vendored
5
web/static/vendor/flags/it.svg
vendored
@@ -1,5 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3 2" aria-hidden="true">
|
||||
<rect width="1" height="2" x="0" y="0" fill="#009246"/>
|
||||
<rect width="1" height="2" x="1" y="0" fill="#ffffff"/>
|
||||
<rect width="1" height="2" x="2" y="0" fill="#ce2b37"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 259 B |
2
web/static/vendor/flowbite.js
vendored
2
web/static/vendor/flowbite.js
vendored
File diff suppressed because one or more lines are too long
1
web/static/vendor/htmx.min.js
vendored
1
web/static/vendor/htmx.min.js
vendored
File diff suppressed because one or more lines are too long
101
web/static/vendor/theme.js
vendored
101
web/static/vendor/theme.js
vendored
@@ -1,101 +0,0 @@
|
||||
(function () {
|
||||
var STORAGE_KEY = "theme";
|
||||
var root = document.documentElement;
|
||||
var mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
var isAuthenticated = window.__TC_IS_AUTHENTICATED === true || window.__TC_IS_AUTHENTICATED === "true";
|
||||
var serverTheme = normalizeTheme(window.__TC_SERVER_THEME);
|
||||
|
||||
function normalizeTheme(theme) {
|
||||
if (!theme) return "";
|
||||
return String(theme).trim().toLowerCase();
|
||||
}
|
||||
|
||||
function getStoredTheme() {
|
||||
var value = null;
|
||||
try {
|
||||
value = localStorage.getItem(STORAGE_KEY);
|
||||
} catch (e) {
|
||||
value = null;
|
||||
}
|
||||
return value === "dark" || value === "light" ? value : null;
|
||||
}
|
||||
|
||||
function getPreferredTheme() {
|
||||
return mediaQuery.matches ? "dark" : "light";
|
||||
}
|
||||
|
||||
function applyTheme(theme) {
|
||||
root.classList.toggle("dark", theme === "dark");
|
||||
}
|
||||
|
||||
function currentTheme() {
|
||||
return root.classList.contains("dark") ? "dark" : "light";
|
||||
}
|
||||
|
||||
function setStoredTheme(theme) {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, theme);
|
||||
} catch (e) {
|
||||
// localStorage may be unavailable in private mode or blocked contexts.
|
||||
}
|
||||
}
|
||||
|
||||
function persistThemePreference(theme) {
|
||||
if (!isAuthenticated) return;
|
||||
fetch("/preferences/theme", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
credentials: "same-origin",
|
||||
body: JSON.stringify({ theme: theme }),
|
||||
}).catch(function () {});
|
||||
}
|
||||
|
||||
function updateToggleState(theme) {
|
||||
var button = document.getElementById("themeToggle");
|
||||
if (!button) return;
|
||||
|
||||
var isDark = theme === "dark";
|
||||
button.setAttribute("aria-pressed", isDark ? "true" : "false");
|
||||
button.textContent = isDark ? "Light mode" : "Dark mode";
|
||||
}
|
||||
|
||||
function applyInitialTheme() {
|
||||
if (isAuthenticated && (serverTheme === "dark" || serverTheme === "light")) {
|
||||
setStoredTheme(serverTheme);
|
||||
applyTheme(serverTheme);
|
||||
return;
|
||||
}
|
||||
var stored = getStoredTheme();
|
||||
applyTheme(stored || getPreferredTheme());
|
||||
}
|
||||
|
||||
window.toggleTheme = function toggleTheme() {
|
||||
var next = currentTheme() === "dark" ? "light" : "dark";
|
||||
applyTheme(next);
|
||||
setStoredTheme(next);
|
||||
persistThemePreference(next);
|
||||
updateToggleState(next);
|
||||
};
|
||||
|
||||
window.initThemeToggle = function initThemeToggle() {
|
||||
updateToggleState(currentTheme());
|
||||
};
|
||||
|
||||
if (typeof mediaQuery.addEventListener === "function") {
|
||||
mediaQuery.addEventListener("change", function (event) {
|
||||
if (getStoredTheme()) return;
|
||||
var theme = event.matches ? "dark" : "light";
|
||||
applyTheme(theme);
|
||||
updateToggleState(theme);
|
||||
});
|
||||
} else if (typeof mediaQuery.addListener === "function") {
|
||||
mediaQuery.addListener(function (event) {
|
||||
if (getStoredTheme()) return;
|
||||
var theme = event.matches ? "dark" : "light";
|
||||
applyTheme(theme);
|
||||
updateToggleState(theme);
|
||||
});
|
||||
}
|
||||
|
||||
applyInitialTheme();
|
||||
})();
|
||||
5
web/templates/admin.html
Normal file
5
web/templates/admin.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{{define "content"}}
|
||||
<section class="rounded-lg border border-gray-200 bg-white p-8 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">admin page</h1>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -1,55 +0,0 @@
|
||||
{{define "navbar"}}
|
||||
<nav class="border-b border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900">
|
||||
<div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between p-4">
|
||||
<a href="/" class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||
<span class="self-center whitespace-nowrap text-xl font-semibold">Trustcontact</span>
|
||||
</a>
|
||||
|
||||
<button data-collapse-toggle="navbar-main" type="button" class="inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-700 md:hidden" aria-controls="navbar-main" aria-expanded="false">
|
||||
<span class="sr-only" data-i18n="nav.open_main_menu">Apri menu principale</span>
|
||||
<svg class="h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="hidden w-full items-center justify-between md:order-1 md:flex md:w-auto" id="navbar-main">
|
||||
<ul class="mt-4 flex flex-col gap-2 rounded-lg border border-gray-100 bg-gray-50 p-4 text-sm font-medium md:mt-0 md:flex-row md:items-center md:gap-1 md:border-0 md:bg-transparent md:p-0 dark:border-gray-700 dark:bg-gray-800 md:dark:bg-transparent">
|
||||
<li><a href="/admin" class="block rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700">Dashboard</a></li>
|
||||
<li><a href="/admin/users" class="block rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-i18n="nav.users">Users</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-4 flex items-center gap-3 md:mt-0 md:ms-4">
|
||||
{{template "navbar_controls" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
{{define "navbar_controls"}}
|
||||
{{template "language_dropdown" .}}
|
||||
|
||||
{{if .CurrentUser}}
|
||||
<div class="relative">
|
||||
<button type="button" class="inline-flex h-8 items-center rounded-lg bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700 dark:focus:ring-gray-700" id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown" data-dropdown-placement="bottom">
|
||||
<span class="sr-only" data-i18n="nav.open_user_menu">Apri menu utente</span>
|
||||
<span class="inline-flex items-center justify-center">
|
||||
<svg class="h-4 w-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<div class="z-50 my-4 hidden w-56 list-none divide-y divide-gray-100 rounded-lg bg-white text-base shadow-sm dark:divide-gray-700 dark:bg-gray-800" id="user-dropdown">
|
||||
<div class="px-4 py-3">
|
||||
<span class="block truncate text-sm text-gray-900 dark:text-gray-100">{{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}Utente{{end}}</span>
|
||||
<span class="block truncate text-sm text-gray-500 dark:text-gray-400">{{.CurrentUser.Email}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<form action="/logout" method="post" class="px-2">
|
||||
<button type="submit" class="block w-full rounded-lg px-2 py-2 text-left text-sm text-red-700 hover:bg-red-50 dark:text-red-300 dark:hover:bg-red-900/40" data-i18n="nav.logout">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,36 +0,0 @@
|
||||
{{define "content"}}
|
||||
<section class="space-y-6">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white" data-i18n="audit.title">Audit Logs</h1>
|
||||
|
||||
<div class="mb-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<ul class="-mb-px flex flex-wrap text-center text-sm font-medium" id="audit-tab" data-tabs-toggle="#audit-tab-content" role="tablist">
|
||||
<li class="me-2" role="presentation">
|
||||
<button class="inline-block rounded-t-lg border-b-2 p-4 dark:text-gray-200" id="activity-tab" data-tabs-target="#activity" type="button" role="tab" aria-controls="activity" aria-selected="true" data-i18n="audit.activity">Activity</button>
|
||||
</li>
|
||||
<li class="me-2" role="presentation">
|
||||
<button class="inline-block rounded-t-lg border-b-2 p-4 dark:text-gray-200" id="security-tab" data-tabs-target="#security" type="button" role="tab" aria-controls="security" aria-selected="false" data-i18n="audit.security">Security</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="audit-tab-content">
|
||||
<div class="hidden rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800" id="activity" role="tabpanel" aria-labelledby="activity-tab">
|
||||
<div class="relative overflow-x-auto">
|
||||
<table class="w-full text-left text-sm text-gray-500 dark:text-gray-400">
|
||||
<thead class="bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-300">
|
||||
<tr>
|
||||
<th class="px-6 py-3" data-i18n="audit.timestamp">Timestamp</th>
|
||||
<th class="px-6 py-3" data-i18n="audit.actor">Actor</th>
|
||||
<th class="px-6 py-3" data-i18n="audit.action">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr class="border-b bg-white dark:border-gray-700 dark:bg-gray-800"><td class="px-6 py-4">-</td><td class="px-6 py-4">-</td><td class="px-6 py-4">-</td></tr></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800" id="security" role="tabpanel" aria-labelledby="security-tab">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300" data-i18n="audit.placeholder">Security logs placeholder.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -1,29 +0,0 @@
|
||||
{{define "content"}}
|
||||
<section class="space-y-6">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white" data-i18n="admin.dashboard.title">Admin Dashboard</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300" data-i18n="admin.dashboard.area">Area amministrazione.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400" data-i18n="admin.users_count">Utenti</p>
|
||||
<p class="mt-2 text-3xl font-semibold text-gray-900 dark:text-white">{{if .PageData}}{{.PageData.Total}}{{else}}-{{end}}</p>
|
||||
</article>
|
||||
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400" data-i18n="admin.current_role">Ruolo corrente</p>
|
||||
<p class="mt-2">
|
||||
{{if and .CurrentUser (eq .CurrentUser.Role "admin")}}
|
||||
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800" data-i18n="user.role_admin">admin</span>
|
||||
{{else}}
|
||||
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800" data-i18n="user.role_user">user</span>
|
||||
{{end}}
|
||||
</p>
|
||||
</article>
|
||||
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<p class="text-sm font-medium text-gray-500 dark:text-gray-400" data-i18n="admin.navigation">Navigazione</p>
|
||||
<a href="/admin/users" class="mt-2 inline-flex rounded-lg bg-blue-700 px-4 py-2 text-sm font-medium text-white hover:bg-blue-800" data-i18n="admin.manage_users">Gestione utenti</a>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -1,8 +0,0 @@
|
||||
{{define "content"}}
|
||||
<section class="space-y-4">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white" data-i18n="users.title">Admin Users</h1>
|
||||
<div class="rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<p class="text-gray-600 dark:text-gray-300" data-i18n="users.new_user_modal_placeholder">Template pagina utenti admin in stile Flowbite.</p>
|
||||
</div>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -1,33 +0,0 @@
|
||||
{{define "users_modal"}}
|
||||
<div class="text-sm text-gray-700 dark:text-gray-200 ">
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="table.id">ID</span>:
|
||||
<span>{{.User.ID}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="table.role">Role</span>:
|
||||
{{if eq .User.Role "admin"}}
|
||||
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800" data-i18n="user.role_admin">admin</span>
|
||||
{{else}}
|
||||
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800" data-i18n="user.role_user">user</span>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="table.name">Name</span>:
|
||||
<span>{{if .User.Name}}{{.User.Name}}{{else}}-{{end}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="table.email">Email</span>:
|
||||
<span>{{.User.Email}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="user.verified">Verified</span>:
|
||||
<span>{{if .User.EmailVerified}}<span data-i18n="user.yes">yes</span>{{else}}<span data-i18n="user.no">no</span>{{end}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<span class="font-semibold text-gray-900 dark:text-white" data-i18n="user.created">Created</span>:
|
||||
<span data-localize-date="{{.User.CreatedAt.Format "2006-01-02T15:04:05Z07:00"}}">{{.User.CreatedAt}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{end}}
|
||||
@@ -1,53 +0,0 @@
|
||||
{{define "users_table"}}
|
||||
{{ $p := .PageData }}
|
||||
<div class="relative overflow-x-auto">
|
||||
<table class="w-full text-left text-sm text-gray-500 rtl:text-right dark:text-gray-400">
|
||||
<thead class="bg-gray-50 text-xs uppercase text-gray-700 dark:bg-gray-700 dark:text-gray-300">
|
||||
<tr>
|
||||
<th scope="col" class="px-6 py-3">
|
||||
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=id&dir={{if and (eq $p.Sort "id") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML" data-i18n="table.id">ID</button>
|
||||
</th>
|
||||
<th scope="col" class="px-6 py-3">
|
||||
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=name&dir={{if and (eq $p.Sort "name") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML" data-i18n="table.name">Name</button>
|
||||
</th>
|
||||
<th scope="col" class="px-6 py-3">
|
||||
<button type="button" class="inline-flex items-center gap-1 hover:text-blue-700" hx-get="/admin/users/table?q={{$p.Q}}&sort=email&dir={{if and (eq $p.Sort "email") (eq $p.Dir "asc")}}desc{{else}}asc{{end}}&page=1&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML" data-i18n="table.email">Email</button>
|
||||
</th>
|
||||
<th scope="col" class="px-6 py-3" data-i18n="table.role">Role</th>
|
||||
<th scope="col" class="px-6 py-3" data-i18n="users.actions">Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range $u := $p.Users}}
|
||||
<tr class="border-b bg-white hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:hover:bg-gray-700/60">
|
||||
<td class="px-6 py-4">{{$u.ID}}</td>
|
||||
<td class="px-6 py-4 font-medium text-gray-900 dark:text-white">{{if $u.Name}}{{$u.Name}}{{else}}-{{end}}</td>
|
||||
<td class="px-6 py-4">{{$u.Email}}</td>
|
||||
<td class="px-6 py-4">
|
||||
{{if eq $u.Role "admin"}}
|
||||
<span class="rounded-sm bg-red-100 px-2.5 py-0.5 text-xs font-medium text-red-800" data-i18n="user.role_admin">admin</span>
|
||||
{{else}}
|
||||
<span class="rounded-sm bg-blue-100 px-2.5 py-0.5 text-xs font-medium text-blue-800" data-i18n="user.role_user">user</span>
|
||||
{{end}}
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<button type="button" class="rounded-lg bg-blue-700 px-3 py-2 text-xs font-medium text-white hover:bg-blue-800" data-modal-target="userModal" data-modal-toggle="userModal" hx-get="/admin/users/{{$u.ID}}/modal" hx-target="#userModalContent" hx-swap="innerHTML" data-i18n="users.open">Apri</button>
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr class="bg-white dark:bg-gray-800">
|
||||
<td colspan="5" class="px-6 py-4 text-center text-gray-500 dark:text-gray-400" data-i18n="users.none">Nessun utente trovato.</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 flex flex-wrap items-center justify-between gap-3">
|
||||
<div class="text-sm text-gray-600 dark:text-gray-300"><span data-i18n="users.total">Totale</span>: {{$p.Total}} <span data-i18n="users.users_label">utenti</span>. <span data-i18n="users.page">Pagina</span> {{$p.Page}}{{if gt $p.TotalPages 0}} / {{$p.TotalPages}}{{end}}</div>
|
||||
<div class="inline-flex gap-2">
|
||||
<button type="button" class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-900 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700" {{if not $p.HasPrev}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.PrevPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML" data-i18n="users.prev">Prev</button>
|
||||
<button type="button" class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-900 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700" {{if not $p.HasNext}}disabled{{end}} hx-get="/admin/users/table?q={{$p.Q}}&sort={{$p.Sort}}&dir={{$p.Dir}}&page={{$p.NextPage}}&pageSize={{$p.PageSize}}" hx-target="#usersTableContainer" hx-swap="innerHTML" data-i18n="users.next">Next</button>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1,81 +0,0 @@
|
||||
{{define "content"}}
|
||||
<section class="space-y-6">
|
||||
<div class="flex flex-wrap items-center justify-between gap-3">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white" data-i18n="users.title">Users</h1>
|
||||
<p class="text-gray-600 dark:text-gray-300" data-i18n="users.subtitle">Ricerca, ordinamento e paging server-side via HTMX.</p>
|
||||
</div>
|
||||
<button type="button" data-modal-target="newUserModal" data-modal-toggle="newUserModal" class="inline-flex items-center rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300" data-i18n="users.new_user">
|
||||
Nuovo Utente
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form id="usersFilters" class="flex gap-4 rounded-lg border border-gray-200 bg-white p-4 shadow-sm dark:border-gray-700 dark:bg-gray-800 md:grid-cols-4" hx-get="/admin/users/table" hx-target="#usersTableContainer" hx-swap="innerHTML">
|
||||
<div class="flex-auto">
|
||||
<label for="users-q" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white" data-i18n="users.search">Search</label>
|
||||
<input id="users-q" type="text" name="q" placeholder="Cerca nome o email" data-i18n-placeholder="users.search_placeholder" value="{{.PageData.Q}}" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400">
|
||||
</div>
|
||||
<div style="max-width: 100px;" class="flex-none">
|
||||
<label for="users-size" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white" data-i18n="users.page_size">Page size</label>
|
||||
<select id="users-size" name="pageSize" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 focus:border-blue-500 focus:ring-blue-500 dark:border-gray-600 dark:bg-gray-700 dark:text-white" hx-get="/admin/users/table" hx-target="#usersTableContainer" hx-swap="innerHTML" hx-include="#usersFilters" hx-trigger="change">
|
||||
<option value="5" {{if eq .PageData.PageSize 5}}selected{{end}}>5</option>
|
||||
<option value="10" {{if eq .PageData.PageSize 10}}selected{{end}}>10</option>
|
||||
<option value="20" {{if eq .PageData.PageSize 20}}selected{{end}}>20</option>
|
||||
<option value="50" {{if eq .PageData.PageSize 50}}selected{{end}}>50</option>
|
||||
<option value="100" {{if eq .PageData.PageSize 100}}selected{{end}}>100</option>
|
||||
<option value="500" {{if eq .PageData.PageSize 500}}selected{{end}}>500</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="max-width: 120px;" class="flex-auto self-end">
|
||||
<button type="submit" class="w-full rounded-lg bg-blue-700 px-5 py-2.5 text-sm font-medium text-white hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300" data-i18n="users.search_button">Cerca</button>
|
||||
</div>
|
||||
<input type="hidden" name="sort" value="{{.PageData.Sort}}">
|
||||
<input type="hidden" name="dir" value="{{.PageData.Dir}}">
|
||||
<input type="hidden" name="page" value="1">
|
||||
</form>
|
||||
|
||||
<div id="usersTableContainer" class="rounded-lg border border-gray-200 bg-white p-2 shadow-sm dark:border-gray-700 dark:bg-gray-800 md:p-4" hx-get="/admin/users/table?q={{.PageData.Q}}&sort={{.PageData.Sort}}&dir={{.PageData.Dir}}&page={{.PageData.Page}}&pageSize={{.PageData.PageSize}}" hx-trigger="load" hx-swap="innerHTML">
|
||||
{{template "users_table" .}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="userModal" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
|
||||
<div class="relative max-h-full w-full max-w-2xl">
|
||||
<div class="relative rounded-lg bg-white shadow-sm dark:bg-gray-800">
|
||||
<div class="flex items-start justify-between rounded-t border-b p-4 dark:border-gray-700 md:p-5">
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white" data-i18n="users.user_detail">Dettaglio utente</h3>
|
||||
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-700 dark:hover:text-white" data-modal-hide="userModal" aria-label="Close modal">
|
||||
<span class="sr-only" data-i18n="users.close">Close modal</span>
|
||||
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div id="userModalContent" class="space-y-4 p-4 md:p-5"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="newUserModal" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
|
||||
<div class="relative max-h-full w-full max-w-xl">
|
||||
<div class="relative rounded-lg bg-white shadow-sm dark:bg-gray-800">
|
||||
<div class="flex items-start justify-between rounded-t border-b p-4 dark:border-gray-700 md:p-5">
|
||||
<h3 class="text-xl font-semibold text-gray-900 dark:text-white" data-i18n="users.new_user_modal_title">Nuovo utente</h3>
|
||||
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900 dark:hover:bg-gray-700 dark:hover:text-white" data-modal-hide="newUserModal" aria-label="Close modal">
|
||||
<span class="sr-only" data-i18n="users.close">Close modal</span>
|
||||
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-4 p-4 md:p-5">
|
||||
<p class="text-sm text-gray-600 dark:text-gray-300" data-i18n="users.new_user_modal_placeholder">Placeholder UI Flowbite. La creazione utente può essere collegata a una route backend quando disponibile.</p>
|
||||
<div>
|
||||
<label for="new-user-email" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white" data-i18n="form.email">Email</label>
|
||||
<input id="new-user-email" type="email" class="block w-full rounded-lg border border-gray-300 bg-gray-50 p-2.5 text-sm text-gray-900 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:placeholder-gray-400" placeholder="name@company.com" disabled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1,13 +0,0 @@
|
||||
{{define "flowbite_collapse"}}
|
||||
<button data-collapse-toggle="collapseExample" type="button" class="flex w-full items-center justify-between rounded-lg bg-gray-100 px-5 py-2.5 text-left text-sm font-medium text-gray-500 hover:bg-gray-200" aria-expanded="false" aria-controls="collapseExample">
|
||||
<span>Toggle collapse</span>
|
||||
<svg data-accordion-icon class="h-3 w-3 shrink-0" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5 5 1 1 5"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div id="collapseExample" class="hidden">
|
||||
<div class="rounded-b-lg border border-gray-200 p-5">
|
||||
<p class="text-sm text-gray-500">Collapsed content.</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1,16 +0,0 @@
|
||||
{{define "flowbite_dropdown"}}
|
||||
<button id="dropdownDefaultButton" data-dropdown-toggle="dropdown" class="inline-flex items-center rounded-lg bg-blue-700 px-5 py-2.5 text-center text-sm font-medium text-white hover:bg-blue-800" type="button">
|
||||
Dropdown
|
||||
<svg class="ms-3 h-2.5 w-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div id="dropdown" class="z-10 hidden w-44 divide-y divide-gray-100 rounded-lg bg-white shadow-sm">
|
||||
<ul class="py-2 text-sm text-gray-700" aria-labelledby="dropdownDefaultButton">
|
||||
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Dashboard</a></li>
|
||||
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Settings</a></li>
|
||||
<li><a href="#" class="block px-4 py-2 hover:bg-gray-100">Sign out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1,17 +0,0 @@
|
||||
{{define "flowbite_flash"}}
|
||||
{{if .FlashSuccess}}
|
||||
<div class="mb-4 flex items-center rounded-lg border border-green-200 bg-green-50 p-4 text-green-800" role="alert">
|
||||
<span class="text-sm font-medium">{{.FlashSuccess}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .FlashError}}
|
||||
<div class="mb-4 flex items-center rounded-lg border border-red-200 bg-red-50 p-4 text-red-800" role="alert">
|
||||
<span class="text-sm font-medium">{{.FlashError}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .FlashWarning}}
|
||||
<div class="mb-4 flex items-center rounded-lg border border-yellow-200 bg-yellow-50 p-4 text-yellow-800" role="alert">
|
||||
<span class="text-sm font-medium">{{.FlashWarning}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,25 +0,0 @@
|
||||
{{define "flowbite_modal"}}
|
||||
<div id="{{.ModalID}}" tabindex="-1" aria-hidden="true" class="fixed left-0 right-0 top-0 z-50 hidden h-[calc(100%-1rem)] max-h-full w-full items-center justify-center overflow-y-auto overflow-x-hidden p-4 md:inset-0">
|
||||
<div class="relative max-h-full w-full max-w-2xl">
|
||||
<div class="relative rounded-lg bg-white shadow-sm">
|
||||
<div class="flex items-start justify-between rounded-t border-b p-4 md:p-5">
|
||||
<h3 class="text-xl font-semibold text-gray-900">{{.ModalTitle}}</h3>
|
||||
<button type="button" class="ms-auto inline-flex h-8 w-8 items-center justify-center rounded-lg bg-transparent text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900" data-modal-hide="{{.ModalID}}" aria-label="Close modal">
|
||||
<span class="sr-only">Close modal</span>
|
||||
<svg class="h-3 w-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="space-y-4 p-4 md:p-5">
|
||||
{{template .ModalBodyTemplate .}}
|
||||
</div>
|
||||
{{if .ModalFooterTemplate}}
|
||||
<div class="flex items-center rounded-b border-t border-gray-200 p-4 md:p-5">
|
||||
{{template .ModalFooterTemplate .}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -1,21 +0,0 @@
|
||||
{{define "flowbite_navbar"}}
|
||||
<nav class="border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900">
|
||||
<div class="mx-auto flex max-w-screen-xl flex-wrap items-center justify-between p-4">
|
||||
<a href="#" class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||
<span class="self-center whitespace-nowrap text-2xl font-semibold">Trustcontact</span>
|
||||
</a>
|
||||
<button data-collapse-toggle="navbar-default" type="button" class="inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-700 md:hidden" aria-controls="navbar-default" aria-expanded="false">
|
||||
<span class="sr-only">Open main menu</span>
|
||||
<svg class="h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="hidden w-full md:block md:w-auto" id="navbar-default">
|
||||
<ul class="mt-4 flex flex-col rounded-lg border border-gray-100 bg-gray-50 p-4 font-medium md:mt-0 md:flex-row md:space-x-8 md:border-0 md:bg-white md:p-0 rtl:space-x-reverse dark:border-gray-700 dark:bg-gray-800 md:dark:bg-gray-900">
|
||||
<li><a href="#" class="block rounded-sm bg-blue-700 px-3 py-2 text-white md:bg-transparent md:p-0 md:text-blue-700" aria-current="page">Home</a></li>
|
||||
<li><a href="#" class="block rounded-sm px-3 py-2 text-gray-900 hover:bg-gray-100 md:p-0 md:hover:bg-transparent md:hover:text-blue-700 dark:text-gray-100 dark:hover:bg-gray-700 md:dark:hover:bg-transparent">About</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
@@ -1,20 +0,0 @@
|
||||
{{define "flowbite_tabs"}}
|
||||
<div class="mb-4 border-b border-gray-200">
|
||||
<ul class="-mb-px flex flex-wrap text-center text-sm font-medium" id="default-tab" data-tabs-toggle="#default-tab-content" role="tablist">
|
||||
<li class="me-2" role="presentation">
|
||||
<button class="inline-block rounded-t-lg border-b-2 p-4" id="profile-tab" data-tabs-target="#profile" type="button" role="tab" aria-controls="profile" aria-selected="false">Profile</button>
|
||||
</li>
|
||||
<li class="me-2" role="presentation">
|
||||
<button class="inline-block rounded-t-lg border-b-2 p-4" id="dashboard-tab" data-tabs-target="#dashboard" type="button" role="tab" aria-controls="dashboard" aria-selected="false">Dashboard</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="default-tab-content">
|
||||
<div class="hidden rounded-lg bg-gray-50 p-4" id="profile" role="tabpanel" aria-labelledby="profile-tab">
|
||||
<p class="text-sm text-gray-500">Profile tab content.</p>
|
||||
</div>
|
||||
<div class="hidden rounded-lg bg-gray-50 p-4" id="dashboard" role="tabpanel" aria-labelledby="dashboard-tab">
|
||||
<p class="text-sm text-gray-500">Dashboard tab content.</p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
5
web/templates/private.html
Normal file
5
web/templates/private.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{{define "content"}}
|
||||
<section class="rounded-lg border border-gray-200 bg-white p-8 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<h1 class="text-3xl font-bold text-gray-900 dark:text-white">private page</h1>
|
||||
</section>
|
||||
{{end}}
|
||||
@@ -1,54 +0,0 @@
|
||||
{{define "navbar"}}
|
||||
<nav class="border-b border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-900">
|
||||
<div class="mx-auto flex max-w-7xl flex-wrap items-center justify-between p-4">
|
||||
<a href="/" class="flex items-center space-x-3 rtl:space-x-reverse">
|
||||
<span class="self-center whitespace-nowrap text-xl font-semibold">Trustcontact</span>
|
||||
</a>
|
||||
|
||||
<button data-collapse-toggle="navbar-main" type="button" class="inline-flex h-10 w-10 items-center justify-center rounded-lg p-2 text-sm text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-700 md:hidden" aria-controls="navbar-main" aria-expanded="false">
|
||||
<span class="sr-only" data-i18n="nav.open_main_menu">Apri menu principale</span>
|
||||
<svg class="h-5 w-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="hidden w-full items-center justify-between md:order-1 md:flex md:w-auto" id="navbar-main">
|
||||
<ul class="mt-4 flex flex-col gap-2 rounded-lg border border-gray-100 bg-gray-50 p-4 text-sm font-medium md:mt-0 md:flex-row md:items-center md:gap-1 md:border-0 md:bg-transparent md:p-0 dark:border-gray-700 dark:bg-gray-800 md:dark:bg-transparent">
|
||||
<li><a href="/welcome" class="block rounded-lg px-3 py-2 text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700">Welcome</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="mt-4 flex items-center gap-3 md:mt-0 md:ms-4">
|
||||
{{template "navbar_controls" .}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
{{end}}
|
||||
|
||||
{{define "navbar_controls"}}
|
||||
{{template "language_dropdown" .}}
|
||||
|
||||
{{if .CurrentUser}}
|
||||
<div class="relative">
|
||||
<button type="button" class="inline-flex h-8 items-center rounded-lg bg-white px-3 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:bg-gray-800 dark:text-gray-100 dark:hover:bg-gray-700 dark:focus:ring-gray-700" id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown" data-dropdown-placement="bottom">
|
||||
<span class="sr-only" data-i18n="nav.open_user_menu">Apri menu utente</span>
|
||||
<span class="inline-flex items-center justify-center">
|
||||
<svg class="h-4 w-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 17 14">
|
||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M1 1h15M1 7h15M1 13h15" />
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<div class="z-50 my-4 hidden w-56 list-none divide-y divide-gray-100 rounded-lg bg-white text-base shadow-sm dark:divide-gray-700 dark:bg-gray-800" id="user-dropdown">
|
||||
<div class="px-4 py-3">
|
||||
<span class="block truncate text-sm text-gray-900 dark:text-gray-100">{{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}Utente{{end}}</span>
|
||||
<span class="block truncate text-sm text-gray-500 dark:text-gray-400">{{.CurrentUser.Email}}</span>
|
||||
</div>
|
||||
<div class="py-2">
|
||||
<form action="/logout" method="post" class="px-2">
|
||||
<button type="submit" class="block w-full rounded-lg px-2 py-2 text-left text-sm text-red-700 hover:bg-red-50 dark:text-red-300 dark:hover:bg-red-900/40" data-i18n="nav.logout">Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -1,22 +0,0 @@
|
||||
{{define "content"}}
|
||||
<section class="grid gap-6 md:grid-cols-3">
|
||||
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800 md:col-span-2">
|
||||
<h1 class="mb-2 text-2xl font-bold text-gray-900 dark:text-white">welcome</h1>
|
||||
{{if .CurrentUser}}
|
||||
<p class="text-gray-600 dark:text-gray-300"><span data-i18n="welcome.back_prefix">Bentornato</span> {{if .CurrentUser.Name}}{{.CurrentUser.Name}}{{else}}{{.CurrentUser.Email}}{{end}}.</p>
|
||||
{{else}}
|
||||
<p class="text-gray-600 dark:text-gray-300" data-i18n="welcome.generic">Benvenuto.</p>
|
||||
{{end}}
|
||||
</article>
|
||||
|
||||
<article class="rounded-lg border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-700 dark:bg-gray-800">
|
||||
<h2 class="mb-3 text-lg font-semibold text-gray-900 dark:text-white" data-i18n="welcome.quick_links">Quick Links</h2>
|
||||
<div class="space-y-2">
|
||||
<a href="/welcome" class="block rounded-lg px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700">welcome</a>
|
||||
{{if and .CurrentUser (eq .CurrentUser.Role "admin")}}
|
||||
<a href="/admin/users" class="block rounded-lg px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-i18n="nav.users">Users</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user