added project detail report (#2651)
- avatars via css only - random colors for entities - improves print view - added colors for teams - added color to tag
This commit is contained in:
53
src/Reporting/ProjectDetails/ProjectDetailsForm.php
Normal file
53
src/Reporting/ProjectDetails/ProjectDetailsForm.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Reporting\ProjectDetails;
|
||||
|
||||
use App\Form\Type\ProjectType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class ProjectDetailsForm extends AbstractType
|
||||
{
|
||||
/**
|
||||
* Simplify cross linking between pages by removing the block prefix.
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getBlockPrefix()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder->add('project', ProjectType::class, [
|
||||
'required' => false,
|
||||
'label' => false,
|
||||
'width' => false,
|
||||
'join_customer' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => ProjectDetailsQuery::class,
|
||||
'csrf_protection' => false,
|
||||
'method' => 'GET',
|
||||
]);
|
||||
}
|
||||
}
|
||||
158
src/Reporting/ProjectDetails/ProjectDetailsModel.php
Normal file
158
src/Reporting/ProjectDetails/ProjectDetailsModel.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Reporting\ProjectDetails;
|
||||
|
||||
use App\Entity\Project;
|
||||
use App\Entity\User;
|
||||
use App\Model\ActivityStatistic;
|
||||
use App\Model\Statistic\UserYear;
|
||||
use App\Model\Statistic\Year;
|
||||
use App\Model\UserStatistic;
|
||||
|
||||
final class ProjectDetailsModel
|
||||
{
|
||||
/**
|
||||
* @var Project
|
||||
*/
|
||||
private $project;
|
||||
/**
|
||||
* @var Year[]
|
||||
*/
|
||||
private $years = [];
|
||||
/**
|
||||
* @var array<string, array<ActivityStatistic>>
|
||||
*/
|
||||
private $yearlyActivities = [];
|
||||
/**
|
||||
* @var array<string, array<int, UserYear>>
|
||||
*/
|
||||
private $usersMonthly = [];
|
||||
/**
|
||||
* @var ActivityStatistic[]
|
||||
*/
|
||||
private $activities = [];
|
||||
|
||||
public function __construct(Project $project)
|
||||
{
|
||||
$this->project = $project;
|
||||
}
|
||||
|
||||
public function getProject(): Project
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
public function addActivity(ActivityStatistic $activityStatistic): void
|
||||
{
|
||||
$this->activities[$activityStatistic->getActivity()->getId()] = $activityStatistic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ActivityStatistic[]
|
||||
*/
|
||||
public function getActivities(): array
|
||||
{
|
||||
return array_values($this->activities);
|
||||
}
|
||||
|
||||
public function addYearActivity(string $year, ActivityStatistic $activityStatistic): void
|
||||
{
|
||||
$this->yearlyActivities[$year][] = $activityStatistic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @return ActivityStatistic[]
|
||||
*/
|
||||
public function getYearActivities(string $year): ?array
|
||||
{
|
||||
if (!\array_key_exists($year, $this->yearlyActivities)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->yearlyActivities[$year];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserStatistic[]
|
||||
*/
|
||||
public function getUserStats(): array
|
||||
{
|
||||
$users = [];
|
||||
foreach ($this->usersMonthly as $year) {
|
||||
foreach ($year as $id => $userYear) {
|
||||
if (\array_key_exists($id, $users)) {
|
||||
$userStat = $users[$id];
|
||||
} else {
|
||||
$userStat = new UserStatistic($userYear->getUser());
|
||||
$users[$id] = $userStat;
|
||||
}
|
||||
$userStat->setRecordDuration($userStat->getRecordDuration() + $userYear->getDuration());
|
||||
$userStat->setRecordRate($userStat->getRecordRate() + $userYear->getRate());
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
public function setUserYear(Year $year, User $user): void
|
||||
{
|
||||
$this->usersMonthly[$year->getYear()][$user->getId()] = new UserYear($user, $year);
|
||||
}
|
||||
|
||||
public function getUserYear(string $year, User $user): ?Year
|
||||
{
|
||||
if (!\array_key_exists($year, $this->usersMonthly) || !\array_key_exists($user->getId(), $this->usersMonthly[$year])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->usersMonthly[$year][$user->getId()]->getYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @return UserYear[]
|
||||
*/
|
||||
public function getUserYears(string $year): array
|
||||
{
|
||||
if (!\array_key_exists($year, $this->usersMonthly)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->usersMonthly[$year];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Year[]
|
||||
*/
|
||||
public function getYears(): array
|
||||
{
|
||||
return $this->years;
|
||||
}
|
||||
|
||||
public function getYear(string $year): ?Year
|
||||
{
|
||||
foreach ($this->years as $tmp) {
|
||||
if ($tmp->getYear() === $year) {
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Year[] $years
|
||||
*/
|
||||
public function setYears(array $years): void
|
||||
{
|
||||
$this->years = $years;
|
||||
}
|
||||
}
|
||||
56
src/Reporting/ProjectDetails/ProjectDetailsQuery.php
Normal file
56
src/Reporting/ProjectDetails/ProjectDetailsQuery.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Reporting\ProjectDetails;
|
||||
|
||||
use App\Entity\Project;
|
||||
use App\Entity\User;
|
||||
use DateTime;
|
||||
|
||||
final class ProjectDetailsQuery
|
||||
{
|
||||
/**
|
||||
* @var Project|null
|
||||
*/
|
||||
private $project;
|
||||
/**
|
||||
* @var DateTime
|
||||
*/
|
||||
private $today;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct(DateTime $today, User $user)
|
||||
{
|
||||
$this->today = $today;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function getToday(): DateTime
|
||||
{
|
||||
return $this->today;
|
||||
}
|
||||
|
||||
public function getUser(): User
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getProject(): ?Project
|
||||
{
|
||||
return $this->project;
|
||||
}
|
||||
|
||||
public function setProject(?Project $project): void
|
||||
{
|
||||
$this->project = $project;
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,9 @@ final class ReportingService
|
||||
}
|
||||
if ($this->security->isGranted('budget_project')) {
|
||||
$event->addReport(new Report('project_view', 'report_project_view', 'report_project_view', 'project'));
|
||||
if ($this->security->isGranted('details_project')) {
|
||||
$event->addReport(new Report('project_details', 'report_project_details', 'report_project_details', 'project'));
|
||||
}
|
||||
$event->addReport(new Report('inactive_projects', 'report_project_inactive', 'report_inactive_project', 'project'));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user