Next major version 2 with PHP 8.1, Symfony 6, Tabler UI, 2FA ... (#2902)
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ render_widget(widgets.0) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
{% if widgets|length > 1 %}
|
||||
<div class="row">
|
||||
{% set width = (widgets|length) - 1 %}
|
||||
{% set rawWidth = 12 / width %}
|
||||
{% set columnWidth = rawWidth|round(0, 'floor') %}
|
||||
{% for widget in widgets|slice(1, width) %}
|
||||
{% set data = widget.data %}
|
||||
{% if widget.option('dataType') == 'duration' %}
|
||||
{% set data = widget.data|duration %}
|
||||
{% elseif widget.option('dataType') == 'money' %}
|
||||
{% set data = widget.data|money %}
|
||||
{% endif %}
|
||||
<div class="col-sm-{{ columnWidth }} col-xs-{{ columnWidth * 2 }}">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data }}</h5>
|
||||
<span class="description-text">{{ widget.title|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,22 +0,0 @@
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set width = widgets|length %}
|
||||
{% if width > 0 %}
|
||||
{% if not title is empty %}
|
||||
{{ widgets.page_header(title) }}
|
||||
{% endif %}
|
||||
|
||||
{% set rawWidth = 12 / width %}
|
||||
{% set columnWidth = rawWidth|round(0, 'floor') %}
|
||||
<div class="row">
|
||||
{% for widget in widgets %}
|
||||
{% set columnSize = columnWidth %}
|
||||
{% if width == 5 and (loop.first or loop.last) %}
|
||||
{% set columnSize = columnWidth + 1 %}
|
||||
{% endif %}
|
||||
<div class="col-md-{{ columnSize }} col-sm-{{ columnSize * 2 }} col-xs-{{ columnSize * 4 }}">
|
||||
{{ render_widget(widget) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
4
templates/widget/widget-counter-duration.html.twig
Normal file
4
templates/widget/widget-counter-duration.html.twig
Normal file
@@ -0,0 +1,4 @@
|
||||
{% extends 'widget/widget-counter.html.twig' %}
|
||||
{% block widget_data %}
|
||||
{{ data|duration }}
|
||||
{% endblock %}
|
||||
16
templates/widget/widget-counter-money.html.twig
Normal file
16
templates/widget/widget-counter-money.html.twig
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends 'widget/widget-counter.html.twig' %}
|
||||
{% from 'macros/widgets.html.twig' import label %}
|
||||
{% block widget_data %}
|
||||
{% if data is empty %}
|
||||
{% set data = {(null): 0.00} %}
|
||||
{% endif %}
|
||||
{% if data|length > 1 %}
|
||||
{% for currency, revenue in data %}
|
||||
{{ label(revenue|money(currency|default(options.currency|default(null))), options.color) }}
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
{% for currency, revenue in data %}
|
||||
{{ revenue|money(currency|default(options.currency|default(null))) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -3,26 +3,26 @@
|
||||
{% set url = path(options.route, options.routeOptions|default([])) %}
|
||||
{% endif %}
|
||||
|
||||
<div class="info-box">
|
||||
<span class="info-box-icon bg-{{ options.color|default('green') }}"><i class="{{ options.icon|icon(options.icon) }}"></i></span>
|
||||
|
||||
<div class="info-box-content">
|
||||
{% if not url is empty %}<a href="{{ url }}" class="small-box-footer">{% endif %}
|
||||
<span class="info-box-text">{{ title|trans }}</span>
|
||||
<span class="info-box-number">
|
||||
{% if data is iterable %}
|
||||
{{ 'Invalid data' }}
|
||||
{% else %}
|
||||
{% block widget_data %}
|
||||
{% if options.dataType == 'duration' %}
|
||||
{% set data = data|duration %}
|
||||
{% elseif options.dataType == 'money' %}
|
||||
{% set data = data|money %}
|
||||
{% endif %}
|
||||
{{ data }}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% if not url is empty %}</a>{% endif %}
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-{{ options.color|default('green') }} text-white avatar">
|
||||
<i class="{{ options.icon|icon(true, options.icon) }}"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
{% if not url is empty %}<a href="{{ url }}">{% endif %}
|
||||
<div class="font-weight-medium">
|
||||
{{ title|trans }}
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
{% block widget_data %}
|
||||
{{ data }}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% if not url is empty %}</a>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
{% set data = data.data %}
|
||||
|
||||
<div class="chart">
|
||||
<canvas id="{{ chart_id }}" style="height: {{ config('theme.chart.height') }}px;"></canvas>
|
||||
<canvas id="{{ chart_id }}" style="height: {{ config('theme.chart.height') }}px; width: 100%;"></canvas>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var myChart = null;
|
||||
|
||||
|
||||
var paintChart = function() {
|
||||
myChart = new Chart(
|
||||
document.getElementById('{{ chart_id }}').getContext('2d'), {
|
||||
@@ -19,7 +19,7 @@
|
||||
data: {
|
||||
labels: [
|
||||
{% for day in data -%}
|
||||
moment('{{ day.day|date_format('Y-m-d') }}').format('ll')
|
||||
'{{ day.day|date_format('d.') }} {{ day.day|month_name(true) }}'
|
||||
{% if not loop.last %},{% endif -%}
|
||||
{%- endfor %}
|
||||
],
|
||||
@@ -72,18 +72,17 @@
|
||||
},
|
||||
options: {
|
||||
maintainAspectRatio: true,
|
||||
responsive: true,
|
||||
legend: false,
|
||||
responsive: false,
|
||||
barPercentage: 0.5,
|
||||
categoryPercentage: 0.9,
|
||||
categoryPercentage: 1.0,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
x: {
|
||||
stacked: true,
|
||||
gridLines: {
|
||||
display: false
|
||||
},
|
||||
}],
|
||||
yAxes: [{
|
||||
},
|
||||
y: {
|
||||
stacked: true,
|
||||
ticks: {
|
||||
beginAtZero: true
|
||||
@@ -93,37 +92,42 @@
|
||||
color: '{{ gridColor }}',
|
||||
lineWidth: 1
|
||||
}
|
||||
}],
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: function(tooltipItem, data) {
|
||||
var tooltipData = data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
||||
return ' ' + tooltipData.duration + ': ' + tooltipData.activity;
|
||||
},
|
||||
beforeTitle: function(tooltipItems, data) {
|
||||
var tooltipItem = tooltipItems[0];
|
||||
var tooltipData = data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
||||
return tooltipData.customer;
|
||||
},
|
||||
title: function(tooltipItems, data) {
|
||||
var tooltipItem = tooltipItems[0];
|
||||
var tooltipData = data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
||||
return tooltipData.project;
|
||||
},
|
||||
afterTitle: function(tooltipItems, data) {
|
||||
return ' ';
|
||||
},
|
||||
footer: function(tooltipItems, data) {
|
||||
var tooltipItem = tooltipItems[0];
|
||||
var tooltipData = data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
||||
return '{{ 'stats.durationTotal'|trans }}: ' + tooltipData.total + '\n{{ 'label.billable'|trans }}: ' + tooltipData.billable;
|
||||
},
|
||||
beforeFooter: function(tooltipItems, data) {
|
||||
return ' ';
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(tooltipItem) {
|
||||
const tooltipData = tooltipItem.dataset.realData[tooltipItem.dataIndex];
|
||||
return ' ' + tooltipData.duration + ': ' + tooltipData.activity;
|
||||
},
|
||||
beforeTitle: function(tooltipItems) {
|
||||
const tooltipItem = tooltipItems[0];
|
||||
const tooltipData = tooltipItem.dataset.realData[tooltipItem.dataIndex];
|
||||
return tooltipData.customer;
|
||||
},
|
||||
title: function(tooltipItems) {
|
||||
const tooltipItem = tooltipItems[0];
|
||||
const tooltipData = tooltipItem.dataset.realData[tooltipItem.dataIndex];
|
||||
return tooltipData.project;
|
||||
},
|
||||
afterTitle: function(tooltipItems) {
|
||||
return ' ';
|
||||
},
|
||||
footer: function(tooltipItems) {
|
||||
const tooltipItem = tooltipItems[0];
|
||||
const tooltipData = tooltipItem.dataset.realData[tooltipItem.dataIndex];
|
||||
return '{{ 'stats.durationTotal'|trans }}: ' + tooltipData.total + '\n{{ 'billable'|trans }}: ' + tooltipData.billable;
|
||||
},
|
||||
beforeFooter: function(tooltipItems) {
|
||||
return ' ';
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -132,10 +136,14 @@
|
||||
var destroyChart = function () {
|
||||
myChart.destroy();
|
||||
};
|
||||
|
||||
{% if app.request.xmlHttpRequest %}
|
||||
|
||||
{% if kimai_context.javascriptRequest %}
|
||||
paintChart();
|
||||
{% else %}
|
||||
document.addEventListener('kimai.initialized', paintChart);
|
||||
if (document.getElementById('dashboard-grid-container') !== null) {
|
||||
document.addEventListener('dashboard.initialized', paintChart);
|
||||
} else {
|
||||
document.addEventListener('kimai.initialized', paintChart);
|
||||
}
|
||||
{% endif %}
|
||||
</script>
|
||||
|
||||
4
templates/widget/widget-more-duration.html.twig
Normal file
4
templates/widget/widget-more-duration.html.twig
Normal file
@@ -0,0 +1,4 @@
|
||||
{% extends 'widget/widget-more.html.twig' %}
|
||||
{% block widget_data %}
|
||||
{{ data|duration }}
|
||||
{% endblock %}
|
||||
4
templates/widget/widget-more-money.html.twig
Normal file
4
templates/widget/widget-more-money.html.twig
Normal file
@@ -0,0 +1,4 @@
|
||||
{% extends 'widget/widget-more.html.twig' %}
|
||||
{% block widget_data %}
|
||||
{{ data|money(options.currency|default(null)) }}
|
||||
{% endblock %}
|
||||
@@ -3,31 +3,31 @@
|
||||
{% set url = path(options.route, options.routeOptions|default([])) %}
|
||||
{% endif %}
|
||||
|
||||
<div class="small-box bg-{{ options.color|default('green') }}">
|
||||
<div class="inner">
|
||||
<h3>
|
||||
{% if data is iterable %}
|
||||
{{ 'Invalid data' }}
|
||||
{% else %}
|
||||
{% block widget_data %}
|
||||
{% if options.dataType == 'duration' %}
|
||||
{% set data = data|duration %}
|
||||
{% elseif options.dataType == 'money' %}
|
||||
{% set data = data|money %}
|
||||
<div class="card card-sm">
|
||||
<div class="card-body">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-auto">
|
||||
<span class="bg-{{ options.color|default('green') }} text-white avatar">
|
||||
<i class="{{ options.icon|icon(true, options.icon) }}"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="font-weight-medium">
|
||||
<a href="{{ url }}" class="link-dark stretched-link text-reset">
|
||||
{{ title|trans }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="text-muted">
|
||||
{% if data is iterable %}
|
||||
{{ 'Invalid data' }}
|
||||
{% else %}
|
||||
{% block widget_data %}
|
||||
{{ data }}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{{ data }}
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
<sup style="font-size: 20px">{{ unit|default('') }}</sup>
|
||||
</h3>
|
||||
<p>{{ title|trans }}</p>
|
||||
<sup style="font-size: 20px">{{ unit|default('') }}</sup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="{{ options.icon|icon(options.icon) }}"></i>
|
||||
</div>
|
||||
{% if not url is empty %}
|
||||
<a href="{{ url }}" class="small-box-footer">
|
||||
{{ 'more.info.link'|trans }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
@@ -1,83 +1,76 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_attributes %}
|
||||
id="PaginatedWorkingTimeChart" data-href="#" data-reload=""
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
<ul class="pagination pagination-sm inline">
|
||||
{% set prevYear = options.year %}
|
||||
{% set prevWeek = options.week %}
|
||||
{% set nextYear = options.year %}
|
||||
{% set nextWeek = options.week %}
|
||||
{% if options.week == 1 %}
|
||||
{% set prevYear = prevYear - 1 %}
|
||||
{% set prevWeek = data.lastWeekInLastYear %}
|
||||
{% else %}
|
||||
{% set prevWeek = prevWeek - 1 %}
|
||||
{% endif %}
|
||||
{% if options.week == data.lastWeekInYear %}
|
||||
{% set nextYear = nextYear + 1 %}
|
||||
{% set nextWeek = 1 %}
|
||||
{% else %}
|
||||
{% set nextWeek = nextWeek + 1 %}
|
||||
{% endif %}
|
||||
<li class="prev"><a onclick="destroyChart()" href="{{ path('widgets_working_time_chart', {'year': prevYear, 'week': prevWeek}) }}" rel="prev"><i class="{{ 'left'|icon }}"></i></a></li>
|
||||
<li class="next"><a onclick="destroyChart()" href="{{ path('widgets_working_time_chart', {'year': nextYear, 'week': nextWeek}) }}" rel="next"><i class="{{ 'right'|icon }}"></i></a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ render_widget('DailyWorkingTimeChart', options|merge({'begin': data.begin, 'end': data.end})) }}
|
||||
</div>
|
||||
{% embed '@theme/embeds/card.html.twig' with {'margin_bottom': 0} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_attributes %}
|
||||
id="PaginatedWorkingTimeChartBox" data-href="#" data-reload=""
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{% set prevYear = options.year %}
|
||||
{% set prevWeek = options.week %}
|
||||
{% set nextYear = options.year %}
|
||||
{% set nextWeek = options.week %}
|
||||
{% if options.week == 1 %}
|
||||
{% set prevYear = prevYear - 1 %}
|
||||
{% set prevWeek = data.lastWeekInLastYear %}
|
||||
{% else %}
|
||||
{% set prevWeek = prevWeek - 1 %}
|
||||
{% endif %}
|
||||
{% if options.week == data.lastWeekInYear %}
|
||||
{% set nextYear = nextYear + 1 %}
|
||||
{% set nextWeek = 1 %}
|
||||
{% else %}
|
||||
{% set nextWeek = nextWeek + 1 %}
|
||||
{% endif %}
|
||||
{{ widgets.card_tool_button('left', {'class': 'pagination-link', 'onclick': 'myChart.destroy()', 'url': path('widgets_working_time_chart', {'year': prevYear, 'week': prevWeek})}) }}
|
||||
{{ widgets.card_tool_button('right', {'class': 'pagination-link', 'onclick': 'myChart.destroy()', 'url': path('widgets_working_time_chart', {'year': nextYear, 'week': nextWeek})}) }}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ render_widget('DailyWorkingTimeChart', options|merge({'begin': data.begin, 'end': data.end})) }}
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="text-center">
|
||||
<h5>{{ data.day|duration }}</h5>
|
||||
<span>{{ 'stats.workingTimeToday'|trans({'%day%': 'now'|date_short}) }}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data.day|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.workingTimeToday'|trans({'%day%': 'now'|date_short}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data.week|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.workingTimeWeek'|trans({'%week%': data.begin|date_format('W')}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data.month|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.workingTimeMonth'|trans({'%month%': data.thisMonth|month_name, '%year%': data.thisMonth|date_format('Y')}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% if data.financial is not null %}
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data.financial|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.workingTimeFinancialYear'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data.year|duration }}</h5>
|
||||
<span class="description-text">{{ 'stats.workingTimeYear'|trans({'%year%': data.thisMonth|date_format('Y')}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="text-center">
|
||||
<h5>{{ data.week|duration }}</h5>
|
||||
<span>{{ 'stats.workingTimeWeek'|trans({'%week%': data.begin|date_format('W')}) }}</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="text-center">
|
||||
<h5>{{ data.month|duration }}</h5>
|
||||
<span>{{ 'stats.workingTimeMonth'|trans({'%month%': data.thisMonth|month_name, '%year%': data.thisMonth|date_format('Y')}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% if data.financial is not null %}
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="text-center">
|
||||
<h5>{{ data.financial|duration }}</h5>
|
||||
<span>{{ 'stats.workingTimeFinancialYear'|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-sm-3 col-xs-6">
|
||||
<div class="text-center">
|
||||
<h5>{{ data.year|duration }}</h5>
|
||||
<span>{{ 'stats.workingTimeYear'|trans({'%year%': data.thisMonth|date_format('Y')}) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% if not kimai_context.javascriptRequest %}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function() {
|
||||
KimaiPaginatedBoxWidget.create('#PaginatedWorkingTimeChart');
|
||||
KimaiPaginatedBoxWidget.create('#PaginatedWorkingTimeChartBox');
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
@@ -1,42 +1,34 @@
|
||||
{% set projectStats = data %}
|
||||
{% set title = options.title|default('label.my_team_projects') %}
|
||||
{% set widgetId = options.id %}
|
||||
{% set title = options.title|default('my_team_projects') %}
|
||||
|
||||
{% if projectStats|length > 0 %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_attributes %}id="{{ widgetId }}"{% endblock %}
|
||||
{% block box_body_class %}no-padding box-body-scrollable{% endblock %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table table-hover dataTable" role="grid">
|
||||
<tbody>
|
||||
{% for row in projectStats|sort((a, b) => a.entity.name <=> b.entity.name) %}
|
||||
{% set project = row.entity %}
|
||||
<tr{% if is_granted('details', project) %} class="alternative-link open-edit" data-href="{{ path('project_details', {'id': project.id}) }}"{% endif %}>
|
||||
<td>
|
||||
{{ widgets.label_project(project) }}
|
||||
<br>
|
||||
<small>{{ widgets.label_customer(project.customer) }}</small>
|
||||
</td>
|
||||
<td style="width:50%">
|
||||
{% if row.hasBudget() and is_granted('budget', row.entity) %}
|
||||
{{ progress.progressbar_budget(row, row.entity.customer.currency) }}
|
||||
{% elseif row.hasTimeBudget() and is_granted('time', row.entity) %}
|
||||
{{ progress.progressbar_timebudget(row) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% embed '@theme/embeds/card.html.twig' with {'margin_bottom': 0} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_body_class %}p-0 box-body-scrollable{% endblock %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table table-hover dataTable" role="grid">
|
||||
<tbody>
|
||||
{% for row in projectStats|sort((a, b) => a.entity.name <=> b.entity.name) %}
|
||||
{% set project = row.entity %}
|
||||
<tr{% if is_granted('details', project) %} class="alternative-link open-edit" data-href="{{ path('project_details', {'id': project.id}) }}"{% endif %}>
|
||||
<td>
|
||||
{{ widgets.label_project(project) }}
|
||||
<br>
|
||||
<small>{{ widgets.label_customer(project.customer) }}</small>
|
||||
</td>
|
||||
<td style="width:50%">
|
||||
{% if row.hasBudget() and is_granted('budget', row.entity) %}
|
||||
{{ progress.progressbar_budget(row, row.entity.customer.currency) }}
|
||||
{% elseif row.hasTimeBudget() and is_granted('time', row.entity) %}
|
||||
{{ progress.progressbar_timebudget(row) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
{% set teams = data %}
|
||||
{% set title = options.title|default(title|default('label.teams')) %}
|
||||
{% set widgetId = options.id %}
|
||||
{% set title = options.title|default(title|default('teams')) %}
|
||||
|
||||
{% if teams|length > 0 %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'border': false} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}{{ title|trans }}{% endblock %}
|
||||
{% block box_attributes %}id="{{ widgetId }}"{% endblock %}
|
||||
{% block box_body_class %}no-padding box-body-scrollable{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ widgets.team_list(teams, false) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% embed '@theme/embeds/card.html.twig' with {'border': false, 'margin_bottom': 0} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}{{ title|trans }}{% endblock %}
|
||||
{% block box_body_class %}p-0 box-body-scrollable{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ widgets.team_list(teams, {title: false}) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
@@ -25,7 +25,7 @@ document.addEventListener('kimai.initialized', function() {
|
||||
document.getElementById('timeChart').getContext('2d'), {
|
||||
type: '{{ type }}',
|
||||
data: {
|
||||
labels: moment.months(),
|
||||
labels: {{ month_names()|json_encode|raw }},
|
||||
datasets: [
|
||||
{% for yearName, year in data %}
|
||||
{% set yearBackgroundColor = backgroundColor %}
|
||||
@@ -71,26 +71,28 @@ document.addEventListener('kimai.initialized', function() {
|
||||
maintainAspectRatio: true,
|
||||
responsive: true,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
x: {
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
},
|
||||
y: {
|
||||
gridLines: {
|
||||
display: true,
|
||||
color: '{{ gridColor }}',
|
||||
lineWidth: 1
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: function(tooltipItem, data) {
|
||||
return data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
||||
plugins: {
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: function(tooltipItem) {
|
||||
return tooltipItem.dataset.realData[tooltipItem.dataIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user