eliminato flowbit-ui

This commit is contained in:
fabio 2026-03-01 17:19:23 +01:00
parent b852f656d4
commit a5dda58555
13 changed files with 51 additions and 1439 deletions

1
.gitignore vendored
View File

@ -38,4 +38,3 @@ ui-kit/node_modules/
# Root JS deps # Root JS deps
node_modules/ node_modules/
flowbite-ui/node_modules/

View File

@ -1,16 +1,16 @@
.PHONY: tw-build tw-watch htmx-copy flowbite-copy assets server test db-reset fmt .PHONY: tw-build tw-watch htmx-copy flowbite-copy assets server test db-reset fmt
tw-build: tw-build:
npm --prefix flowbite-ui run tw:build npm run tw:build
tw-watch: tw-watch:
npm --prefix flowbite-ui run tw:watch npm run tw:watch
htmx-copy: htmx-copy:
mkdir -p web/static/vendor && cp flowbite-ui/node_modules/htmx.org/dist/htmx.min.js web/static/vendor/htmx.min.js mkdir -p web/static/vendor && cp node_modules/htmx.org/dist/htmx.min.js web/static/vendor/htmx.min.js
flowbite-copy: flowbite-copy:
mkdir -p web/static/vendor && cp flowbite-ui/node_modules/flowbite/dist/flowbite.min.js web/static/vendor/flowbite.js mkdir -p web/static/vendor && cp node_modules/flowbite/dist/flowbite.min.js web/static/vendor/flowbite.js
assets: htmx-copy flowbite-copy tw-build assets: htmx-copy flowbite-copy tw-build

View File

@ -7,7 +7,7 @@ Boilerplate GoFiber MVC + HTMX + Flowbite + GORM, con auth server-rendered, area
Terminale 1: Terminale 1:
```bash ```bash
npm i --prefix flowbite-ui npm i
make assets make assets
make tw-watch make tw-watch
``` ```
@ -19,7 +19,7 @@ make server
``` ```
`make assets` esegue: `make assets` esegue:
- copia di `flowbite-ui/node_modules/flowbite/dist/flowbite.min.js` in `web/static/vendor/flowbite.js` - copia di `node_modules/flowbite/dist/flowbite.min.js` in `web/static/vendor/flowbite.js`
- build Tailwind in `web/static/css/app.css` - build Tailwind in `web/static/css/app.css`
Dark mode globale: Dark mode globale:
@ -31,7 +31,7 @@ Dark mode globale:
```bash ```bash
cp .env.example .env cp .env.example .env
npm i --prefix flowbite-ui npm i
make assets make assets
make server make server
``` ```
@ -76,7 +76,7 @@ In `develop`, le email vengono salvate in `./data/emails`.
- `make tw-build` -> build Tailwind CSS - `make tw-build` -> build Tailwind CSS
- `make tw-watch` -> watch Tailwind CSS - `make tw-watch` -> watch Tailwind CSS
- `make flowbite-copy` -> copia `flowbite-ui/node_modules/flowbite/dist/flowbite.min.js` in `web/static/vendor/flowbite.js` - `make flowbite-copy` -> copia `node_modules/flowbite/dist/flowbite.min.js` in `web/static/vendor/flowbite.js`
- `make assets` -> `flowbite-copy` + `tw-build` - `make assets` -> `flowbite-copy` + `tw-build`
- `make server` -> `go run ./cmd/server` - `make server` -> `go run ./cmd/server`
- `make test` -> `go test ./...` - `make test` -> `go test ./...`

View File

@ -1 +1,13 @@
@import "../../flowbite-ui/node_modules/tailwindcss/index.css"; @import "tailwindcss";
@layer utilities {
.flag-lang {
width: 32px;
height: 22px;
}
.flag-lang-ch {
width: 22px;
height: 22px;
}
}

BIN
cmd/server/__debug_bin1179590223 Executable file

Binary file not shown.

View File

