From bb4233ddfe2c75c62205873d4abd86a07ed0df03 Mon Sep 17 00:00:00 2001 From: Kevin Papst Date: Sun, 16 Aug 2020 01:43:38 +0200 Subject: [PATCH] use stacked bars in dashboard to show different working tasks per day --- src/Widget/Type/DailyWorkingTimeChart.php | 26 +++++- .../widget-dailyworkingtimechart.html.twig | 93 ++++++++++++++----- 2 files changed, 94 insertions(+), 25 deletions(-) diff --git a/src/Widget/Type/DailyWorkingTimeChart.php b/src/Widget/Type/DailyWorkingTimeChart.php index 8efb8414..9e73af88 100644 --- a/src/Widget/Type/DailyWorkingTimeChart.php +++ b/src/Widget/Type/DailyWorkingTimeChart.php @@ -9,6 +9,8 @@ namespace App\Widget\Type; +use App\Entity\Activity; +use App\Entity\Project; use App\Repository\TimesheetRepository; use App\Security\CurrentUser; use App\Timesheet\UserDateTimeFactory; @@ -75,6 +77,28 @@ class DailyWorkingTimeChart extends SimpleWidget $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, + ]; } } diff --git a/templates/widget/widget-dailyworkingtimechart.html.twig b/templates/widget/widget-dailyworkingtimechart.html.twig index a2efaa16..252122e1 100644 --- a/templates/widget/widget-dailyworkingtimechart.html.twig +++ b/templates/widget/widget-dailyworkingtimechart.html.twig @@ -1,16 +1,9 @@ {% set type = options.type|default('bar') %} {% set chart_id = options.id %} {% set backgroundColor = kimai_context.chart.background_color %} -{% set borderColor = kimai_context.chart.border_color %} {% set gridColor = kimai_context.chart.grid_color %} -{% set colors = options.color|default('')|split(';') %} -{% if colors.0 is defined and not colors.0 is empty %} - {% 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 %} +{% set activities = data.activities %} +{% set data = data.data %}
@@ -31,22 +24,50 @@ {%- endfor %} ], datasets: [ + {% for activityId, activity in activities -%} + {% set activityColor = activity.activity|color|default(activity.project|color|default(backgroundColor)) %} + {% set activityName = activity.activity.name %} { - backgroundColor: '{{ backgroundColor }}', - borderColor: '{{ borderColor }}', + label: '{{ activityName }}', + backgroundColor: '{{ activityColor }}', + borderColor: '#fff', + borderWidth: 1, data: [ - {% for day in data -%} - {{ (day.totalDuration / 3600)|number_format(2, '.', '') }} - {%- if not loop.last %},{% endif -%} - {%- endfor %} + {%- for day in data -%} + {% 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 -%} + {%- endfor -%} ], realData: [ - {% for day in data -%} - '{{ day.totalDuration|duration }}' - {%- if not loop.last %},{% endif -%} - {%- endfor %} + {%- for day in data -%} + {% 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 -%} + {%- endfor -%} ] - } + }, + {%- endfor %} ] }, options: { @@ -57,11 +78,13 @@ categoryPercentage: 0.9, scales: { xAxes: [{ + stacked: true, gridLines: { display: false }, }], yAxes: [{ + stacked: true, ticks: { beginAtZero: true }, @@ -70,14 +93,36 @@ color: '{{ gridColor }}', lineWidth: 1 } - }] + }], }, tooltips: { callbacks: { 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 ' '; + }, + }, } } }