* refactored toolbars forms for re-usage #33
This commit is contained in:
@@ -14,22 +14,47 @@
|
|||||||
|
|
||||||
{% macro label_role(role) %}
|
{% macro label_role(role) %}
|
||||||
{% import _self as macro %}
|
{% import _self as macro %}
|
||||||
{{ macro.label(role, 'primary') }}
|
{% if role == 'ROLE_SUPER_ADMIN' %}
|
||||||
|
{{ macro.label(role, 'danger') }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.label(role, 'primary') }}
|
||||||
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro label_activity(role) %}
|
{% macro username(user) %}
|
||||||
|
{{ user.alias|default(user.username) }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro label_user(user) %}
|
||||||
{% import _self as macro %}
|
{% import _self as macro %}
|
||||||
{{ macro.label(role, 'primary') }}
|
{{ macro.label(macro.username(user), 'primary') }}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro label_activity(activity) %}
|
||||||
|
{% import _self as macro %}
|
||||||
|
{% if activity.visible and activity.project.visible and activity.project.customer.visible %}
|
||||||
|
{{ macro.label(activity.name, 'primary', activity.project.customer.name ~ ': ' ~ activity.project.name) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.label(activity.name, 'warning', activity.project.customer.name ~ ': ' ~ activity.project.name) }}
|
||||||
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro label_project(project) %}
|
{% macro label_project(project) %}
|
||||||
{% import _self as macro %}
|
{% import _self as macro %}
|
||||||
{{ macro.label(project.name, 'primary') }}
|
{% if project.visible and project.customer.visible %}
|
||||||
|
{{ macro.label(project.name, 'primary', project.customer.name) }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.label(project.name, 'warning', project.customer.name) }}
|
||||||
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro label_customer(customer) %}
|
{% macro label_customer(customer) %}
|
||||||
{% import _self as macro %}
|
{% import _self as macro %}
|
||||||
{{ macro.label(customer.name, 'primary') }}
|
{% if customer.visible %}
|
||||||
|
{{ macro.label(customer.name, 'primary') }}
|
||||||
|
{% else %}
|
||||||
|
{{ macro.label(customer.name, 'warning') }}
|
||||||
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro badge_counter(count, url) %}
|
{% macro badge_counter(count, url) %}
|
||||||
@@ -40,9 +65,9 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro label(title, type) %}
|
{% macro label(title, type, tooltip) %}
|
||||||
{# success, warning, danger, primary #}
|
{# success, warning, danger, primary #}
|
||||||
<span class="label label-{{ type|default('success') }}">{{ title|trans }}</span>
|
<span {% if tooltip %}title="{{ tooltip }}" {% endif %}class="label label-{{ type|default('success') }}">{{ title|trans }}</span>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro badge(title, color) %}
|
{% macro badge(title, color) %}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class BaseQuery
|
|||||||
const RESULT_TYPE_PAGER = 'PagerFanta';
|
const RESULT_TYPE_PAGER = 'PagerFanta';
|
||||||
const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
|
const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \stdClass
|
||||||
|
*/
|
||||||
|
protected $hiddenEntity;
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
@@ -146,4 +150,23 @@ class BaseQuery
|
|||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \stdClass
|
||||||
|
*/
|
||||||
|
public function getHiddenEntity()
|
||||||
|
{
|
||||||
|
return $this->hiddenEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \stdClass $hiddenEntity
|
||||||
|
* @return BaseQuery
|
||||||
|
*/
|
||||||
|
public function setHiddenEntity($hiddenEntity)
|
||||||
|
{
|
||||||
|
$this->hiddenEntity = $hiddenEntity;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,14 @@ namespace AppBundle\Repository\Query;
|
|||||||
*/
|
*/
|
||||||
trait VisibilityTrait
|
trait VisibilityTrait
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @var integer
|
||||||
|
*/
|
||||||
protected $visibility = self::SHOW_VISIBLE;
|
protected $visibility = self::SHOW_VISIBLE;
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $exclusiveVisibility = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int
|
* @return int
|
||||||
@@ -39,4 +46,25 @@ trait VisibilityTrait
|
|||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isExclusiveVisibility()
|
||||||
|
{
|
||||||
|
return $this->exclusiveVisibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If set to true, this will ONLY filter the visibility on the main queried object.
|
||||||
|
*
|
||||||
|
* @param bool $exclusiveVisibility
|
||||||
|
* @return VisibilityTrait
|
||||||
|
*/
|
||||||
|
public function setExclusiveVisibility($exclusiveVisibility)
|
||||||
|
{
|
||||||
|
$this->exclusiveVisibility = (bool) $exclusiveVisibility;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
|
|||||||
use TimesheetBundle\Entity\Customer;
|
use TimesheetBundle\Entity\Customer;
|
||||||
use TimesheetBundle\Entity\Project;
|
use TimesheetBundle\Entity\Project;
|
||||||
use TimesheetBundle\Form\ActivityEditForm;
|
use TimesheetBundle\Form\ActivityEditForm;
|
||||||
use TimesheetBundle\Form\ActivityToolbarForm;
|
use TimesheetBundle\Form\Toolbar\ActivityToolbarForm;
|
||||||
use TimesheetBundle\Repository\Query\ActivityQuery;
|
use TimesheetBundle\Repository\Query\ActivityQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,7 +41,7 @@ class ActivityController extends AbstractController
|
|||||||
*/
|
*/
|
||||||
protected function getQueryForRequest(Request $request)
|
protected function getQueryForRequest(Request $request)
|
||||||
{
|
{
|
||||||
$visibility = $request->get('visibility');
|
$visibility = $request->get('visibility', ActivityQuery::SHOW_VISIBLE);
|
||||||
if (strlen($visibility) == 0 || (int)$visibility != $visibility) {
|
if (strlen($visibility) == 0 || (int)$visibility != $visibility) {
|
||||||
$visibility = ActivityQuery::SHOW_BOTH;
|
$visibility = ActivityQuery::SHOW_BOTH;
|
||||||
}
|
}
|
||||||
@@ -70,6 +70,7 @@ class ActivityController extends AbstractController
|
|||||||
->setVisibility($visibility)
|
->setVisibility($visibility)
|
||||||
->setCustomer($customer)
|
->setCustomer($customer)
|
||||||
->setProject($project)
|
->setProject($project)
|
||||||
|
->setExclusiveVisibility(true)
|
||||||
;
|
;
|
||||||
|
|
||||||
return $query ;
|
return $query ;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use TimesheetBundle\Entity\Customer;
|
|||||||
use TimesheetBundle\Entity\Project;
|
use TimesheetBundle\Entity\Project;
|
||||||
use TimesheetBundle\Entity\Timesheet;
|
use TimesheetBundle\Entity\Timesheet;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use TimesheetBundle\Form\TimesheetToolbarForm;
|
use TimesheetBundle\Form\Toolbar\TimesheetToolbarForm;
|
||||||
use TimesheetBundle\Repository\Query\TimesheetQuery;
|
use TimesheetBundle\Repository\Query\TimesheetQuery;
|
||||||
use TimesheetBundle\Repository\TimesheetRepository;
|
use TimesheetBundle\Repository\TimesheetRepository;
|
||||||
|
|
||||||
|
|||||||
@@ -179,17 +179,18 @@ class LoadFixtures extends AppBundleLoadFixtures
|
|||||||
|
|
||||||
$allCustomer = $this->getCustomers();
|
$allCustomer = $this->getCustomers();
|
||||||
shuffle($allCustomer);
|
shuffle($allCustomer);
|
||||||
$i = 0;
|
$i = 1;
|
||||||
|
|
||||||
foreach ($allCustomer as $customerName) {
|
foreach ($allCustomer as $customerName) {
|
||||||
|
$visible = $i++ % 6 != 0;
|
||||||
$entry = new Customer();
|
$entry = new Customer();
|
||||||
$entry
|
$entry
|
||||||
->setCurrency($this->getRandomCurrency())
|
->setCurrency($this->getRandomCurrency())
|
||||||
->setVat(rand(0, 30))
|
->setVat(rand(0, 30))
|
||||||
->setName($customerName)
|
->setName($customerName . ($visible ? '' : '.'))
|
||||||
->setAddress($this->getRandomLocation())
|
->setAddress($this->getRandomLocation())
|
||||||
->setComment($this->getRandomPhrase())
|
->setComment($this->getRandomPhrase())
|
||||||
->setVisible($i++ % 3 != 0)
|
->setVisible($visible)
|
||||||
->setTimezone($allTimezones[rand(1, $amountTimezone)]);
|
->setTimezone($allTimezones[rand(1, $amountTimezone)]);
|
||||||
|
|
||||||
$manager->persist($entry);
|
$manager->persist($entry);
|
||||||
@@ -203,15 +204,16 @@ class LoadFixtures extends AppBundleLoadFixtures
|
|||||||
|
|
||||||
foreach ($allCustomer as $id => $customer) {
|
foreach ($allCustomer as $id => $customer) {
|
||||||
$projectForCustomer = rand(0, 7);
|
$projectForCustomer = rand(0, 7);
|
||||||
for ($i = 0; $i < $projectForCustomer; $i++) {
|
for ($i = 1; $i <= $projectForCustomer; $i++) {
|
||||||
|
$visible = $i % 5 != 0;
|
||||||
$entry = new Project();
|
$entry = new Project();
|
||||||
|
|
||||||
$entry
|
$entry
|
||||||
->setName($this->getRandomProject())
|
->setName($this->getRandomProject() . ($visible ? '' : '.'))
|
||||||
->setBudget(rand(500, 100000))
|
->setBudget(rand(500, 100000))
|
||||||
->setComment($this->getRandomPhrase())
|
->setComment($this->getRandomPhrase())
|
||||||
->setCustomer($customer)
|
->setCustomer($customer)
|
||||||
->setVisible($i % 3 != 0);
|
->setVisible($visible);
|
||||||
|
|
||||||
$manager->persist($entry);
|
$manager->persist($entry);
|
||||||
}
|
}
|
||||||
@@ -225,13 +227,14 @@ class LoadFixtures extends AppBundleLoadFixtures
|
|||||||
|
|
||||||
foreach ($allProject as $projectId => $project) {
|
foreach ($allProject as $projectId => $project) {
|
||||||
$activityCount = rand(0, 10);
|
$activityCount = rand(0, 10);
|
||||||
for ($i = 0; $i < $activityCount; $i++) {
|
for ($i = 1; $i <= $activityCount; $i++) {
|
||||||
|
$visible = $i % 4 != 0;
|
||||||
$entry = new Activity();
|
$entry = new Activity();
|
||||||
$entry
|
$entry
|
||||||
|
->setName($this->getRandomActivity() . ($visible ? '' : '.'))
|
||||||
->setProject($project)
|
->setProject($project)
|
||||||
->setName($this->getRandomActivity())
|
|
||||||
->setComment($this->getRandomPhrase())
|
->setComment($this->getRandomPhrase())
|
||||||
->setVisible($i % 3 != 0);
|
->setVisible($visible);
|
||||||
|
|
||||||
$manager->persist($entry);
|
$manager->persist($entry);
|
||||||
}
|
}
|
||||||
@@ -266,7 +269,11 @@ class LoadFixtures extends AppBundleLoadFixtures
|
|||||||
'Eating',
|
'Eating',
|
||||||
'Watching TV',
|
'Watching TV',
|
||||||
'Talking',
|
'Talking',
|
||||||
'Cooking'
|
'Cooking',
|
||||||
|
'Writing',
|
||||||
|
'Reading',
|
||||||
|
'Brainstroming',
|
||||||
|
'Post Processing',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,6 +304,14 @@ class LoadFixtures extends AppBundleLoadFixtures
|
|||||||
'Software Upgrade',
|
'Software Upgrade',
|
||||||
'Office Management',
|
'Office Management',
|
||||||
'Project X',
|
'Project X',
|
||||||
|
'Customer Excellence',
|
||||||
|
'Crazy Monkey',
|
||||||
|
'Interface Design',
|
||||||
|
'Human Ressources',
|
||||||
|
'Book Release',
|
||||||
|
'Studio Photography',
|
||||||
|
'Professional Art',
|
||||||
|
'Video Production',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Kimai package.
|
|
||||||
*
|
|
||||||
* (c) Kevin Papst <kevin@kevinpapst.de>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace TimesheetBundle\Form;
|
|
||||||
|
|
||||||
use AppBundle\Form\Type\PageSizeType;
|
|
||||||
use AppBundle\Form\Type\VisibilityType;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
||||||
use TimesheetBundle\Repository\Query\CustomerQuery;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the form used for filtering the customer.
|
|
||||||
*
|
|
||||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
|
||||||
*/
|
|
||||||
class CustomerToolbarForm extends AbstractType
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Dirty hack to enable easy handling of GET form in controller and javascript.
|
|
||||||
*Cleans up the name of all form elents (and unfortunately of the form itself).
|
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
|
||||||
public function getBlockPrefix()
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
|
||||||
{
|
|
||||||
/** @var CustomerQuery $query */
|
|
||||||
$query = $options['data'];
|
|
||||||
|
|
||||||
$builder
|
|
||||||
->add('pageSize', PageSizeType::class, [
|
|
||||||
'required' => false,
|
|
||||||
])
|
|
||||||
->add('visibility', VisibilityType::class, [
|
|
||||||
'required' => false,
|
|
||||||
])
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
|
||||||
{
|
|
||||||
$resolver->setDefaults([
|
|
||||||
'data_class' => CustomerQuery::class,
|
|
||||||
'csrf_protection' => false,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||||||
use TimesheetBundle\Entity\Customer;
|
use TimesheetBundle\Entity\Customer;
|
||||||
use TimesheetBundle\Entity\Timesheet;
|
use TimesheetBundle\Entity\Timesheet;
|
||||||
use TimesheetBundle\Form\Type\ActivityGroupedWithCustomerNameType;
|
use TimesheetBundle\Form\Type\ActivityGroupedWithCustomerNameType;
|
||||||
|
use TimesheetBundle\Repository\ActivityRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the form used to manipulate Timesheet entries.
|
* Defines the form used to manipulate Timesheet entries.
|
||||||
@@ -34,6 +35,14 @@ class TimesheetEditForm extends AbstractType
|
|||||||
*/
|
*/
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
|
/** @var Timesheet $entry */
|
||||||
|
$entry = $options['data'];
|
||||||
|
|
||||||
|
$activity = null;
|
||||||
|
if ($entry->getId() !== null) {
|
||||||
|
$activity = $entry->getActivity();
|
||||||
|
}
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
// datetime
|
// datetime
|
||||||
->add('begin', DateTimeType::class, [
|
->add('begin', DateTimeType::class, [
|
||||||
@@ -46,16 +55,12 @@ class TimesheetEditForm extends AbstractType
|
|||||||
'date_widget' => 'single_text',
|
'date_widget' => 'single_text',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
])
|
])
|
||||||
// integer
|
|
||||||
/*
|
|
||||||
// User
|
|
||||||
->add('user', UserType::class, [
|
|
||||||
'label' => 'label.user',
|
|
||||||
])
|
|
||||||
*/
|
|
||||||
// Activity
|
// Activity
|
||||||
->add('activity', ActivityGroupedWithCustomerNameType::class, [
|
->add('activity', ActivityGroupedWithCustomerNameType::class, [
|
||||||
'label' => 'label.activity',
|
'label' => 'label.activity',
|
||||||
|
'query_builder' => function (ActivityRepository $repo) use ($activity) {
|
||||||
|
return $repo->builderForEntityType($activity);
|
||||||
|
},
|
||||||
])
|
])
|
||||||
// customer
|
// customer
|
||||||
->add('description', TextareaType::class, [
|
->add('description', TextareaType::class, [
|
||||||
|
|||||||
33
src/TimesheetBundle/Form/Toolbar/AbstractToolbarForm.php
Normal file
33
src/TimesheetBundle/Form/Toolbar/AbstractToolbarForm.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai package.
|
||||||
|
*
|
||||||
|
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the base form used for all toolbars.
|
||||||
|
*
|
||||||
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*/
|
||||||
|
abstract class AbstractToolbarForm extends AbstractType
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Dirty hack to enable easy handling of GET form in controller and javascript.
|
||||||
|
*Cleans up the name of all form elents (and unfortunately of the form itself).
|
||||||
|
*
|
||||||
|
* @return null|string
|
||||||
|
*/
|
||||||
|
public function getBlockPrefix()
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace TimesheetBundle\Form;
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
@@ -29,11 +29,11 @@ class ActivityToolbarForm extends ProjectToolbarForm
|
|||||||
*/
|
*/
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
|
parent::buildForm($builder, $options);
|
||||||
|
|
||||||
/** @var ActivityQuery $query */
|
/** @var ActivityQuery $query */
|
||||||
$query = $options['data'];
|
$query = $options['data'];
|
||||||
|
|
||||||
parent::buildForm($builder, $options);
|
|
||||||
|
|
||||||
if ($query->getCustomer() === null) {
|
if ($query->getCustomer() === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
35
src/TimesheetBundle/Form/Toolbar/CustomerToolbarForm.php
Normal file
35
src/TimesheetBundle/Form/Toolbar/CustomerToolbarForm.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai package.
|
||||||
|
*
|
||||||
|
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use TimesheetBundle\Repository\Query\CustomerQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the form used for filtering the customer.
|
||||||
|
*
|
||||||
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*/
|
||||||
|
class CustomerToolbarForm extends VisibilityToolbarForm
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => CustomerQuery::class,
|
||||||
|
'csrf_protection' => false,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/TimesheetBundle/Form/Toolbar/PagedToolbarForm.php
Normal file
40
src/TimesheetBundle/Form/Toolbar/PagedToolbarForm.php
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai package.
|
||||||
|
*
|
||||||
|
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
|
use AppBundle\Form\Type\PageSizeType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use TimesheetBundle\Repository\Query\CustomerQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the base form used for all toolbars with pageSizes.
|
||||||
|
*
|
||||||
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*/
|
||||||
|
class PagedToolbarForm extends AbstractToolbarForm
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
/** @var CustomerQuery $query */
|
||||||
|
$query = $options['data'];
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add('pageSize', PageSizeType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,11 +9,13 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace TimesheetBundle\Form;
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use TimesheetBundle\Form\Type\CustomerType;
|
use TimesheetBundle\Form\Type\CustomerType;
|
||||||
|
use TimesheetBundle\Repository\CustomerRepository;
|
||||||
|
use TimesheetBundle\Repository\Query\CustomerQuery;
|
||||||
use TimesheetBundle\Repository\Query\ProjectQuery;
|
use TimesheetBundle\Repository\Query\ProjectQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +23,7 @@ use TimesheetBundle\Repository\Query\ProjectQuery;
|
|||||||
*
|
*
|
||||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
*/
|
*/
|
||||||
class ProjectToolbarForm extends CustomerToolbarForm
|
class ProjectToolbarForm extends VisibilityToolbarForm
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,13 +31,17 @@ class ProjectToolbarForm extends CustomerToolbarForm
|
|||||||
*/
|
*/
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
/** @var ProjectQuery $query */
|
|
||||||
$query = $options['data'];
|
|
||||||
|
|
||||||
parent::buildForm($builder, $options);
|
parent::buildForm($builder, $options);
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
->add('customer', CustomerType::class, [
|
->add('customer', CustomerType::class, [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'query_builder' => function (CustomerRepository $repo) {
|
||||||
|
$query = new CustomerQuery();
|
||||||
|
$query->setVisibility(CustomerQuery::SHOW_BOTH); // this field is the reason for the query here
|
||||||
|
$query->setResultType(CustomerQuery::RESULT_TYPE_QUERYBUILDER);
|
||||||
|
return $repo->findByQuery($query);
|
||||||
|
},
|
||||||
])
|
])
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -9,16 +9,12 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace TimesheetBundle\Form;
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
use AppBundle\Form\Type\PageSizeType;
|
|
||||||
use Symfony\Component\Form\AbstractType;
|
|
||||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use TimesheetBundle\Form\Type\ActivityType;
|
use TimesheetBundle\Form\Type\ActivityType;
|
||||||
use TimesheetBundle\Form\Type\CustomerType;
|
|
||||||
use TimesheetBundle\Form\Type\ProjectType;
|
|
||||||
use TimesheetBundle\Repository\Query\TimesheetQuery;
|
use TimesheetBundle\Repository\Query\TimesheetQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,31 +22,15 @@ use TimesheetBundle\Repository\Query\TimesheetQuery;
|
|||||||
*
|
*
|
||||||
* @author Kevin Papst <kevin@kevinpapst.de>
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
*/
|
*/
|
||||||
class TimesheetToolbarForm extends AbstractType
|
class TimesheetToolbarForm extends ActivityToolbarForm
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Dirty hack to enable easy handling of GET form in controller and javascript.
|
|
||||||
*Cleans up the name of all form elents (and unfortunately of the form itself).
|
|
||||||
*
|
|
||||||
* @return null|string
|
|
||||||
*/
|
|
||||||
public function getBlockPrefix()
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
{
|
{
|
||||||
/** @var TimesheetQuery $query */
|
|
||||||
$query = $options['data'];
|
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
->add('pageSize', PageSizeType::class, [
|
|
||||||
'required' => false,
|
|
||||||
])
|
|
||||||
->add('state', ChoiceType::class, [
|
->add('state', ChoiceType::class, [
|
||||||
'label' => 'label.entryState',
|
'label' => 'label.entryState',
|
||||||
'choices' => [
|
'choices' => [
|
||||||
@@ -59,35 +39,11 @@ class TimesheetToolbarForm extends AbstractType
|
|||||||
'entryState.stopped' => TimesheetQuery::STATE_STOPPED
|
'entryState.stopped' => TimesheetQuery::STATE_STOPPED
|
||||||
],
|
],
|
||||||
])
|
])
|
||||||
->add('customer', CustomerType::class, [
|
|
||||||
'required' => false,
|
|
||||||
])
|
|
||||||
;
|
;
|
||||||
|
parent::buildForm($builder, $options);
|
||||||
|
$this->addActivityChoice($builder, $options['data']);
|
||||||
|
|
||||||
$this->addProjectChoice($builder, $query);
|
$builder->remove('visibility');
|
||||||
$this->addActivityChoice($builder, $query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param FormBuilderInterface $builder
|
|
||||||
* @param TimesheetQuery $query
|
|
||||||
*/
|
|
||||||
protected function addProjectChoice(FormBuilderInterface $builder, TimesheetQuery $query)
|
|
||||||
{
|
|
||||||
if ($query->getCustomer() === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$choices = [];
|
|
||||||
foreach ($query->getCustomer()->getProjects() as $project) {
|
|
||||||
$choices[] = $project;
|
|
||||||
}
|
|
||||||
|
|
||||||
$builder
|
|
||||||
->add('project', ProjectType::class, [
|
|
||||||
'required' => false,
|
|
||||||
'choices' => $choices,
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,7 +59,6 @@ class TimesheetToolbarForm extends AbstractType
|
|||||||
$choices = [];
|
$choices = [];
|
||||||
foreach ($query->getProject()->getActivities() as $activity) {
|
foreach ($query->getProject()->getActivities() as $activity) {
|
||||||
$choices[] = $activity;
|
$choices[] = $activity;
|
||||||
//$choices[$activity->getName()] = $activity->getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
38
src/TimesheetBundle/Form/Toolbar/VisibilityToolbarForm.php
Normal file
38
src/TimesheetBundle/Form/Toolbar/VisibilityToolbarForm.php
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Kimai package.
|
||||||
|
*
|
||||||
|
* (c) Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace TimesheetBundle\Form\Toolbar;
|
||||||
|
|
||||||
|
use AppBundle\Form\Type\VisibilityType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines the form used for filtering entities with a "visibility" field.
|
||||||
|
*
|
||||||
|
* @author Kevin Papst <kevin@kevinpapst.de>
|
||||||
|
*/
|
||||||
|
class VisibilityToolbarForm extends PagedToolbarForm
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
{
|
||||||
|
parent::buildForm($builder, $options);
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add('visibility', VisibilityType::class, [
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,15 @@ class ActivityGroupedWithCustomerNameType extends ActivityType
|
|||||||
*/
|
*/
|
||||||
public function groupBy(Activity $activity, $key, $index)
|
public function groupBy(Activity $activity, $key, $index)
|
||||||
{
|
{
|
||||||
return $activity->getProject()->getCustomer()->getName() . ': ' . $activity->getProject()->getName();
|
return $activity->getProject()->getCustomer()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Activity $activity
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function choiceLabel(Activity $activity)
|
||||||
|
{
|
||||||
|
return $activity->getProject()->getName() . ': ' . $activity->getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ use Symfony\Component\Form\AbstractType;
|
|||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use TimesheetBundle\Entity\Activity;
|
use TimesheetBundle\Entity\Activity;
|
||||||
use TimesheetBundle\Repository\ActivityRepository;
|
use TimesheetBundle\Repository\ActivityRepository;
|
||||||
use TimesheetBundle\Repository\Query\ActivityQuery;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom form field type to select an activity.
|
* Custom form field type to select an activity.
|
||||||
@@ -26,6 +25,22 @@ use TimesheetBundle\Repository\Query\ActivityQuery;
|
|||||||
class ActivityType extends AbstractType
|
class ActivityType extends AbstractType
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function groupBy(Activity $activity, $key, $index)
|
||||||
|
{
|
||||||
|
return '[' . $activity->getProject()->getId() . '] ' . $activity->getProject()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function choiceLabel(Activity $activity)
|
||||||
|
{
|
||||||
|
return $activity->getName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
@@ -34,15 +49,10 @@ class ActivityType extends AbstractType
|
|||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'label' => 'label.activity',
|
'label' => 'label.activity',
|
||||||
'class' => 'TimesheetBundle:Activity',
|
'class' => 'TimesheetBundle:Activity',
|
||||||
'choice_label' => 'name',
|
'choice_label' => [$this, 'choiceLabel'],
|
||||||
'group_by' => function (Activity $activity, $key, $index) {
|
'group_by' => [$this, 'groupBy'],
|
||||||
return '[' . $activity->getProject()->getId() . '] ' . $activity->getProject()->getName();
|
|
||||||
},
|
|
||||||
'query_builder' => function (ActivityRepository $repo) {
|
'query_builder' => function (ActivityRepository $repo) {
|
||||||
$query = new ActivityQuery();
|
return $repo->builderForEntityType(null);
|
||||||
$query->setVisibility(ActivityQuery::SHOW_BOTH);
|
|
||||||
$query->setResultType(ActivityQuery::RESULT_TYPE_QUERYBUILDER);
|
|
||||||
return $repo->findByQuery($query);
|
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ class ActivityRepository extends AbstractRepository
|
|||||||
->join('a.project', 'p')
|
->join('a.project', 'p')
|
||||||
->join('p.customer', 'c')
|
->join('p.customer', 'c')
|
||||||
->where($qb->expr()->isNotNull('t.end'))
|
->where($qb->expr()->isNotNull('t.end'))
|
||||||
|
->andWhere('a.visible = 1')
|
||||||
|
->andWhere('p.visible = 1')
|
||||||
|
->andWhere('c.visible = 1')
|
||||||
->groupBy('a.id')
|
->groupBy('a.id')
|
||||||
->orderBy('t.end', 'DESC')
|
->orderBy('t.end', 'DESC')
|
||||||
->setMaxResults(10)
|
->setMaxResults(10)
|
||||||
@@ -93,6 +96,20 @@ class ActivityRepository extends AbstractRepository
|
|||||||
return $stats;
|
return $stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a query builder that is used for ActivityType and your own 'query_builder' option.
|
||||||
|
*
|
||||||
|
* @param Activity|null $entity
|
||||||
|
* @return \Doctrine\ORM\QueryBuilder
|
||||||
|
*/
|
||||||
|
public function builderForEntityType(Activity $entity = null)
|
||||||
|
{
|
||||||
|
$query = new ActivityQuery();
|
||||||
|
$query->setHiddenEntity($entity);
|
||||||
|
$query->setResultType(ActivityQuery::RESULT_TYPE_QUERYBUILDER);
|
||||||
|
return $this->findByQuery($query);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ActivityQuery $query
|
* @param ActivityQuery $query
|
||||||
* @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta
|
* @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta
|
||||||
@@ -108,11 +125,19 @@ class ActivityRepository extends AbstractRepository
|
|||||||
->orderBy('a.' . $query->getOrderBy(), $query->getOrder());
|
->orderBy('a.' . $query->getOrderBy(), $query->getOrder());
|
||||||
|
|
||||||
if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) {
|
if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) {
|
||||||
|
if (!$query->isExclusiveVisibility()) {
|
||||||
|
$qb->andWhere('c.visible = 1');
|
||||||
|
$qb->andWhere('p.visible = 1');
|
||||||
|
}
|
||||||
$qb->andWhere('a.visible = 1');
|
$qb->andWhere('a.visible = 1');
|
||||||
// TODO check for visibility of customer and project
|
|
||||||
|
/** @var Activity $entity */
|
||||||
|
$entity = $query->getHiddenEntity();
|
||||||
|
if ($entity !== null) {
|
||||||
|
$qb->orWhere('a.id = :activity')->setParameter('activity', $entity);
|
||||||
|
}
|
||||||
} elseif ($query->getVisibility() == ActivityQuery::SHOW_HIDDEN) {
|
} elseif ($query->getVisibility() == ActivityQuery::SHOW_HIDDEN) {
|
||||||
$qb->andWhere('a.visible = 0');
|
$qb->andWhere('a.visible = 0');
|
||||||
// TODO check for visibility of customer and project
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($query->getProject() !== null) {
|
if ($query->getProject() !== null) {
|
||||||
|
|||||||
@@ -36,8 +36,10 @@
|
|||||||
<td>‐</td>
|
<td>‐</td>
|
||||||
<td>‐</td>
|
<td>‐</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="hidden-xs hidden-sm">{{ widgets.label_activity(entry.activity.name) }}</td>
|
<td class="hidden-xs hidden-sm">
|
||||||
<td class="hidden-xs"><a href="{{ path('profile'|route_alias, {'username' : entry.user.username}) }}">{{ entry.user.username }}</a></td>
|
<a href="{{ path('admin_activity_edit', {'id': entry.activity.id}) }}">{{ widgets.label_activity(entry.activity) }}</a>
|
||||||
|
</td>
|
||||||
|
<td class="hidden-xs"><a href="{{ path('profile'|route_alias, {'username' : entry.user.username}) }}">{{ widgets.label_user(entry.user) }}</a></td>
|
||||||
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
|
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if entry.end %}
|
{% if entry.end %}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
<td class="hidden-xs"><i>{{ entry.duration|duration }}</i></td>
|
<td class="hidden-xs"><i>{{ entry.duration|duration }}</i></td>
|
||||||
<td class="hidden-xs">‐</td>
|
<td class="hidden-xs">‐</td>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<td class="hidden-xs hidden-sm">{{ widgets.label_activity(entry.activity.name) }}</td>
|
<td class="hidden-xs hidden-sm">{{ widgets.label_activity(entry.activity) }}</td>
|
||||||
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
|
<td class="hidden-xs hidden-sm">{{ entry.description }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if entry.end %}
|
{% if entry.end %}
|
||||||
|
|||||||
Reference in New Issue
Block a user