@ -1,17 +0,0 @@
@config "./tailwind.config.js";
@source "../web/templates/**/*.{html,gohtml}";
@source "../web/static/**/*.js";
@source "./node_modules/flowbite/**/*.js";
@import "tailwindcss";
@layer utilities {
.flag-lang {
width: 32px;
height: 22px;
}
.flag-lang-ch {
width: 22px;
height: 22px;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,8 +3,8 @@
"private": true, "private": true,
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"tw:build": "npx @tailwindcss/cli -i ./input.css -o ../web/static/css/app.css --minify", "tw:build": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --minify",
"tw:watch": "npx @tailwindcss/cli -i ./input.css -o ../web/static/css/app.css --watch" "tw:watch": "npx @tailwindcss/cli -i ./assets/tailwind/input.css -o ./web/static/css/app.css --watch"
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/cli": "^4.1.13", "@tailwindcss/cli": "^4.1.13",

View File

@ -1,8 +1,8 @@
module.exports = { module.exports = {
darkMode: "class", darkMode: "class",
content: [ content: [
"../web/templates/**/*.{html,gohtml}", "./web/templates/**/*.{html,gohtml}",
"../web/static/**/*.js", "./web/static/**/*.js",
"./node_modules/flowbite/**/*.js" "./node_modules/flowbite/**/*.js"
], ],
theme: { extend: {} }, theme: { extend: {} },

View File

@ -17,25 +17,14 @@
</div> </div>
<div style="max-width: 100px;" class="flex-none"> <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> <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>
<div class="relative"> <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">
<input id="users-size-value" type="hidden" name="pageSize" value="{{.PageData.PageSize}}"> <option value="5" {{if eq .PageData.PageSize 5}}selected{{end}}>5</option>
<button id="users-size-button" data-dropdown-toggle="users-size-dropdown" type="button" class="inline-flex w-full items-center justify-between rounded-lg border border-gray-300 bg-gray-50 px-3 py-2.5 text-sm text-gray-900 hover:bg-gray-100 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-600 dark:focus:ring-gray-700"> <option value="10" {{if eq .PageData.PageSize 10}}selected{{end}}>10</option>
<span id="users-size-label">{{.PageData.PageSize}}</span> <option value="20" {{if eq .PageData.PageSize 20}}selected{{end}}>20</option>
<svg class="ms-2 h-2.5 w-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6"> <option value="50" {{if eq .PageData.PageSize 50}}selected{{end}}>50</option>
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4" /> <option value="100" {{if eq .PageData.PageSize 100}}selected{{end}}>100</option>
</svg> <option value="500" {{if eq .PageData.PageSize 500}}selected{{end}}>500</option>
</button> </select>
<div id="users-size-dropdown" class="z-50 mt-1 hidden w-full divide-y divide-gray-100 rounded-lg bg-white shadow-sm dark:divide-gray-600 dark:bg-gray-700">
<ul class="py-1 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="users-size-button">
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="5">5</button></li>
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="10">10</button></li>
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="20">20</button></li>
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="50">50</button></li>
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="100">100</button></li>
<li><button type="button" class="block w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-600" data-page-size-option="500">500</button></li>
</ul>
</div>
</div>
</div> </div>
<div style="max-width: 120px;" class="flex-auto self-end"> <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> <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>

View File

@ -111,16 +111,6 @@
return !!dictionaries[normalizeLang(lang)]; return !!dictionaries[normalizeLang(lang)];
} }
function persistLangPreference(lang) {
if (!IS_AUTHENTICATED) return;
fetch('/preferences/lang', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify({ lang: lang })
}).catch(function () {});
}
function getLang() { function getLang() {
var serverLang = normalizeLang(SERVER_LANG); var serverLang = normalizeLang(SERVER_LANG);
if (IS_AUTHENTICATED && isSupportedLang(serverLang)) { if (IS_AUTHENTICATED && isSupportedLang(serverLang)) {
@ -166,20 +156,9 @@
function applyTranslations(root) { function applyTranslations(root) {
var lang = getLang(); var lang = getLang();
document.documentElement.setAttribute('lang', lang.replace('_', '-')); document.documentElement.setAttribute('lang', lang.replace('_', '-'));
var label = document.getElementById('lang-current'); var langSelect = document.getElementById('lang-select');
var flag = document.getElementById('lang-flag'); var flag = document.getElementById('lang-flag');
if (label) { if (langSelect && langSelect.value !== lang) langSelect.value = lang;
var labels = {
it: 'Italiano',
en: 'English',
en_us: 'English USA',
de: 'Deutsch',
fr: 'Français',
de_ch: 'Deutsch CH',
fr_ch: 'Français CH'
};
label.textContent = labels[lang] || 'Italiano';
}
if (flag) { if (flag) {
var flags = { var flags = {
it: '/static/vendor/flags/it.svg', it: '/static/vendor/flags/it.svg',
@ -219,47 +198,14 @@
}); });
} }
document.querySelectorAll('[data-lang-select]').forEach(function (btn) { var langSelect = document.getElementById('lang-select');
btn.addEventListener('click', function () { if (langSelect) {
var selectedLang = normalizeLang(btn.getAttribute('data-lang-select')); langSelect.addEventListener('change', function () {
var selectedLang = normalizeLang(langSelect.value);
localStorage.setItem(STORAGE_KEY, selectedLang); localStorage.setItem(STORAGE_KEY, selectedLang);
persistLangPreference(selectedLang);
applyTranslations(document); applyTranslations(document);
var dropdownInstance = window.FlowbiteInstances && window.FlowbiteInstances.getInstance });
? window.FlowbiteInstances.getInstance('Dropdown', 'lang-dropdown')
: null;
if (dropdownInstance && typeof dropdownInstance.hide === 'function') {
dropdownInstance.hide();
return;
} }
var langButton = document.getElementById('lang-menu-button');
var langDropdown = document.getElementById('lang-dropdown');
if (langDropdown) langDropdown.classList.add('hidden');
if (langButton) langButton.setAttribute('aria-expanded', 'false');
});
});
document.querySelectorAll('[data-page-size-option]').forEach(function (btn) {
btn.addEventListener('click', function () {
var value = btn.getAttribute('data-page-size-option');
var input = document.getElementById('users-size-value');
var label = document.getElementById('users-size-label');
if (input) input.value = value;
if (label) label.textContent = value;
var dropdownInstance = window.FlowbiteInstances && window.FlowbiteInstances.getInstance
? window.FlowbiteInstances.getInstance('Dropdown', 'users-size-dropdown')
: null;
if (dropdownInstance && typeof dropdownInstance.hide === 'function') {
dropdownInstance.hide();
return;
}
var button = document.getElementById('users-size-button');
var dropdown = document.getElementById('users-size-dropdown');
if (dropdown) dropdown.classList.add('hidden');
if (button) button.setAttribute('aria-expanded', 'false');
});
});
function reinitFlowbiteComponents(target) { function reinitFlowbiteComponents(target) {
if (typeof window.initDropdowns === 'function') window.initDropdowns(); if (typeof window.initDropdowns === 'function') window.initDropdowns();

View File

@ -1,19 +1,14 @@
{{define "language_dropdown"}} {{define "language_dropdown"}}
<div class="relative flex items-center gap-2 text-sm font-small text-gray-7000"> <div class="relative flex items-center gap-2 text-sm">
<img id="lang-flag" class="rounded object-cover dark:outline" src="/static/vendor/flags/it.svg" alt="Italiano" style="width:32px;height:22px;"> <img id="lang-flag" class="rounded object-cover dark:outline" src="/static/vendor/flags/it.svg" alt="Italiano" style="width:32px;height:22px;">
<button id="lang-menu-button" data-dropdown-toggle="lang-dropdown" 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" aria-expanded="false"> <select id="lang-select" name="lang" class="inline-flex h-8 min-w-[95px] items-center rounded-lg bg-white px-3 py-1 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" {{if .CurrentUser}}hx-post="/preferences/lang" hx-trigger="change" hx-swap="none"{{end}}>
<span id="lang-current" class="inline-block min-w-[95px]">Italiano</span> <option value="it">Italiano</option>
</button> <option value="en">English</option>
<div id="lang-dropdown" class="z-50 my-2 hidden w-40 list-none divide-y divide-gray-100 rounded-lg bg-white text-sm shadow-sm dark:divide-gray-700 dark:bg-gray-800"> <option value="en_us">English USA</option>
<ul class="py-1" aria-labelledby="lang-menu-button"> <option value="de">Deutsch</option>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="it"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang rounded-sm object-cover" src="/static/vendor/flags/it.svg" alt=""></div><span class="leading-none">Italiano</span></button></li> <option value="de_ch">Deutsch CH</option>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="en"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang rounded-sm object-cover" src="/static/vendor/flags/en.svg" alt=""></div><span class="leading-none">English</span></button></li> <option value="fr">Français</option>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="en_us"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang rounded-sm object-cover" src="/static/vendor/flags/en_us.svg" alt=""></div><span class="leading-none">English USA</span></button></li> <option value="fr_ch">Français CH</option>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="de"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang rounded-sm object-cover" src="/static/vendor/flags/de.svg" alt=""></div><span class="leading-none">Deutsch</span></button></li> </select>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="de_ch"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang-ch rounded-sm object-cover" src="/static/vendor/flags/ch.svg" alt=""></div><span class="leading-none">Deutsch CH</span></button></li>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="fr"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang rounded-sm object-cover" src="/static/vendor/flags/fr.svg" alt=""></div><span class="leading-none">Français</span></button></li>
<li><button type="button" class="flex w-full items-center gap-2 px-4 py-2 text-left text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-700" data-lang-select="fr_ch"><div class="flex w-8 shrink-0 items-center justify-center"><img class="flag-lang-ch rounded-sm object-cover" src="/static/vendor/flags/ch.svg" alt=""></div><span class="leading-none">Français CH</span></button></li>
</ul>
</div>
</div> </div>
{{end}} {{end}}

View File

@ -4,7 +4,7 @@
<h1 class="mb-1 text-2xl font-bold text-gray-900 dark:text-white" data-i18n="login.title">Login</h1> <h1 class="mb-1 text-2xl font-bold text-gray-900 dark:text-white" data-i18n="login.title">Login</h1>
<p class="mb-6 text-sm text-gray-500 dark:text-gray-400" data-i18n="login.subtitle">Accedi al tuo account.</p> <p class="mb-6 text-sm text-gray-500 dark:text-gray-400" data-i18n="login.subtitle">Accedi al tuo account.</p>
<form hx-post="/login" class="space-y-5"> <form action="/login" method="post" class="space-y-5">
<div> <div>
<label for="email" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white" data-i18n="form.email">Email</label> <label for="email" class="mb-2 block text-sm font-medium text-gray-900 dark:text-white" data-i18n="form.email">Email</label>
<input id="email" type="text" name="email" value="{{.Email}}" 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" required /> <input id="email" type="text" name="email" value="{{.Email}}" 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" required />