upgraded to symfony 4 #74 (#81)

This commit is contained in:
Kevin Papst
2018-01-12 20:39:07 +01:00
committed by GitHub
parent c011b83b73
commit a87355695e
232 changed files with 5260 additions and 4231 deletions

View File

@@ -0,0 +1,48 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.name': '',
'label.customer': '',
'label.project': '',
'label.comment': 'hidden-xs',
'label.visible': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_activity_create')}) }}
{% for entry in entries %}
<tr>
<td>{{ entry.name }}</td>
<td>
<a href="{{ path('admin_customer_edit', {'id' : entry.project.customer.id}) }}">{{ widgets.label_customer(entry.project.customer) }}</a>
</td>
<td>
<a href="{{ path('admin_project_edit', {'id' : entry.project.id}) }}">{{ widgets.label_project(entry.project) }}</a>
</td>
<td class="hidden-xs">{{ entry.comment }}</td>
<td>{{ widgets.label_visible(entry.visible) }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_activity_edit', {'id': entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_activity_delete', {'id': entry.id})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_activity_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }}{% endblock %}
{% block main %}
{% set params = {
'%activity%': '<strong>' ~ activity.name ~ '</strong>',
'%project%': '<strong>' ~ activity.project.name ~ '</strong>',
'%customer%': '<strong>' ~ activity.project.customer.name ~ '</strong>',
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
} %}
{{ include('default/_form_delete.html.twig', {
'message': "admin_activity.delete_confirm"|trans(params)|raw,
'form': form,
'back': path('admin_activity')
}) }}
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_activity.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_activity.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': activity.name|default('create'|trans),
'form': form,
'back': path('admin_activity')
}) }}
{% endblock %}

View File

@@ -0,0 +1,54 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{# Available fields: vat; contact; address; country; phone; fax; mobile; mail; homepage; timezone; #}
{{ tables.data_table_header({
'label.id': 'hidden-xs',
'label.name': '',
'label.project': '',
'label.comment': 'hidden-xs',
'label.country': 'hidden-xs',
'label.currency': 'hidden-xs',
'label.visible': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_customer_create')}) }}
{% for entry in entries %}
<tr>
<td class="hidden-xs">{{ entry.id }}</td>
<td>{{ entry.name }} {% if entry.company is not empty %}({{ entry.company }}){% endif %}</td>
<td>
{% for project in entry.projects %}
<a href="{{ path('admin_project_edit', {'id' : project.id}) }}">{{ widgets.label_project(project) }}</a>
{% endfor %}
</td>
<td class="hidden-xs">{{ entry.comment }}</td>
<td class="hidden-xs">{{ entry.country|country }}</td>
<td class="hidden-xs">{{ entry.currency }} {{ entry.currency|currency }}</td>
<td>{{ widgets.label_visible(entry.visible) }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_customer_edit', {'id': entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_customer_delete', {'id': entry.id})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_customer_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }}{% endblock %}
{% block main %}
{% set params = {
'%activity%': '<strong>' ~ stats.activityAmount ~ '</strong>',
'%project%': '<strong>' ~ stats.projectAmount ~ '</strong>',
'%customer%': '<strong>' ~ customer.name ~ '</strong>',
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
} %}
{{ include('default/_form_delete.html.twig', {
'message': "admin_customer.delete_confirm"|trans(params)|raw,
'form': form,
'back': path('admin_customer')
}) }}
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': customer.name|default('create'|trans),
'form': form,
'back': path('admin_customer')
}) }}
{% endblock %}

View File

@@ -0,0 +1,48 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_project.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.id': 'hidden-xs',
'label.name': '',
'label.customer': '',
'label.comment': 'hidden-xs hidden-sm',
'label.budget': 'hidden-xs',
'label.visible': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_project_create')}) }}
{% for entry in entries %}
<tr>
<td class="hidden-xs">{{ entry.id }}</td>
<td>{{ entry.name }}</td>
<td>
<a href="{{ path('admin_customer_edit', {'id' : entry.customer.id}) }}">{{ widgets.label_customer(entry.customer) }}</a>
</td>
<td class="hidden-xs hidden-sm">{{ entry.comment }}</td>
<td class="hidden-xs">{{ entry.budget|money(entry.customer.currency) }}</td>
<td>{{ widgets.label_visible(entry.visible) }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_project_edit', {'id': entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_project_delete', {'id': entry.id})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_project_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,24 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_project.subtitle'|trans }}{% endblock %}
{% block main %}
{% set params = {
'%project%': '<strong>' ~ project.name ~ '</strong>',
'%customer%': '<strong>' ~ project.customer.name ~ '</strong>',
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
'%activities%': '<strong>' ~ stats.activityAmount ~ '</strong>',
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
} %}
{{ include('default/_form_delete.html.twig', {
'message': "admin_project.delete_confirm"|trans(params)|raw,
'form': form,
'back': path('admin_project')
}) }}
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_project.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': project.name|default('create'|trans),
'form': form,
'back': path('admin_project')
}) }}
{% endblock %}

