Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)

This commit is contained in:
Kevin Papst
2022-12-31 21:19:55 +01:00
committed by GitHub
parent 95e06746bd
commit 90a0fd8a22
2164 changed files with 83700 additions and 86426 deletions

View File

@@ -1,29 +1,55 @@
{% macro icon(icon) %}
<i class="{{ icon|icon(icon) }}"></i>
{% endmacro %}
{%- macro page_actions(tools) -%}
<div class="breadcrumb">
<div class="box-tools">
{{ _self.button_group(tools) }}
</div>
</div>
{%- endmacro -%}
{%- macro entity_actions(tools) -%}
<div class="breadcrumb">
<div class="box-tools">
<div class="btn-group">
{% set actions = {} %}
{%- for icon, values in tools %}
{% if icon == 'back' %}
{{ _self.action_button(icon, values) }}
{%- macro page_actions(actions) -%}
{% set large = true %}
{% set btnClasses = 'btn-primary' %}
{% set helpClasses = '' %}
{% if tabler_bundle.isNavbarOverlapping() %}
{% set helpClasses = 'btn-dark' %}
{% elseif not tabler_bundle.isDarkMode() %}
{% set btnClasses = 'btn-white' %}
{% endif %}
{% set later = {} %}
{% set help = null %}
<div class="page-actions">
<div class="pa-desktop d-none d-sm-inline-flex btn-list">
{%- apply spaceless -%}
{%- for icon, values in actions %}
{% if 'help' in icon %}
{% set help = values %}
{% elseif 'divider' in icon and values is null %}
{# what to do here ? #}
{% else %}
{% set actions = actions|merge({(icon): values}) %}
{% if values.children is defined and values.children|length > 0 %}
<div class="dropdown">
<button type="button" class="btn {{ btnClasses}} dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ icon(icon, true) }}{% if large %} {{ values.title is defined ? values.title|trans : icon|trans({}, 'actions') }}{% endif %}
</button>
<div class="dropdown-menu">
{%- for icon, values in values.children %}
{% set values = values|merge({class: 'dropdown-item action-' ~ icon ~ ' ' ~ (values.class|default(''))}) %}
{{ _self.action_button(false, values, false) }}
{% endfor %}
</div>
</div>
{% else %}
{% set values = values|merge({combined: large, class: btnClasses ~ ' action-' ~ icon ~ ' ' ~ (values.class|default(''))}) %}
{{ _self.action_button(icon, values) }}
{% endif %}
{% endif %}
{% endfor %}
{{ _self.table_actions(actions, '') }}
</div>
{% endfor -%}
{% endapply %}
{% if help is not null %}
{% set help = help|merge({class: helpClasses ~ ' action-help ' ~ (help.class|default(''))}) %}
{{ _self.action_button('help', help) }}
{% endif %}
</div>
<div class="pa-mobile d-inline-flex d-sm-none btn-list">
{% set btnClass = 'btn btn-icon ' %}
{% if tabler_bundle.isNavbarOverlapping() %}
{% set btnClass = 'btn btn-icon btn-dark' %}
{% elseif not tabler_bundle.isDarkMode() %}
{% set btnClass = 'btn btn-icon btn-white' %}
{% endif %}
{{ _self.table_actions(actions, btnClass) }}
</div>
</div>
{%- endmacro -%}
@@ -70,35 +96,43 @@
{{ _self.label_color(team.name, team.color|colorize(team.name)) }}
{% endmacro %}
{% macro user_avatar(user, tooltip, class) %}
{% macro user_avatar(user, tooltip, class, badge) %}
{% set avatar = null %}
{% if user.avatar is not empty and kimai_config.themeAllowAvatarUrls %}
{% set avatar = asset(user.avatar, 'avatars') %}
{% if tooltip is same as (false) %}
<img src="{{ avatar }}" class="img-circle avatar{% if class is not empty %} {{ class }}{% endif %}" alt="{{ user.displayName }}" />
{% else %}
<img src="{{ avatar }}" class="img-circle avatar{% if class is not empty %} {{ class }}{% endif %}" alt="{{ user.displayName }}" data-toggle="tooltip" data-placement="top" title="{{ tooltip|default(user.displayName) }}" />
{% endif %}
{% else %}
{% set color = user.color|colorize(user.displayName) %}
<span class="avatar {{ class }}" style="background-color: {{ color }}; color: {{ color|font_contrast }}"
{%- if tooltip is not same as (false) %} data-toggle="tooltip" data-placement="top" title="{{ tooltip|default(user.displayName) }}"{% endif -%}>
<span class="initials">{{ user.initials }}</span>
</span>
{% endif %}
{% if not user.enabled %}
{% set badge = 'danger' %}
{% endif %}
{% set color = user.color|colorize(user.displayName) %}
<span class="avatar {{ class }}"
{%- if tooltip is not same as (false) %} data-toggle="tooltip" data-placement="top" title="{{ tooltip|default(user.displayName) }}"{% endif -%}
{% if avatar is not null %}
style="background-image: url({{ avatar }})">&nbsp;
{% else %}
style="background-color: {{ color }}; color: {{ color|font_contrast }}">{{ user.initials }}
{% endif %}
{%- if badge is not null -%}<span class="badge bg-{{ badge }}"></span>{%-endif -%}
</span>
{% endmacro %}
{% macro avatar(initials, color, tooltip, class) %}
{% set color = color|colorize(initials) %}
<span class="avatar {{ class ?? '' }}" style="background-color: {{ color }}; color: {{ color|font_contrast }}"
{%- if tooltip is not same as null %} data-toggle="tooltip" data-placement="top" title="{{ tooltip }}"{% endif -%}>{{ initials }}</span>
{% endmacro %}
{#
options = {'inherit': true, 'random': false}
options = {'inherit': true}
#}
{% macro label_activity(activity, options) %}
{% set inherit = options.inherit ?? true %}
{% set random = options.random ?? false %}
{% set isVisible = activity.visible %}
{% set color = activity.color %}
{% if color is empty and inherit and activity.project is not null %}
{% set color = activity.project.color ?? activity.project.customer.color %}
{% endif %}
{% if color is empty and random %}
{% if color is empty %}
{% set color = color|colorize(activity.name) %}
{% endif %}
{% if isVisible and not activity.project is null %}
@@ -111,11 +145,10 @@
{% endmacro %}
{#
options = {'inherit': true, 'random': false}
options = {'inherit': true}
#}
{% macro label_project(project, options) %}
{% set inherit = options.inherit ?? true %}
{% set random = options.random ?? false %}
{% set isVisible = false %}
{% if project.visible and project.customer.visible %}
{% set isVisible = true %}
@@ -124,19 +157,15 @@
{% if color is empty and inherit %}
{% set color = project.customer.color %}
{% endif %}
{% if color is empty and random %}
{% if color is empty %}
{% set color = color|colorize(project.name) %}
{% endif %}
{{ _self.label_color_dot('project', isVisible, project.name, null, color) }}
{% endmacro %}
{#
options = {'random': false}
#}
{% macro label_customer(customer, options) %}
{% set random = options.random ?? false %}
{% macro label_customer(customer) %}
{% set color = customer.color %}
{% if color is empty and random %}
{% if color is empty %}
{% set color = color|colorize(customer.name) %}
{% endif %}
{{ _self.label_color_dot('customer', customer.visible, customer.name, null, color) }}
@@ -155,27 +184,15 @@
{# for @internal use only #}
{% macro label_color_dot(type, isVisible, name, url, color) %}
{% apply spaceless %}
<span class="label-{{ type }}{{ isVisible is same as (false) ? ' label-invisible' : '' }}">
<span class="name">
<i class="dot {{ 'dot'|icon }} fa-fw"{% if color is not empty %} style="color:{{ color }}"{% endif %}></i>
<span class="name-inner">
{%- if url is not empty -%}
<a href="{{ url }}">{{ name }}</a>
{%- else -%}
{{ name }}
{%- endif -%}
</span>
</span>
{%- if url is not empty -%}<a href="{{ url }}">{% endif %}
<span class="pe-1 label-{{ type }}{{ isVisible is same as (false) ? ' label-invisible' : '' }}">
<span class="badge me-1" {% if color is not empty %} style="background-color:{{ color }}"{% endif %}></span>
{{- name -}}
</span>
{%- if url is not empty -%}</a>{% endif %}
{% endapply %}
{% endmacro %}
{% macro color_dot(color, tooltip) %}
<span class="label-color" data-toggle="tooltip" data-placement="top" title="{{ tooltip }}">
<i class="dot {{ 'dot'|icon }} fa-fw"{% if color is not empty %} style="color:{{ color }}"{% endif %}></i>
</span>
{% endmacro %}
{% macro badge_team_access(teams) %}
{% if teams|length > 0 %}
{{ _self.badge_counter(teams|length) }}
@@ -193,268 +210,63 @@
{% endmacro %}
{% macro label(title, type, tooltip) %}
<span {% if tooltip %}data-toggle="tooltip" data-placement="top" title="{{ tooltip }}" {% endif %}class="label label-{{ type|default('success') }}">{{ title }}</span>
<span {% if tooltip %}data-toggle="tooltip" data-placement="top" title="{{ tooltip }}" {% endif %}class="badge bg-{{ type|default('success') }}">{{ title }}</span>
{% endmacro %}
{% macro label_color(title, color) %}
<span class="label" style="background-color: {{ color|default_color }};color: {{ color|default_color|font_contrast }}">{{ title }}</span>
<span class="badge" style="background-color: {{ color|default_color }};color: {{ color|default_color|font_contrast }}">{{ title }}</span>
{% endmacro %}
{% macro badge(title, color) %}
<span class="badge"{% if color is not null %} style="background-color:{{ color }}; color:{{ color|font_contrast }}"{% endif %}>{{ title }}</span>
{% endmacro %}
{% macro alert(type, description, title, icon) %}
<div class="alert alert-{{ type|default('danger') }} alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
{% if title and icon %}
<h4><i class="icon {{ icon|icon(icon) }}"></i> {{ title|trans }}</h4>
{{ description|trans }}
{% elseif icon %}
<i class="icon {{ icon|icon(icon) }}"></i> {{ description|trans }}
{% else %}
{{ description|trans }}
{% macro form_errors(form) %}
{% if form.vars.errors|length > 0 %}
{% set message = '' %}
{% for error in form.vars.errors %}
{% set message = message ~ error.message %}
{% if not loop.last %}
{% set message = message ~ '<br>' %}
{% endif %}
{% endfor %}
{% if message != '' %}
{{ _self.alert('danger', message) }}
{% endif %}
</div>
{% endif %}
{% endmacro %}
{% macro alert(type, description, title, icon, dismissible) %}
{% from '@theme/components/alert.html.twig' import alert %}
{{ alert({type: type, description: description|trans, title: title|trans, icon: icon, dismissible: dismissible}) }}
{% endmacro %}
{% macro callout(type, description, title, icon) %}
<div class="callout callout-{{ type|default('danger') }} lead">
{% if title %}<h4>{% if icon %}<i class="{{ icon|icon(icon) }}">{% endif %}</i> {{ title|trans }}</h4>{% endif %}
<p>{{ description|trans }}</p>
</div>
{% endmacro %}
{% macro info_box_progress(title, description, amount, percentage, icon, color) %}
<div class="info-box bg-{{ color }}">
<span class="info-box-icon"><i class="{{ icon|icon(icon) }}"></i></span>
<div class="info-box-content">
<span class="info-box-text">{{ title|trans }}</span>
<span class="info-box-number">{{ amount }}</span>
<div class="progress">
<div class="progress-bar" style="width: {{ percentage }}%"></div>
</div>
<span class="progress-description">
{{ description }}
</span>
</div>
<!-- /.info-box-content -->
</div>
{% endmacro %}
{% macro button_group_dropdown(title, actions) %}
<div class="btn-group">
<button type="button" class="btn btn-default">{{ title|trans }}</button>
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="caret"></span>
<span class="sr-only">{{ 'label.toggle_dropdown'|trans }}</span>
</button>
<ul class="dropdown-menu" role="menu">
{% for url, entry in actions %}
<li><a href="{{ url }}">{{ entry|trans }}</a></li>
{% endfor %}
</ul>
</div>
{% from '@theme/components/alert.html.twig' import alert %}
{{ alert({type: type|default('danger'), description: description|trans, title: title|trans, icon: icon, dismissible: false, important: true}) }}
{% endmacro %}
{% macro table_actions(actions, class) %}
{% if actions|length >= 1 %}
{% if class is null %}
{% set class = 'btn-sm' %}
{% endif %}
{% set trash = null %}
{% set divider = false %}
<div class="btn-group dropdown">
<button type="button" class="btn btn-default {{ class }} dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
<span class="fa fa-chevron-down"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
{%- apply spaceless -%}
{%- for icon,values in actions %}
{% if 'divider' in icon and values is null %}
{% if not loop.last and divider is same as (false) %}
<li class="divider"></li>
{% endif %}
{% set divider = true %}
{% else %}
{% if values is iterable %}
{% if values['title'] is not defined %}
{% set values = values|merge({'title': icon|trans({}, 'actions')}) %}
{% endif %}
{% else %}
{% set values = {'url': values, 'title': icon|trans({}, 'actions')} %}
{% endif %}
{% if icon == 'trash' %}
{% set trash = values %}
{% else %}
{% set divider = false %}
{% if values.children is defined %}
{%- for childIcon, childValues in values.children %}
<li>
{{ _self.action_button(childIcon, childValues, false) }}
</li>
{% endfor %}
{% else %}
<li>
{{ _self.action_button(icon, values, false) }}
</li>
{% endif %}
{% endif %}
{% endif %}
{% endfor -%}
{%- if trash is not null %}
{% if actions|length > 1 and divider is same as (false) %}
<li class="divider"></li>
{% endif %}
<li class="delete">
{{ _self.action_button('trash', trash, false) }}
</li>
{% endif -%}
{% endapply %}
</ul>
</div>
{% import '@theme/components/actions.html.twig' as macro %}
{{ macro.actions(actions, {'class': class|default('btn-sm'), translationDomain: 'actions'}) }}
{% endif %}
{% endmacro %}
{% macro list_group_actions(actions, highlightUrl) %}
{% if actions|length > 0 %}
<div class="list-group">
{% for icon, values in actions %}
{% if 'divider' in icon and values is null %}
</div><div class="list-group">
{# <a class="list-group-item disabled list-group-divider"></a> #}
{% else %}
{% if values is not iterable %}
{% set values = {'url': values} %}
{% endif %}
{% if values['children'] is defined %}
{{ _self.list_group_actions(values['children'], highlightUrl) }}
{% else %}
{% if values['title'] is not defined %}
{% set values = values|merge({'title': icon|trans({}, 'actions')}) %}
{% endif %}
{% set class = 'list-group-item' %}
{% if highlightUrl == values.url %}
{% set class = class ~ ' active' %}
{% endif %}
{% set values = values|merge({'class': class}) %}
{{ _self.action_button(icon, values, false) }}
{% endif %}
{% endif %}
{% endfor %}
</div>
{% endif %}
{% macro card_tool_visibility(tableName) %}
{{ _self.card_tool_button('visibility', {'modal': ('#modal_' ~ tableName)}) }}
{% endmacro %}
{% macro card_tool_button(icon, values) %}
{% import '@theme/components/buttons.html.twig' as macro %}
{% set values = values|merge({'tooltip_attr': 'data-toggle'}) %}
{{ macro.action_cardtoolbutton(icon, values) }}
{% endmacro %}
{% macro action_button(icon, values, type) %}
{%- apply spaceless -%}
{% set id = null %}
{% set onclick = null %}
{% set modal = null %}
{% set toggle = null %}
{% set url = null %}
{% set target = null %}
{% set title = null %}
{% set disabled = false %}
{% set attr = {} %}
{% set label = null %}
{% set accesskey = null %}
{% set translation_domain = 'messages' %}
{% if type is same as (false) %}
{% set class = "" %}
{% elseif type is null %}
{% set class = "btn btn-default btn-" ~ icon ~ " " %}
{% else %}
{% set class = "btn btn-" ~ type ~ " btn-" ~ icon ~ " " %}
{% endif %}
{% if values is not iterable %}
{% deprecated 'Passing a non iterable action_button is deprecated since 1.15 and will be removed with 2.0' %}
{% set url = values %}
{% if 'onclick:' in url %}
{% set onclick = url|replace({'onclick:': ''}) %}
{% set url = '#' %}
{% endif %}
{% if '#collapse' in url %}
{% set toggle = 'collapse' %}
{% endif %}
{% if '#modal' in url %}
{% set modal = url %}
{% set url = '#' %}
{% endif %}
{% else %}
{% set icon = values.icon ?? icon %}
{% set disabled = values.disabled ?? false %}
{% set url = values.url ?? '#' %}
{% set onclick = values.onclick ?? null %}
{% set modal = values.modal ?? null %}
{% set toggle = values.toggle ?? null %}
{% set target = values.target ?? null %}
{% set id = values.id ?? null %}
{% set title = values.title ?? null %}
{% set class = class ~ ( values.class | default("")) %}
{% set attr = values.attr ?? {} %}
{% set label = values.label ?? null %}
{% set translation_domain = values.translation_domain ?? translation_domain %}
{% set accesskey = values.accesskey ?? null %}
{% endif %}
{% if disabled is same as (true) %}
{% set class = class ~ " disabled" %}
{% endif %}
<a class="{{ class | trim }}" href="{{ url }}"
{%- if disabled is same as (true) %} disabled="disabled"{% endif %}
{%- if id is not empty %} id="{{ id }}"{% endif %}
{%- if toggle is not empty %} data-toggle="{{ toggle }}"{% endif %}
{%- if modal is not empty %} data-toggle="modal" data-target="{{ modal }}"{% endif %}
{%- if onclick is not empty %} onclick="{{ onclick }}"{% endif %}
{%- if target is not empty %} target="{{ target }}"{% endif %}
{%- if accesskey is not empty %} accesskey="{{ accesskey }}"{% endif %}
{%- if attr is not empty %}
{% for name, value in attr %}
{{ ' ' ~ name }}={% if '"' in value %}'{{ value|raw }}'{% else %}"{{ value|raw }}"{% endif %}
{% endfor %}
{% endif %}
>{% if title is not null %}{{ title|trans({}, translation_domain) }}{% else %}{{ _self.icon(icon) }}{% endif %}{% if label is not null %}<span class="label bg-yellow">{{ label }}</span>{% endif %}</a>
{% endapply %}
{% endmacro %}
{% macro button_group(actions, type) %}
<div class="btn-group">
{%- apply spaceless -%}
{%- for icon,values in actions %}
{% if 'divider' in icon and values is null %}
{# what to do here ? #}
{% else %}
{% if values.children is defined %}
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
{{ _self.icon(icon) }}&nbsp;
<span class="caret"></span>
<span class="sr-only">{{ 'label.toggle_dropdown'|trans }}</span>
</button>
<ul class="dropdown-menu dropdown-menu-right" role="menu">
{% for childIcon,childValues in values.children %}
<li>{{ _self.action_button(childIcon, childValues, false) }}</li>
{% endfor %}
</ul>
</div>
{% else %}
{{ _self.action_button(icon, values, type) }}
{% endif %}
{% endif %}
{% endfor -%}
{% endapply %}
</div>
{% endmacro %}
{% macro button_action(icon, url) %}
<a href="{{ url }}" class="btn btn-default btn-{{ icon }}">
{{ _self.icon(icon) }}
</a>
{% import '@theme/components/button.html.twig' as macro %}
{% set values = values|merge({'tooltip_attr': 'data-toggle'}) %}
{{ macro.button(icon, values, type) }}
{% endmacro %}
{% macro tag_list(taglist) %}
@@ -463,9 +275,21 @@
{% endfor %}
{% endmacro %}
{% macro meta_field_value(entity, field) %}
{% set metaField = entity.metaField(field.name) %}
{% if not metaField is null and metaField.value is not null and metaField.value is not empty %}
{% set metaField = metaField.merge(field) %}
{{ _self.form_type_value(metaField.type, metaField.value, entity) }}
{% endif %}
{% endmacro %}
{% macro form_type_value(type, value, entity) %}
{% if '\\ColorPickerType' in type %}
{{ _self.color_dot(value, value) }}
{% if '\\ColorPickerType' in type or '\\ColorChoiceType' in type %}
{% if value is not empty %}
<span class="label-color" data-toggle="tooltip" data-placement="top" title="{{ value }}">
<i class="dot {{ 'dot'|icon(true) }} fa-fw" style="color:{{ value }}"></i>
</span>
{% endif %}
{% elseif '\\DurationType' in type %}
{{ value|duration }}
{% elseif '\\YesNoType' in type or '\\CheckBoxType' in type %}
@@ -473,14 +297,20 @@
{% elseif '\\DatePickerType' in type %}
{{ value|date_short }}
{% elseif '\\DateTimePickerType' in type %}
{{ value|date_full }}
{{ value|date_time }}
{% elseif '\\CountryType' in type %}
{{ value|country }}
{{ value|country_name }}
{% elseif '\\CurrencyType' in type %}
{{ value|currency }}
{{ value|currency_name }}
{% elseif '\\LanguageType' in type %}
{{ value|language }}
{% elseif '\\MoneyType' in type %}
{{ value|locale_name }}
{% elseif '\\TagsType' in type %}
{% for tag in value|split(',') %}
{% if tag is not empty %}
{{ _self.badge(tag, null|colorize(tag)) }}
{% endif %}
{% endfor %}
{% elseif '\\MoneyType' in type %}
{% set classname = class_name(entity) %}
{% if entity is null %}
{{ value }}
@@ -506,46 +336,35 @@
{% endif %}
{% endmacro %}
{% macro team_list(teams, showTitle, collapseAt) %}
{% set collapseAt = collapseAt ?? 12 %}
{% if showTitle is null %}
{% set showTitle = true %}
{% endif %}
{% macro team_list(teams, options) %}
{% set showTitle = options['title'] ?? true %}
{% set collapseAt = options['collapse'] ?? 12 %}
{% set nameClass = options['name_class'] ?? '' %}
{% set viewTeam = is_granted('view_team') %}
<table class="table table-hover dataTable" role="grid">
{% if showTitle %}
<thead>
<tr>
<th class="hw-min">{{ 'label.team'|trans }}</th>
<th>{{ 'label.user'|trans }}</th>
<th class="hw-min">{{ 'team'|trans }}</th>
<th class="d-none d-sm-table-cell">{{ 'team.member'|trans({}, 'teams') }}</th>
</tr>
</thead>
{% endif %}
<tbody>
{% for team in teams|sort((a, b) => a.name <=> b.name) %}
{% set members = team.members|filter(m => m.user.enabled) %}
{% set userTeamCount = members|length %}
<tr{% if is_granted('edit', team) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_team_member', {'id': team.id}) }}"{% endif %}>
<td>
{% set class = 'avatar-rounded' %}
<tr{% if viewTeam and is_granted('edit', team) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_team_member', {'id': team.id}) }}"{% endif %}>
<td class="{{ nameClass }}">
{{ _self.label_color_dot('color', true, team.name, null, team.color|colorize(team.name)) }}
</td>
<td class="avatars">
{% set teamHiddenId = 'team_' ~ team.id ~ '_hiddenUser' ~ random() %}
{% set counter = 0 %}
<td class="d-none d-sm-table-cell avatars avatar-list avatar-list-stacked">
{% for member in members|sort((a, b) => b.teamlead <=> a.teamlead) %}
{% set user = member.user %}
{% if member.teamlead %}
{{ _self.user_avatar(user, ('label.teamlead'|trans ~ ': ' ~ user.displayName), 'teamlead') }}
{{ _self.user_avatar(user, ('teamlead'|trans ~ ': ' ~ user.displayName), (class ~ ' teamlead'), 'info') }}
{% else %}
{{ _self.user_avatar(user) }}
{% endif %}
{% set counter = counter + 1 %}
{% if userTeamCount > (collapseAt + 1) and counter == (collapseAt - 1) and loop.index != userTeamCount %}
<a href="#" onclick="$(this).parent().append($('#{{ teamHiddenId }}').contents());$('#{{ teamHiddenId }}').remove();$(this).remove();return false;" class="badge">{{ 'label.plus_more'|trans({'%count%': (userTeamCount - collapseAt)}) }}</a>
<span class="hidden" id="{{ teamHiddenId }}">
{% set counter = counter + 1 %}
{% endif %}
{% if userTeamCount > collapseAt and counter != (collapseAt - 1) and loop.index == userTeamCount %}
</span>
{{ _self.user_avatar(user, null, class) }}
{% endif %}
{% endfor %}
</td>
@@ -571,7 +390,7 @@
<tr class="{{ class_customer_row(customer, now) }}">
#}
{% macro class_customer_row(customer, now) %}
{%- if not customer.visible %}warning{% endif -%}
{%- if not customer.visible %}bg-orange-lt{% endif -%}
{% endmacro %}
{#
@@ -593,7 +412,7 @@
<tr class="{{ class_project_row(project, now) }}">
#}
{% macro class_project_row(project, now) %}
{%- if not project.visible or (project.end is not null and project.end < now) %}warning{% endif -%}
{%- if not project.visible or (project.end is not null and project.end < now) %}bg-orange-lt{% endif -%}
{% endmacro %}
{#
@@ -615,7 +434,7 @@
<tr {{ class_activity_row(activity, now) }}>
#}
{% macro class_activity_row(activity, now) %}
{%- if not activity.visible %}warning{% endif -%}
{%- if not activity.visible %}bg-orange-lt{% endif -%}
{% endmacro %}
{#
@@ -637,7 +456,7 @@
<tr class="{{ class_user_row(user, now) }}">
#}
{% macro class_user_row(user) %}
{%- if not user.enabled %}warning{% endif -%}
{%- if not user.enabled %}bg-orange-lt{% endif -%}
{% endmacro %}
{#
@@ -676,3 +495,11 @@
{{ 0|number_format(2) }} %
{% endif %}
{% endmacro %}
{% macro page_reloader(events, full_reload) %}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('{{ events }}', {% if full_reload is same as true %}true{% else %}false{% endif %});
});
</script>
{% endmacro %}