UI updates - new user menu, updated about and profile screen and more (#723)
This commit is contained in:
60
templates/about/layout.html.twig
Normal file
60
templates/about/layout.html.twig
Normal file
@@ -0,0 +1,60 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "macros/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'about.title'|trans({}, 'about') }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.about('index') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
|
||||
<div class="box box-primary">
|
||||
<div class="box-body">
|
||||
<img src="{{ asset('apple-touch-icon.png') }}" class="profile-user-img img-responsive img-circle" alt="Kimai logo" style="border: 0;">
|
||||
<h3 class="profile-username text-center">{{ constant('App\\Constants::SOFTWARE') }}</h3>
|
||||
|
||||
<p class="text-muted text-center">
|
||||
{{ constant('App\\Constants::VERSION') }}
|
||||
{{ constant('App\\Constants::STATUS') }}
|
||||
({{ constant('App\\Constants::NAME') }})
|
||||
</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<ul class="nav nav-stacked">
|
||||
<li>
|
||||
<a href="{{ ''|docu_link }}" target="_blank">
|
||||
<i class="menu-icon fas fa-question bg-navy"></i>
|
||||
{{ 'help'|trans({}, 'about') }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ constant('App\\Constants::GITHUB') }}" target="_blank">
|
||||
<i class="menu-icon fab fa-github bg-gray"></i>
|
||||
{{ 'support'|trans({}, 'about') }}
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ constant('App\\Constants::HOMEPAGE') }}" target="_blank">
|
||||
<i class="menu-icon fa fa-home bg-green"></i>
|
||||
{{ 'website'|trans({}, 'about') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<p class="text-center">
|
||||
Made with ♥ by <a href="https://www.kevinpapst.de/">Kevin Papst</a> and <a href="{{ constant('App\\Constants::GITHUB') }}graphs/contributors" target="_blank">great contributors</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block about_box %}{% endblock %}
|
||||
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{% block about %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
39
templates/about/license.html.twig
Normal file
39
templates/about/license.html.twig
Normal file
@@ -0,0 +1,39 @@
|
||||
{% extends 'about/layout.html.twig' %}
|
||||
|
||||
{% block about %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}{{ constant('App\\Constants::SOFTWARE') }} is published under{% endblock %}
|
||||
{% block box_body %}
|
||||
<pre>
|
||||
{{ license }}
|
||||
</pre>
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
<a class="btn btn-default" href="https://choosealicense.com/licenses/mit/" target="_blank">choosealicense.com</a>
|
||||
<a class="btn btn-default" href="https://en.wikipedia.org/wiki/MIT_License" target="_blank">wikipedia.org</a>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}Special thanks ...{% endblock %}
|
||||
{% block box_body %}
|
||||
<p>... to the authors of the following libraries, Kimai wouldn't be possible without them:</p>
|
||||
<ul>
|
||||
<li>AdminLTE: <a href="https://adminlte.io" target="_blank">https://adminlte.io</a></li>
|
||||
<li>Bootstrap: <a href="https://getbootstrap.com" target="_blank">https://getbootstrap.com</a></li>
|
||||
<li>Bootstrap-Select: <a href="https://developer.snapappointments.com/bootstrap-select" target="_blank">https://developer.snapappointments.com/bootstrap-select</a></li>
|
||||
<li>chart.js: <a href="https://www.chartjs.org" target="_blank">https://www.chartjs.org</a></li>
|
||||
<li>DateRangePicker: <a href="http://www.daterangepicker.com/" target="_blank">http://www.daterangepicker.com/</a></li>
|
||||
<li>Doctrine: <a href="https://www.doctrine-project.org" target="_blank">https://www.doctrine-project.org</a></li>
|
||||
<li>FontAwesome: <a href="https://fontawesome.com" target="_blank">https://fontawesome.com</a></li>
|
||||
<li>FullCalendar: <a href="https://fullcalendar.io" target="_blank">https://fullcalendar.io</a></li>
|
||||
<li>jQuery: <a href="https://jquery.com" target="_blank">https://jquery.com</a></li>
|
||||
<li>jQuery UI: <a href="https://jqueryui.com" target="_blank">http://jqueryui.com</a></li>
|
||||
<li>MomentJS: <a href="https://momentjs.com" target="_blank">https://momentjs.com</a></li>
|
||||
<li>PHPOffice: <a href="https://github.com/PHPOffice" target="_blank">https://github.com/PHPOffice</a></li>
|
||||
<li>Symfony: <a href="https://symfony.com" target="_blank">https://symfony.com</a></li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
@@ -1,149 +1,69 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% extends 'about/layout.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% block page_title %}{{ 'about.title'|trans({}, 'about') }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'about.subtitle'|trans({}, 'about') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% block about_box %}
|
||||
{% if is_granted('system_actions') %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'boxtype': 'warning'} %}
|
||||
{% block box_title %}{{ 'label.actions'|trans }}{% endblock %}
|
||||
{% block box_body %}
|
||||
{% if content_action is defined and content_action is not empty %}
|
||||
<pre>
|
||||
{{ content_action }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
|
||||
{{ widgets.callout('info', 'Thank you for using Kimai ' ~ constant('App\\Constants::VERSION') ~ ' ' ~ constant('App\\Constants::STATUS') ~ ' - ' ~ constant('App\\Constants::NAME'), 'Kimai ' ~ constant('App\\Constants::VERSION'), 'fas fa-thumbs-up') }}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation"class ="active"><a href="#systeminfo" aria-controls="systeminfo" role="tab" data-toggle="tab">{{ 'tab.system'|trans({}, 'about') }}</a></li>
|
||||
<li role="presentation"><a href="#license" aria-controls="license" role="tab" data-toggle="tab">{{ 'tab.license'|trans({}, 'about') }}</a></li>
|
||||
<li role="presentation"><a href="#thanks" aria-controls="thanks" role="tab" data-toggle="tab">{{ 'tab.thanks'|trans({}, 'about') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="systeminfo">
|
||||
<div class="box-group" id="accordion">
|
||||
{% if is_granted('system_actions') %}
|
||||
<div class="panel box">
|
||||
<div class="box-header with-border">
|
||||
<h4 class="box-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseSystemAction" aria-expanded="true">
|
||||
{{ 'label.actions'|trans }}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseSystemAction" class="panel-collapse collapse in" aria-expanded="true">
|
||||
<div class="box-body">
|
||||
<p>
|
||||
<a href="{{ path('system_flush_cache') }}" class="btn btn-primary" onclick="$(this).html('Clear cache <i class=\'fas fa-spinner fa-spin\'></i>')">Clear cache</a>
|
||||
</p>
|
||||
|
||||
{% if content_action is defined and content_action is not empty %}
|
||||
<pre>
|
||||
{{ content_action }}
|
||||
</pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel box">
|
||||
<div class="box-header with-border">
|
||||
<h4 class="box-title">
|
||||
<a data-toggle="collapse" role="button" data-parent="#accordion" href="#collapseEnvironment" aria-expanded="false" aria-controls="collapseEnvironment">
|
||||
Environment
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseEnvironment" class="panel-collapse collapse" aria-expanded="false" role="tabpanel">
|
||||
<div class="box-body">
|
||||
|
||||
<dl>
|
||||
{% for name, value in dotenv %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel box">
|
||||
<div class="box-header with-border">
|
||||
<h4 class="box-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapsePhp" class="collapsed" aria-expanded="false">
|
||||
PHP
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapsePhp" class="panel-collapse collapse" aria-expanded="false">
|
||||
<div class="box-body">
|
||||
|
||||
<dl>
|
||||
<dt>Version</dt><dd>{{ constant('PHP_VERSION') }}</dd>
|
||||
<dt>Modules</dt><dd>{{ modules|join(', ') }}</dd>
|
||||
{% for name, value in settings %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>
|
||||
{% if value is empty %}
|
||||
<i>unknown</i>
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel box">
|
||||
<div class="box-header with-border">
|
||||
<h4 class="box-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion" href="#collapseSystem" class="collapsed" aria-expanded="false">
|
||||
Server
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapseSystem" class="panel-collapse collapse" aria-expanded="false">
|
||||
<div class="box-body">
|
||||
|
||||
<dl>
|
||||
{% for name, value in info %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>{{ value|raw }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="license">
|
||||
<pre>{{ license }}</pre>
|
||||
<p>
|
||||
<a href="https://choosealicense.com/licenses/mit/" target="_blank">choosealicense.com</a>,
|
||||
<a href="https://en.wikipedia.org/wiki/MIT_License" target="_blank">wikipedia.org</a>
|
||||
</p>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="thanks">
|
||||
<p>Special thanks to the authors of the following libraries, Kimai wouldn't be possible without them:</p>
|
||||
<ul>
|
||||
<li>AdminLTE: <a href="https://adminlte.io" target="_blank">https://adminlte.io</a></li>
|
||||
<li>Bootstrap: <a href="https://getbootstrap.com" target="_blank">https://getbootstrap.com</a></li>
|
||||
<li>Bootstrap-Select: <a href="https://developer.snapappointments.com/bootstrap-select" target="_blank">https://developer.snapappointments.com/bootstrap-select</a></li>
|
||||
<li>chart.js: <a href="https://www.chartjs.org" target="_blank">https://www.chartjs.org</a></li>
|
||||
<li>DateRangePicker: <a href="http://www.daterangepicker.com/" target="_blank">http://www.daterangepicker.com/</a></li>
|
||||
<li>Doctrine: <a href="https://www.doctrine-project.org" target="_blank">https://www.doctrine-project.org</a></li>
|
||||
<li>FontAwesome: <a href="https://fontawesome.com" target="_blank">https://fontawesome.com</a></li>
|
||||
<li>FullCalendar: <a href="https://fullcalendar.io" target="_blank">https://fullcalendar.io</a></li>
|
||||
<li>jQuery: <a href="https://jquery.com" target="_blank">https://jquery.com</a></li>
|
||||
<li>jQuery UI: <a href="https://jqueryui.com" target="_blank">http://jqueryui.com</a></li>
|
||||
<li>MomentJS: <a href="https://momentjs.com" target="_blank">https://momentjs.com</a></li>
|
||||
<li>Symfony: <a href="https://symfony.com" target="_blank">https://symfony.com</a></li>
|
||||
<li>...</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>
|
||||
<a href="{{ path('system_flush_cache') }}" class="btn btn-primary" onclick="$(this).html('Clear cache <i class=\'fas fa-spinner fa-spin\'></i>')">Clear cache</a>
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block about %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}Environment{% endblock %}
|
||||
{% block box_body %}
|
||||
<dl>
|
||||
{% for name, value in dotenv %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>{{ value }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}PHP{% endblock %}
|
||||
{% block box_body %}
|
||||
<dl>
|
||||
<dt>Version</dt><dd>{{ constant('PHP_VERSION') }}</dd>
|
||||
<dt>Modules</dt><dd>{{ modules|join(', ') }}</dd>
|
||||
{% for name, value in settings %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>
|
||||
{% if value is empty %}
|
||||
<i>unknown</i>
|
||||
{% else %}
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}Server{% endblock %}
|
||||
{% block box_body %}
|
||||
<dl>
|
||||
{% for name, value in info %}
|
||||
<dt>{{ name }}</dt>
|
||||
<dd>{{ value|raw }}</dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
{% set columns = {
|
||||
'name': 'alwaysVisible',
|
||||
'customer': 'hidden-xs',
|
||||
'project': '',
|
||||
'project': 'hidden-xs',
|
||||
'comment': 'hidden-xs',
|
||||
'visible': 'hidden-xs',
|
||||
'visible': '',
|
||||
'actions': 'alwaysVisible',
|
||||
} %}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% extends '@AdminLTE/layout/default-layout-avanzu.html.twig' %}
|
||||
{% extends '@AdminLTE/layout/default-layout.html.twig' %}
|
||||
|
||||
{% block avanzu_after_body_start %}
|
||||
{% block after_body_start %}
|
||||
{% embed 'embeds/modal.html.twig' %}
|
||||
{% block modal_id %}remote_form_modal{% endblock %}
|
||||
{% block modal_title %}{% endblock %}
|
||||
@@ -9,7 +9,7 @@
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_page_content_before %}
|
||||
{% block page_content_before %}
|
||||
{% set event = trigger(constant('App\\Event\\ThemeEvent::CONTENT_BEFORE')) %}
|
||||
{{ event.content|raw }}
|
||||
<div class="toolbar-pad no-print">
|
||||
@@ -17,13 +17,13 @@
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_page_content_after %}
|
||||
{% block page_content_after %}
|
||||
{% block main_after %}{% endblock %}
|
||||
{% set event = trigger(constant('App\\Event\\ThemeEvent::CONTENT_AFTER')) %}
|
||||
{{ event.content|raw }}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_page_content %}
|
||||
{% block page_content %}
|
||||
{% set event = trigger(constant('App\\Event\\ThemeEvent::CONTENT_START')) %}
|
||||
{{ event.content|raw }}
|
||||
{% block main %}{% endblock %}
|
||||
@@ -31,33 +31,25 @@
|
||||
{{ event.content|raw }}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_document_title %}
|
||||
{% block title %}{{ 'browser.title'|trans }}{% endblock %}
|
||||
{% block title %}
|
||||
{{ 'browser.title'|trans }}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_page_title %}
|
||||
{% block page_title %}{% endblock %}
|
||||
{% endblock %}
|
||||
{% block page_subtitle %}{% endblock %}
|
||||
|
||||
{% block avanzu_page_subtitle %}
|
||||
{% block page_subtitle %}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_logo_mini %}
|
||||
{% block logo_mini %}
|
||||
<b>K</b>TT
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_logo_lg %}
|
||||
{% block logo_large %}
|
||||
<b>Kimai</b> - Time Tracking
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_footer %}
|
||||
{% block footer %}
|
||||
{% block footer %}
|
||||
<!-- Page rendered on {{ 'now'|localizeddate('long', 'long', null, 'UTC') }} -->
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_navbar_messages %}
|
||||
{% block navbar_messages %}
|
||||
{% if app.user is not null and is_granted('IS_AUTHENTICATED_REMEMBERED') %}
|
||||
{% if is_granted('view_own_timesheet') %}
|
||||
<li class="visible-xs-inline-block">
|
||||
@@ -85,23 +77,76 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_navbar_notifications %}
|
||||
{% block navbar_notifications %}
|
||||
{% if app.user is not null and is_granted('IS_AUTHENTICATED_REMEMBERED') %}
|
||||
{{ render(controller('App\\Controller\\NavbarController::recentActivitiesAction')) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{# deactivated blocks #}
|
||||
{% block avanzu_navbar_tasks %}{% endblock %}
|
||||
{% block avanzu_navbar_user %}{% endblock %}
|
||||
{% block avanzu_sidebar_user %}{% endblock %}
|
||||
{% block avanzu_sidebar_search %}{% endblock %}
|
||||
{% block navbar_tasks %}{% endblock %}
|
||||
{% block sidebar_user %}{% endblock %}
|
||||
{% block sidebar_search %}{% endblock %}
|
||||
|
||||
{% block avanzu_breadcrumb %}
|
||||
{{ block('page_actions') }}
|
||||
{% block navbar_user %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
<li class="dropdown user-menu">
|
||||
<a href="#" class="dropdown-toggle ddt-large" data-toggle="dropdown">
|
||||
<i class="{{ 'user'|icon }} fa-2x"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
{% if app.user is not null %}
|
||||
<li>
|
||||
<a href="{{ path('user_profile', {'username' : app.user.username}) }}">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
<i class="{{ 'profile-stats'|icon }}"></i>
|
||||
{{ widgets.username(app.user) }}
|
||||
</h4>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('user_profile_edit', {'username' : app.user.username}) }}">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
<i class="{{ 'profile'|icon }}"></i>
|
||||
{{ 'profile.title'|trans }}
|
||||
</h4>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('user_profile_preferences', {'username' : app.user.username}) }}">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
<i class="{{ 'settings'|icon }}"></i>
|
||||
{{ 'profile.preferences'|trans }}
|
||||
</h4>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('fos_user_security_logout') }}">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
<i class="{{ 'logout'|icon }}"></i>
|
||||
{{ 'menu.logout'|trans }}
|
||||
</h4>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if kimai_context.show_about %}
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="{{ path('about') }}">
|
||||
<h4 class="control-sidebar-subheading">
|
||||
<i class="{{ 'about'|icon }}"></i>
|
||||
{{ 'about.title'|trans({}, 'about') }}
|
||||
</h4>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_actions %}{% endblock %}
|
||||
{% block breadcrumb %}
|
||||
{% block page_actions %}{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block stylesheets %}
|
||||
{# we do not call parent() as we use a custom built for the frontend assets and don't want the default <stylesheet> #}
|
||||
|
||||
@@ -1,31 +1,5 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block page_title %}{{ 'http_error.title'|trans({}, 'exceptions') }}{% endblock %}
|
||||
{% block page_subtitle %}{{ status_code }}{% endblock %}
|
||||
{% extends 'error.html.twig' %}
|
||||
|
||||
{% block main %}
|
||||
{% set errorTitleKey = "http_error_#{status_code}.description" %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorTitleKey == errorTitleTrans %}
|
||||
{% set errorTitleKey = 'http_error.description' %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
{% set errorMessageKey = "http_error_#{status_code}.suggestion" %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorMessageKey == errorMessageTrans %}
|
||||
{% set errorMessageKey = 'http_error.suggestion' %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-yellow"> {{ status_code }}</h2>
|
||||
|
||||
<div class="error-content">
|
||||
<h3><i class="fas fa-unlock-alt text-yellow"></i> {{ errorTitleTrans }}</h3>
|
||||
<p>{{ errorMessageTrans }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% block error_icon %}
|
||||
<i class="fas fa-unlock-alt text-yellow"></i>
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_control_sidebar %}{% endblock %}
|
||||
{% block avanzu_navbar_control_sidebar_toggle %}{% endblock %}
|
||||
|
||||
@@ -1,31 +1 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block page_title %}{{ 'http_error.title'|trans({}, 'exceptions') }}{% endblock %}
|
||||
{% block page_subtitle %}{{ status_code }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% set errorTitleKey = "http_error_#{status_code}.description" %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorTitleKey == errorTitleTrans %}
|
||||
{% set errorTitleKey = 'http_error.description' %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
{% set errorMessageKey = "http_error_#{status_code}.suggestion" %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorMessageKey == errorMessageTrans %}
|
||||
{% set errorMessageKey = 'http_error.suggestion' %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-yellow"> {{ status_code }}</h2>
|
||||
|
||||
<div class="error-content">
|
||||
<h3><i class="fas fa-unlock-alt text-yellow"></i> {{ errorTitleTrans }}</h3>
|
||||
<p>{{ errorMessageTrans }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block avanzu_control_sidebar %}{% endblock %}
|
||||
{% block avanzu_navbar_control_sidebar_toggle %}{% endblock %}
|
||||
{% extends 'error.html.twig' %}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block modal_footer %}
|
||||
<button type="submit" class="btn {% if used %}btn-outline{% else %}btn-primary{% endif %} pull-left modal-form-save" data-loading-text="{{ 'action.delete'|trans }}..." id="{{ block('modal_id') }}_save">{{ 'action.delete'|trans }}</button>
|
||||
<button type="button" class="btn btn-default btn-cancel" data-dismiss="modal">{{ 'action.close'|trans }}</button>
|
||||
<button type="submit" class="btn {% if used %}btn-outline{% else %}btn-primary{% endif %} modal-form-save" data-loading-text="{{ 'action.delete'|trans }}..." id="{{ block('modal_id') }}_save">{{ 'action.delete'|trans }}</button>
|
||||
{% endblock %}
|
||||
{% block modal_end %}{{ form_end(form) }}{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
{{ form_widget(form) }}
|
||||
{% endblock %}
|
||||
{% block modal_footer %}
|
||||
<button type="submit" class="btn btn-primary pull-left modal-form-save" data-loading-text="{{ 'action.save'|trans }}..." id="{{ block('modal_id') }}_save">{{ 'action.save'|trans }}</button>
|
||||
<button type="button" class="btn btn-default btn-cancel" data-dismiss="modal">{{ 'action.close'|trans }}</button>
|
||||
<button type="submit" class="btn btn-primary modal-form-save" data-loading-text="{{ 'action.save'|trans }}..." id="{{ block('modal_id') }}_save">{{ 'action.save'|trans }}</button>
|
||||
{% endblock %}
|
||||
{% block modal_end %}{{ form_end(form) }}{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
33
templates/error.html.twig
Normal file
33
templates/error.html.twig
Normal file
@@ -0,0 +1,33 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block page_title %}{{ 'http_error.title'|trans({}, 'exceptions') }}{% endblock %}
|
||||
{% block page_subtitle %}{{ status_code }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% set errorTitleKey = "http_error_#{status_code}.description" %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorTitleKey == errorTitleTrans %}
|
||||
{% set errorTitleKey = 'http_error.description' %}
|
||||
{% set errorTitleTrans = errorTitleKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
{% set errorMessageKey = "http_error_#{status_code}.suggestion" %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% if errorMessageKey == errorMessageTrans %}
|
||||
{% set errorMessageKey = 'http_error.suggestion' %}
|
||||
{% set errorMessageTrans = errorMessageKey|trans({ '%status_code%': status_code }, 'exceptions') %}
|
||||
{% endif %}
|
||||
|
||||
<div class="error-page">
|
||||
<h2 class="headline text-yellow"> {{ status_code }}</h2>
|
||||
|
||||
{% block error_content %}
|
||||
<div class="error-content">
|
||||
<h3>{% block error_icon %}{% endblock %} {{ errorTitleTrans }}</h3>
|
||||
<p>{{ errorMessageTrans }}</p>
|
||||
<a class="btn btn-primary" href="javascript:window.history.back();">{{ 'action.back'|trans }}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -8,6 +8,7 @@
|
||||
{% block page_actions %}
|
||||
{% set actions = {
|
||||
'filter': '#collapseExport',
|
||||
'visibility': '#modal_export',
|
||||
'off': {'id':'export-toggle-button'}
|
||||
} %}
|
||||
{{ widgets.page_actions(actions) }}
|
||||
@@ -27,13 +28,13 @@
|
||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||
{% else %}
|
||||
{% set columns = {
|
||||
'date': '',
|
||||
'date': 'alwaysVisible',
|
||||
'user': 'hidden-xs hidden-sm',
|
||||
'customer': 'hidden-xs hidden-sm',
|
||||
'project': 'hidden-xs hidden-sm',
|
||||
'activity': 'hidden-xs hidden-sm',
|
||||
'description': 'hidden-xs hidden-sm',
|
||||
'unit_price': '',
|
||||
'unit_price': 'hidden-xs',
|
||||
'duration': '',
|
||||
'total_rate': '',
|
||||
'exported': 'alwaysVisible',
|
||||
@@ -55,20 +56,20 @@
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td class="text-nowrap">{{ entry.begin|date_short }}</td>
|
||||
<td class="hidden-xs hidden-sm">{{ widgets.label_user(entry.user) }}</td>
|
||||
<td class="hidden-xs hidden-sm">{{ widgets.label_customer(entry.project.customer) }}</td>
|
||||
<td class="hidden-xs hidden-sm">{{ widgets.label_project(entry.project) }}</td>
|
||||
<td class="hidden-xs hidden-sm">{{ widgets.label_activity(entry.activity) }}</td>
|
||||
<td class="hidden-xs hidden-sm timesheet-description">
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'user') }}">{{ widgets.label_user(entry.user) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'customer') }}">{{ widgets.label_customer(entry.project.customer) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'project') }}">{{ widgets.label_project(entry.project) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'activity') }}">{{ widgets.label_activity(entry.activity) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'description') }} timesheet-description">
|
||||
{{ entry.description }}
|
||||
</td>
|
||||
<td class="text-nowrap">
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'unit_price') }} text-nowrap">
|
||||
{{ rate|money(currency) }}
|
||||
</td>
|
||||
<td class="text-nowrap">
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'duration') }} text-nowrap">
|
||||
{{ duration }}
|
||||
</td>
|
||||
<td class="text-nowrap">
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'total_rate') }} text-nowrap">
|
||||
{{ entry.rate|money(currency) }}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
{% block page_title %}{{ 'invoice.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'invoice.subtitle'|trans }}{% endblock %}
|
||||
{% block page_actions %}
|
||||
{% set actions = {'filter': '#collapseInvoice'} %}
|
||||
{% set actions = {'filter': '#collapseInvoice', 'visibility': '#modal_invoice'} %}
|
||||
{% if is_granted('create_invoice_template') %}
|
||||
{% set actions = actions|merge({'create': path('admin_invoice_template_create')}) %}
|
||||
{% endif %}
|
||||
@@ -37,10 +37,10 @@
|
||||
{{ widgets.callout('success', 'invoice.preview') }}
|
||||
|
||||
{% set columns = {
|
||||
'date': '',
|
||||
'user': 'hidden-xs hidden-sm',
|
||||
'activity': 'hidden-xs hidden-sm',
|
||||
'unit_price': 'text-center',
|
||||
'date': 'alwaysVisible',
|
||||
'user': 'hidden-sm',
|
||||
'description': 'hidden-xs hidden-sm',
|
||||
'unit_price': 'hidden-xs text-center',
|
||||
'amount': 'text-center',
|
||||
'total_rate': 'text-right',
|
||||
} %}
|
||||
@@ -60,17 +60,17 @@
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td class="text-nowrap">{{ entry.begin|date_short }}</td>
|
||||
<td class="hidden-xs hidden-sm">{{ widgets.label_user(entry.user) }}</td>
|
||||
<td class="hidden-xs hidden-sm timesheet-description">
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'user') }}">{{ widgets.label_user(entry.user) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'description') }} timesheet-description">
|
||||
{% if entry.description is not empty %}
|
||||
{{ entry.description|desc2html }}
|
||||
{% else %}
|
||||
{{ entry.activity.name }} / {{ entry.project.name }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-center">{{ rate|money(model.calculator.currency) }}</td>
|
||||
<td class="text-center text-nowrap">{{ duration }}</td>
|
||||
<td class="text-right text-nowrap">{{ entry.rate|money(model.calculator.currency) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'unit_price') }} text-center">{{ rate|money(model.calculator.currency) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'amount') }} text-center text-nowrap">{{ duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'total_rate') }} text-right text-nowrap">{{ entry.rate|money(model.calculator.currency) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{{ tables.data_table_footer(entries) }}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'label.date'|trans }}</th>
|
||||
<th>{{ 'label.activity'|trans }}</th>
|
||||
<th>{{ 'label.description'|trans }}</th>
|
||||
<th>{{ 'label.unit_price'|trans }}</th>
|
||||
<th>{{ 'label.hours'|trans }}</th>
|
||||
<th>{{ 'label.total_rate'|trans }}</th>
|
||||
|
||||
@@ -244,3 +244,31 @@
|
||||
{{ widgets.page_actions(event.payload.actions) }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro about(view) %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set actions = {'about': {'url': path('about')}} %}
|
||||
{% if is_granted('system_information') %}
|
||||
{% set actions = actions|merge({'debug': path('about_debug')}) %}
|
||||
{% endif %}
|
||||
|
||||
{% set event = trigger('actions.about', {'actions': actions, 'view': view}) %}
|
||||
{{ widgets.page_actions(event.payload.actions) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro profile(view, user) %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set actions = {'profile-stats': {'url': path('user_profile', {'username' : user.username})}} %}
|
||||
|
||||
{% if is_granted('edit', user) %}
|
||||
{% set actions = actions|merge({'profile': {'url': path('user_profile_edit', {'username' : user.username})}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('preferences', user) %}
|
||||
{% set actions = actions|merge({'settings': {'url': path('user_profile_preferences', {'username' : user.username})}}) %}
|
||||
{% endif %}
|
||||
|
||||
{% set event = trigger('actions.profile', {'actions': actions, 'view': view}) %}
|
||||
{{ widgets.page_actions(event.payload.actions) }}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
<p>{{ 'modal.columns.description'|trans }}</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary pull-left" onclick="$.datatable.saveVisibility('#modal_{{ name }}')">{{ 'action.save'|trans }}</button>
|
||||
<button type="button" class="btn btn-warning pull-left" onclick="$.datatable.resetVisibility('#modal_{{ name }}')">{{ 'action.delete'|trans }}</button>
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'action.close'|trans }}</button>
|
||||
<button type="button" class="btn btn-primary" onclick="$.datatable.saveVisibility('#modal_{{ name }}')">{{ 'action.save'|trans }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,10 +19,10 @@
|
||||
{% else %}
|
||||
{% set columns = {
|
||||
'name': 'alwaysVisible',
|
||||
'customer': '',
|
||||
'customer': 'hidden-xs',
|
||||
'comment': 'hidden-xs hidden-sm',
|
||||
'budget': 'hidden-xs',
|
||||
'visible': 'hidden-xs',
|
||||
'visible': '',
|
||||
'actions': 'alwaysVisible',
|
||||
} %}
|
||||
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set version = constant('App\\Constants::VERSION') ~ ' ' ~ constant('App\\Constants::STATUS') %}
|
||||
|
||||
<h3 class="control-sidebar-heading">Kimai v2 - {{ version }}</h3>
|
||||
<div class="form-group">
|
||||
{{ 'home.betainfo'|trans({'%version%': version}, 'sidebar')|raw|nl2br }}
|
||||
</div>
|
||||
|
||||
<ul class="control-sidebar-menu">
|
||||
<li>
|
||||
<a href="{{ constant('App\\Constants::GITHUB') }}" target="_blank">
|
||||
<i class="menu-icon fab fa-github bg-gray"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">GitHub</h4>
|
||||
<p>{{ 'home.github'|trans({}, 'sidebar')|raw }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ constant('App\\Constants::HOMEPAGE') }}" target="_blank">
|
||||
<i class="menu-icon fa fa-home bg-green"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'home.website'|trans({}, 'sidebar') }}</h4>
|
||||
<p>www.kimai.org</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% if is_granted('system_information') %}
|
||||
<li>
|
||||
<a href="{{ path('about') }}">
|
||||
<i class="menu-icon far fa-copyright bg-aqua"></i>
|
||||
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'about.title'|trans({}, 'about') }}</h4>
|
||||
<p>{{ 'about.subtitle'|trans({}, 'about') }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
<p><br>Made with ♥ by <a href="https://www.kevinpapst.de/">Kevin Papst</a> and <a href="{{ constant('App\\Constants::GITHUB') }}graphs/contributors" target="_blank">great contributors</a>.</p>
|
||||
@@ -1,68 +0,0 @@
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set linkUserProfile = path('user_profile', {'username' : user.username}) %}
|
||||
{% if not is_granted('view_own_profile') %}
|
||||
{% set linkUserProfile = '#' %}
|
||||
{% endif %}
|
||||
|
||||
<ul class="control-sidebar-menu">
|
||||
<li>
|
||||
<a href="{{ linkUserProfile }}">
|
||||
<div class="pull-left image">
|
||||
{{ macro.avatar(user.avatar, user.username, 'img-circle') }}
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ widgets.username(user) }}</h4>
|
||||
<p>{{ user.title }}</p>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="control-sidebar-menu">
|
||||
{% if is_granted('edit_own_profile') %}
|
||||
<li>
|
||||
<a href="{{ path('user_profile_edit', {'username' : user.username}) }}">
|
||||
<div class="pull-left image">
|
||||
<i class="{{ 'user'|icon }} text-gray"></i>
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'profile.title'|trans }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('preferences_own_profile') %}
|
||||
<li>
|
||||
<a href="{{ path('user_profile_preferences', {'username' : user.username}) }}">
|
||||
<div class="pull-left image">
|
||||
<i class="{{ 'settings'|icon }} text-gray"></i>
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'profile.preferences'|trans }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<a href="{{ ''|docu_link }}" target="_blank">
|
||||
<div class="pull-left image">
|
||||
<i class="{{ 'help'|icon }} text-gray"></i>
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'home.help'|trans({}, 'sidebar') }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('fos_user_security_logout') }}">
|
||||
<div class="pull-left image">
|
||||
<i class="{{ 'logout'|icon }} text-gray"></i>
|
||||
</div>
|
||||
<div class="menu-info">
|
||||
<h4 class="control-sidebar-subheading">{{ 'menu.logout'|trans }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
16
templates/user/form.html.twig
Normal file
16
templates/user/form.html.twig
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends 'user/layout.html.twig' %}
|
||||
{% import "macros/actions.html.twig" as actions %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}{{ ('profile.' ~ tab)|trans }}{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% endblock %}
|
||||
@@ -28,7 +28,7 @@
|
||||
'username': 'hidden-xs',
|
||||
'email': 'hidden-xs hidden-sm',
|
||||
'title': 'hidden-xs',
|
||||
'roles': '',
|
||||
'roles': 'hidden-xs',
|
||||
'active': '',
|
||||
'actions': 'alwaysVisible',
|
||||
} %}
|
||||
|
||||
151
templates/user/layout.html.twig
Normal file
151
templates/user/layout.html.twig
Normal file
@@ -0,0 +1,151 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "macros/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'profile.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'profile.subtitle'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.profile(tab, user) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% import _self as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
|
||||
{% block profile_content %}{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
{{ macro.profile_box(user, stats) }}
|
||||
{{ macro.profile_infos(user, stats) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% macro profile_infos(user, stats) %}
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'profile.about_me'|trans }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<ul class="nav nav-stacked">
|
||||
{# colors = purple, blue, aqua, red, green #}
|
||||
<li><a href="#">{{ 'label.id'|trans }} <span class="pull-right badge bg-aqua">{{ user.id }}</span></a></li>
|
||||
<li><a href="#">{{ 'label.username'|trans }} <span class="pull-right badge bg-blue">{{ user.username }}</span></a></li>
|
||||
<li><a href="#">{{ 'profile.first_entry'|trans }} <span class="pull-right badge bg-purple">{{ stats.firstEntry|date_short }}</span></a></li>
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li><a href="#">{{ 'label.hourlyRate'|trans }} <span class="pull-right badge bg-blue">{{ user.preferenceValue('hourly_rate') }}</span></a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro profile_box(user, stats) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-primary">
|
||||
<div class="box-body box-profile">
|
||||
{{ macro.avatar(user.avatar, user.username, 'profile-user-img img-responsive img-circle') }}
|
||||
<h3 class="profile-username text-center">{{ widgets.username(user) }}</h3>
|
||||
|
||||
<p class="text-muted text-center">{{ user.title }}</p>
|
||||
|
||||
<ul class="list-group list-group-unbordered">
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationMonth'|trans }}</b> <a class="pull-right">{{ stats.durationThisMonth|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountMonth'|trans }}</b> <a class="pull-right">{{ stats.amountThisMonth|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationTotal'|trans }}</b> <a class="pull-right">{{ stats.durationTotal|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountTotal'|trans }}</b> <a class="pull-right">{{ stats.amountTotal|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
|
||||
{% macro profile_list_unused(user, items, color) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-widget widget-user-2">
|
||||
<!-- Add the bg color to the header using any of the bg-* classes -->
|
||||
<div class="widget-user-header bg-{{ color|default(kimai_context.box_color) }}">
|
||||
<div class="widget-user-image">
|
||||
{{ macro.avatar(user.avatar, user.username) }}
|
||||
</div>
|
||||
<!-- /.widget-user-image -->
|
||||
<h3 class="widget-user-username">{{ widgets.username(user) }}</h3>
|
||||
<h5 class="widget-user-desc">{{ user.title }}</h5>
|
||||
</div>
|
||||
<div class="box-footer no-padding">
|
||||
<ul class="nav nav-stacked">
|
||||
{% for entry in items %}
|
||||
<li><a href="{{ entry.url }}">{{ entry.title|trans }} <span class="pull-right badge bg-{{ entry.color }}">{{ entry.value }}</span></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
|
||||
{% macro profile_box_unused(user, stats, color) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-widget widget-user">
|
||||
<div class="widget-user-header bg-{{ color|default(kimai_context.box_color) }}">
|
||||
<h3 class="widget-user-username">{{ widgets.username(user) }}</h3>
|
||||
<h5 class="widget-user-desc">{{ user.title }}</h5>
|
||||
</div>
|
||||
<div class="widget-user-image">
|
||||
{{ macro.avatar(user.avatar, user.username) }}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.durationTotal|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.durationTotal'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.amountTotal|money }}</h5>
|
||||
<span class="description-text">{{ 'stats.amountTotal'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.durationThisMonth|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.durationMonth'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.amountThisMonth|money }}</h5>
|
||||
<span class="description-text">{{ 'stats.amountMonth'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
@@ -1,117 +1,24 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block page_title %}{{ 'profile.title'|trans }}{% endblock %}
|
||||
{% block page_subtitle %}{{ 'profile.subtitle'|trans }}{% endblock %}
|
||||
{% extends 'user/layout.html.twig' %}
|
||||
{% import "macros/actions.html.twig" as actions %}
|
||||
|
||||
{% block main %}
|
||||
{% import _self as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
{{ macro.profile_box(user, stats) }}
|
||||
{{ macro.profile_infos(user, stats, local_time) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
|
||||
<div class="col-md-12">
|
||||
<div class="nav-tabs-custom">
|
||||
<ul class="nav nav-tabs">
|
||||
<li {% if tab == "charts" %}class="active"{% endif %}><a href="#charts" data-toggle="tab" aria-expanded="true">{{ 'profile.tab_monthly'|trans }}</a></li>
|
||||
{% for formName, form in forms %}
|
||||
<li {% if tab == formName %}class="active"{% endif %}><a href="#{{ formName }}" data-toggle="tab" aria-expanded="false">{{ ('profile.' ~ formName)|trans }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane {% if tab == "charts" %}active{% endif %}" id="charts">
|
||||
{% if years is empty %}
|
||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||
{% endif %}
|
||||
|
||||
<script type="text/javascript">
|
||||
var userProfileChartOptions = {
|
||||
maintainAspectRatio : true,
|
||||
responsive : true,
|
||||
legend : false,
|
||||
barPercentage : 0.5,
|
||||
categoryPercentage : 0.9,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: 'rgba(0,0,0,.05)',
|
||||
lineWidth: 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
var userProfileChartLabels = [
|
||||
{% for i in 1..12 %}
|
||||
'{{ ('month.' ~i)|trans }}'
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
];
|
||||
</script>
|
||||
|
||||
{% for year,yearStat in years %}
|
||||
<h2>{{ year }}</h2>
|
||||
<div class="chart">
|
||||
<canvas id="userProfileChart{{ year }}" style="height: 200px;"></canvas>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
var userProfileChartData{{ year }} = {
|
||||
labels: userProfileChartLabels,
|
||||
datasets: [
|
||||
{
|
||||
label: '{{ year }}',
|
||||
backgroundColor : '#00a65a',
|
||||
borderColor : '#00a65a',
|
||||
data: [
|
||||
{% for month in yearStat.months %}
|
||||
{{ (month.totalDuration / 3600)|round }}
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var userProfileChartCanvas{{ year }} = $("#userProfileChart{{ year }}").get(0).getContext("2d");
|
||||
|
||||
{% if tab == 'charts' %}
|
||||
var userProfileChart{{ year }} = new Chart(
|
||||
userProfileChartCanvas{{ year }}, {
|
||||
type: 'bar',
|
||||
data: userProfileChartData{{ year }},
|
||||
options: userProfileChartOptions
|
||||
}
|
||||
);
|
||||
{% endif %}
|
||||
|
||||
$('a[href="#charts"]').on('shown.bs.tab', function(event){
|
||||
var userProfileChart{{ year }} = new Chart(
|
||||
userProfileChartCanvas{{ year }}, {
|
||||
type: 'bar',
|
||||
data: userProfileChartData{{ year }},
|
||||
options: userProfileChartOptions
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% for formName, form in forms %}
|
||||
<div class="tab-pane {% if tab == formName %}active{% endif %}" id="{{ formName }}">
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
|
||||
{{ form_widget(form) }}
|
||||
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
@@ -120,131 +27,3 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% macro profile_infos(user, stats, local_time) %}
|
||||
<div class="box box-primary">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'profile.about_me'|trans }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<ul class="nav nav-stacked">
|
||||
{# colors = purple, blue, aqua, red, green #}
|
||||
<li><a href="#">{{ 'label.id'|trans }} <span class="pull-right badge bg-aqua">{{ user.id }}</span></a></li>
|
||||
<li><a href="#">{{ 'label.username'|trans }} <span class="pull-right badge bg-blue">{{ user.username }}</span></a></li>
|
||||
<li><a href="#">{{ 'profile.first_entry'|trans }} <span class="pull-right badge bg-purple">{{ stats.firstEntry|date_short }}</span></a></li>
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li><a href="#">{{ 'label.hourlyRate'|trans }} <span class="pull-right badge bg-blue">{{ user.preferenceValue('hourly_rate') }}</span></a></li>
|
||||
{% endif %}
|
||||
<li><a href="#">{{ 'label.now'|trans }} <span class="pull-right badge bg-blue">{{ local_time|date_short }} {{ local_time|time }}</span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro profile_box(user, stats) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-primary">
|
||||
<div class="box-body box-profile">
|
||||
{{ macro.avatar(user.avatar, user.username, 'profile-user-img img-responsive img-circle') }}
|
||||
<h3 class="profile-username text-center">{{ widgets.username(user) }}</h3>
|
||||
|
||||
<p class="text-muted text-center">{{ user.title }}</p>
|
||||
|
||||
<ul class="list-group list-group-unbordered">
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationMonth'|trans }}</b> <a class="pull-right">{{ stats.durationThisMonth|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountMonth'|trans }}</b> <a class="pull-right">{{ stats.amountThisMonth|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationTotal'|trans }}</b> <a class="pull-right">{{ stats.durationTotal|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountTotal'|trans }}</b> <a class="pull-right">{{ stats.amountTotal|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
|
||||
{% macro profile_list_unused(user, items, color) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-widget widget-user-2">
|
||||
<!-- Add the bg color to the header using any of the bg-* classes -->
|
||||
<div class="widget-user-header bg-{{ color|default(kimai_context.box_color) }}">
|
||||
<div class="widget-user-image">
|
||||
{{ macro.avatar(user.avatar, user.username) }}
|
||||
</div>
|
||||
<!-- /.widget-user-image -->
|
||||
<h3 class="widget-user-username">{{ widgets.username(user) }}</h3>
|
||||
<h5 class="widget-user-desc">{{ user.title }}</h5>
|
||||
</div>
|
||||
<div class="box-footer no-padding">
|
||||
<ul class="nav nav-stacked">
|
||||
{% for entry in items %}
|
||||
<li><a href="{{ entry.url }}">{{ entry.title|trans }} <span class="pull-right badge bg-{{ entry.color }}">{{ entry.value }}</span></a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
|
||||
{% macro profile_box_unused(user, stats, color) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-widget widget-user">
|
||||
<div class="widget-user-header bg-{{ color|default(kimai_context.box_color) }}">
|
||||
<h3 class="widget-user-username">{{ widgets.username(user) }}</h3>
|
||||
<h5 class="widget-user-desc">{{ user.title }}</h5>
|
||||
</div>
|
||||
<div class="widget-user-image">
|
||||
{{ macro.avatar(user.avatar, user.username) }}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.durationTotal|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.durationTotal'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.amountTotal|money }}</h5>
|
||||
<span class="description-text">{{ 'stats.amountTotal'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.durationThisMonth|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.durationMonth'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 border-right">
|
||||
<div class="description-block">
|
||||
<h5 class="description-header">{{ stats.amountThisMonth|money }}</h5>
|
||||
<span class="description-text">{{ 'stats.amountMonth'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
97
templates/user/stats.html.twig
Normal file
97
templates/user/stats.html.twig
Normal file
@@ -0,0 +1,97 @@
|
||||
{% extends 'user/layout.html.twig' %}
|
||||
{% import "macros/actions.html.twig" as actions %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% block profile_content %}
|
||||
|
||||
{% if years is empty %}
|
||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||
{% endif %}
|
||||
|
||||
<script type="text/javascript">
|
||||
var userProfileChartOptions = {
|
||||
maintainAspectRatio : true,
|
||||
responsive : true,
|
||||
legend : false,
|
||||
barPercentage : 0.5,
|
||||
categoryPercentage : 0.9,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: 'rgba(0,0,0,.05)',
|
||||
lineWidth: 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
var userProfileChartLabels = [
|
||||
{% for i in 1..12 %}
|
||||
'{{ ('month.' ~i)|trans }}'
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
];
|
||||
</script>
|
||||
|
||||
{% for year,yearStat in years %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}{{ year }}{% endblock %}
|
||||
{% block box_body %}
|
||||
|
||||
<div class="chart">
|
||||
<canvas id="userProfileChart{{ year }}" style="height: 200px;"></canvas>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
var userProfileChartData{{ year }} = {
|
||||
labels: userProfileChartLabels,
|
||||
datasets: [
|
||||
{
|
||||
label: '{{ year }}',
|
||||
backgroundColor : '#00a65a',
|
||||
borderColor : '#00a65a',
|
||||
data: [
|
||||
{% for month in yearStat.months %}
|
||||
{{ (month.totalDuration / 3600)|round }}
|
||||
{% if not loop.last %},{% endif %}
|
||||
{% endfor %}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var userProfileChartCanvas{{ year }} = $("#userProfileChart{{ year }}").get(0).getContext("2d");
|
||||
|
||||
{% if tab == 'charts' %}
|
||||
var userProfileChart{{ year }} = new Chart(
|
||||
userProfileChartCanvas{{ year }}, {
|
||||
type: 'bar',
|
||||
data: userProfileChartData{{ year }},
|
||||
options: userProfileChartOptions
|
||||
}
|
||||
);
|
||||
{% endif %}
|
||||
|
||||
$('a[href="#charts"]').on('shown.bs.tab', function(event){
|
||||
var userProfileChart{{ year }} = new Chart(
|
||||
userProfileChartCanvas{{ year }}, {
|
||||
type: 'bar',
|
||||
data: userProfileChartData{{ year }},
|
||||
options: userProfileChartOptions
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user