- Add ~60 new keys to both fr and en translation objects (dashboard, printers_new, printer_list, clients, client_detail, drivers, packages, printer_detail, edit_modal) - Fix test_dashboard_shows_recent_packages to use class-specific empty-state assertion (string now appears in i18n JS dictionary)
342 lines
14 KiB
HTML
342 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en" data-theme="auto">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>ImpTune</title>
|
|
<link rel="stylesheet" href="/static/pico.min.css">
|
|
<link rel="stylesheet" href="/static/app.css">
|
|
<script>
|
|
document.addEventListener('alpine:init', () => {
|
|
// Theme store: cycles Light -> Dark -> System, persists in localStorage
|
|
Alpine.store('theme', {
|
|
current: localStorage.getItem('imptune_theme') || 'auto',
|
|
icons: { light: '☀', dark: '☾', auto: '◑' },
|
|
init() {
|
|
document.documentElement.setAttribute('data-theme', this.current);
|
|
},
|
|
cycle() {
|
|
const order = ['light', 'dark', 'auto'];
|
|
this.current = order[(order.indexOf(this.current) + 1) % order.length];
|
|
localStorage.setItem('imptune_theme', this.current);
|
|
document.documentElement.setAttribute('data-theme', this.current);
|
|
}
|
|
});
|
|
|
|
// i18n store: FR/EN toggle, persists in localStorage
|
|
Alpine.store('i18n', {
|
|
lang: (() => {
|
|
const saved = localStorage.getItem('imptune_lang');
|
|
if (saved) return saved;
|
|
return navigator.language && navigator.language.startsWith('en') ? 'en' : 'fr';
|
|
})(),
|
|
t(key) {
|
|
return (this.translations[this.lang] || {})[key] || key;
|
|
},
|
|
toggle() {
|
|
this.lang = this.lang === 'fr' ? 'en' : 'fr';
|
|
localStorage.setItem('imptune_lang', this.lang);
|
|
},
|
|
translations: {
|
|
fr: {
|
|
dashboard: 'Tableau de bord',
|
|
drivers: 'Pilotes',
|
|
printers: 'Imprimantes',
|
|
clients: 'Clients',
|
|
packages: 'Paquets',
|
|
add_printer: 'Ajouter une imprimante',
|
|
add_client: 'Ajouter un client',
|
|
printer_library: 'Biblioth\u00e8que d\u2019imprimantes',
|
|
edit: 'Modifier',
|
|
delete: 'Supprimer',
|
|
save: 'Enregistrer',
|
|
cancel: 'Annuler',
|
|
upload_driver: 'T\u00e9l\u00e9charger un pilote',
|
|
printer_name: 'Nom de l\u2019imprimante',
|
|
ip_address: 'Adresse IP',
|
|
port_name: 'Nom du port',
|
|
driver: 'Pilote',
|
|
duplex_mode: 'Mode recto-verso',
|
|
one_sided: 'Recto simple',
|
|
long_edge: 'Grand c\u00f4t\u00e9',
|
|
short_edge: 'Petit c\u00f4t\u00e9',
|
|
color_mode: 'Mode couleur',
|
|
paper_size: 'Format papier',
|
|
collate: 'Assembler',
|
|
client: 'Client',
|
|
edit_printer: 'Modifier l\u2019imprimante',
|
|
no_printers: 'Aucune imprimante configur\u00e9e.',
|
|
no_clients: 'Aucun client configur\u00e9.',
|
|
client_list: 'Liste des clients',
|
|
name: 'Nom',
|
|
created: 'Cr\u00e9\u00e9 le',
|
|
back_to_printers: 'Retour aux imprimantes',
|
|
theme_label: 'Th\u00e8me',
|
|
lang_label: 'FR',
|
|
// Dashboard page
|
|
new_printer: 'Nouvelle imprimante',
|
|
upload_driver_btn: 'T\u00e9l\u00e9charger un pilote',
|
|
export_package: 'Exporter un paquet',
|
|
recent_activity: 'Activit\u00e9 r\u00e9cente',
|
|
recent_printers: 'Imprimantes r\u00e9centes',
|
|
recent_packages: 'Paquets r\u00e9cents',
|
|
no_packages: 'Aucun paquet export\u00e9 pour l\u2019instant.',
|
|
// Printers new page
|
|
add_printer_title: 'Ajouter une imprimante',
|
|
back_to_printer_library: '\u2190 Retour \u00e0 la biblioth\u00e8que',
|
|
save_printer: 'Enregistrer l\u2019imprimante',
|
|
upload_new_driver: 'T\u00e9l\u00e9charger un nouveau pilote',
|
|
no_driver_option: '-- Aucun pilote --',
|
|
unassigned_option: '-- Non assign\u00e9 --',
|
|
// Printer list table headers
|
|
th_name: 'Nom',
|
|
th_ip: 'Adresse IP',
|
|
th_port: 'Port',
|
|
th_driver: 'Pilote',
|
|
th_duplex: 'Recto-verso',
|
|
th_color: 'Couleur',
|
|
th_paper: 'Format',
|
|
th_collate: 'Assemblage',
|
|
th_actions: 'Actions',
|
|
yes: 'Oui',
|
|
no: 'Non',
|
|
no_driver_assigned: '\u2014',
|
|
// Clients page
|
|
client_name_label: 'Nom du client',
|
|
add_client_section: 'Ajouter un client',
|
|
client_list_section: 'Liste des clients',
|
|
// Client detail page
|
|
back_to_clients: '\u2190 Tous les clients',
|
|
printers_section: 'Imprimantes',
|
|
// Drivers page
|
|
drivers_title: 'Pilotes',
|
|
upload_driver_section: 'T\u00e9l\u00e9charger un package de pilote',
|
|
driver_library: 'Biblioth\u00e8que de pilotes',
|
|
uploading: 'T\u00e9l\u00e9chargement...',
|
|
upload_btn: 'T\u00e9l\u00e9charger',
|
|
driver_filename: 'Nom du fichier',
|
|
driver_names_col: 'Nom(s) du pilote',
|
|
architecture: 'Architecture',
|
|
uploaded_at: 'T\u00e9l\u00e9charg\u00e9 le',
|
|
unknown: 'Inconnu',
|
|
no_drivers: 'Aucun pilote t\u00e9l\u00e9charg\u00e9.',
|
|
// Packages page
|
|
packages_title: 'Paquets',
|
|
packages_description: 'Imprimantes avec pilotes assign\u00e9s \u2014 pr\u00eates pour l\u2019export.',
|
|
printer_col: 'Imprimante',
|
|
client_col: 'Client',
|
|
driver_col: 'Pilote',
|
|
downloads_col: 'T\u00e9l\u00e9chargements',
|
|
no_packages_ready: 'Aucune imprimante pr\u00eate. Assignez un pilote pour activer l\u2019export.',
|
|
// Printer detail page
|
|
configuration: 'Configuration',
|
|
duplex_mode_label: 'Mode recto-verso',
|
|
color_mode_label: 'Mode couleur',
|
|
color_value: 'Couleur',
|
|
grayscale_value: 'Niveaux de gris',
|
|
paper_size_label: 'Format papier',
|
|
collate_label: 'Assemblage',
|
|
client_label: 'Client',
|
|
unassigned: 'Non assign\u00e9',
|
|
driver_section: 'Pilote',
|
|
package_label: 'Package',
|
|
driver_names_label: 'Nom(s) du pilote',
|
|
architecture_label: 'Architecture',
|
|
no_driver_detail: 'Aucun pilote assign\u00e9',
|
|
intune_commands: 'Commandes Intune',
|
|
install_cmd_label: 'Commande d\u2019installation',
|
|
uninstall_cmd_label: 'Commande de d\u00e9sinstallation',
|
|
copy: 'Copier',
|
|
copied: 'Copi\u00e9\u00a0!',
|
|
scripts_section: 'Scripts',
|
|
download_install: 'T\u00e9l\u00e9charger le script d\u2019installation',
|
|
download_uninstall: 'T\u00e9l\u00e9charger le script de d\u00e9sinstallation',
|
|
download_detect: 'T\u00e9l\u00e9charger le script de d\u00e9tection',
|
|
export_section: 'Export',
|
|
download_ninja: 'T\u00e9l\u00e9charger NinjaRMM ZIP',
|
|
download_intunewin: 'T\u00e9l\u00e9charger .intunewin',
|
|
icon_section: 'Ic\u00f4ne',
|
|
icon_uploaded: 'Ic\u00f4ne t\u00e9l\u00e9charg\u00e9e',
|
|
upload_icon: 'T\u00e9l\u00e9charger l\u2019ic\u00f4ne',
|
|
back_to_printers_btn: 'Retour aux imprimantes',
|
|
// Edit modal
|
|
edit_printer_title: 'Modifier l\u2019imprimante',
|
|
// Driver upload section
|
|
driver_package_label: 'Package de pilote (ZIP contenant .inf + fichiers pilote)'
|
|
},
|
|
en: {
|
|
dashboard: 'Dashboard',
|
|
drivers: 'Drivers',
|
|
printers: 'Printers',
|
|
clients: 'Clients',
|
|
packages: 'Packages',
|
|
add_printer: 'Add Printer',
|
|
add_client: 'Add Client',
|
|
printer_library: 'Printer Library',
|
|
edit: 'Edit',
|
|
delete: 'Delete',
|
|
save: 'Save',
|
|
cancel: 'Cancel',
|
|
upload_driver: 'Upload Driver',
|
|
printer_name: 'Printer Name',
|
|
ip_address: 'IP Address',
|
|
port_name: 'Port Name',
|
|
driver: 'Driver',
|
|
duplex_mode: 'Duplex Mode',
|
|
one_sided: 'One-Sided',
|
|
long_edge: 'Long Edge',
|
|
short_edge: 'Short Edge',
|
|
color_mode: 'Color Mode',
|
|
paper_size: 'Paper Size',
|
|
collate: 'Collate',
|
|
client: 'Client',
|
|
edit_printer: 'Edit Printer',
|
|
no_printers: 'No printers configured yet.',
|
|
no_clients: 'No clients configured yet.',
|
|
client_list: 'Client List',
|
|
name: 'Name',
|
|
created: 'Created',
|
|
back_to_printers: 'Back to Printers',
|
|
theme_label: 'Theme',
|
|
lang_label: 'EN',
|
|
// Dashboard page
|
|
new_printer: 'New Printer',
|
|
upload_driver_btn: 'Upload Driver',
|
|
export_package: 'Export Package',
|
|
recent_activity: 'Recent Activity',
|
|
recent_printers: 'Recent Printers',
|
|
recent_packages: 'Recent Packages',
|
|
no_packages: 'No packages exported yet.',
|
|
// Printers new page
|
|
add_printer_title: 'Add Printer',
|
|
back_to_printer_library: '\u2190 Back to Printer Library',
|
|
save_printer: 'Save Printer',
|
|
upload_new_driver: 'Upload New Driver',
|
|
no_driver_option: '-- No driver --',
|
|
unassigned_option: '-- Unassigned --',
|
|
// Printer list table headers
|
|
th_name: 'Name',
|
|
th_ip: 'IP Address',
|
|
th_port: 'Port',
|
|
th_driver: 'Driver',
|
|
th_duplex: 'Duplex',
|
|
th_color: 'Color',
|
|
th_paper: 'Paper',
|
|
th_collate: 'Collate',
|
|
th_actions: 'Actions',
|
|
yes: 'Yes',
|
|
no: 'No',
|
|
no_driver_assigned: '\u2014',
|
|
// Clients page
|
|
client_name_label: 'Client Name',
|
|
add_client_section: 'Add Client',
|
|
client_list_section: 'Client List',
|
|
// Client detail page
|
|
back_to_clients: '\u2190 All Clients',
|
|
printers_section: 'Printers',
|
|
// Drivers page
|
|
drivers_title: 'Drivers',
|
|
upload_driver_section: 'Upload Driver Package',
|
|
driver_library: 'Driver Library',
|
|
uploading: 'Uploading...',
|
|
upload_btn: 'Upload',
|
|
driver_filename: 'Filename',
|
|
driver_names_col: 'Driver Name(s)',
|
|
architecture: 'Architecture',
|
|
uploaded_at: 'Uploaded',
|
|
unknown: 'Unknown',
|
|
no_drivers: 'No drivers uploaded yet.',
|
|
// Packages page
|
|
packages_title: 'Packages',
|
|
packages_description: 'Printers with drivers assigned \u2014 ready for deployment package export.',
|
|
printer_col: 'Printer',
|
|
client_col: 'Client',
|
|
driver_col: 'Driver',
|
|
downloads_col: 'Downloads',
|
|
no_packages_ready: 'No package-ready printers yet. Assign a driver to a printer to enable package export.',
|
|
// Printer detail page
|
|
configuration: 'Configuration',
|
|
duplex_mode_label: 'Duplex Mode',
|
|
color_mode_label: 'Color Mode',
|
|
color_value: 'Color',
|
|
grayscale_value: 'Grayscale',
|
|
paper_size_label: 'Paper Size',
|
|
collate_label: 'Collate',
|
|
client_label: 'Client',
|
|
unassigned: 'Unassigned',
|
|
driver_section: 'Driver',
|
|
package_label: 'Package',
|
|
driver_names_label: 'Driver Name(s)',
|
|
architecture_label: 'Architecture',
|
|
no_driver_detail: 'No driver assigned',
|
|
intune_commands: 'Intune Commands',
|
|
install_cmd_label: 'Install command',
|
|
uninstall_cmd_label: 'Uninstall command',
|
|
copy: 'Copy',
|
|
copied: 'Copied!',
|
|
scripts_section: 'Scripts',
|
|
download_install: 'Download Install Script',
|
|
download_uninstall: 'Download Uninstall Script',
|
|
download_detect: 'Download Detect Script',
|
|
export_section: 'Export',
|
|
download_ninja: 'Download NinjaRMM ZIP',
|
|
download_intunewin: 'Download .intunewin',
|
|
icon_section: 'Icon',
|
|
icon_uploaded: 'Icon uploaded',
|
|
upload_icon: 'Upload Icon',
|
|
back_to_printers_btn: 'Back to Printers',
|
|
// Edit modal
|
|
edit_printer_title: 'Edit Printer',
|
|
// Driver upload section
|
|
driver_package_label: 'Driver Package (ZIP containing .inf + driver files)'
|
|
}
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
<script defer src="/static/alpine.min.js"></script>
|
|
<script src="/static/htmx.min.js"></script>
|
|
</head>
|
|
<body>
|
|
<div class="layout">
|
|
<nav class="sidebar">
|
|
<div class="sidebar-brand">
|
|
<strong>ImpTune</strong>
|
|
</div>
|
|
<ul class="sidebar-nav">
|
|
<li><a href="/" {% if request.url.path == "/" %}class="active"{% endif %}
|
|
x-data x-text="$store.i18n.t('dashboard')">Dashboard</a></li>
|
|
<li><a href="/drivers" {% if request.url.path == "/drivers" %}class="active"{% endif %}
|
|
x-data x-text="$store.i18n.t('drivers')">Drivers</a></li>
|
|
<li><a href="/printers" {% if request.url.path == "/printers" %}class="active"{% endif %}
|
|
x-data x-text="$store.i18n.t('printers')">Printers</a></li>
|
|
<li><a href="/clients" {% if request.url.path == "/clients" %}class="active"{% endif %}
|
|
x-data x-text="$store.i18n.t('clients')">Clients</a></li>
|
|
<li><a href="/packages" {% if request.url.path == "/packages" %}class="active"{% endif %}
|
|
x-data x-text="$store.i18n.t('packages')">Packages</a></li>
|
|
</ul>
|
|
</nav>
|
|
<div class="main-wrapper">
|
|
<header class="topbar">
|
|
<div class="topbar-controls" x-data>
|
|
<!-- Theme toggle button: cycles Light -> Dark -> System -->
|
|
<button class="secondary outline"
|
|
x-html="$store.theme.icons[$store.theme.current]"
|
|
:aria-label="$store.theme.current"
|
|
@click="$store.theme.cycle()"
|
|
title="Toggle theme">◑</button>
|
|
<!-- Language toggle button -->
|
|
<button class="secondary outline"
|
|
x-text="$store.i18n.t('lang_label')"
|
|
@click="$store.i18n.toggle()"
|
|
title="Toggle language">FR</button>
|
|
</div>
|
|
</header>
|
|
<main class="main-content">
|
|
{% block content %}{% endblock %}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</body>
|
|
</html>
|