View File

@@ -0,0 +1,61 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'admin_timesheet.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_timesheet.subtitle'|trans }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.date': '',
'label.starttime': 'hidden-xs',
'label.endtime': 'hidden-xs',
'label.duration': '',
'label.rate': '',
'label.activity': 'hidden-xs hidden-sm',
'label.username': 'hidden-xs',
'label.description': 'hidden-xs hidden-sm',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_timesheet_create')}) }}
{% for entry in entries %}
<tr>
<td>{{ entry.begin|date(kimai_context.date_1) }}</td>
<td class="hidden-xs">{{ entry.begin|date("H:i") }}</td>
{% if entry.end %}
<td class="hidden-xs">{{ entry.end|date("H:i") }}</td>
<td>{{ entry.duration|duration }}</td>
<td>{{ entry.rate|money(entry.activity.project.customer.currency) }}</td>
{% else %}
<td class="hidden-xs">&dash;</td>
<td>&dash;</td>
<td>&dash;</td>
{% endif %}
<td class="hidden-xs hidden-sm">
<a href="{{ path('admin_activity_edit', {'id': entry.activity.id}) }}">{{ widgets.label_activity(entry.activity) }}</a>
</td>
<td class="hidden-xs"><a href="{{ path('profile'|route_alias, {'username' : entry.user.username}) }}">{{ widgets.label_user(entry.user) }}</a></td>
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('admin_timesheet_edit', {'id' : entry.id, 'page': page})}|merge(actionButtons) %}
{% endif %}
{% if not entry.end and is_granted('stop', entry) %}
{% set actionButtons = {'stop': path('admin_timesheet_stop', {'id' : entry.id})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('admin_timesheet_delete', {'id' : entry.id, 'page': page})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_timesheet_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'timesheet.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'timesheet.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': (entry.id ? 'timesheet.edit'|trans : 'create'|trans),
'form': form,
'back': path('admin_timesheet')
}) }}
{% endblock %}

View File

@@ -0,0 +1,52 @@
{% extends 'base.html.twig' %}
{% import "macros/datatables.html.twig" as tables %}
{% import "macros/widgets.html.twig" as widgets %}
{% block page_title %}{{ 'admin_user.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_user.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.id': 'hidden-xs',
'label.alias': '',
'label.username': 'hidden-xs',
'label.email': 'hidden-xs hidden-sm',
'label.title': 'hidden-xs',
'label.active': '',
'label.roles': '',
'label.actions': '',
}, toolbarForm, {'plus-square': path('admin_user_create')}) }}
{% for entry in entries %}
<tr>
<td class="hidden-xs">{{ entry.id }}</td>
<td>{{ widgets.username(entry) }}</td>
<td class="hidden-xs">{{ entry.username }}</td>
<td class="hidden-xs hidden-sm">{{ entry.email }}</td>
<td class="hidden-xs">{{ entry.title }}</td>
<td>{{ widgets.label_visible(entry.active) }}</td>
<td>
{% for role in entry.roles %}
{{ widgets.label_role(role) }}
{% endfor %}
</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('user_profile', {'username' : entry.username})}|merge(actionButtons) %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': '#'}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'admin_user_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends 'base.html.twig' %}
{% block page_title %}{{ 'admin_user.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_user.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': 'create'|trans,
'form': form,
'back': path('admin_user')
}) }}
{% endblock %}

100
templates/base.html.twig Normal file
View File

