feat: driver rename, driver icons, web image + driver search
Driver rename and icons: `Driver.display_name` plus a `DriverIcon` table, both global/shared like the `Driver` row they hang off, so a rename or an icon is what every Owner sees. The rename/icon dialog keeps its forms as siblings (nested forms are invalid HTML) and the icon routes return an `hx-swap-oob` thumbnail refresh rather than re-rendering the table, which would tear the open `<dialog>` out of the DOM. Web image picker: `GET /web/images` renders a pickable grid for a printer or a driver icon, with the search term prefilled from the entity name and editable. Picking one downloads it server-side and normalizes it. Driver download search: `GET /web/drivers` searches for a vendor-wide driver (the term is rewritten into the vendor's real product name for 15 brands) or for the exact model as typed. Links only — nothing is downloaded, and the fragment says the results are unvetted. Icon uploads no longer reject off-size or non-PNG files: `normalize_icon()` letterboxes any decodable raster into a 256x256 PNG. An already-exact 256x256 PNG is returned byte-identical, because icon storage is content-addressed and re-encoding would move the file on every save. `fetch_image()` makes the request from the server, so `assert_fetchable()` refuses any URL resolving to a private, loopback, or link-local address, and re-runs on every redirect. ImpTune sits on the same LAN as the printers it configures; an unguarded fetcher would be a port scanner for anyone who can reach the UI. DuckDuckGo is scraped, not called through an API — no key needed, but fragile, so both search functions swallow parse failures and return [] instead of 500ing a page. `WEB_SEARCH=false` disables every outbound request and hides the controls, for air-gapped installs. Also: one shared `Jinja2Templates` in `templating.py` instead of five per-router instances, so a template global is declared once; `_add_missing_columns()` in `database.py` adds new nullable columns to a pre-existing table, which `create_tables(safe=True)` skips; `db_env` in test_db.py now closes its connection on teardown, or the next test's ORM writes land in the previous test's DB file. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -224,6 +224,35 @@
|
||||
replace_icon: 'Remplacer l’icône',
|
||||
no_icon: 'Aucune icône. Intune affichera l’icône par défaut.',
|
||||
hint_icon: 'PNG, exactement 256 × 256, 750 Ko maximum.',
|
||||
hint_any_image: 'N’importe quelle image — redimensionnée en PNG 256 × 256. 750 Ko maximum.',
|
||||
// Recherche d’images sur le web
|
||||
search_web_image: 'Chercher une image sur le web',
|
||||
search_btn: 'Chercher',
|
||||
searching: 'Recherche…',
|
||||
image_results_for: 'Résultats pour',
|
||||
image_pick_hint: 'Cliquez sur une image : elle est téléchargée puis redimensionnée en PNG 256 × 256.',
|
||||
no_image_results: 'Aucun résultat. Essayez un autre terme.',
|
||||
web_search_off: 'Les recherches web sont désactivées sur ce serveur.',
|
||||
unknown_target: 'Cible de recherche inconnue.',
|
||||
printer_not_found: 'Imprimante introuvable.',
|
||||
driver_not_found: 'Pilote introuvable.',
|
||||
type_to_search_image: 'Saisissez un terme à rechercher.',
|
||||
type_to_search_driver: 'Saisissez une marque ou un modèle d’imprimante.',
|
||||
// Pilotes : renommage et icône
|
||||
edit_driver_title: 'Modifier le pilote',
|
||||
section_driver_name: 'Nom',
|
||||
driver_display_name: 'Nom affiché',
|
||||
hint_driver_rename: 'Visible par tout le monde — la bibliothèque de pilotes est partagée. Laissez vide pour afficher le nom du ZIP.',
|
||||
no_driver_icon: 'Aucune icône.',
|
||||
// Recherche de pilotes sur le web
|
||||
find_driver_online: 'Trouver un pilote en ligne',
|
||||
find_driver_intro: 'Cherchez un pilote universel du constructeur, ou un modèle précis. ImpTune n’affiche que des liens : téléchargez le ZIP puis téléversez-le ci-dessus.',
|
||||
driver_search_label: 'Marque ou modèle d’imprimante',
|
||||
search_generic_btn: 'Chercher le pilote universel',
|
||||
search_exact_btn: 'Chercher le modèle exact',
|
||||
searched_for: 'Recherche effectuée pour',
|
||||
driver_search_warning: 'Résultats web bruts, sans filtrage ni validation. Ne téléchargez un pilote que depuis le site du constructeur, puis téléversez le ZIP ci-dessus.',
|
||||
no_driver_results: 'Aucun résultat. Essayez le nom exact du modèle.',
|
||||
back_to_printers_btn: 'Retour aux imprimantes',
|
||||
export_locked: 'Assignez un pilote à cette imprimante pour débloquer les scripts et l’export.',
|
||||
// Edit modal
|
||||
@@ -410,6 +439,35 @@
|
||||
replace_icon: 'Replace icon',
|
||||
no_icon: 'No icon. Intune will show its default.',
|
||||
hint_icon: 'PNG, exactly 256 × 256, 750 KB max.',
|
||||
hint_any_image: 'Any image — resized to 256 × 256 PNG. 750 KB max.',
|
||||
// Web image search
|
||||
search_web_image: 'Search the web for an image',
|
||||
search_btn: 'Search',
|
||||
searching: 'Searching…',
|
||||
image_results_for: 'Results for',
|
||||
image_pick_hint: 'Click an image — it is downloaded and resized to 256 × 256 PNG.',
|
||||
no_image_results: 'No results. Try another search term.',
|
||||
web_search_off: 'Web lookups are disabled on this server.',
|
||||
unknown_target: 'Unknown search target.',
|
||||
printer_not_found: 'Printer not found.',
|
||||
driver_not_found: 'Driver not found.',
|
||||
type_to_search_image: 'Type something to search for.',
|
||||
type_to_search_driver: 'Type a printer model or brand to search for.',
|
||||
// Driver rename + icon
|
||||
edit_driver_title: 'Edit driver',
|
||||
section_driver_name: 'Name',
|
||||
driver_display_name: 'Display name',
|
||||
hint_driver_rename: 'Shared with everyone — the driver library is global. Leave empty to show the ZIP filename.',
|
||||
no_driver_icon: 'No icon yet.',
|
||||
// Driver web search
|
||||
find_driver_online: 'Find a driver online',
|
||||
find_driver_intro: 'Search for a vendor-wide driver, or for an exact model. ImpTune only shows links — you download the ZIP and upload it above.',
|
||||
driver_search_label: 'Brand or printer model',
|
||||
search_generic_btn: 'Find generic driver',
|
||||
search_exact_btn: 'Search exact model',
|
||||
searched_for: 'Searched for',
|
||||
driver_search_warning: 'Unfiltered web results, not a vetted list. Download drivers only from the manufacturer’s own site, then upload the ZIP above.',
|
||||
no_driver_results: 'No results. Try the exact model name instead.',
|
||||
back_to_printers_btn: 'Back to printers',
|
||||
export_locked: 'Assign a driver to this printer to unlock scripts and export.',
|
||||
// Edit modal
|
||||
|
||||
Reference in New Issue
Block a user