use stacked bars in dashboard to show different working tasks per day
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
namespace App\Widget\Type;
|
namespace App\Widget\Type;
|
||||||
|
|
||||||
|
use App\Entity\Activity;
|
||||||
|
use App\Entity\Project;
|
||||||
use App\Repository\TimesheetRepository;
|
use App\Repository\TimesheetRepository;
|
||||||
use App\Security\CurrentUser;
|
use App\Security\CurrentUser;
|
||||||
use App\Timesheet\UserDateTimeFactory;
|
use App\Timesheet\UserDateTimeFactory;
|
||||||
@@ -75,6 +77,28 @@ class DailyWorkingTimeChart extends SimpleWidget
|
|||||||
$end = new DateTime($options['end'], $this->dateTimeFactory->getTimezone());
|
$end = new DateTime($options['end'], $this->dateTimeFactory->getTimezone());
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->repository->getDailyStats($user, $begin, $end);
|
$activities = [];
|
||||||
|
$statistics = $this->repository->getDailyStats($user, $begin, $end);
|
||||||
|
|
||||||
|
foreach ($statistics as $day) {
|
||||||
|
foreach ($day->getDetails() as $entry) {
|
||||||
|
/** @var Activity $activity */
|
||||||
|
$activity = $entry['activity'];
|
||||||
|
/** @var Project $project */
|
||||||
|
$project = $entry['project'];
|
||||||
|
|
||||||
|
$id = $project->getId() . '_' . $activity->getId();
|
||||||
|
|
||||||
|
$activities[$id] = [
|
||||||
|
'activity' => $activity,
|
||||||
|
'project' => $project,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'activities' => $activities,
|
||||||
|
'data' => $statistics,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,9 @@
|
|||||||
{% set type = options.type|default('bar') %}
|
{% set type = options.type|default('bar') %}
|
||||||
{% set chart_id = options.id %}
|
{% set chart_id = options.id %}
|
||||||
{% set backgroundColor = kimai_context.chart.background_color %}
|
{% set backgroundColor = kimai_context.chart.background_color %}
|
||||||
{% set borderColor = kimai_context.chart.border_color %}
|
|
||||||
{% set gridColor = kimai_context.chart.grid_color %}
|
{% set gridColor = kimai_context.chart.grid_color %}
|
||||||
{% set colors = options.color|default('')|split(';') %}
|
{% set activities = data.activities %}
|
||||||
{% if colors.0 is defined and not colors.0 is empty %}
|
{% set data = data.data %}
|
||||||
{% set backgroundColor = colors.0 %}
|
|
||||||
{% set borderColor = colors.0 %}
|
|
||||||
{% if colors.1 is defined and not colors.1 is empty %}
|
|
||||||
{% set borderColor = colors.1 %}
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="chart">
|
<div class="chart">
|
||||||
<canvas id="{{ chart_id }}" style="height: {{ kimai_context.chart.height }}px;"></canvas>
|
<canvas id="{{ chart_id }}" style="height: {{ kimai_context.chart.height }}px;"></canvas>
|
||||||
@@ -31,22 +24,50 @@
|
|||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
],
|
],
|
||||||
datasets: [
|
datasets: [
|
||||||
|
{% for activityId, activity in activities -%}
|
||||||
|
{% set activityColor = activity.activity|color|default(activity.project|color|default(backgroundColor)) %}
|
||||||
|
{% set activityName = activity.activity.name %}
|
||||||
{
|
{
|
||||||
backgroundColor: '{{ backgroundColor }}',
|
label: '{{ activityName }}',
|
||||||
borderColor: '{{ borderColor }}',
|
backgroundColor: '{{ activityColor }}',
|
||||||
|
borderColor: '#fff',
|
||||||
|
borderWidth: 1,
|
||||||
data: [
|
data: [
|
||||||
{% for day in data -%}
|
{%- for day in data -%}
|
||||||
{{ (day.totalDuration / 3600)|number_format(2, '.', '') }}
|
{% set realDayData = null %}
|
||||||
|
{%- for entry in day.details -%}
|
||||||
|
{% set loopId = (entry.project.id ~ '_' ~ entry.activity.id) %}
|
||||||
|
{%- if loopId == activityId -%}
|
||||||
|
{% set realDayData = (entry.duration / 3600)|number_format(2, '.', '') %}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if realDayData is not null -%}
|
||||||
|
'{{ realDayData }}'
|
||||||
|
{%- else -%}
|
||||||
|
0
|
||||||
|
{%- endif -%}
|
||||||
{%- if not loop.last %},{% endif -%}
|
{%- if not loop.last %},{% endif -%}
|
||||||
{%- endfor %}
|
{%- endfor -%}
|
||||||
],
|
],
|
||||||
realData: [
|
realData: [
|
||||||
{% for day in data -%}
|
{%- for day in data -%}
|
||||||
'{{ day.totalDuration|duration }}'
|
{% set realDayData = null %}
|
||||||
|
{%- for entry in day.details -%}
|
||||||
|
{% set loopId = (entry.project.id ~ '_' ~ entry.activity.id) %}
|
||||||
|
{%- if loopId == activityId -%}
|
||||||
|
{% set realDayData = {duration: entry.duration|duration, project: entry.project.name, customer: entry.project.customer.name, activity: entry.activity.name, total: day.totalDuration|duration} %}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
{%- if realDayData is not null -%}
|
||||||
|
{{ realDayData|json_encode|raw }}
|
||||||
|
{%- else -%}
|
||||||
|
0
|
||||||
|
{%- endif -%}
|
||||||
{%- if not loop.last %},{% endif -%}
|
{%- if not loop.last %},{% endif -%}
|
||||||
{%- endfor %}
|
{%- endfor -%}
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
{%- endfor %}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
@@ -57,11 +78,13 @@
|
|||||||
categoryPercentage: 0.9,
|
categoryPercentage: 0.9,
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
|
stacked: true,
|
||||||
gridLines: {
|
gridLines: {
|
||||||
display: false
|
display: false
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
yAxes: [{
|
yAxes: [{
|
||||||
|
stacked: true,
|
||||||
ticks: {
|
ticks: {
|
||||||
beginAtZero: true
|
beginAtZero: true
|
||||||
},
|
},
|
||||||
@@ -70,14 +93,36 @@
|
|||||||
color: '{{ gridColor }}',
|
color: '{{ gridColor }}',
|
||||||
lineWidth: 1
|
lineWidth: 1
|
||||||
}
|
}
|
||||||
}]
|
}],
|
||||||
},
|
},
|
||||||
tooltips: {
|
tooltips: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
label: function(tooltipItem, data) {
|
label: function(tooltipItem, data) {
|
||||||
return data.datasets[tooltipItem.datasetIndex].realData[tooltipItem.index];
|
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;
|
||||||
|
},
|
||||||
|
beforeFooter: function(tooltipItems, data) {
|
||||||
|
return ' ';
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user