User profile layout (#2402)

This commit is contained in:
Kevin Papst
2021-03-06 12:34:34 +01:00
committed by GitHub
parent d3099aca39
commit 5583caa9e4
30 changed files with 550 additions and 268 deletions

View File

@@ -3,28 +3,26 @@
{% endmacro %}
{%- macro page_actions(tools) -%}
{% import _self as macro %}
<div class="breadcrumb">
<div class="box-tools">
{{ macro.button_group(tools) }}
{{ _self.button_group(tools) }}
</div>
</div>
{%- endmacro -%}
{%- macro entity_actions(tools) -%}
{% import _self as macro %}
<div class="breadcrumb">
<div class="box-tools">
<div class="btn-group">
{% set actions = {} %}
{%- for icon, values in tools %}
{% if icon == 'back' %}
{{ macro.action_button(icon, values) }}
{{ _self.action_button(icon, values) }}
{% else %}
{% set actions = actions|merge({(icon): values}) %}
{% endif %}
{% endfor %}
{{ macro.table_actions(actions, '') }}
{{ _self.table_actions(actions, '') }}
</div>
</div>
</div>
@@ -35,21 +33,18 @@
{% endmacro %}
{% macro label_boolean(visible) %}
{% import _self as macro %}
{% if visible %}
{{ macro.label('yes'|trans, 'success') }}
{{ _self.label('yes'|trans, 'success') }}
{% else %}
{{ macro.label('no'|trans, 'default') }}
{{ _self.label('no'|trans, 'default') }}
{% endif %}
{% endmacro %}
{% macro label_visible(visible) %}
{% import _self as macro %}
{{ macro.label_boolean(visible) }}
{{ _self.label_boolean(visible) }}
{% endmacro %}
{% macro label_role(role) %}
{% import _self as macro %}
{% set color = 'primary' %}
{% if role == 'ROLE_SUPER_ADMIN' %}
{% set color = 'danger' %}
@@ -60,7 +55,7 @@
{% elseif role == 'ROLE_USER' %}
{% set color = 'gray' %}
{% endif %}
{{ macro.label(role|trans, color) }}
{{ _self.label(role|trans, color) }}
{% endmacro %}
{% macro username(user) %}
@@ -68,13 +63,11 @@
{% endmacro %}
{% macro label_user(user) %}
{% import _self as macro %}
{{ macro.label(user.displayName, 'primary') }}
{{ _self.label(user.displayName, 'primary') }}
{% endmacro %}
{% macro label_team(team, class) %}
{% import _self as macro %}
{{ macro.label(team.name, class|default('primary')) }}
{{ _self.label(team.name, class|default('primary')) }}
{% endmacro %}
{% macro user_avatar(user, tooltip, class) %}
@@ -87,7 +80,6 @@
{% endmacro %}
{% macro label_activity(activity, url) %}
{% import _self as macro %}
{% set isVisible = activity.visible %}
{% set color = activity.color %}
{% if color is empty and activity.project is not null %}
@@ -99,22 +91,19 @@
{% set isVisible = activity.project.customer.visible %}
{% endif %}
{% endif %}
{{ macro.label_color_dot('activity', isVisible, activity.name, url, color) }}
{{ _self.label_color_dot('activity', isVisible, activity.name, url, color) }}
{% endmacro %}
{% macro label_project(project, url) %}
{% import _self as macro %}
{% set isVisible = false %}
{% if project.visible and project.customer.visible %}
{% set isVisible = true %}
{% endif %}
{{ macro.label_color_dot('project', isVisible, project.name, url, (project.color ?? project.customer.color)) }}
{{ _self.label_color_dot('project', isVisible, project.name, url, (project.color ?? project.customer.color)) }}
{% endmacro %}
{% macro label_customer(customer, url) %}
{% import _self as macro %}
{% set isVisible = customer.visible %}
{{ macro.label_color_dot('customer', isVisible, customer.name, url, customer.color) }}
{{ _self.label_color_dot('customer', customer.visible, customer.name, url, customer.color) }}
{% endmacro %}
{% macro label_color_dot(type, isVisible, name, url, color) %}
@@ -137,11 +126,10 @@
{% endmacro %}
{% macro badge_team_access(teams) %}
{% import _self as macro %}
{% if teams|length > 0 %}
{{ macro.badge_counter(teams|length) }}
{{ _self.badge_counter(teams|length) }}
{% else %}
{{ macro.icon('unlocked') }}
{{ _self.icon('unlocked') }}
{% endif %}
{% endmacro %}
@@ -218,7 +206,6 @@
{% endmacro %}
{% macro table_actions(actions, class) %}
{%- import _self as macro -%}
{% if actions|length >= 1 %}
{% if class is null %}
{% set class = 'btn-sm' %}
@@ -249,9 +236,17 @@
{% set trash = values %}
{% else %}
{% set divider = false %}
<li>
{{ macro.action_button(icon, values, false) }}
</li>
{% 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 -%}
@@ -260,7 +255,7 @@
<li class="divider"></li>
{% endif %}
<li class="delete">
{{ macro.action_button('trash', trash, false) }}
{{ _self.action_button('trash', trash, false) }}
</li>
{% endif -%}
{% endapply %}
@@ -269,8 +264,37 @@
{% 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 %}
{% endmacro %}
{% macro action_button(icon, values, type) %}
{%- import _self as macro -%}
{%- apply spaceless -%}
{% set id = null %}
{% set onclick = null %}
@@ -281,6 +305,7 @@
{% set title = null %}
{% set disabled = false %}
{% set attr = {} %}
{% set translation_domain = 'messages' %}
{% if type is same as (false) %}
{% set class = "" %}
{% elseif type is null %}
@@ -289,7 +314,7 @@
{% set class = "btn btn-" ~ type ~ " btn-" ~ icon ~ " " %}
{% endif %}
{% if not values is iterable %}
{% if values is not iterable %}
{% set url = values %}
{% if 'onclick:' in url %}
{% set onclick = url|replace({'onclick:': ''}) %}
@@ -314,6 +339,7 @@
{% set title = values.title ?? null %}
{% set class = class ~ ( values.class | default("")) %}
{% set attr = values.attr ?? {} %}
{% set translation_domain = values.translation_domain ?? translation_domain %}
{% endif %}
{% if disabled is same as (true) %}
@@ -332,30 +358,33 @@
{{ ' ' ~ name }}={% if '"' in value %}'{{ value|raw }}'{% else %}"{{ value|raw }}"{% endif %}
{% endfor %}
{% endif %}
>{% if title is not null %}{{ title }}{% else %}{{ macro.icon(icon) }}{% endif %}</a>
>{% if title is not null %}{{ title|trans({}, translation_domain) }}{% else %}{{ _self.icon(icon) }}{% endif %}</a>
{% endapply %}
{% endmacro %}
{% macro button_group(actions, type) %}
{%- import _self as macro -%}
<div class="btn-group">
{%- apply spaceless -%}
{%- for icon,values in actions %}
{% if values.children is defined %}
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
{{ macro.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>{{ macro.action_button(childIcon, childValues, false) }}</li>
{% endfor %}
</ul>
</div>
{% if 'divider' in icon and values is null %}
{# what to do here ? #}
{% else %}
{{ macro.action_button(icon, values, type) }}
{% 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 %}
@@ -416,7 +445,8 @@
{% endif %}
{% endmacro %}
{% macro team_list(teams, showTitle) %}
{% macro team_list(teams, showTitle, collapseAt) %}
{% set collapseAt = collapseAt ?? 5 %}
{% if showTitle is null %}
{% set showTitle = true %}
{% endif %}
@@ -447,12 +477,12 @@
{{ macro.user_avatar(user) }}
{% set counter = counter + 1 %}
{% endif %}
{% if userTeamCount > 5 and counter == 4 and loop.index != userTeamCount %}
<a href="#" onclick="$('#{{ teamHiddenId }}').toggleClass('hidden');$(this).hide();return false;" class="badge">{{ 'label.plus_more'|trans({'%count%': (userTeamCount - 5)}) }}</a>
{% if userTeamCount > collapseAt and counter == (collapseAt - 1) and loop.index != userTeamCount %}
<a href="#" onclick="$('#{{ teamHiddenId }}').toggleClass('hidden');$(this).hide();return false;" class="badge">{{ 'label.plus_more'|trans({'%count%': (userTeamCount - collapseAt)}) }}</a>
<span class="hidden" id="{{ teamHiddenId }}">
{% set counter = counter + 1 %}
{% endif %}
{% if userTeamCount > 5 and counter != 4 and loop.index == userTeamCount %}
{% if userTeamCount > collapseAt and counter != (collapseAt - 1) and loop.index == userTeamCount %}
</span>
{% endif %}
{% endfor %}

View File

@@ -28,80 +28,17 @@
{% endmacro %}
{% macro user_permissions(view) %}
{% import "macros/widgets.html.twig" as widgets %}
{% set actions = {} %}
{% if view != 'index' and is_granted('role_permissions') %}
{% set actions = actions|merge({'permissions': path('admin_user_permissions')}) %}
{% endif %}
{% if view != 'role' and is_granted('role_permissions') %}
{% set actions = actions|merge({'create': {'url': path('admin_user_roles'), 'class': 'modal-ajax-form'}}) %}
{% endif %}
{% set actions = actions|merge({'help': {'url': 'permissions.html'|docu_link, 'target': '_blank'}}) %}
{% set event = trigger('actions.user_permissions', {'actions': actions, 'view': view}) %}
{{ widgets.page_actions(event.payload.actions) }}
{% deprecated 'The "user_permissions" macro from user/action.html.twig is deprecated since 1.14 and will be removed with 2.0. Use "permission/actions.html.twig" instead.' %}
{% import "permission/actions.html.twig" as realMacro %}
{{ realMacro.user_permissions(view) }}
{% endmacro %}
{% macro user(user, view, options) %}
{% import "macros/widgets.html.twig" as widgets %}
{% set actions = {} %}
{% if user.id is not empty %}
{% set view_other = is_granted('view_other_timesheet') %}
{% if is_granted('view', user) %}
{% set actions = actions|merge({'profile-stats': {'url': path('user_profile', {'username' : user.username})}}) %}
{% endif %}
{% if actions|length > 0 %}
{% set actions = actions|merge({'divider': null}) %}
{% endif %}
{% set subActions = {} %}
{% if is_granted('edit', user) %}
{% set subActions = subActions|merge({'edit': path('user_profile_edit', {'username' : user.username})}) %}
{% endif %}
{% if is_granted('preferences', user) %}
{% set subActions = subActions|merge({'settings': {'url': path('user_profile_preferences', {'username' : user.username})}}) %}
{% endif %}
{% if is_granted('password', user) %}
{% set subActions = subActions|merge({'password': {'url': path('user_profile_password', {'username' : user.username}), 'title': ('profile.password'|trans)}}) %}
{% endif %}
{% if is_granted('api-token', user) %}
{% set subActions = subActions|merge({'api-token': {'url': path('user_profile_api_token', {'username' : user.username}), 'title': ('profile.api-token'|trans)}}) %}
{% endif %}
{% if is_granted('teams', user) %}
{% set subActions = subActions|merge({'teams': {'url': path('user_profile_teams', {'username' : user.username}), 'title': ('profile.teams'|trans)}}) %}
{% endif %}
{% if is_granted('roles', user) %}
{% set subActions = subActions|merge({'roles': {'url': path('user_profile_roles', {'username' : user.username}), 'title': ('profile.roles'|trans)}}) %}
{% endif %}
{% if subActions|length > 0 %}
{% set actions = actions|merge(subActions) %}
{% set actions = actions|merge({'divider2': null}) %}
{% endif %}
{% if is_granted('view_reporting') %}
{% if view_other or app.user.id == user.id %}
{% set actions = actions|merge({'report': path('report_user_month', {'user': user.id})}) %}
{% endif %}
{% endif %}
{% if view_other and user.enabled %}
{% set actions = actions|merge({'timesheet': path('admin_timesheet', {'users': [user.id]})}) %}
{% endif %}
{% if view == 'index' and is_granted('delete', user) %}
{% set actions = actions|merge({'trash': {'url': path('admin_user_delete', {'id': user.id}), 'class': 'modal-ajax-form'}}) %}
{% endif %}
{% endif %}
{% if options.back is defined %}
{% set actions = actions|merge({'back': options.back}) %}
{% endif %}
{% set event = trigger('actions.user', {'actions': actions, 'view': view, 'user': user}) %}
{% set event = actions(app.user, 'user', {'view': view, 'user': user}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{{ widgets.table_actions(event.actions) }}
{% else %}
{{ widgets.entity_actions(event.payload.actions) }}
{{ widgets.page_actions(event.actions) }}
{% endif %}
{% endmacro %}

View File

@@ -1,6 +1,6 @@
{% extends 'user/layout.html.twig' %}
{% block main %}
{% block profile_content %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}

View File

@@ -1,6 +1,7 @@
{% extends 'user/layout.html.twig' %}
{% block main %}
{% block profile_content %}
{{ form_start(form) }}
{% for section in sections %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}

View File

@@ -5,8 +5,9 @@
{% import "user/actions.html.twig" as actions %}
{% set columns = {
'avatar': {'class': 'alwaysVisible w-min', 'title': null, 'orderBy': false},
'alias': {'class': 'alwaysVisible'},
'title': {'class': 'hidden-xs hidden-sm'},
'title': {'class': 'hidden-xs hidden-sm hidden'},
'email': {'class': 'hidden-xs hidden-sm hidden', 'orderBy': false},
'lastLogin': {'class': 'hidden-xs hidden-sm hidden', 'orderBy': false},
'roles': {'class': 'hidden-sm', 'orderBy': false},
@@ -27,9 +28,10 @@
{% block page_title %}{{ 'admin_user.title'|trans }}{% endblock %}
{% block page_search %}{{ toolbar.dropDownSearch(toolbarForm) }}{% endblock %}
{% block page_actions %}{{ actions.users('index') }}{% endblock %}
{% block page_icon %}{{ 'user'|icon }}{% endblock %}
{% block main_before %}
{{ tables.data_table_column_modal(tableName, columns) }}
{{ tables.data_table_column_modal(tableName, columns, 'kimai.userUpdate') }}
{% endblock %}
{% block main %}
@@ -41,7 +43,8 @@
{% for entry in entries %}
<tr{% if is_granted('view', entry) %} class="open-edit alternative-link" data-href="{{ path('user_profile', {'username': entry.username}) }}"{% endif %}>
<td class="{{ tables.data_table_column_class(tableName, columns, 'alias') }}">{{ widgets.user_avatar(entry) }} {{ widgets.username(entry) }}</td>
<td class="{{ tables.data_table_column_class(tableName, columns, 'avatar') }}">{{ widgets.user_avatar(entry) }}</td>
<td class="{{ tables.data_table_column_class(tableName, columns, 'alias') }}">{{ widgets.username(entry) }}</td>
<td class="{{ tables.data_table_column_class(tableName, columns, 'title') }}">{{ entry.title }}</td>
<td class="{{ tables.data_table_column_class(tableName, columns, 'email') }}">{{ entry.email }}</td>
<td class="{{ tables.data_table_column_class(tableName, columns, 'lastLogin') }}">{% if entry.lastLogin is not null %}{{ entry.lastLogin|date_full }}{% endif %}</td>

View File

@@ -1,111 +1,31 @@
{% extends 'base.html.twig' %}
{% import "user/actions.html.twig" as actions %}
{% import "macros/widgets.html.twig" as widgets %}
{% block page_title %}{% if not user.alias is empty %}{{ user.alias }}{% else %}{{ user.username }}{% endif %}{% endblock %}
{% block page_subtitle %}{% if not user.alias is empty %}{{ user.username }}{% endif %}{% endblock %}
{% block page_title %}{{ 'admin_user.title'|trans }}{% endblock %}
{% block page_actions %}{{ actions.user(user, tab) }}{% endblock %}
{% block page_icon %}{{ 'user'|icon }}{% endblock %}
{% block main %}
<div class="row">
<div class="col-md-8">
<div class="col-xs-12 col-sm-9 col-md-9 col-lg-10">
{% block profile_intro %}
<div class="panel panel-default">
<div class="panel-body">
{{ widgets.user_avatar(user, false, 'avatar-md') }}
{{ user.displayName }}
{% if user.title is not empty %} &ndash; {{ user.title }} {% endif %}
</div>
</div>
{% endblock %}
{% block profile_content %}{% endblock %}
</div>
<div class="col-md-4">
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_body_class %}box-profile{% endblock %}
{% block box_body %}
<div class="text-center">
{{ widgets.user_avatar(user) }}
<h3 class="profile-username">{{ widgets.username(user) }}</h3>
<p class="text-muted">{{ user.title }}</p>
</div>
{% set seeOwnRate = is_granted('view_rate_own_timesheet') %}
<table class="table">
<tr>
<th>{{ 'stats.durationMonth'|trans }}</th>
<td class="text-nowrap pull-right">{{ stats.durationThisMonth|duration }}</td>
</tr>
{% if seeOwnRate %}
<tr>
<th>{{ 'stats.amountMonth'|trans }}</th>
{# TODO which currency shall we use here? #}
<td class="text-nowrap pull-right">{{ stats.amountThisMonth|money }}</td>
</tr>
{% endif %}
<tr>
<th>{{ 'stats.durationTotal'|trans }}</th>
<td class="text-nowrap pull-right">{{ stats.durationTotal|duration }}</td>
</tr>
{% if seeOwnRate %}
<tr>
<th>{{ 'stats.amountTotal'|trans }}</th>
{# TODO which currency shall we use here? #}
<td class="text-nowrap pull-right">{{ stats.amountTotal|money }}</td>
</tr>
{% endif %}
</table>
{% endblock %}
{% endembed %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% block box_title %}{{ 'profile.about_me'|trans }}{% endblock %}
{% block box_body %}
{# colors = purple, blue, aqua, red, green #}
<table class="table no-border">
<tr>
<th>{{ 'label.id'|trans }}</th>
<td class="text-nowrap pull-right">{{ user.id }}</td>
</tr>
<tr>
<th>{{ 'label.username'|trans }}</th>
<td class="text-nowrap pull-right">{{ user.username }}</td>
</tr>
<tr>
<th>{{ 'profile.first_entry'|trans }}</th>
<td class="text-nowrap pull-right">{{ stats.firstEntry|date_short }}</td>
</tr>
<tr>
<th>{{ 'profile.registration_date'|trans }}</th>
<td class="text-nowrap pull-right">{{ user.registeredAt|date_short }}</td>
</tr>
{% if is_granted('hourly-rate', user) %}
<tr>
<th>{{ 'label.hourlyRate'|trans }}</th>
<td class="text-nowrap pull-right">{{ user.preferenceValue('hourly_rate') }}</td>
</tr>
{% endif %}
</table>
{% endblock %}
{% endembed %}
{% if user.teams is not empty and (is_granted('teams', user) or (app.user == user and is_granted('view_team_member'))) %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_title %}{{ 'label.my_teams'|trans }}{% endblock %}
{% block box_tools %}
{% if is_granted('roles', user) %}
<a class="btn-box-tool" href="{{ path('user_profile_teams', {'username': user.username}) }}"><i class="{{ 'edit'|icon }}"></i></a>
{% endif %}
{% endblock %}
{% block box_body %}
{{ widgets.team_list(user.teams) }}
{% endblock %}
{% endembed %}
{% endif %}
<div class="col-xs-12 col-sm-3 col-md-3 col-lg-2">
<div class="hidden-xs">
{% set event = actions(app.user, 'user', {'view': tab, 'user': user}) %}
{{ widgets.list_group_actions(event.actions, app.request.requestUri) }}
</div>
{% block profile_navbar %}{% endblock %}
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('kimai.teamUpdate', true);
});
</script>
{% endblock %}

View File

@@ -1,6 +1,6 @@
{% extends 'user/layout.html.twig' %}
{% block main %}
{% block profile_content %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}

View File

@@ -11,8 +11,16 @@
{{ encore_entry_script_tags('chart') }}
{% endblock %}
{% block profile_navbar %}
{{ _self.about_me(user, stats) }}
{% endblock %}
{% block profile_intro %}{% endblock %}
{% block profile_content %}
{{ _self.profile_box_horizontal(user, stats) }}
{% if years is empty %}
{{ widgets.nothing_found() }}
{% endif %}
@@ -49,14 +57,13 @@
}
}
}
{%- if is_granted('view_reporting') and (app.user.id == user.id or is_granted('view_other_timesheet')) -%}
{%- if user.enabled and is_granted('view_reporting') and (app.user.id == user.id or is_granted('view_other_timesheet')) -%}
,
onClick: function(event, elements) {
var element = elements[0];
var month = this.data.datasets[0].monthData[element._index];
var formattedMonth = moment(month).format('{{ stat_date_format }}');
var reportUrl = '{{ path('report_user_month', {'user': user.id, 'date': 'XXXXX'})|raw }}'.replace('XXXXX', formattedMonth);
document.location = reportUrl;
document.location = '{{ path('report_user_month', {'user': user.id, 'date': 'XXXXX'})|raw }}'.replace('XXXXX', formattedMonth);
}
{% endif %}
};
@@ -116,4 +123,147 @@
{% endfor %}
{% if user.teams is not empty and (is_granted('teams', user) or (app.user == user and is_granted('view_team_member'))) %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_title %}{{ 'label.my_teams'|trans }}{% endblock %}
{% block box_body %}
{{ widgets.team_list(user.teams) }}
{% endblock %}
{% endembed %}
{% endif %}
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script type="text/javascript">
document.addEventListener('kimai.initialized', function() {
KimaiReloadPageWidget.create('kimai.teamUpdate', true);
});
</script>
{% endblock %}
{% macro about_me(user, stats) %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_title %}
<a href="mailto:{{ user.email }}" title="{{ 'label.email'|trans }}">{{ widgets.icon('mail') }}</a>
<span data-toggle="tooltip" title="{{ 'label.id'|trans }}: {{ user.id }}">{{ 'profile.about_me'|trans }}</span>
{% endblock %}
{% block box_body %}
<p>
<strong>{{ 'profile.first_entry'|trans }}</strong><br>
{# FIXME use a configuration for it #}
{{ stats.firstEntry|date_short }}
</p>
<p>
<strong>{{ 'profile.registration_date'|trans }}</strong><br>
{{ user.registeredAt|date_short }}
</p>
{% if is_granted('hourly-rate', user) and user.preferenceValue('hourly_rate') is not null %}
<p>
<strong>{{ 'label.hourlyRate'|trans }}</strong><br>
{{ user.preferenceValue('hourly_rate') }}
</p>
{% endif %}
{% endblock %}
{% endembed %}
{% endmacro %}
{% macro profile_box_vertical(user, stats) %}
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block box_body_class %}box-profile box-user-profile{% endblock %}
{% block box_body %}
<div class="text-center">
{{ widgets.user_avatar(user) }}
<h3 class="profile-username">{{ widgets.username(user) }}</h3>
<p class="text-muted">{{ user.title }}</p>
</div>
{% set seeOwnRate = is_granted('view_rate_own_timesheet') %}
<table class="table">
<tr>
<th>{{ 'stats.durationMonth'|trans }}</th>
<td class="text-nowrap pull-right">{{ stats.durationThisMonth|duration }}</td>
</tr>
{% if seeOwnRate %}
<tr>
<th>{{ 'stats.amountMonth'|trans }}</th>
{# TODO which currency shall we use here? #}
<td class="text-nowrap pull-right">{{ stats.amountThisMonth|money }}</td>
</tr>
{% endif %}
<tr>
<th>{{ 'stats.durationTotal'|trans }}</th>
<td class="text-nowrap pull-right">{{ stats.durationTotal|duration }}</td>
</tr>
{% if seeOwnRate %}
<tr>
<th>{{ 'stats.amountTotal'|trans }}</th>
{# TODO which currency shall we use here? #}
<td class="text-nowrap pull-right">{{ stats.amountTotal|money }}</td>
</tr>
{% endif %}
</table>
{% endblock %}
{% endembed %}
{% endmacro %}
{% macro profile_box_horizontal(user, stats) %}
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
{% import "macros/widgets.html.twig" as widgets %}
{% set color = kimai_context.chart.background_color %}
{% set event = trigger('user.profile_background', {'color': color, 'font': color|font_contrast, 'user': user, 'image': null}) %}
{% set config = event.payload %}
<div class="box box-widget widget-user box-user-profile">
<div class="widget-user-header" style="{% if config.image is not null %}background: url('{{ config.image }}') center center;{% else %}background-color: {{ config.color }}{% endif %}">
<h3 class="widget-user-username" style="color: {{ config.font }}">
{{ widgets.username(user) }}
</h3>
<h5 class="widget-user-desc" style="color: {{ config.font }}">{{ user.title }}</h5>
</div>
<div class="widget-user-image">
{{ widgets.user_avatar(user) }}
</div>
<div class="box-footer">
{% if stats is not null %}
{% set seeOwnRate = is_granted('view_rate_own_timesheet') %}
{% set columnLength = seeOwnRate ? 3 : 6 %}
<div class="row">
<div class="col-sm-{{ columnLength }} border-right">
<div class="description-block">
<h5 class="description-header">{{ stats.durationThisMonth|duration }}</h5>
<span class="description-text">{{ 'stats.durationMonth'|trans }}</span>
</div>
</div>
{% if seeOwnRate %}
<div class="col-sm-{{ columnLength }} border-right">
<div class="description-block">
<h5 class="description-header">{{ stats.amountThisMonth|money }}</h5>
<span class="description-text">{{ 'stats.amountMonth'|trans }}</span>
</div>
</div>
{% endif %}
<div class="col-sm-{{ columnLength }} border-right">
<div class="description-block">
<h5 class="description-header">{{ stats.durationTotal|duration }}</h5>
<span class="description-text">{{ 'stats.durationTotal'|trans }}</span>
</div>
</div>
{% if seeOwnRate %}
<div class="col-sm-{{ columnLength }} border-right">
<div class="description-block">
<h5 class="description-header">{{ stats.amountTotal|money }}</h5>
<span class="description-text">{{ 'stats.amountTotal'|trans }}</span>
</div>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endmacro %}

View File

@@ -1,7 +1,7 @@
{% extends 'user/layout.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block main %}
{% block profile_content %}
<div class="row">
<div class="col-md-12">