Release 2.5.0 (#4454)

- added command to list users
- corrected wrong german translation
- work contract validations
- prevent error with missing params
- use collapsible, minor UI improvement
- added classes to target menu buttons in custom rules
- disable webpack notifier, incompatible with mac arm
- use explicit menu service to generate menu
- bump to fontawesome 6 and replace restart icon
- change repeat icon for recent activities
- moved user bookmarks (favorites) to top nav
- fix totp seconds window (leeway)
- new migration to fix remaining user preferences with dots in name
- remove duplicate named column in user screen
- unify and added translations
- added missing filter and tags to InvoiceSecurity
This commit is contained in:
Kevin Papst
2023-12-01 11:38:17 +01:00
committed by GitHub
parent 16d4a691f8
commit 02bcd45116
72 changed files with 922 additions and 562 deletions

View File

@@ -100,6 +100,7 @@
{% if is_granted('view_own_timesheet') %}
{% include 'partials/recent-activities.html.twig' %}
{% endif %}
{% include 'partials/user-shortcuts.html.twig' %}
{% block navbar_extensions_after %}
{% set event = trigger(constant('App\\Event\\ThemeEvent::TOOLBAR')) %}
{{ event.content|raw }}

View File

@@ -87,56 +87,8 @@
{% endembed %}
{% endif %}
{% if withWorkHourConfiguration %}
{% set expectedWeekTimes = user.workHoursMonday + user.workHoursTuesday + user.workHoursWednesday + user.workHoursThursday + user.workHoursFriday + user.workHoursSaturday + user.workHoursSunday %}
{% embed '@theme/embeds/card.html.twig' with {'collapsed': box_configuration.collapsed} %}
{% from "macros/status.html.twig" import status_duration %}
{% block box_title %}
{{ 'work_times_should'|trans }}
{{ status_duration(expectedWeekTimes|duration) }}
{% endblock %}
{% block box_body %}
<div class="datagrid">
<div class="datagrid-item">
<div class="datagrid-title">{{ 'agendaWeek'|trans }}</div>
<div class="datagrid-content">{{ expectedWeekTimes|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Monday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursMonday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Tuesday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursTuesday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Wednesday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursWednesday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Thursday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursThursday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Friday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursFriday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Saturday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursSaturday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Sunday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursSunday|duration }}</div>
</div>
</div>
{% endblock %}
{% endembed %}
{% endif %}
{% if year is defined %}
{% embed '@theme/embeds/card.html.twig' with {'collapsed': box_configuration.collapsed, 'id': 'working_time_detail_box', 'fullsize': true} %}
{% embed '@theme/embeds/collapsible.html.twig' with {open: not box_configuration.collapsed, id: 'working_time_detail_box', border: false, item: {options: {bodyExtraClass: 'border-top'}, bodyClasses: 'p-0 table-responsive'}} %}
{% set yearShould = 0 %}
{% set yearIs = 0 %}
{% set approved = 0 %}
@@ -154,17 +106,14 @@
{% endfor %}
{% from "macros/widgets.html.twig" import work_times_result, table_actions, card_tool_button, username %}
{% from "macros/status.html.twig" import status_count %}
{% block box_title %}
{% block title %}
{{ 'work_times'|trans }}
{% if withWorkHourConfiguration %}
&nbsp;
{{ status_count(approved ~ '/' ~ year.months|length) }}
{% endif %}
{% endblock %}
{% block box_body_classes %}card-table table-responsive{% endblock %}
{% block box_tools %}
{# {{ card_tool_button('visibility', {'onclick': "toggleDays(); return false;", 'id': 'toggleDaysIcon'}) }} #}
{% endblock %}
{% block box_body %}
{% block body %}
<table id="working_times_details" class="table table-vcenter table-hover dataTable">
<thead>
<tr>
@@ -276,6 +225,51 @@
{% endembed %}
{% endif %}
{% if withWorkHourConfiguration %}
{% set expectedWeekTimes = user.workHoursMonday + user.workHoursTuesday + user.workHoursWednesday + user.workHoursThursday + user.workHoursFriday + user.workHoursSaturday + user.workHoursSunday %}
{% embed '@theme/embeds/collapsible.html.twig' with {open: not box_configuration.collapsed, id: 'work_contract_should_preview', border: false, item: {options: {bodyExtraClass: 'border-top'}}} %}
{% from "macros/status.html.twig" import status_duration %}
{% block title %}
{{ 'work_times_should'|trans }}
&nbsp;
{{ status_duration(expectedWeekTimes|duration) }}
{% endblock %}
{% block body %}
<div class="datagrid">
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Monday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursMonday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Tuesday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursTuesday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Wednesday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursWednesday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Thursday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursThursday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Friday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursFriday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Saturday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursSaturday|duration }}</div>
</div>
<div class="datagrid-item">
<div class="datagrid-title">{{ 'Sunday'|trans({}, 'system-configuration') }}</div>
<div class="datagrid-content">{{ user.workHoursSunday|duration }}</div>
</div>
</div>
{% endblock %}
{% endembed %}
{% endif %}
{% for controller in boxes %}
{{ render(controller(controller, {'year': year, 'boxConfiguration': box_configuration})) }}
{% endfor %}

