mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-12-06 02:59:29 +00:00
Implemented the ability to set user-defined synonyms/labels for internal element types
* Implementiere bevorzugte Sprachauswahl und Datenquellen-Synonyme Die Spracheinstellungen/System-Settings wurden um die Möglichkeit ergänzt, bevorzugte Sprachen für die Dropdown-Menüs festzulegen. Zudem wurde ein Datenquellen-Synonymsystem implementiert, um benutzerfreundlichere Bezeichnungen anzuzeigen und zu personalisieren. * Anpassung aus Analyse * Entferne alten JSON-basierten Datenquellen-Synonym-Handler Die Verwaltung der Datenquellen-Synonyme wurde überarbeitet, um ein flexibleres und strukturiertes Konzept zu ermöglichen. Der bestehende JSON-basierte Ansatz wurde durch eine neue Service-basierte Architektur ersetzt, die eine bessere Handhabung und Erweiterbarkeit erlaubt. * Ermögliche Rückgabe aller möglichen Sprachoptionen in Verbindung mit den vom Nutzer freigeschalteten. * Removed unnecessary service definition The tag is applied via autoconfiguration * Use default translations for the NotBlank constraint * Started refactoring ElementTypeNameGenerator * Made ElementTypeNameGenerator class readonly * Modified form to work properly with new datastructure * Made the form more beautiful and space saving * Made synonym form even more space saving * Allow to define overrides for any element label there is * Use defined synonyms in ElementTypeNameGenerator * Use ElementTypeNameGenerator where possible * Register synonyms for element types as global translation parameters * Revert changes done to permission layout * Use new synonym system for admin page titles * Removed now unnecessary services * Reworked settings name and translation * Renamed all files to Synonyms * Removed unnecessary translations * Removed unnecessary translations * Fixed duplicate check * Renamed synoynms translations * Use our synonyms for permission translations * Fixed phpstan issue * Added tests --------- Co-authored-by: Marcel Diegelmann <marcel.diegelmann@gmail.com> Co-authored-by: Jan Böhmer <mail@jan-boehmer.de>
This commit is contained in:
parent
5e3bd26e27
commit
54f318ecac
43 changed files with 1504 additions and 335 deletions
|
|
@ -15,4 +15,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}attachment_type.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-tags fa-fw"></i> {% trans %}category.labelp{% endtrans %}
|
||||
<i class="fas fa-tags fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_pills %}
|
||||
|
|
@ -61,4 +61,4 @@
|
|||
</div>
|
||||
{{ form_row(form.eda_info.kicad_symbol) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{% import "vars.macro.twig" as vars %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fa-solid fa-coins"></i> {% trans %}currency.caption{% endtrans %}
|
||||
<i class="fa-solid fa-coins"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_controls %}
|
||||
|
|
@ -41,4 +41,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}currency.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-microchip fa-fw"></i> {% trans %}footprint.labelp{% endtrans %}
|
||||
<i class="fas fa-microchip fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block master_picture_block %}
|
||||
|
|
@ -34,4 +34,4 @@
|
|||
</div>
|
||||
{{ form_row(form.eda_info.kicad_footprint) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-users fa-fw"></i> {% trans %}group.edit.caption{% endtrans %}
|
||||
<i class="fas fa-users fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
|
@ -27,4 +27,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}group.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-qrcode fa-fw"></i> {% trans %}label_profile.caption{% endtrans %}
|
||||
<i class="fas fa-qrcode fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_pills %}
|
||||
|
|
@ -58,4 +58,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}label_profile.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_company_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-industry fa-fw"></i> {% trans %}manufacturer.caption{% endtrans %}
|
||||
<i class="fas fa-industry fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_title %}
|
||||
|
|
@ -10,4 +10,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}manufacturer.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-balance-scale fa-fw"></i> {% trans %}measurement_unit.caption{% endtrans %}
|
||||
<i class="fas fa-balance-scale fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_title %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-balance-scale fa-tools"></i> {% trans %}part_custom_state.caption{% endtrans %}
|
||||
<i class="fas fa-balance-scale fa-tools"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_title %}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
{# @var entity App\Entity\ProjectSystem\Project #}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-archive fa-fw"></i> {% trans %}project.caption{% endtrans %}
|
||||
<i class="fas fa-archive fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block edit_title %}
|
||||
|
|
@ -59,4 +59,4 @@
|
|||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{% import "label_system/dropdown_macro.html.twig" as dropdown %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-cube fa-fw"></i> {% trans %}storelocation.labelp{% endtrans %}
|
||||
<i class="fas fa-cube fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_controls %}
|
||||
|
|
@ -38,4 +38,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}storelocation.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{% extends "admin/base_company_admin.html.twig" %}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-truck fa-fw"></i> {% trans %}supplier.caption{% endtrans %}
|
||||
<i class="fas fa-truck fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_panes %}
|
||||
|
|
@ -19,4 +19,4 @@
|
|||
|
||||
{% block new_title %}
|
||||
{% trans %}supplier.new{% endtrans %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
{# @var entity \App\Entity\UserSystem\User #}
|
||||
|
||||
{% block card_title %}
|
||||
<i class="fas fa-user fa-fw"></i> {% trans %}user.edit.caption{% endtrans %}
|
||||
<i class="fas fa-user fa-fw"></i> {{ type_label_p(entity) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block comment %}{% endblock %}
|
||||
|
|
@ -111,4 +111,4 @@
|
|||
|
||||
{% block preview_picture %}
|
||||
<img src="{{ avatar_helper.avatarURL(entity) }}" style="height: 50px;">
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
{% macro sidebar_dropdown() %}
|
||||
{% set currentLocale = app.request.locale %}
|
||||
|
||||
{# Format is [mode, route, label, show_condition] #}
|
||||
{% set data_sources = [
|
||||
['categories', path('tree_category_root'), 'category.labelp', is_granted('@categories.read') and is_granted('@parts.read')],
|
||||
['locations', path('tree_location_root'), 'storelocation.labelp', is_granted('@storelocations.read') and is_granted('@parts.read')],
|
||||
['footprints', path('tree_footprint_root'), 'footprint.labelp', is_granted('@footprints.read') and is_granted('@parts.read')],
|
||||
['manufacturers', path('tree_manufacturer_root'), 'manufacturer.labelp', is_granted('@manufacturers.read') and is_granted('@parts.read')],
|
||||
['suppliers', path('tree_supplier_root'), 'supplier.labelp', is_granted('@suppliers.read') and is_granted('@parts.read')],
|
||||
['projects', path('tree_device_root'), 'project.labelp', is_granted('@projects.read')],
|
||||
['tools', path('tree_tools'), 'tools.label', true],
|
||||
['categories', path('tree_category_root'), '@category@@', is_granted('@categories.read') and is_granted('@parts.read')],
|
||||
['locations', path('tree_location_root'), '@storage_location@@', is_granted('@storelocations.read') and is_granted('@parts.read'), ],
|
||||
['footprints', path('tree_footprint_root'), '@footprint@@', is_granted('@footprints.read') and is_granted('@parts.read')],
|
||||
['manufacturers', path('tree_manufacturer_root'), '@manufacturer@@', is_granted('@manufacturers.read') and is_granted('@parts.read'), 'manufacturer'],
|
||||
['suppliers', path('tree_supplier_root'), '@supplier@@', is_granted('@suppliers.read') and is_granted('@parts.read'), 'supplier'],
|
||||
['projects', path('tree_device_root'), '@project@@', is_granted('@projects.read'), 'project'],
|
||||
['tools', path('tree_tools'), 'tools.label', true, 'tool'],
|
||||
] %}
|
||||
|
||||
<li class="dropdown-header">{% trans %}actions{% endtrans %}</li>
|
||||
|
|
@ -18,9 +20,20 @@
|
|||
|
||||
{% for source in data_sources %}
|
||||
{% if source[3] %} {# show_condition #}
|
||||
<li><button class="tree-btns dropdown-item" data-mode="{{ source[0] }}" data-url="{{ source[1] }}" data-text="{{ source[2] | trans }}"
|
||||
{{ stimulus_action('elements/sidebar_tree', 'changeDataSource') }}
|
||||
>{{ source[2] | trans }}</button></li>
|
||||
<li>
|
||||
{% if source[2] starts with '@' %}
|
||||
{% set label = type_label_p(source[2]|replace({'@': ''})) %}
|
||||
{% else %}
|
||||
{% set label = source[2]|trans %}
|
||||
{% endif %}
|
||||
|
||||
<button class="tree-btns dropdown-item"
|
||||
data-mode="{{ source[0] }}"
|
||||
data-url="{{ source[1] }}"
|
||||
data-text="{{ label }}"
|
||||
{{ stimulus_action('elements/sidebar_tree', 'changeDataSource') }}
|
||||
>{{ label }}</button>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
|
@ -61,4 +74,4 @@
|
|||
|
||||
<div class="treeview-sm mt-2" {{ stimulus_target('elements/tree', 'tree') }}></div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% endmacro %}
|
||||
|
|
|
|||
59
templates/form/synonyms_collection.html.twig
Normal file
59
templates/form/synonyms_collection.html.twig
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{% macro renderForm(child) %}
|
||||
<div class="tc-item mt-1 px-2 pb-1 border-bottom">
|
||||
{% form_theme child "form/vertical_bootstrap_layout.html.twig" %}
|
||||
<div class="row">
|
||||
<div class="col">{{ form_row(child.dataSource) }}</div>
|
||||
<div class="col">{{ form_row(child.locale) }}</div>
|
||||
<div class="col">{{ form_row(child.translation_singular) }}</div>
|
||||
<div class="col">{{ form_row(child.translation_plural) }}</div>
|
||||
<div class="col">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm tc-remove" {{ stimulus_action('pages/synonyms_collection', 'remove' )}}>
|
||||
<i class="fa fa-trash"></i> {{ 'settings.synonyms.type_synonym.remove_entry'|trans }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% block type_synonyms_collection_widget %}
|
||||
{% set _attrs = attr|default({}) %}
|
||||
{% set _attrs = _attrs|merge({
|
||||
class: (_attrs.class|default('') ~ ' type_synonyms_collection-widget')|trim
|
||||
}) %}
|
||||
|
||||
{% set has_proto = prototype is defined %}
|
||||
{% if has_proto %}
|
||||
{% set __proto %}
|
||||
{{- _self.renderForm(prototype) -}}
|
||||
{% endset %}
|
||||
{% set _proto_html = __proto|e('html_attr') %}
|
||||
{% set _proto_name = form.vars.prototype_name|default('__name__') %}
|
||||
{% set _index = form|length %}
|
||||
{% endif %}
|
||||
|
||||
<div
|
||||
{{ stimulus_controller('pages/synonyms_collection', {
|
||||
prototype: has_proto ? _proto_html : '',
|
||||
prototypeName: has_proto ? _proto_name : '__name__',
|
||||
index: has_proto ? _index : (form|length)
|
||||
}) }}
|
||||
{{ block('widget_container_attributes')|raw }}{% for k,v in _attrs %} {{ k }}="{{ v }}"{% endfor %}
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col text-center"><strong>{% trans%}settings.synonyms.type_synonym.type{% endtrans%}</strong></div>
|
||||
<div class="col text-center"><strong>{% trans%}settings.synonyms.type_synonym.language{% endtrans%}</strong></div>
|
||||
<div class="col text-center"><strong>{% trans%}settings.synonyms.type_synonym.translation_singular{% endtrans%}</strong></div>
|
||||
<div class="col text-center"><strong>{% trans%}settings.synonyms.type_synonym.translation_plural{% endtrans%}</strong></div>
|
||||
<div class="col text-center"></div>
|
||||
</div>
|
||||
|
||||
<div class="tc-items" {{ stimulus_target('pages/synonyms_collection', 'items') }}>
|
||||
{% for child in form %}
|
||||
{{ _self.renderForm(child) }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm mt-2 tc-add" {{ stimulus_action('pages/synonyms_collection', 'add')}}>
|
||||
<i class="fa fa-plus"></i> {{ 'settings.synonyms.type_synonym.add_entry'|trans }}
|
||||
</button>
|
||||
</div>
|
||||
{% endblock %}
|
||||
26
templates/form/vertical_bootstrap_layout.html.twig
Normal file
26
templates/form/vertical_bootstrap_layout.html.twig
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
{% extends 'bootstrap_5_layout.html.twig' %}
|
||||
|
||||
|
||||
{%- block choice_widget_collapsed -%}
|
||||
{# Only add the BS5 form-select class if we dont use bootstrap-selectpicker #}
|
||||
{# {% if attr["data-controller"] is defined and attr["data-controller"] not in ["elements--selectpicker"] %}
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%}
|
||||
{% else %}
|
||||
{# If it is an selectpicker add form-control class to fill whole width
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%}
|
||||
{% endif %}
|
||||
#}
|
||||
|
||||
{%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-select')|trim}) -%}
|
||||
|
||||
{# If no data-controller was explictly defined add data-controller=elements--select #}
|
||||
{% if attr["data-controller"] is not defined %}
|
||||
{%- set attr = attr|merge({"data-controller": "elements--select"}) -%}
|
||||
|
||||
{% if attr["data-empty-message"] is not defined %}
|
||||
{%- set attr = attr|merge({"data-empty-message": ("selectpicker.nothing_selected"|trans)}) -%}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{- block("choice_widget_collapsed", "bootstrap_base_layout.html.twig") -}}
|
||||
{%- endblock choice_widget_collapsed -%}
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
{% for section_widget in tab_widget %}
|
||||
{% set settings_object = section_widget.vars.value %}
|
||||
|
||||
{% if section_widget.vars.compound ?? false %}
|
||||
{% if section_widget.vars.embedded_settings_metadata is defined %} {# Check if we have nested embedded settings or not #}
|
||||
<fieldset>
|
||||
<legend class="offset-3">
|
||||
<i class="fa-solid {{ settings_icon(settings_object)|default('fa-sliders') }} fa-fw"></i>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue