added new report: project view (#1738)
This commit is contained in:
committed by
GitHub
parent
0b7d551048
commit
c34e9f576d
@@ -7,6 +7,9 @@
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{% if customer.visible and is_granted('create_project') %}
|
||||
{% if is_granted('view_reporting') and is_granted('budget_project') %}
|
||||
<a class="btn btn-default btn-sm btn-pager" href="{{ path('report_project_view', {'customer': customer.id}) }}" data-toggle="tooltip" data-placement="top" title="{{ 'report_project_view'|trans({}, 'reporting') }}"><i class="{{ 'reporting'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
<a class="modal-ajax-form open-edit btn btn-default btn-sm btn-pager" data-href="{{ path('admin_project_create_with_customer', {'customer': customer.id}) }}" data-toggle="tooltip" data-placement="top" title="{{ 'create'|trans }}"><i class="{{ 'create'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% if projects|length > 0 %}
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
{{ 'export.page_of'|trans({'%page%': '{PAGENO}', '%pages%': '{nb}'}) }}
|
||||
{% if not showUserColumn and query.user %}
|
||||
–
|
||||
{{ 'label.user'|trans }}: {{ query.user.displayName }}
|
||||
{{ 'label.user'|trans }}: {{ query.user.displayName }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td align="right">
|
||||
|
||||
@@ -46,62 +46,58 @@
|
||||
{% set orderBy = false %}
|
||||
{% set order = false %}
|
||||
{% endif %}
|
||||
{% set striped = options.striped|default(true) %}
|
||||
{% set striped = options.striped ?? true %}
|
||||
{% set bordered = options.bordered ?? false %}
|
||||
{% set reloadEvent = options.reload|default('') %}
|
||||
{% set translationDomain = options.translationDomain|default('messages') %}
|
||||
{# |default does not work here, as the prefix might be an empty string #}
|
||||
{% set translationPrefix = 'label.' %}
|
||||
{% if options.translationPrefix is defined %}
|
||||
{% set translationPrefix = options.translationPrefix %}
|
||||
{% endif %}
|
||||
{% set translationPrefix = options.translationPrefix ?? 'label.' %}
|
||||
{% set boxClass = options.boxClass ?? 'box box-' ~ admin_lte_context.widget.type ~ ' data_table' %}
|
||||
|
||||
{% import _self as macro %}
|
||||
<div class="box box-{{ admin_lte_context.widget.type }} data_table" id="datatable_{{ tableName }}">
|
||||
<div class="{{ boxClass }}" id="datatable_{{ tableName }}">
|
||||
<div class="box-body no-padding">
|
||||
<div class="dataTables_wrapper form-inline dt-bootstrap">
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<table class="table {% if striped %}table-striped {% endif %}table-hover dataTable" role="grid" data-reload-event="{{ reloadEvent }}" id="dt_{{ tableName }}">
|
||||
<thead>
|
||||
<tr>
|
||||
{%- for title, headerOptions in columns -%}
|
||||
{% if not headerOptions is iterable %}
|
||||
{% set headerOptions = {'class': headerOptions} %}
|
||||
{% endif %}
|
||||
{% if not headerOptions.orderBy is defined %}
|
||||
{% if orderBy is same as(false) %}
|
||||
{% set headerOptions = headerOptions|merge({'orderBy': false}) %}
|
||||
{% else %}
|
||||
{% set headerOptions = headerOptions|merge({'orderBy': title}) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set headerClass = macro.data_table_column_class(tableName, columns, title) %}
|
||||
{% if title != 'actions' and not headerOptions.orderBy is same as(false) %}
|
||||
{% if orderBy == headerOptions.orderBy %}
|
||||
{% set headerClass = headerClass ~ ' sortable sorting_' ~ (order) %}
|
||||
{% else %}
|
||||
{% set headerClass = headerClass ~ ' sortable sorting' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set headerTitle = '' %}
|
||||
{% if headerOptions.title is defined %}
|
||||
{% set headerTitle = headerOptions.title %}
|
||||
{% elseif title is not empty and title != 'actions' %}
|
||||
{% set headerTitle = (translationPrefix ~ title)|trans({}, translationDomain) %}
|
||||
{% endif %}
|
||||
<th data-field="{{ title }}" {% if not headerOptions.orderBy is same as(false) %}data-order="{{ headerOptions.orderBy }}" {% endif %}class="{{ headerClass }}">
|
||||
{% if headerOptions.html_before is defined %}
|
||||
{{ headerOptions.html_before|raw }}
|
||||
{% endif %}
|
||||
{{ headerTitle }}
|
||||
{% if headerOptions.html_after is defined %}
|
||||
{{ headerOptions.html_after|raw }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<table class="table {% if striped %}table-striped {% endif %}{% if bordered %}table-bordered {% endif %}table-hover dataTable" role="grid" data-reload-event="{{ reloadEvent }}" id="dt_{{ tableName }}">
|
||||
<thead>
|
||||
<tr>
|
||||
{%- for title, headerOptions in columns -%}
|
||||
{% if not headerOptions is iterable %}
|
||||
{% set headerOptions = {'class': headerOptions} %}
|
||||
{% endif %}
|
||||
{% if not headerOptions.orderBy is defined %}
|
||||
{% if orderBy is same as(false) %}
|
||||
{% set headerOptions = headerOptions|merge({'orderBy': false}) %}
|
||||
{% else %}
|
||||
{% set headerOptions = headerOptions|merge({'orderBy': title}) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set headerClass = macro.data_table_column_class(tableName, columns, title) %}
|
||||
{% if title != 'actions' and not headerOptions.orderBy is same as(false) %}
|
||||
{% if orderBy == headerOptions.orderBy %}
|
||||
{% set headerClass = headerClass ~ ' sortable sorting_' ~ (order) %}
|
||||
{% else %}
|
||||
{% set headerClass = headerClass ~ ' sortable sorting' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set headerTitle = '' %}
|
||||
{% if headerOptions.title is defined %}
|
||||
{% set headerTitle = headerOptions.title %}
|
||||
{% elseif title is not empty and title != 'actions' %}
|
||||
{% set headerTitle = (translationPrefix ~ title)|trans({}, translationDomain) %}
|
||||
{% endif %}
|
||||
<th data-field="{{ title }}" {% if not headerOptions.orderBy is same as(false) %}data-order="{{ headerOptions.orderBy }}" {% endif %}class="{{ headerClass }}">
|
||||
{% if headerOptions.html_before is defined %}
|
||||
{{ headerOptions.html_before|raw }}
|
||||
{% endif %}
|
||||
{{ headerTitle }}
|
||||
{% if headerOptions.html_after is defined %}
|
||||
{{ headerOptions.html_after|raw }}
|
||||
{% endif %}
|
||||
</th>
|
||||
{%- endfor -%}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro data_table_column_class(name, columns, column) %}
|
||||
@@ -185,10 +181,8 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro data_table_footer(entries, route, multi_update_form) %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
118
templates/reporting/project_view.html.twig
Normal file
118
templates/reporting/project_view.html.twig
Normal file
@@ -0,0 +1,118 @@
|
||||
{% extends 'reporting/layout.html.twig' %}
|
||||
{% import "macros/datatables.html.twig" as tables %}
|
||||
|
||||
{% block report_title %}{{ 'report_project_view'|trans({}, 'reporting') }}{% endblock %}
|
||||
|
||||
{% set columns = {
|
||||
'name': {'class': 'alwaysVisible'},
|
||||
'today': {'class': 'text-nowrap text-right', 'title': 'daterangepicker.today'|trans({}, 'daterangepicker')},
|
||||
'week': {'class': 'text-nowrap text-right', 'title': 'agendaWeek'|trans},
|
||||
'month': {'class': 'text-nowrap text-right', 'title': 'month'|trans},
|
||||
'durationTotal': {'class': 'hidden-md hidden-sm hidden-xs text-nowrap text-right', 'title': 'stats.durationTotal'|trans},
|
||||
'timeBudget': {'class': 'text-nowrap', 'title': 'label.timeBudget'|trans},
|
||||
'budget': {'class': 'text-nowrap', 'title': 'label.budget'|trans},
|
||||
'stateDuration': {'class': 'hidden-sm hidden-xs text-nowrap text-right', 'title': 'entryState.not_exported'|trans},
|
||||
'stateMoney': {'class': 'hidden-sm hidden-xs text-nowrap text-right', 'title': 'entryState.not_exported'|trans},
|
||||
'projectEnd': {'class': 'hidden-md hidden-sm hidden-xs hidden text-nowrap text-center', 'title': 'label.project_end'|trans},
|
||||
'comment': {'class': 'hidden-md hidden-sm hidden-xs hidden', 'title': 'label.comment'|trans},
|
||||
} %}
|
||||
{% set tableName = 'project_view_reporting' %}
|
||||
|
||||
{% block main_before %}
|
||||
{{ tables.data_table_column_modal(tableName, columns) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block report %}
|
||||
|
||||
{% set hasData = entries|length > 0 %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "macros/datatables.html.twig" as tables %}
|
||||
{% block box_body_class %}project-view-reporting-box {% if hasData %}no-padding{% endif %} table-responsive{% endblock %}
|
||||
{% block box_before %}
|
||||
{{ form_start(form, {'attr': {'class': 'form-inline form-reporting', 'id': 'project-view-form'}}) }}
|
||||
{% endblock %}
|
||||
{% block box_after %}
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{{ widgets.action_button('visibility', {'modal': '#modal_project_view_reporting', 'class': 'btn-sm'}) }}
|
||||
{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ form_widget(form) }}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{% if not hasData %}
|
||||
{{ widgets.nothing_found() }}
|
||||
{% else %}
|
||||
{{ tables.datatable_header(tableName, columns, null, {'bordered': true, 'striped': false, 'boxClass': ''}) }}
|
||||
|
||||
{% for id, mapping in entries|sort((a, b) => a.customer.name <=> b.customer.name) %}
|
||||
{% if is_granted('budget', mapping.customer) %}
|
||||
<tr>
|
||||
<th colspan="11">{{ widgets.label_customer(mapping.customer) }}</th>
|
||||
</tr>
|
||||
{% for entry in mapping.projects|sort((a, b) => a.project.name <=> b.project.name) %}
|
||||
{% set project = entry.project %}
|
||||
{% set currency = project.customer.currency %}
|
||||
{% if is_granted('budget', project) %}
|
||||
<tr{% if is_granted('view', project) %} class="alternative-link open-edit" data-href="{{ path('project_details', {'id': project.id}) }}"{% endif %}>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'name') }}">{{ widgets.label_project(project) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'today') }}">{{ entry.durationDay|duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'week') }}">{{ entry.durationWeek|duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'month') }}">{{ entry.durationMonth|duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'durationTotal') }}">{{ entry.durationTotal|duration }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'timeBudget') }}">
|
||||
{% if project.timeBudget > 0 %}
|
||||
{{ progress.progressbar(project.timeBudget, entry.durationTotal|default(0), entry.durationTotal|duration ~ ' / ' ~ project.timeBudget|duration, '') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'budget') }}">
|
||||
{% if project.budget > 0 %}
|
||||
{{ progress.progressbar(project.budget, entry.rateTotal|default(0), entry.rateTotal|money(currency) ~ ' / ' ~ project.budget|money(currency), '') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'stateDuration') }}">
|
||||
{% if is_granted('create_export') %}
|
||||
<a href="{{ path('export', {'customers[]': project.customer.id, 'projects[]': project.id, 'daterange': '', 'preview': true}) }}">
|
||||
{{ entry.notExportedDuration|duration }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ entry.notExportedDuration|duration }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'stateMoney') }}">
|
||||
{% if is_granted('view_invoice') %}
|
||||
<a href="{{ path('invoice', {'customer': project.customer.id, 'projects[]': project.id, 'daterange': ''}) }}">
|
||||
{{ entry.notExportedRate|money(currency) }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ entry.notExportedRate|money(currency) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'projectEnd') }}">{% if project.end is not null %}{{ project.end|date_short }}{% endif %}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">{{ project.comment }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ tables.data_table_footer(entries) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function() {
|
||||
$('#project-view-form').on('change', function(ev) {
|
||||
$(this).submit();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user