View File

@@ -277,7 +277,7 @@
{% macro action_button(icon, values, type) %}
{% import '@theme/components/button.html.twig' as macro %}
{% set values = values|merge({'tooltip_attr': 'data-toggle'}) %}
{% set values = (values ?? {})|merge({'tooltip_attr': 'data-toggle'}) %}
{{ macro.button(icon, values, type) }}
{% endmacro %}

View File

@@ -1,11 +1,7 @@
{% if is_granted('start_own_timesheet') %}
{% set class = "btn-outline-white" %}
{% if tabler_bundle.isDarkMode() or tabler_bundle.isNavbarOverlapping() %}
{% set class = "btn-dark" %}
{% endif %}
<div class="nav-item d-flex me-sm-3 me-1">
<a href="{{ path('favorites_timesheets') }}" class="btn btn-icon {{ class}} px-0 remote-modal-load" data-modal-title="{{ 'recent.activities'|trans }}" tabindex="-1" aria-label="{{ 'recent.activities'|trans }}">
{{ icon('repeat') }}
<div class="nav-item d-flex me-1 recent-activities">
<a href="{{ path('favorites_timesheets') }}" class="nav-link px-0 remote-modal-load recent-activities-btn" data-modal-title="{{ 'recent.activities'|trans }}" tabindex="-1" aria-label="{{ 'recent.activities'|trans }}">
{{ icon('repeat', true) }}
</a>
</div>
{% endif %}

View File

@@ -4,7 +4,7 @@
{# fake entry, because at least one html template node is needed #}
{% set active_timesheets = [{'id': '000', 'begin': null, 'activity': {'name': ''}, 'project': {'name': '', 'customer': {'name': ''}}}] %}
{% endif %}
<div class="nav-item d-flex me-sm-3 me-1">
<div class="nav-item d-flex me-1 ticktac">
<div class="btn-list">
{% set class = "btn-outline-white" %}
{% if tabler_bundle.isDarkMode() or tabler_bundle.isNavbarOverlapping() %}

View File

@@ -0,0 +1,36 @@
{% set user_shortcuts = user_shortcuts(app.user) %}
{% if user_shortcuts|length > 0 %}
<div class="nav-item dropdown d-flex me-1 user-shortcuts">
<a class="nav-link px-0 user-shortcuts-toggle" href="javascript:void(0);" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="true">
{{ icon('far fa-bookmark', true) }}
</a>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow dropdown-menu-card" data-bs-popper="static">
<div class="card">
<div class="card-header text-nowrap">{{ 'favorite_routes'|trans }}</div>
<div class="card-body user-shortcuts-list scrollable-container p-0 pb-2">
<div class="row overflow-visible g-0">
{% for menu in user_shortcuts %}
{% if not loop.first and loop.index0 % 2 == 0 %}
</div>
<div class="row overflow-visible g-0">
{% endif %}
<div class="text-center pt-3 px-3 col">
<a href="{{ path(menu.route) }}" class="text-decoration-none">
<span class="user-shortcuts-icon rounded-circle mb-2">
<i class="{{ menu.icon|icon }} fs-2"></i>
</span>
</a>
<a href="{{ path(menu.route) }}" class="nav-link">
{{- menu.label|trans -}}
</a>
</div>
{% endfor %}
{% if user_shortcuts|length > 1 and user_shortcuts|length % 2 == 1 %}
<div class="pt-3 px-3 col"></div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endif %}