From 4b00697f02346d223de342a4e30f7cfe41c2c793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20B=C3=B6hmer?= Date: Sun, 7 Sep 2025 19:27:02 +0200 Subject: [PATCH] Allow to customize which items get shown on the homepage and in which order This fixes issue #470 and #894 --- .../SystemSettings/CustomizationSettings.php | 27 ++++++++-- src/Settings/SystemSettings/HomepageItems.php | 51 +++++++++++++++++++ templates/homepage.html.twig | 44 +++++++++++----- translations/messages.en.xlf | 12 +++++ 4 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 src/Settings/SystemSettings/HomepageItems.php diff --git a/src/Settings/SystemSettings/CustomizationSettings.php b/src/Settings/SystemSettings/CustomizationSettings.php index d7e92a51..a5f40cdf 100644 --- a/src/Settings/SystemSettings/CustomizationSettings.php +++ b/src/Settings/SystemSettings/CustomizationSettings.php @@ -28,10 +28,13 @@ use App\Form\Type\ThemeChoiceType; use App\Settings\SettingsIcon; use App\Validator\Constraints\ValidTheme; use Jbtronics\SettingsBundle\Metadata\EnvVarMode; +use Jbtronics\SettingsBundle\ParameterTypes\ArrayType; +use Jbtronics\SettingsBundle\ParameterTypes\EnumType; use Jbtronics\SettingsBundle\Settings\Settings; use Jbtronics\SettingsBundle\Settings\SettingsParameter; use Jbtronics\SettingsBundle\Settings\SettingsTrait; use Symfony\Component\Translation\TranslatableMessage as TM; +use Symfony\Component\Validator\Constraints as Assert; #[Settings(name: "customization", label: new TM("settings.system.customization"))] #[SettingsIcon("fa-paint-roller")] @@ -46,6 +49,13 @@ class CustomizationSettings )] public string $instanceName = "Part-DB"; + #[SettingsParameter( + label: new TM("settings.system.customization.theme"), + formType: ThemeChoiceType::class, formOptions: ['placeholder' => false] + )] + #[ValidTheme] + public string $theme = 'bootstrap'; + #[SettingsParameter( label: new TM("settings.system.customization.banner"), formType: RichTextEditorType::class, formOptions: ['mode' => 'markdown-full'], @@ -53,10 +63,17 @@ class CustomizationSettings )] public ?string $banner = null; - #[SettingsParameter( - label: new TM("settings.system.customization.theme"), - formType: ThemeChoiceType::class, formOptions: ['placeholder' => false] + /** + * @var HomepageItems[] The items to show in the sidebar. + */ + #[SettingsParameter(ArrayType::class, + label: new TM("settings.behavior.hompepage.items"), + description: new TM("settings.behavior.homepage.items.help"), + options: ['type' => EnumType::class, 'options' => ['class' => HomepageItems::class]], + formType: \Symfony\Component\Form\Extension\Core\Type\EnumType::class, + formOptions: ['class' => HomepageItems::class, 'multiple' => true, 'ordered' => true] )] - #[ValidTheme] - public string $theme = 'bootstrap'; + #[Assert\NotBlank()] + #[Assert\Unique()] + public array $homepageitems = [HomepageItems::SEARCH, HomepageItems::BANNER, HomepageItems::FIRST_STEPS, HomepageItems::LICENSE, HomepageItems::LAST_ACTIVITY]; } diff --git a/src/Settings/SystemSettings/HomepageItems.php b/src/Settings/SystemSettings/HomepageItems.php new file mode 100644 index 00000000..7366dfa2 --- /dev/null +++ b/src/Settings/SystemSettings/HomepageItems.php @@ -0,0 +1,51 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Settings\SystemSettings; + +use Symfony\Contracts\Translation\TranslatableInterface; +use Symfony\Contracts\Translation\TranslatorInterface; + +use function Symfony\Component\Translation\t; + +enum HomepageItems: string implements TranslatableInterface +{ + case SEARCH = 'search'; + case BANNER = 'banner'; + case LICENSE = 'license'; + case FIRST_STEPS = 'first_steps'; + case LAST_ACTIVITY = 'last_activity'; + + public function trans(TranslatorInterface $translator, ?string $locale = null): string + { + $key = match($this) { + self::SEARCH => 'search.placeholder', + self::BANNER => 'settings.system.customization.banner', + self::LICENSE => 'homepage.license', + self::FIRST_STEPS => 'homepage.first_steps.title', + self::LAST_ACTIVITY => 'homepage.last_activity', + }; + + return $translator->trans($key, locale: $locale); + } +} diff --git a/templates/homepage.html.twig b/templates/homepage.html.twig index 3f820a53..0db7cf17 100644 --- a/templates/homepage.html.twig +++ b/templates/homepage.html.twig @@ -4,18 +4,13 @@ {% import "components/search.macro.html.twig" as search %} {% import "vars.macro.twig" as vars %} -{% block content %} - - {% if is_granted('@system.show_updates') %} - {{ nv.new_version_alert(new_version_available, new_version, new_version_url) }} - {% endif %} - +{% block item_search %} {% if is_granted('@parts.read') %} {{ search.search_form("standalone") }} -
{% endif %} +{% endblock %} - +{% block item_banner %}

{{ vars.partdb_title() }}

@@ -31,9 +26,11 @@

{% endif %} +{% endblock %} +{% block item_first_steps %} {% if show_first_steps %} -
+

{% trans %}homepage.first_steps.title{% endtrans %}

@@ -51,8 +48,10 @@
{% endif %} +{% endblock %} -
+{% block item_license %} +

{% trans %}homepage.license{% endtrans %}

@@ -68,9 +67,11 @@ {% trans %}homepage.forum.caption{% endtrans %}: {% trans with {'%href%': 'https://github.com/Part-DB/Part-DB-server/discussions'}%}homepage.forum.text{% endtrans %}
+{% endblock %} +{% block item_last_activity %} {% if datatable is not null %} -
+
{% trans %}homepage.last_activity{% endtrans %}
{% import "components/history_log_macros.html.twig" as log %} @@ -78,4 +79,23 @@
{% endif %} -{% endblock %} \ No newline at end of file +{% endblock %} + +{% block content %} + + {% if is_granted('@system.show_updates') %} + {{ nv.new_version_alert(new_version_available, new_version, new_version_url) }} + {% endif %} + + {% for item in settings_instance('customization').homepageitems %} + {% if block('item_' ~ item.value) is defined %} + {{ block('item_' ~ item.value) }} +
+ {% else %} + + {% endif %} + {% endfor %} + +{% endblock %} diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index 41ad8358..7e2a816b 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -13441,5 +13441,17 @@ Please note, that you can not impersonate a disabled user. If you try you will g Label profile updated successfully. + + + settings.behavior.hompepage.items + Homepage items + + + + + settings.behavior.homepage.items.help + + +