From b84e12f289cbc003288af02c7fbe9fc31e062882 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 24 Sep 2026 18:20:43 +0200 Subject: [PATCH 1/6] Compute colspan of empty lists, drop orphan table end and duplicate type attributes --- templates/default/categories_list.html.twig | 32 ++-- templates/default/list_lent_object.html.twig | 50 +++--- templates/default/objects_list.html.twig | 171 +++++++++---------- templates/default/status_list.html.twig | 48 +++--- 4 files changed, 142 insertions(+), 159 deletions(-) diff --git a/templates/default/categories_list.html.twig b/templates/default/categories_list.html.twig index fdef393..f9ac984 100644 --- a/templates/default/categories_list.html.twig +++ b/templates/default/categories_list.html.twig @@ -9,6 +9,18 @@ {% set nb = nb_categories %} +{% set columns = [ + { + 'label': '#', + 'collapse': true + }, + {'label': _T("Name", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Categories::ORDERBY_NAME')}, + { + 'label': _T("Active", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Categories::ORDERBY_ACTIVITY'), + 'collapse': true + }, +] %} + {% set form = { 'order': { 'name': 'objectslend_categories' @@ -32,27 +44,12 @@ {% endblock %} -{% block header %} - {% set columns = [ - { - 'label': '#', - 'collapse': true - }, - {'label': _T("Name", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Categories::ORDERBY_NAME')}, - { - 'label': _T("Active", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Categories::ORDERBY_ACTIVITY'), - 'collapse': true - }, - ] %} - {{ parent() }} -{% endblock %} - {% block search %}
- +
@@ -148,8 +145,7 @@ {% else %} - {{ _T("No category", "objectslend") }} + {{ _T("No category", "objectslend") }} {% endfor %} - {% endblock %} diff --git a/templates/default/list_lent_object.html.twig b/templates/default/list_lent_object.html.twig index 531e2a1..dab2150 100644 --- a/templates/default/list_lent_object.html.twig +++ b/templates/default/list_lent_object.html.twig @@ -10,33 +10,29 @@ {% set no_action = true %} {% set is_paginated = false %} -{% block infoline %} -{% endblock %} +{% set columns = [ + { + 'label': _T("Id", "objectslend"), + 'collapse': true + }, + {'label': _T("Status", "objectslend")}, + { + 'label': _T("Begin date", "objectslend"), + 'collapse': true + }, + { + 'label': _T("End date", "objectslend"), + 'collapse': true + }, + { + 'label': _T("Return", "objectslend"), + 'collapse': true + }, + {'label': _T("Name", "objectslend")}, + {'label': _T("Comments", "objectslend")}, +] %} -{% block header %} - {% set columns = [ - { - 'label': _T("Id", "objectslend"), - 'collapse': true - }, - {'label': _T("Status", "objectslend")}, - { - 'label': _T("Begin date", "objectslend"), - 'collapse': true - }, - { - 'label': _T("End date", "objectslend"), - 'collapse': true - }, - { - 'label': _T("Return", "objectslend"), - 'collapse': true - }, - {'label': _T("Name", "objectslend")}, - {'label': _T("Comments", "objectslend")}, - ] %} - - {{ parent() }} +{% block infoline %} {% endblock %} {% block body %} @@ -55,7 +51,7 @@ {% else %} - {{ _T("No lend found", "objectslend") }} + {{ _T("No lend found", "objectslend") }} {% endfor %} {% endblock %} diff --git a/templates/default/objects_list.html.twig b/templates/default/objects_list.html.twig index 7c7fd65..cc02004 100644 --- a/templates/default/objects_list.html.twig +++ b/templates/default/objects_list.html.twig @@ -9,6 +9,87 @@ {% set nb = nb_objects %} +{% set columns = [] %} + +{% if login.isAdmin() or login.isStaff() %} + {% set columns = columns|merge([ + { + 'label': '#', + 'collapse': true + }, + ]) %} +{% endif %} + +{% if olendsprefs.imagesInLists() %} + {% set columns = columns|merge([ + { + 'label': _T("Picture"), + 'collapse': true + }, + ]) %} +{% endif %} + +{% set columns = columns|merge([ + {'label': _T("Name", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_NAME")}, +]) %} + +{% if lendsprefs.view_serial %} + {% set columns = columns|merge([ + {'label': _T("Serial", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_SERIAL")}, + ]) %} +{% endif %} + +{% if lendsprefs.view_price %} + {% set columns = columns|merge([ + {'label': _T("Price", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_PRICE")}, + ]) %} +{% endif %} + +{% if lendsprefs.view_lend_price %} + {% set columns = columns|merge([ + {'label': _T("Borrow price", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_RENTPRICE")}, + ]) %} +{% endif %} + +{% if lendsprefs.view_dimension %} + {% set columns = columns|merge([ + {'label': _T("Dimensions", "objectslend")}, + ]) %} +{% endif %} + +{% if lendsprefs.view_weight %} + {% set columns = columns|merge([ + {'label': _T("Weight", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_WEIGHT")}, + ]) %} +{% endif %} + +{% set columns = columns|merge([ + {'label': _T("Status", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_STATUS")}, + { + 'label': _T("Since", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_BDATE"), + 'collapse': true + }, + {'label': _T("By", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_MEMBER")}, +]) %} + +{% if lendsprefs.view_date_forecast %} + {% set columns = columns|merge([ + { + 'label': _T("Return", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_FDATE"), + 'collapse': true + }, + ]) %} +{% endif %} + +{% if login.isAdmin() or login.isStaff() %} + {% set columns = columns|merge([ + { + 'label': _T("Active", "objectslend"), + 'collapse': true + }, + ]) %} +{% endif %} + {% set form = { 'order': { 'name': "objectslend_objects" @@ -40,98 +121,13 @@ {% endif %} {% endblock %} -{% block header %} - {% set columns = [] %} - - {% if login.isAdmin() or login.isStaff() %} - {% set columns = columns|merge([ - { - 'label': '#', - 'collapse': true - }, - ]) %} - {% endif %} - - {% if olendsprefs.imagesInLists() %} - {% set columns = columns|merge([ - { - 'label': _T("Picture"), - 'collapse': true - }, - ]) %} - {% endif %} - - {% set columns = columns|merge([ - {'label': _T("Name", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_NAME")}, - ]) %} - - {% if lendsprefs.view_serial %} - {% set columns = columns|merge([ - {'label': _T("Serial", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_SERIAL")}, - ]) %} - {% endif %} - - {% if lendsprefs.view_price %} - {% set columns = columns|merge([ - {'label': _T("Price", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_PRICE")}, - ]) %} - {% endif %} - - {% if lendsprefs.view_lend_price %} - {% set columns = columns|merge([ - {'label': _T("Borrow price", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_RENTPRICE")}, - ]) %} - {% endif %} - - {% if lendsprefs.view_dimension %} - {% set columns = columns|merge([ - {'label': _T("Dimensions", "objectslend")}, - ]) %} - {% endif %} - - {% if lendsprefs.view_weight %} - {% set columns = columns|merge([ - {'label': _T("Weight", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_WEIGHT")}, - ]) %} - {% endif %} - - {% set columns = columns|merge([ - {'label': _T("Status", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_STATUS")}, - { - 'label': _T("Since", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_BDATE"), - 'collapse': true - }, - {'label': _T("By", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_MEMBER")}, - ]) %} - - {% if lendsprefs.view_date_forecast %} - {% set columns = columns|merge([ - { - 'label': _T("Return", "objectslend"), 'order': constant("GaletteObjectsLend\\Repository\\Objects::ORDERBY_FDATE"), - 'collapse': true - }, - ]) %} - {% endif %} - - {% if login.isAdmin() or login.isStaff() %} - {% set columns = columns|merge([ - { - 'label': _T("Active", "objectslend"), - 'collapse': true - }, - ]) %} - {% endif %} - - {{ parent() }} -{% endblock %} - {% block search %}
- +
@@ -375,9 +371,8 @@ {% else %} - {# FIXME: calculate colspan #} - {{ _T("No object has been found", "objectslend") }} + {{ _T("No object has been found", "objectslend") }} {% endfor %} {% endblock %} diff --git a/templates/default/status_list.html.twig b/templates/default/status_list.html.twig index f557034..33a5df3 100644 --- a/templates/default/status_list.html.twig +++ b/templates/default/status_list.html.twig @@ -8,6 +8,26 @@ {% set nb = nb_status %} +{% set columns = [ + { + 'label': '#', order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_ID'), + 'collapse': true + }, + {'label': _T("Status", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_NAME')}, + { + 'label': _T("Active", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_ACTIVE'), + 'collapse': true + }, + { + 'label': _T("Stock", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_STOCK'), + 'collapse': true + }, + { + 'label': _T("Days for rent", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_RENTDAYS'), + 'collapse': true + } +] %} + {% set form = { 'order': { 'name': "objectslend_statuses" @@ -36,37 +56,13 @@ {% endblock %} -{% block header %} - {% set columns = [ - { - 'label': '#', order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_ID'), - 'collapse': true - }, - {'label': _T("Status", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_NAME')}, - { - 'label': _T("Active", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_ACTIVE'), - 'collapse': true - }, - { - 'label': _T("Stock", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_STOCK'), - 'collapse': true - }, - { - 'label': _T("Days for rent", "objectslend"), order: constant('GaletteObjectsLend\\Repository\\Status::ORDERBY_RENTDAYS'), - 'collapse': true - } - ] %} - - {{ parent() }} -{% endblock %} - {% block search %}
- +
@@ -192,6 +188,6 @@ {% else %} - {{ _T("No status has been found", "objectslend") }} + {{ _T("No status has been found", "objectslend") }} {% endfor %} {% endblock %} From 50c7db67231517d3f163903066f34b738cfda234 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 24 Sep 2026 18:20:50 +0200 Subject: [PATCH 2/6] Share search, active filter and buttons of filter forms --- templates/default/categories_list.html.twig | 41 ++----------- templates/default/macros.twig | 44 ++++++++++++++ templates/default/objects_list.html.twig | 41 ++----------- templates/default/status_list.html.twig | 67 ++------------------- 4 files changed, 58 insertions(+), 135 deletions(-) create mode 100644 templates/default/macros.twig diff --git a/templates/default/categories_list.html.twig b/templates/default/categories_list.html.twig index f9ac984..abc371b 100644 --- a/templates/default/categories_list.html.twig +++ b/templates/default/categories_list.html.twig @@ -6,6 +6,7 @@ {% extends 'elements/list.html.twig' %} {% import "macros.twig" as macros %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% set nb = nb_categories %} @@ -47,44 +48,10 @@ {% block search %}
-
- - -
+ {{ lend.searchField(filters.filter_str) }}
-
-
- -
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- - -
+ {{ lend.triStateFilter('active_filter', 'active', _T("Active:", "objectslend"), filters.active_filter, {dc: constant('GaletteObjectsLend\\Repository\\Categories::ALL_CATEGORIES'), yes: constant('GaletteObjectsLend\\Repository\\Categories::ACTIVE_CATEGORIES'), no: constant('GaletteObjectsLend\\Repository\\Categories::INACTIVE_CATEGORIES')}) }} + {{ lend.filterButtons() }}
diff --git a/templates/default/macros.twig b/templates/default/macros.twig new file mode 100644 index 0000000..b9c7701 --- /dev/null +++ b/templates/default/macros.twig @@ -0,0 +1,44 @@ +{# + # This file is part of Galette Objects Lend plugin (https://galette.eu). + # SPDX-FileCopyrightText: Copyright © 2013-2026 The Galette Team + # SPDX-License-Identifier: GPL-3.0-or-later + #} + +{# Free text search of the filter forms #} +{% macro searchField(value) %} +
+ + +
+{% endmacro %} + +{# "Don't care", "Yes" and "No" radio buttons; values are keyed by dc, yes and no #} +{% macro triStateFilter(name, suffix, label, current, values) %} +
+
+ + {% for key, text in {dc: _T("Don't care"), yes: _T("Yes"), no: _T("No")} %} +
+
+ + +
+
+ {% endfor %} +
+
+{% endmacro %} + +{# Submit and reset buttons of the filter forms #} +{% macro filterButtons(extra_class) %} +
+ + +
+{% endmacro %} diff --git a/templates/default/objects_list.html.twig b/templates/default/objects_list.html.twig index cc02004..2449721 100644 --- a/templates/default/objects_list.html.twig +++ b/templates/default/objects_list.html.twig @@ -6,6 +6,7 @@ {% extends 'elements/list.html.twig' %} {% import "macros.twig" as macros %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% set nb = nb_objects %} @@ -125,10 +126,7 @@
-
- - -
+ {{ lend.searchField(filters.filter_str) }}
- -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- - -
+ {{ lend.triStateFilter('active_filter', 'active', _T("Active:", "objectslend"), filters.active_filter, {dc: constant('GaletteObjectsLend\\Repository\\Objects::ALL_OBJECTS'), yes: constant('GaletteObjectsLend\\Repository\\Objects::ACTIVE_OBJECTS'), no: constant('GaletteObjectsLend\\Repository\\Objects::INACTIVE_OBJECTS')}) }} + {{ lend.filterButtons() }}
diff --git a/templates/default/status_list.html.twig b/templates/default/status_list.html.twig index 33a5df3..8a05132 100644 --- a/templates/default/status_list.html.twig +++ b/templates/default/status_list.html.twig @@ -35,6 +35,7 @@ } %} {% import "macros.twig" as macros %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% block infoline %} {% set infoline = { @@ -59,69 +60,13 @@ {% block search %}
-
-
- - -
-
- -
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
- -
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
+ {{ lend.searchField(filters.filter_str) }} +
+ {{ lend.triStateFilter('active_filter', 'active', _T("Active:", "objectslend"), filters.active_filter, {dc: constant('GaletteObjectsLend\\Repository\\Status::ALL'), yes: constant('GaletteObjectsLend\\Repository\\Status::ACTIVE'), no: constant('GaletteObjectsLend\\Repository\\Status::INACTIVE')}) }} + {{ lend.triStateFilter('stock_filter', 'stock', _T("In stock:", "objectslend"), filters.stock_filter, {dc: constant('GaletteObjectsLend\\Repository\\Status::DC_STOCK'), yes: constant('GaletteObjectsLend\\Repository\\Status::IN_STOCK'), no: constant('GaletteObjectsLend\\Repository\\Status::OUT_STOCK')}) }}
-
- - -
+ {{ lend.filterButtons('sixteen wide') }}
From 6055c47474c46be81878e55d0166236c59f38ea6 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 24 Sep 2026 18:21:54 +0200 Subject: [PATCH 3/6] Share status menus --- templates/default/macros.twig | 21 +++++++++++++++++ templates/default/objects_edit.html.twig | 29 +++--------------------- templates/default/take_object.html.twig | 29 +++--------------------- 3 files changed, 27 insertions(+), 52 deletions(-) diff --git a/templates/default/macros.twig b/templates/default/macros.twig index b9c7701..cb61b50 100644 --- a/templates/default/macros.twig +++ b/templates/default/macros.twig @@ -42,3 +42,24 @@
{% endmacro %} + +{# Status menu; detail adds the rent days ("days") or the stock state ("stock") to each status #} +{% macro statusSelect(id, label, statuses, empty_value, detail) %} + {% set values = {(empty_value): _T("--- Select a status ---", "objectslend")} %} + {% for sta in statuses %} + {% set text = sta.getText() %} + {% if detail == 'days' and sta.getRentDayNumber() %} + {% set text = text ~ ' (' ~ _T("%days days", "objectslend")|replace({'%days': sta.getRentDayNumber()}) ~ ')' %} + {% elseif detail == 'stock' and sta.isInStock() %} + {% set text = text ~ ' (' ~ _T("In stock", "objectslend") ~ ')' %} + {% endif %} + {% set values = values + {(sta.getId()): text} %} + {% endfor %} + + {% include "components/forms/select.html.twig" with { + id: id, + value: '', + values: values, + label: label + } %} +{% endmacro %} diff --git a/templates/default/objects_edit.html.twig b/templates/default/objects_edit.html.twig index 5530a13..4678930 100644 --- a/templates/default/objects_edit.html.twig +++ b/templates/default/objects_edit.html.twig @@ -5,6 +5,7 @@ #} {% extends 'page.html.twig' %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% block content %}
@@ -91,17 +92,7 @@ {% if not object.getId() %} - {% set state_list_values = {(0): _T("--- Select a status ---", "objectslend")} %} - {% for sta in statuses %} - {% set state_list_values = state_list_values + {(sta.getId()): sta.getText()} %} - {% endfor %} - - {% include "components/forms/select.html.twig" with { - id: '1st_status', - value: '', - values: state_list_values, - label: _T("Where is the object?", "objectslend") - } %} + {{ lend.statusSelect('1st_status', _T("Where is the object?", "objectslend"), statuses, 0) }} {% endif %}
@@ -178,21 +169,7 @@
{{ _T("Change status", "objectslend") }}
- {% set state_list_values = {(-1): _T("--- Select a status ---", "objectslend")} %} - {% for sta in statuses %} - {% set text = sta.getText() %} - {% if sta.isInStock() %} - {% set text = text ~ ' (' ~ _T("In stock", "objectslend") ~ ')' %} - {% endif %} - {% set state_list_values = state_list_values + {(sta.getId()): text} %} - {% endfor %} - - {% include "components/forms/select.html.twig" with { - id: 'new_status', - value: '', - values: state_list_values, - label: _T("Status", "objectslend") - } %} + {{ lend.statusSelect('new_status', _T("Status", "objectslend"), statuses, -1, 'stock') }} {% include "components/forms/text.html.twig" with { id: 'new_comment', diff --git a/templates/default/take_object.html.twig b/templates/default/take_object.html.twig index ee12c44..3c488e0 100644 --- a/templates/default/take_object.html.twig +++ b/templates/default/take_object.html.twig @@ -5,6 +5,7 @@ #} {% extends 'page.html.twig' %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% block content %} @@ -103,21 +104,7 @@ {% endif %}
- {% set state_list_values = {(-1): _T("--- Select a status ---", "objectslend")} %} - {% for sta in statuses %} - {% set text = sta.getText() %} - {% if sta.getRentDayNumber() %} - {% set text = text ~ ' (' ~ _T("%days days", "objectslend")|replace({'%days': sta.getRentDayNumber()}) ~ ')' %} - {% endif %} - {% set state_list_values = state_list_values + {(sta.getId()): text} %} - {% endfor %} - - {% include "components/forms/select.html.twig" with { - id: 'status', - value: '', - values: state_list_values, - label: _T("Status:", "objectslend") - } %} + {{ lend.statusSelect('status', _T("Status:", "objectslend"), statuses, -1, 'days') }}
@@ -147,17 +134,7 @@
- {% set state_list_values = {(-1): _T("--- Select a status ---", "objectslend")} %} - {% for sta in statuses %} - {% set state_list_values = state_list_values + {(sta.getId()): sta.getText()} %} - {% endfor %} - - {% include "components/forms/select.html.twig" with { - id: 'status', - value: '', - values: state_list_values, - label: _T("Status:", "objectslend") - } %} + {{ lend.statusSelect('status', _T("Status:", "objectslend"), statuses, -1) }}
From 68a55696a8bee99356806425c4b96fb75d6b5803 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 24 Sep 2026 18:25:57 +0200 Subject: [PATCH 4/6] Move inline javascript to a file, link thumbnails to their full size picture --- templates/default/category_edit.html.twig | 8 +- templates/default/headers.html.twig | 32 ------ templates/default/history_modal.js.twig | 9 +- templates/default/macros.twig | 12 +++ templates/default/objects_edit.html.twig | 7 +- templates/default/objects_list.html.twig | 6 +- templates/default/preferences.html.twig | 14 --- templates/default/scripts.html.twig | 10 ++ templates/default/take_object.html.twig | 123 +--------------------- webroot/objectslend.js | 73 +++++++++++++ 10 files changed, 111 insertions(+), 183 deletions(-) delete mode 100644 templates/default/headers.html.twig create mode 100644 templates/default/scripts.html.twig create mode 100644 webroot/objectslend.js diff --git a/templates/default/category_edit.html.twig b/templates/default/category_edit.html.twig index e56c37b..50f29f6 100644 --- a/templates/default/category_edit.html.twig +++ b/templates/default/category_edit.html.twig @@ -5,6 +5,7 @@ #} {% extends "page.html.twig" %} +{% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% block content %} @@ -35,12 +36,7 @@ max_size: olendsprefs.getUploadSize(), input_id: "picture_file" } %} - {{ _T( + {{ lend.thumbnail("category", category.getId(), picture, olendsprefs, _T("Category photo", "objectslend")) }}
{% if picture.hasPicture() %} {% include "components/forms/checkbox.html.twig" with { diff --git a/templates/default/headers.html.twig b/templates/default/headers.html.twig deleted file mode 100644 index 51ee64a..0000000 --- a/templates/default/headers.html.twig +++ /dev/null @@ -1,32 +0,0 @@ -{# - # This file is part of Galette Objects Lend plugin (https://galette.eu). - # SPDX-FileCopyrightText: Copyright © 2013-2026 The Galette Team - # SPDX-License-Identifier: GPL-3.0-or-later - #} - -{% if olendsprefs is defined %} - -{% endif %} diff --git a/templates/default/history_modal.js.twig b/templates/default/history_modal.js.twig index 1e3f706..5e5bc9e 100644 --- a/templates/default/history_modal.js.twig +++ b/templates/default/history_modal.js.twig @@ -29,7 +29,14 @@ } %} }, error: function(){ - alert("{{ _T("An error occurred loading history display :(", "objectslend")|e("js") }}") + {% include "elements/js/modal.js.twig" with { + modal_title_twig: _T("An error occurred loading history display :(", "objectslend")|e("js"), + modal_without_content: true, + modal_class: "mini", + modal_deny_only: true, + modal_cancel_text: _T("Close")|e("js"), + modal_classname: "redalert", + } %} } }); }); diff --git a/templates/default/macros.twig b/templates/default/macros.twig index cb61b50..03a9fb1 100644 --- a/templates/default/macros.twig +++ b/templates/default/macros.twig @@ -63,3 +63,15 @@ label: label } %} {% endmacro %} + +{# Thumbnail, linked to the full size picture; no id for the default picture #} +{% macro thumbnail(type, id, picture, prefs, alt, extra_class) %} + {% set args = id ? {"type": type, "id": id} : {"type": type} %} + + {{ alt }} + +{% endmacro %} diff --git a/templates/default/objects_edit.html.twig b/templates/default/objects_edit.html.twig index 4678930..5b00158 100644 --- a/templates/default/objects_edit.html.twig +++ b/templates/default/objects_edit.html.twig @@ -128,12 +128,7 @@
- {{ _T( + {{ lend.thumbnail("object", object.getId(), picture, olendsprefs, _T("Object's photo", "objectslend")) }}
{% if picture.hasPicture() %} diff --git a/templates/default/objects_list.html.twig b/templates/default/objects_list.html.twig index 2449721..180ba3c 100644 --- a/templates/default/objects_list.html.twig +++ b/templates/default/objects_list.html.twig @@ -181,11 +181,7 @@ {% endif %} {% if olendsprefs.imagesInLists() %} - {{ _T( + {{ lend.thumbnail("object", object.getId(), object.getPicture(), olendsprefs, _T("Object photo", "objectslend")) }} {% endif %} diff --git a/templates/default/preferences.html.twig b/templates/default/preferences.html.twig index c0c968a..60b466b 100644 --- a/templates/default/preferences.html.twig +++ b/templates/default/preferences.html.twig @@ -173,17 +173,3 @@ {% endif %} {% endblock %} - -{% block javascripts %} - -{% endblock %} diff --git a/templates/default/scripts.html.twig b/templates/default/scripts.html.twig new file mode 100644 index 0000000..fc0fe37 --- /dev/null +++ b/templates/default/scripts.html.twig @@ -0,0 +1,10 @@ +{# + # This file is part of Galette Objects Lend plugin (https://galette.eu). + # SPDX-FileCopyrightText: Copyright © 2013-2026 The Galette Team + # SPDX-License-Identifier: GPL-3.0-or-later + #} + +{# plugin pages only #} +{% if olendsprefs is defined or lendsprefs is defined %} + +{% endif %} diff --git a/templates/default/take_object.html.twig b/templates/default/take_object.html.twig index 3c488e0..da39f6e 100644 --- a/templates/default/take_object.html.twig +++ b/templates/default/take_object.html.twig @@ -8,7 +8,7 @@ {% import "@PluginGaletteObjectslend/macros.twig" as lend %} {% block content %} -
+
@@ -18,11 +18,7 @@
{{ object.getName() }} - {{ _T( + {{ lend.thumbnail("object", object.getId(), object.getPicture(), olendsprefs, _T("Object photo", "objectslend"), "fright") }}
{% if lendsprefs.view_description %} @@ -145,7 +141,8 @@ {% include "components/forms/textarea.html.twig" with { id: 'comments', value: '', - label: _T("Comments:", "objectslend") + label: _T("Comments:", "objectslend"), + maxlength: 200 } %} 200 {{ _T("remaining characters", "objectslend") }}
@@ -183,117 +180,5 @@ {% block javascripts %} {% endblock %} diff --git a/webroot/objectslend.js b/webroot/objectslend.js new file mode 100644 index 0000000..b31766e --- /dev/null +++ b/webroot/objectslend.js @@ -0,0 +1,73 @@ +/** + * This file is part of Galette Objects Lend plugin (https://galette.eu). + * SPDX-FileCopyrightText: Copyright © 2013-2026 The Galette Team + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +/* Thumbnails link to their full size picture; show it in a modal instead of + * leaving the page. + */ +var _lendFullImage = function() { + $(document).on('click', 'a.fullimage', function(e) { + e.preventDefault(); + + var $modal = $(''); + $modal.find('img') + .attr('src', $(this).attr('href')) + .attr('alt', $(this).find('img').attr('alt') || ''); + + $('body').append($modal); + $modal.css('width', 'auto').modal({ + onHidden: function() { + $(this).modal('hide dimmer').remove(); + } + }).modal('show'); + }); +}; + +/* Borrow and return form: it can be submitted once a status, and a member when + * borrowing on behalf of someone, has been chosen. + */ +var _lendTakeForm = function() { + var $form = $('#form_take_object'); + if ($form.length === 0) { + return; + } + + var $submit = $form.find('button[name="valid"]'); + var _validate = function() { + var valid = $('#status').val() !== '-1'; + if ($form.data('mode') === 'take' && $('#id_adh_input').val() === '') { + valid = false; + } + $submit.toggleClass('disabled', !valid); + }; + $form.on('change', _validate); + _validate(); + + var $terms = $('#show_terms_elt').addClass('displaynone'); + $('#show_terms').on('change', function() { + $terms.toggleClass('displaynone', !this.checked); + }); + + var $comments = $('#comments'); + $comments.on('input', function() { + $('#remaining').text($comments.attr('maxlength') - $comments.val().length); + }); +}; + +/* Preferences: contribution fields only matter when a contribution is generated */ +var _lendPreferences = function() { + $('#auto_generate_contribution').on('change', function() { + var generate = $(this).is(':checked'); + $('#generated_contribution_fields').toggleClass('displaynone', !generate) + .find('input[name="pref_objectslend_generated_contribution_type_id"], #contrib_text') + .prop('required', generate); + }); +}; + +$(function() { + _lendFullImage(); + _lendTakeForm(); + _lendPreferences(); +}); From 86b8b702ee295a6bb2d9fd397f3977c64364cbe3 Mon Sep 17 00:00:00 2001 From: Johan Cwiklinski Date: Thu, 24 Sep 2026 18:31:10 +0200 Subject: [PATCH 5/6] Accessibility: name radio groups and row checkboxes, hide decorative icons, no label without a field --- templates/default/categories_list.html.twig | 2 +- templates/default/category_edit.html.twig | 6 +- templates/default/macros.twig | 7 +- templates/default/objects_list.html.twig | 6 +- templates/default/preferences.html.twig | 4 +- templates/default/status_edit.html.twig | 6 +- templates/default/status_list.html.twig | 8 +- templates/default/take_object.html.twig | 145 ++++++++++---------- 8 files changed, 91 insertions(+), 93 deletions(-) diff --git a/templates/default/categories_list.html.twig b/templates/default/categories_list.html.twig index abc371b..62ffe29 100644 --- a/templates/default/categories_list.html.twig +++ b/templates/default/categories_list.html.twig @@ -74,7 +74,7 @@ {{ categ.getName(false) }} - + {% if categ.isActive() %}{{ _T("Active", "objectslend") }}{% else %}{{ _T("Inactive", "objectslend") }}{% endif %} {% if login.isAdmin() or login.isStaff() %} diff --git a/templates/default/category_edit.html.twig b/templates/default/category_edit.html.twig index 50f29f6..9aa0e06 100644 --- a/templates/default/category_edit.html.twig +++ b/templates/default/category_edit.html.twig @@ -10,8 +10,8 @@ {% block content %}
-
- +
+ {{ _T("Category", "objectslend") }}
@@ -53,7 +53,7 @@
diff --git a/templates/default/macros.twig b/templates/default/macros.twig index 03a9fb1..4ede4d7 100644 --- a/templates/default/macros.twig +++ b/templates/default/macros.twig @@ -12,11 +12,12 @@
{% endmacro %} -{# "Don't care", "Yes" and "No" radio buttons; values are keyed by dc, yes and no #} +{# "Don't care", "Yes" and "No" radio buttons; values are keyed by dc, yes and no. + A radio group rather than a fieldset, whose border does not belong in a filter form. #} {% macro triStateFilter(name, suffix, label, current, values) %}
-
- +
+ {% for key, text in {dc: _T("Don't care"), yes: _T("Yes"), no: _T("No")} %}
diff --git a/templates/default/objects_list.html.twig b/templates/default/objects_list.html.twig index 180ba3c..01a3416 100644 --- a/templates/default/objects_list.html.twig +++ b/templates/default/objects_list.html.twig @@ -175,7 +175,8 @@ {% if login.isAdmin() or login.isStaff() %} - + + {% endif %} @@ -242,7 +243,8 @@ + title="{% if object.isActive() %}{{ _T("Object is active", "objectslend") }}{% else %}{{ _T("Object is inactive", "objectslend") }}{% endif %}" + aria-hidden="true"> {% if object.isActive() %}{{ _T("Active", "objectslend") }}{% else %}{{ _T("Inactive", "objectslend") }}{% endif %} diff --git a/templates/default/preferences.html.twig b/templates/default/preferences.html.twig index 60b466b..8e10430 100644 --- a/templates/default/preferences.html.twig +++ b/templates/default/preferences.html.twig @@ -67,7 +67,7 @@