@@ -0,0 +1,100 @@
{% extends '@AvanzuAdminTheme/layout/default-layout.html.twig' %}
{% block avanzu_page_content %}
{{ include('default/_flash_messages.html.twig') }}
{% block main %}{% endblock %}
{% endblock %}
{% block avanzu_document_title %}
{% block title %}{{ 'browser.title'|trans }}{% endblock %}
{% endblock %}
{% block avanzu_page_title %}
{% block page_title %}{% endblock %}
{% endblock %}
{% block avanzu_page_subtitle %}
{% block page_subtitle %}{% endblock %}
{% endblock %}
{% block avanzu_logo_path %}
{{ path('dashboard') }}
{% endblock %}
{% block avanzu_logo_mini %}
<b>K</b>TT
{% endblock %}
{% block avanzu_logo_lg %}
<b>Kimai</b> - Time Tracking
{% endblock %}
{% block avanzu_head %}
<link rel="stylesheet" href="{{ asset('css/kimai.css') }}">
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
{% endblock %}
{% block avanzu_footer %}
{% block footer %}
<footer class="main-footer">
<div class="pull-right hidden-xs">
<b>Version</b> 2.0
</div>
<strong>Copyright &copy; {{ 'now'|date('Y') }} - <a href="http://www.kevinpapst.de">Kevin Papst</a></strong>.
{{ 'footer.license'|trans }}
</footer>
<!-- Page rendered on {{ 'now'|localizeddate('long', 'long', null, 'UTC') }} -->
{% endblock %}
{% endblock %}
{% block avanzu_navbar_messages %}
{% if app.user is not null and is_granted('IS_AUTHENTICATED_FULLY') %}
{{ render(controller('App\\Controller\\TimesheetController::activeEntriesAction')) }}
{% endif %}
{% endblock %}
{% block avanzu_navbar_notifications %}
{% if app.user is not null and is_granted('IS_AUTHENTICATED_FULLY') %}
{{ render(controller('App\\Controller\\ActivityController::recentActivitiesAction')) }}
{% endif %}
{#
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-globe"></i> <span class="caret"></span></a>
<ul class="dropdown-menu locales" role="menu">
{% for locale in locales() %}
<li {% if app.request.locale == locale.code %}class="active"{% endif %}><a href="{{ path(app.request.get('_route', 'homepage'), app.request.get('_route_params', [])|merge({ _locale: locale.code })) }}">{{ locale.name|capitalize }}</a></li>
{% endfor %}
</ul>
</li>
#}
{% endblock %}
{% block avanzu_navbar_toggle %}{{ parent() }}{% endblock %}
{% block avanzu_navbar_tasks %}{{ parent() }}{% endblock %}
{% block avanzu_navbar_user %}{{ parent() }}{% endblock %}
{% block avanzu_navbar_control_sidebar_toggle %}{{ parent() }}{% endblock %}
{% block avanzu_sidebar_user %}{# right now we simply deactivate that box #}{% endblock %}
{% block avanzu_sidebar_search %}{# right now we simply deactivate that box #}{% endblock %}
{% block avanzu_sidebar_nav %}{{ parent() }}{% endblock %}
{% block avanzu_breadcrumb %}{{ parent() }}{% endblock %}
{% block avanzu_control_sidebar %}{{ parent() }}{% endblock %}
{% block avanzu_javascripts %}
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ asset('theme/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('js/kimai.js') }}"></script>
<script src="{{ asset('js/Chart.min.js') }}"></script>
{% block javascript_imports %}{% endblock %}
{% endblock %}
{% block avanzu_javascripts_inline %}
<script type="text/javascript">
$(document).ready(function () {
$('.dropdown-toggle').dropdown();
$(document).kimai({imagePath: '{{ asset('images') }}', confirmDelete: '{{ 'confirm.delete'|trans }}'});
//$(document).kimai('pauseRecord', 'li.messages-menu ul.menu li');
});
</script>
{% endblock %}

View File

@@ -0,0 +1,38 @@
{# User Account: style can be found in dropdown.less #}
{% import "@AvanzuAdminTheme/layout/macros.html.twig" as macro %}
<li class="dropdown user user-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{ macro.avatar(user.avatar, user.username, 'user-image') }}
<span class="hidden-xs">{{ user.name }}</span>
</a>
<ul class="dropdown-menu">
<!-- User image -->
<li class="user-header">
{{ macro.avatar(user.avatar, user.username) }}
<p>
{{user.name}}
<small>{{user.title}}</small>
</p>
</li>
{#
<!-- Menu Body -->
<li class="user-body">
<div class="col-xs-4 text-center">
</div>
<div class="col-xs-4 text-center">
</div>
<div class="col-xs-4 text-center">
</div>
</li>
#}
<!-- Menu Footer-->
<li class="user-footer">
<div class="pull-left">
<a href="{{ path('user_profile', {'username' : user.username}) }}" class="btn btn-default btn-flat">{{ 'label.user_profile'|trans }}</a>
</div>
<div class="pull-right">
<a href="{{ logout_path() }}" class="btn btn-default btn-flat">{{ 'label.logout'|trans }}</a>
</div>
</li>
</ul>
</li>

View File

@@ -0,0 +1,12 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<link rel="stylesheet" href="{{ asset('theme/bootstrap/css/bootstrap.min.css') }}">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
{#<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css">#}
<link rel="stylesheet" href="{{ asset('theme/dist/css/AdminLTE.min.css') }}">
<link rel="stylesheet" href="{{ asset("theme/dist/css/skins/" ~ avanzu_admin_context.skin|default('skin-blue-light') ~ ".min.css") }}">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->

View File

@@ -0,0 +1,28 @@
{#
This template is used to render any error different from 403, 404 and 500.
This is the simplest way to customize error pages in Symfony applications.
In case you need it, you can also hook into the internal exception handling
made by Symfony. This allows you to perform advanced tasks and even recover
your application from some errors.
See http://symfony.com/doc/current/cookbook/controller/error_pages.html
#}
{% extends 'base.html.twig' %}
{% block body_id 'error' %}
{% block main %}
<h1 class="text-danger">{{ 'http_error.name'|trans({ '%status_code%': status_code }) }}</h1>
<p class="lead">
{{ 'http_error.description'|trans({ '%status_code%': status_code }) }}
</p>
<p>
{{ 'http_error.suggestion'|trans({ '%url%': path('homepage') })|raw }}
</p>
{% endblock %}
{% block sidebar %}
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,28 @@
{#
This template is used to render errors of type HTTP 403 (Forbidden)
This is the simplest way to customize error pages in Symfony applications.
In case you need it, you can also hook into the internal exception handling
made by Symfony. This allows you to perform advanced tasks and even recover
your application from some errors.
See http://symfony.com/doc/current/cookbook/controller/error_pages.html
#}
{% extends 'base.html.twig' %}
{% block body_id 'error' %}
{% block main %}
<h1 class="text-danger"><i class="fa fa-unlock-alt"></i> {{ 'http_error.name'|trans({ '%status_code%': 403 }) }}</h1>
<p class="lead">
{{ 'http_error_403.description'|trans }}
</p>
<p>
{{ 'http_error_403.suggestion'|trans }}
</p>
{% endblock %}
{% block sidebar %}
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,28 @@
{#
This template is used to render errors of type HTTP 404 (Not Found)
This is the simplest way to customize error pages in Symfony applications.
In case you need it, you can also hook into the internal exception handling
made by Symfony. This allows you to perform advanced tasks and even recover
your application from some errors.
See http://symfony.com/doc/current/cookbook/controller/error_pages.html
#}
{% extends 'base.html.twig' %}
{% block body_id 'error' %}
{% block main %}
<h1 class="text-danger">{{ 'http_error.name'|trans({ '%status_code%': 404 }) }}</h1>
<p class="lead">
{{ 'http_error_404.description'|trans }}
</p>
<p>
{{ 'http_error_404.suggestion'|trans({ '%url%': path('homepage') })|raw }}
</p>
{% endblock %}
{% block sidebar %}
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,28 @@
{#
This template is used to render errors of type HTTP 500 (Internal Server Error)
This is the simplest way to customize error pages in Symfony applications.
In case you need it, you can also hook into the internal exception handling
made by Symfony. This allows you to perform advanced tasks and even recover
your application from some errors.
See http://symfony.com/doc/current/cookbook/controller/error_pages.html
#}
{% extends 'base.html.twig' %}
{% block body_id 'error' %}
{% block main %}
<h1 class="text-danger">{{ 'http_error.name'|trans({ '%status_code%': 500 }) }}</h1>
<p class="lead">
{{ 'http_error_500.description'|trans }}
</p>
<p>
{{ 'http_error_500.suggestion'|trans({ '%url%': path('homepage') })|raw }}
</p>
{% endblock %}
{% block sidebar %}
{{ parent() }}
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% block page_title %}{{ 'dashboard.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'dashboard.subtitle'|trans }}{% endblock %}
{% block main %}
{% for settings in dashboard_widgets %}
{% if settings.header %}
{{ widgets.page_header(settings.header) }}
{% endif %}
{% set width = settings.widgets|length %}
{% set rawWidth = 12 / width %}
{% set columnWidth = rawWidth|round(0, 'floor') %}
<div class="row">
{% for widgetTemplate in settings.widgets %}
<div class="col-md-{{ columnWidth }} col-sm-{{ columnWidth * 2 }} col-xs-{{ columnWidth * 4 }}">
{% set widgetString = '{% import "macros/widgets.html.twig" as widgets %}' ~ widgetTemplate %}
{{ include(template_from_string(widgetString)) }}
</div>
{% endfor %}
</div>
{% endfor %}
{% endblock %}

View File

@@ -0,0 +1,9 @@
{% import "@AvanzuAdminTheme/layout/macros.html.twig" as macro %}
{% if app.session.started and app.session.flashbag.peekAll|length > 0 %}
<div class="row">
<div class="col-sm-12">
{{ macro.session_flash(avanzu_adminlte_close_alert|default(true), false, '', 'flashmessages') }}
</div>
</div>
{% endif %}

View File

@@ -0,0 +1,16 @@
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">{{ title }}</h3>
</div>
{{ form_start(form) }}
<div class="box-body">
{{ form_widget(form) }}
</div>
<div class="box-footer">
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
{% if back %}
<a href="{{ back }}" class="btn btn-warning">{{ 'action.back'|trans }}</a>
{% endif %}
</div>
{{ form_end(form) }}
</div>

View File

@@ -0,0 +1,20 @@
<div class="box box-solid box-danger">
<div class="box-header">
<h3 class="box-title">{{ title|default('confirm.delete'|trans) }}</h3>
</div>
<div class="box-body">
{{ message|default('confirm.delete_message'|trans)|raw }}
</div>
{{ form_start(form) }}
<div class="box-body">
{{ form_widget(form) }}
</div>
<div class="box-footer">
<input type="submit" value="{{ 'action.delete'|trans }}" class="btn btn-danger" />
{% if back %}
<a href="{{ back }}" class="btn btn-primary">{{ 'action.back'|trans }}</a>
{% endif %}
</div>
{{ form_end(form) }}
</div>

View File

@@ -0,0 +1,19 @@
{#
Each field type is rendered by a template fragment, which is determined
by the name of your form type class (DateTimePickerType -> date_time_picker)
and the suffix "_widget". This can be controlled by overriding getBlockPrefix()
in DateTimePickerType.
See http://symfony.com/doc/current/cookbook/form/create_custom_field_type.html#creating-a-template-for-the-field
#}
{% block date_time_picker_widget %}
{% spaceless %}
<div class="input-group date" data-toggle="datetimepicker">
{{ block('datetime_widget') }}
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
{% endspaceless %}
{% endblock %}

View File

@@ -0,0 +1,78 @@
{% macro data_table_header(entries, form, tools, toolsRight) %}
<div class="box data_table">
{% if form or tools or toolsRight %}
<div class="box-header with-border">
{% if tools %}
<div class="btn-group tools-left">
{% for icon,url in tools %}
<a class="btn btn-default" href="{{ url }}"><i class="fa fa-{{ icon }}"></i></a>
{% endfor %}
</div>
{% endif %}
{% if form %}
<div class="box-title toolbar">
{{ form_start(form) }}
{{ form_widget(form) }}
{{ form_end(form) }}
</div>
{% endif %}
{% if toolsRight %}
<div class="box-tools">
<div class="btn-group">
{% for icon,url in tools %}
<a class="btn btn-default" href="{{ url }}"><i class="fa fa-{{ icon }}"></i></a>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endif %}
<div class="box-body no-padding">
<div class="dataTables_wrapper form-inline dt-bootstrap">
<div class="row">
<div class="col-sm-6"></div>
<div class="col-sm-6"></div>
</div>
<div class="row">
<div class="col-sm-12">
<table class="table table-striped table-hover dataTable" role="grid">
<thead>
<tr>
{% for title, class in entries %}
<th{% if class %} class="{{ class }}"{% endif %}>
{{ title|trans }}
</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% endmacro %}
{% macro data_table_footer(entries, route) %}
</tbody>
</table>
</div>
</div>
{#<div class="row">
<div class="col-sm-5">
{#<div class="dataTables_info" id="example2_info" role="status" aria-live="polite">
{{ 'datatables.entry_counter'|trans({'%from%': '1', '%to%': '10', '%total%': entries.count}) }}
</div># }
</div>
<div class="col-sm-7">
<div class="dataTables_paginate paging_simple_numbers">
{{ pagerfanta(entries, 'twitter_bootstrap3_translated', { routeName: route }) }}
</div>
</div>
</div>#}
</div>
</div>
</div>
<div class="navigation text-center">
{{ pagerfanta(entries, 'twitter_bootstrap3_translated', { routeName: route }) }}
</div>
{% endmacro %}

View File

@@ -0,0 +1,173 @@
{% macro page_header(title) %}
<h2 class="page-header">{{ title|trans }}</h2>
{% endmacro %}
{% macro label_visible(visible) %}
{% import _self as macro %}
{% if visible %}
{{ macro.label('badge.visible', 'success') }}
{% else %}
{{ macro.label('badge.invisible', 'warning') }}
{% endif %}
{% endmacro %}
{% macro label_role(role) %}
{% import _self as macro %}
{% if role == 'ROLE_SUPER_ADMIN' %}
{{ macro.label(role, 'danger') }}
{% else %}
{{ macro.label(role, 'primary') }}
{% endif %}
{% endmacro %}
{% macro username(user) %}
{{ user.alias|default(user.username) }}
{% endmacro %}
{% macro label_user(user) %}
{% import _self as macro %}
{{ macro.label(macro.username(user), 'primary') }}
{% endmacro %}
{% macro label_activity(activity) %}
{% import _self as macro %}
{% if activity.visible and activity.project.visible and activity.project.customer.visible %}
{{ macro.label(activity.name, 'primary', activity.project.customer.name ~ ': ' ~ activity.project.name) }}
{% else %}
{{ macro.label(activity.name, 'warning', activity.project.customer.name ~ ': ' ~ activity.project.name) }}
{% endif %}
{% endmacro %}
{% macro label_project(project) %}
{% import _self as macro %}
{% if project.visible and project.customer.visible %}
{{ macro.label(project.name, 'primary', project.customer.name) }}
{% else %}
{{ macro.label(project.name, 'warning', project.customer.name) }}
{% endif %}
{% endmacro %}
{% macro label_customer(customer) %}
{% import _self as macro %}
{% if customer.visible %}
{{ macro.label(customer.name, 'primary') }}
{% else %}
{{ macro.label(customer.name, 'warning') }}
{% endif %}
{% endmacro %}
{% macro badge_counter(count, url) %}
{% if url %}
<a href="{{ url }}"><span class="badge bg-blue">{{ count }}</span></a>
{% else %}
<span class="badge bg-blue">{{ count }}</span>
{% endif %}
{% endmacro %}
{% macro label(title, type, tooltip) %}
{# success, warning, danger, primary #}
<span {% if tooltip %}title="{{ tooltip }}" {% endif %}class="label label-{{ type|default('success') }}">{{ title|trans }}</span>
{% endmacro %}
{% macro badge(title, color) %}
{# black, green, blue, yellow #}
<span class="badge bg-{{ color|default('red') }}">{{ title|trans }}</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 %}<h4><i class="icon fa fa-{{ icon|default('ban') }}"></i> {{ title|trans }}</h4>{% endif %}
{{ description|trans }}
</div>
{% endmacro %}
{% macro callout(type, description, title) %}
<div class="callout callout-{{ type|default('danger') }} lead">
{% if title %}<h4>{{ title|trans }}</h4>{% endif %}
<p>{{ description|trans }}</p>
</div>
{% endmacro %}
{% macro info_box_counter(title, amount, icon, color, url) %}
<div class="info-box">
<span class="info-box-icon bg-{{ color|default(kimai_context.box_color) }}"><i class="fa fa-{{ icon|default('flag-o') }}"></i></span>
<div class="info-box-content">
{# this is a ugly hack, make me look nicely (dashboard widget with link) #}
{% if url %}
<a href="{{ url }}" class="small-box-footer">
{% endif %}
<span class="info-box-text">{{ title|trans }}</span>
<span class="info-box-number">{{ amount }}</span>
{% if url %}
</a>
{% endif %}
</div>
</div>
{% endmacro %}
{% macro info_box_progress(title, description, amount, percentage, icon, color) %}
<div class="info-box bg-{{ color|default(kimai_context.box_color) }}">
<span class="info-box-icon"><i class="fa fa-{{ icon|default('thumbs-o-up') }}"></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 info_box_more(title, amount, unit, url, icon, color) %}
<div class="small-box bg-{{ color|default(kimai_context.box_color) }}">
<div class="inner">
<h3>{{ amount }}<sup style="font-size: 20px">{{ unit|default('') }}</sup></h3>
<p>{{ title|trans }}</p>
</div>
<div class="icon">
<i class="fa fa-{{ icon|default('bar-chart') }}"></i>
</div>
<a href="{{ url }}" class="small-box-footer">
{{ 'more.info.link'|trans }} <i class="fa fa-arrow-circle-right"></i>
</a>
</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>
{% endmacro %}
{% macro button_group(actions) %}
{% import _self as macro %}
<div class="btn-group">
{% for icon, url in actions %}
{{ macro.button_action(icon, url) }}
{% endfor %}
</div>
{% endmacro %}
{% macro button_action(icon, url) %}
<a href="{{ url }}" class="btn btn-default btn-{{ icon }}">
<i class="fa fa-{{ icon }}"></i>
</a>
{% endmacro %}

View File

@@ -0,0 +1,31 @@
<li class="dropdown messages-menu">
<a href="#" class="dropdown-toggle ddt-large ticktac" data-toggle="dropdown">
<i class="fa fa-play-circle fa-2x"></i>
{% if entries is not empty %}<span class="label label-{% if entries|length >= kimai_context.active_warning %}danger{% else %}warning{% endif %}">{{ entries|length }}</span>{% endif %}
</a>
<ul class="dropdown-menu">
<li class="header">
{{ 'active.entries'|transchoice(entries|length) }}
</li>
<li>
<ul class="menu">
{% for entry in entries %}
<li>
<a href="{{ path('timesheet_stop', {'id' : entry.id}) }}">
<div class="pull-left">
<i class="fa fa-stop-circle fa-2x"></i>
</div>
<h4>
{{ entry.activity.name }}
<small><i class="fa fa-clock-o"></i> {{ entry|durationForEntry }}</small>
</h4>
<p>{{ entry.activity.project.name }} ({{ entry.activity.project.customer.name }})</p>
</a>
</li>
{% endfor %}
</ul>
</li>
<li class="footer"><a href="{{ path('timesheet_create') }}">{{ 'timesheet.start'|trans }}</a></li>
</ul>
</li>

View File

@@ -0,0 +1,23 @@
{% if activities is not empty %}
<li class="dropdown notifications-menu">
<a href="#" class="dropdown-toggle ddt-large" data-toggle="dropdown">
<i class="fa fa-tasks fa-2x"></i>
<span class="label label-success">{{ activities|length }}</span>
</a>
<ul class="dropdown-menu">
<li class="header">{{ 'recent.activities'|transchoice(activities|length) }}</li>
<li>
<ul class="menu">
{% for activity in activities %}
<li>
<a href="{{ path('timesheet_start', {'id' : activity.id}) }}">
<i class="fa fa-play-circle text-green"></i> {{ 'recent.activities.format'|trans({'%activity%': activity.name, '%project%': activity.project.name, '%customer%': activity.project.customer.name}) }}
</a>
</li>
{% endfor %}
</ul>
</li>
<li class="footer"><a href="{{ url('timesheet') }}">{{ 'timesheet.all'|trans }}</a></li>
</ul>
</li>
{% endif %}

View File

@@ -0,0 +1,40 @@
{% extends '@AvanzuAdminTheme/layout/login-layout.html.twig' %}
{% block avanzu_login_title %}{{ 'browser.title'|trans }}{% endblock %}
{% block avanzu_logo_login %}<b>Kimai</b><br>TimeTracking{% endblock %}
{% block avanzu_login_box_msg %}
{{ 'security.title.login'|trans }}
{% if error|default(false) %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
{% endblock %}
{% block avanzu_login_form %}
<form action="{{ path('security_login') }}" method="post">
<div class="form-group has-feedback">
<input type="text" name="_username" class="form-control" placeholder="{{ 'security.label.username'|trans }}" value="{{ last_username }}">
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input name="_password" type="password" class="form-control" placeholder="{{ 'security.label.password'|trans }}">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
{#
<div class="checkbox icheck">
<label>
<input type="checkbox"> {{ 'Remember Me'|trans({}, 'AvanzuAdminTheme') }}
</label>
</div>
#}
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">{{ 'security.action.sign_in'|trans }}</button>
</div>
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}"/>
</form>
{% endblock %}
{% block avanzu_login_social_auth %}{% endblock %}
{% block avanzu_login_actions %}{% endblock %}

View File

@@ -0,0 +1,14 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'timesheet.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'timesheet.subtitle'|trans }}{% endblock %}
{% block main %}
{{ include('default/_form.html.twig', {
'title': (entry.id ? 'timesheet.edit'|trans : 'create'|trans),
'form': form,
'back': path('timesheet')
}) }}
{% endblock %}

View File

@@ -0,0 +1,63 @@
{% extends 'base.html.twig' %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/datatables.html.twig" as tables %}
{% block page_title %}{{ 'timesheet.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'timesheet.subtitle'|trans }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %}
{% if entries.count == 0 %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
{{ tables.data_table_header({
'label.date': '',
'label.starttime': '',
'label.endtime': '',
'label.duration': 'hidden-xs',
'label.rate': 'hidden-xs',
'label.activity': 'hidden-xs hidden-sm',
'label.description': 'hidden-xs hidden-sm',
'label.actions': '',
}, toolbarForm, {'plus-square': path('timesheet_create')}) }}
{% for entry in entries %}
<tr>
<td>{{ entry.begin|date(kimai_context.date_1) }}</td>
<td>{{ entry.begin|date("H:i") }}</td>
{% if entry.end %}
<td>{{ entry.end|date("H:i") }}</td>
<td class="hidden-xs">{{ entry.duration|duration }}</td>
<td class="hidden-xs">{{ entry.rate|money(entry.activity.project.customer.currency) }}</td>
{% else %}
<td>&dash;</td>
<td class="hidden-xs"><i>{{ entry.duration|duration }}</i></td>
<td class="hidden-xs">&dash;</td>
{% endif %}
<td class="hidden-xs hidden-sm">{{ widgets.label_activity(entry.activity) }}</td>
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
<td>
{% set actionButtons = {} %}
{% if is_granted('edit', entry) %}
{% set actionButtons = {'edit': path('timesheet_edit', {'id' : entry.id, 'page': page})}|merge(actionButtons) %}
{% endif %}
{% if entry.end %}
{% if is_granted('start', entry.activity) %}
{% set actionButtons = {'repeat': path('timesheet_start', {'id' : entry.activity.id})}|merge(actionButtons) %}
{% endif %}
{% else %}
{% if is_granted('stop', entry) %}
{% set actionButtons = {'stop': path('timesheet_stop', {'id' : entry.id})}|merge(actionButtons) %}
{% endif %}
{% endif %}
{% if is_granted('delete', entry) %}
{% set actionButtons = actionButtons|merge({'trash': path('timesheet_delete', {'id' : entry.id, 'page': page})}) %}
{% endif %}
{{ widgets.button_group(actionButtons) }}
</td>
</tr>
{% endfor %}
{{ tables.data_table_footer(entries, 'timesheet_paginated') }}
{% endblock %}

View File

@@ -0,0 +1,254 @@
{% extends 'base.html.twig' %}
{% block page_title %}{{ 'profile.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'profile.subtitle'|trans }}{% endblock %}
{% 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) }}
</div>
<div class="col-md-9">
<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>
{% if form %}
<li {% if tab == "profile" %}class="active"{% endif %}><a href="#profile" data-toggle="tab" aria-expanded="false">{{ 'profile.settings'|trans }}</a></li>
{% endif %}
{% if form_password %}
<li {% if tab == "password" %}class="active"{% endif %}><a href="#password" data-toggle="tab" aria-expanded="false">{{ 'profile.password'|trans }}</a></li>
{% endif %}
{% if form_roles %}
<li {% if tab == "roles" %}class="active"{% endif %}><a href="#roles" data-toggle="tab" aria-expanded="false">{{ 'profile.roles'|trans }}</a></li>
{% endif %}
</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 barChartOptions = {
scaleBeginAtZero: true,
scaleShowGridLines: true,
scaleGridLineColor: "rgba(0,0,0,.05)",
scaleGridLineWidth: 1,
scaleShowHorizontalLines: true,
scaleShowVerticalLines: true,
barShowStroke: true,
barStrokeWidth: 2,
barValueSpacing: 5,
barDatasetSpacing: 1,
responsive: true,
maintainAspectRatio: true,
tooltipTemplate: "<%= value %> {{ 'label.hours'|trans }}",
};
var barChartLabels = [
{% for i in 1..11 %}
"{{ ('month.' ~i)|trans }}",
{% endfor %}
"{{ 'month.12'|trans }}"
];
</script>
{% for year,yearStat in years %}
<h2>{{ year }}</h2>
<div class="chart">
<canvas id="barChart{{ year }}" style="height: 230px;"></canvas>
</div>
<script type="text/javascript">
var barChartData{{ year }} = {
labels: barChartLabels,
datasets: [
{
{# label: '# hours',#}
fillColor: "#00a65a",
strokeColor: "#00a65a",
pointColor: "#00a65a",
pointStrokeColor: "#c1c7d1",
pointHighlightFill: "#fff",
pointHighlightStroke: "rgba(220,220,220,1)",
data: [
{% for i in 1..11 %}
{{ (yearStat.month(i).totalDuration / 3600)|round }},
{% endfor %}
{{ (yearStat.month(12).totalDuration / 3600)|round }}
]
}
]
};
{% if tab == "charts" %}
$(function () {
var barChartCanvas{{ year }} = $("#barChart{{ year }}").get(0).getContext("2d");
var barChart = new Chart(barChartCanvas{{ year }});
barChart.Bar(barChartData{{ year }}, barChartOptions);
});
{% endif %}
$('a[href="#charts"]').on('shown.bs.tab', function(e){
var barChartCanvas{{ year }} = $("#barChart{{ year }}").get(0).getContext("2d");
var barChart = new Chart(barChartCanvas{{ year }});
barChart.Bar(barChartData{{ year }}, barChartOptions);
});
</script>
{% endfor %}
</div>
{% if form %}
<div class="tab-pane {% if tab == "profile" %}active{% endif %}" id="profile">
{{ form_start(form) }}
{{ form_widget(form) }}
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
{{ form_end(form) }}
</div>
{% endif %}
{% if form_password %}
<div class="tab-pane {% if tab == "password" %}active{% endif %}" id="password">
{{ form_start(form_password) }}
{{ form_widget(form_password) }}
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
{{ form_end(form_password) }}
</div>
{% endif %}
{% if form_roles %}
<div class="tab-pane {% if tab == "roles" %}active{% endif %}" id="roles">
{{ form_start(form_roles) }}
{{ form_widget(form_roles) }}
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
{{ form_end(form_roles) }}
</div>
{% endif %}
</div>
</div>
</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 #}
{# FIXME hourly rate must be dynamic <li><a href="#">{{ 'label.hourly_rate'|trans }} <span class="pull-right badge bg-blue">70</span></a></li> #}
<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="#">{{ 'label.language'|trans }} <span class="pull-right badge bg-green">{{ user.language }}</span></a></li>
<li><a href="#">{{ 'profile.first_entry'|trans }} <span class="pull-right badge bg-purple">{{ stats.firstEntry|date }}</span></a></li>
</ul>
</div>
</div>
{% endmacro %}
{% macro profile_box(user, stats) %}
{% import "@AvanzuAdminTheme/layout/macros.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.durationThisMonth'|trans }}</b> <a class="pull-right">{{ stats.durationThisMonth|duration }}</a>
</li>
<li class="list-group-item">
<b>{{ 'stats.amountThisMonth'|trans }}</b> <a class="pull-right">{{ stats.amountThisMonth|money }}</a>
</li>
<li class="list-group-item">
<b>{{ 'stats.durationTotal'|trans }}</b> <a class="pull-right">{{ stats.durationTotal|duration }}</a>
</li>
<li class="list-group-item">
<b>{{ 'stats.amountTotal'|trans }}</b> <a class="pull-right">{{ stats.amountTotal|money }}</a>
</li>
</ul>
{# <a href="#" class="btn btn-primary btn-block"><b>Follow</b></a> #}
</div>
<!-- /.box-body -->
</div>
{% endmacro %}
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
{% macro profile_list_unused(user, items, color) %}
{% import "@AvanzuAdminTheme/layout/macros.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 "@AvanzuAdminTheme/layout/macros.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.durationThisMonth'|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.amountThisMonth'|trans }}</span>
</div>
</div>
</div>
</div>
</div>
{% endmacro %}