diff --git a/app/Resources/views/macros/widgets.html.twig b/app/Resources/views/macros/widgets.html.twig index a54df83c..5afdcf15 100644 --- a/app/Resources/views/macros/widgets.html.twig +++ b/app/Resources/views/macros/widgets.html.twig @@ -14,22 +14,47 @@ {% macro label_role(role) %} {% import _self as macro %} - {{ macro.label(role, 'primary') }} + {% if role == 'ROLE_SUPER_ADMIN' %} + {{ macro.label(role, 'danger') }} + {% else %} + {{ macro.label(role, 'primary') }} + {% endif %} {% endmacro %} -{% macro label_activity(role) %} +{% macro username(user) %} + {{ user.alias|default(user.username) }} +{% endmacro %} + +{% macro label_user(user) %} {% 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 %} {% macro label_project(project) %} {% 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 %} {% macro label_customer(customer) %} {% 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 %} {% macro badge_counter(count, url) %} @@ -40,9 +65,9 @@ {% endif %} {% endmacro %} -{% macro label(title, type) %} +{% macro label(title, type, tooltip) %} {# success, warning, danger, primary #} - {{ title|trans }} + {{ title|trans }} {% endmacro %} {% macro badge(title, color) %} diff --git a/src/AppBundle/Repository/Query/BaseQuery.php b/src/AppBundle/Repository/Query/BaseQuery.php index 4c6acc25..c68fc38e 100644 --- a/src/AppBundle/Repository/Query/BaseQuery.php +++ b/src/AppBundle/Repository/Query/BaseQuery.php @@ -28,6 +28,10 @@ class BaseQuery const RESULT_TYPE_PAGER = 'PagerFanta'; const RESULT_TYPE_QUERYBUILDER = 'QueryBuilder'; + /** + * @var \stdClass + */ + protected $hiddenEntity; /** * @var int */ @@ -146,4 +150,23 @@ class BaseQuery } return $this; } + + /** + * @return \stdClass + */ + public function getHiddenEntity() + { + return $this->hiddenEntity; + } + + /** + * @param \stdClass $hiddenEntity + * @return BaseQuery + */ + public function setHiddenEntity($hiddenEntity) + { + $this->hiddenEntity = $hiddenEntity; + return $this; + } + } diff --git a/src/AppBundle/Repository/Query/VisibilityTrait.php b/src/AppBundle/Repository/Query/VisibilityTrait.php index d8ad0292..c1f1670b 100644 --- a/src/AppBundle/Repository/Query/VisibilityTrait.php +++ b/src/AppBundle/Repository/Query/VisibilityTrait.php @@ -18,7 +18,14 @@ namespace AppBundle\Repository\Query; */ trait VisibilityTrait { + /** + * @var integer + */ protected $visibility = self::SHOW_VISIBLE; + /** + * @var bool + */ + protected $exclusiveVisibility = false; /** * @return int @@ -39,4 +46,25 @@ trait VisibilityTrait } 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; + } + } diff --git a/src/TimesheetBundle/Controller/Admin/ActivityController.php b/src/TimesheetBundle/Controller/Admin/ActivityController.php index b11b8c9a..dc9107cc 100644 --- a/src/TimesheetBundle/Controller/Admin/ActivityController.php +++ b/src/TimesheetBundle/Controller/Admin/ActivityController.php @@ -22,7 +22,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; use TimesheetBundle\Entity\Customer; use TimesheetBundle\Entity\Project; use TimesheetBundle\Form\ActivityEditForm; -use TimesheetBundle\Form\ActivityToolbarForm; +use TimesheetBundle\Form\Toolbar\ActivityToolbarForm; use TimesheetBundle\Repository\Query\ActivityQuery; /** @@ -41,7 +41,7 @@ class ActivityController extends AbstractController */ protected function getQueryForRequest(Request $request) { - $visibility = $request->get('visibility'); + $visibility = $request->get('visibility', ActivityQuery::SHOW_VISIBLE); if (strlen($visibility) == 0 || (int)$visibility != $visibility) { $visibility = ActivityQuery::SHOW_BOTH; } @@ -70,6 +70,7 @@ class ActivityController extends AbstractController ->setVisibility($visibility) ->setCustomer($customer) ->setProject($project) + ->setExclusiveVisibility(true) ; return $query ; diff --git a/src/TimesheetBundle/Controller/TimesheetControllerTrait.php b/src/TimesheetBundle/Controller/TimesheetControllerTrait.php index 87d3c119..0368d79a 100644 --- a/src/TimesheetBundle/Controller/TimesheetControllerTrait.php +++ b/src/TimesheetBundle/Controller/TimesheetControllerTrait.php @@ -16,7 +16,7 @@ use TimesheetBundle\Entity\Customer; use TimesheetBundle\Entity\Project; use TimesheetBundle\Entity\Timesheet; use Symfony\Component\HttpFoundation\Request; -use TimesheetBundle\Form\TimesheetToolbarForm; +use TimesheetBundle\Form\Toolbar\TimesheetToolbarForm; use TimesheetBundle\Repository\Query\TimesheetQuery; use TimesheetBundle\Repository\TimesheetRepository; diff --git a/src/TimesheetBundle/DataFixtures/ORM/LoadFixtures.php b/src/TimesheetBundle/DataFixtures/ORM/LoadFixtures.php index 70ab139f..9f254d81 100644 --- a/src/TimesheetBundle/DataFixtures/ORM/LoadFixtures.php +++ b/src/TimesheetBundle/DataFixtures/ORM/LoadFixtures.php @@ -179,17 +179,18 @@ class LoadFixtures extends AppBundleLoadFixtures $allCustomer = $this->getCustomers(); shuffle($allCustomer); - $i = 0; + $i = 1; foreach ($allCustomer as $customerName) { + $visible = $i++ % 6 != 0; $entry = new Customer(); $entry ->setCurrency($this->getRandomCurrency()) ->setVat(rand(0, 30)) - ->setName($customerName) + ->setName($customerName . ($visible ? '' : '.')) ->setAddress($this->getRandomLocation()) ->setComment($this->getRandomPhrase()) - ->setVisible($i++ % 3 != 0) + ->setVisible($visible) ->setTimezone($allTimezones[rand(1, $amountTimezone)]); $manager->persist($entry); @@ -203,15 +204,16 @@ class LoadFixtures extends AppBundleLoadFixtures foreach ($allCustomer as $id => $customer) { $projectForCustomer = rand(0, 7); - for ($i = 0; $i < $projectForCustomer; $i++) { + for ($i = 1; $i <= $projectForCustomer; $i++) { + $visible = $i % 5 != 0; $entry = new Project(); $entry - ->setName($this->getRandomProject()) + ->setName($this->getRandomProject() . ($visible ? '' : '.')) ->setBudget(rand(500, 100000)) ->setComment($this->getRandomPhrase()) ->setCustomer($customer) - ->setVisible($i % 3 != 0); + ->setVisible($visible); $manager->persist($entry); } @@ -225,13 +227,14 @@ class LoadFixtures extends AppBundleLoadFixtures foreach ($allProject as $projectId => $project) { $activityCount = rand(0, 10); - for ($i = 0; $i < $activityCount; $i++) { + for ($i = 1; $i <= $activityCount; $i++) { + $visible = $i % 4 != 0; $entry = new Activity(); $entry + ->setName($this->getRandomActivity() . ($visible ? '' : '.')) ->setProject($project) - ->setName($this->getRandomActivity()) ->setComment($this->getRandomPhrase()) - ->setVisible($i % 3 != 0); + ->setVisible($visible); $manager->persist($entry); } @@ -266,7 +269,11 @@ class LoadFixtures extends AppBundleLoadFixtures 'Eating', 'Watching TV', 'Talking', - 'Cooking' + 'Cooking', + 'Writing', + 'Reading', + 'Brainstroming', + 'Post Processing', ]; } @@ -297,6 +304,14 @@ class LoadFixtures extends AppBundleLoadFixtures 'Software Upgrade', 'Office Management', 'Project X', + 'Customer Excellence', + 'Crazy Monkey', + 'Interface Design', + 'Human Ressources', + 'Book Release', + 'Studio Photography', + 'Professional Art', + 'Video Production', ]; } diff --git a/src/TimesheetBundle/Form/CustomerToolbarForm.php b/src/TimesheetBundle/Form/CustomerToolbarForm.php deleted file mode 100644 index 8ec43b35..00000000 --- a/src/TimesheetBundle/Form/CustomerToolbarForm.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * 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 - */ -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, - ]); - } -} diff --git a/src/TimesheetBundle/Form/TimesheetEditForm.php b/src/TimesheetBundle/Form/TimesheetEditForm.php index 85d71844..0dad7cda 100644 --- a/src/TimesheetBundle/Form/TimesheetEditForm.php +++ b/src/TimesheetBundle/Form/TimesheetEditForm.php @@ -20,6 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolver; use TimesheetBundle\Entity\Customer; use TimesheetBundle\Entity\Timesheet; use TimesheetBundle\Form\Type\ActivityGroupedWithCustomerNameType; +use TimesheetBundle\Repository\ActivityRepository; /** * Defines the form used to manipulate Timesheet entries. @@ -34,6 +35,14 @@ class TimesheetEditForm extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { + /** @var Timesheet $entry */ + $entry = $options['data']; + + $activity = null; + if ($entry->getId() !== null) { + $activity = $entry->getActivity(); + } + $builder // datetime ->add('begin', DateTimeType::class, [ @@ -46,16 +55,12 @@ class TimesheetEditForm extends AbstractType 'date_widget' => 'single_text', 'required' => false, ]) - // integer - /* - // User - ->add('user', UserType::class, [ - 'label' => 'label.user', - ]) - */ // Activity ->add('activity', ActivityGroupedWithCustomerNameType::class, [ 'label' => 'label.activity', + 'query_builder' => function (ActivityRepository $repo) use ($activity) { + return $repo->builderForEntityType($activity); + }, ]) // customer ->add('description', TextareaType::class, [ diff --git a/src/TimesheetBundle/Form/Toolbar/AbstractToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/AbstractToolbarForm.php new file mode 100644 index 00000000..926be590 --- /dev/null +++ b/src/TimesheetBundle/Form/Toolbar/AbstractToolbarForm.php @@ -0,0 +1,33 @@ + + * + * 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 + */ +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 ''; + } +} diff --git a/src/TimesheetBundle/Form/ActivityToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/ActivityToolbarForm.php similarity index 97% rename from src/TimesheetBundle/Form/ActivityToolbarForm.php rename to src/TimesheetBundle/Form/Toolbar/ActivityToolbarForm.php index 7647a3ef..218632fd 100644 --- a/src/TimesheetBundle/Form/ActivityToolbarForm.php +++ b/src/TimesheetBundle/Form/Toolbar/ActivityToolbarForm.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace TimesheetBundle\Form; +namespace TimesheetBundle\Form\Toolbar; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -29,11 +29,11 @@ class ActivityToolbarForm extends ProjectToolbarForm */ public function buildForm(FormBuilderInterface $builder, array $options) { + parent::buildForm($builder, $options); + /** @var ActivityQuery $query */ $query = $options['data']; - parent::buildForm($builder, $options); - if ($query->getCustomer() === null) { return; } diff --git a/src/TimesheetBundle/Form/Toolbar/CustomerToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/CustomerToolbarForm.php new file mode 100644 index 00000000..fa119cea --- /dev/null +++ b/src/TimesheetBundle/Form/Toolbar/CustomerToolbarForm.php @@ -0,0 +1,35 @@ + + * + * 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 + */ +class CustomerToolbarForm extends VisibilityToolbarForm +{ + + /** + * {@inheritdoc} + */ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => CustomerQuery::class, + 'csrf_protection' => false, + ]); + } +} diff --git a/src/TimesheetBundle/Form/Toolbar/PagedToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/PagedToolbarForm.php new file mode 100644 index 00000000..d0d60ee0 --- /dev/null +++ b/src/TimesheetBundle/Form/Toolbar/PagedToolbarForm.php @@ -0,0 +1,40 @@ + + * + * 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 + */ +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, + ]) + ; + } +} diff --git a/src/TimesheetBundle/Form/ProjectToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/ProjectToolbarForm.php similarity index 64% rename from src/TimesheetBundle/Form/ProjectToolbarForm.php rename to src/TimesheetBundle/Form/Toolbar/ProjectToolbarForm.php index 8f564ef7..9090ea4c 100644 --- a/src/TimesheetBundle/Form/ProjectToolbarForm.php +++ b/src/TimesheetBundle/Form/Toolbar/ProjectToolbarForm.php @@ -9,11 +9,13 @@ * file that was distributed with this source code. */ -namespace TimesheetBundle\Form; +namespace TimesheetBundle\Form\Toolbar; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use TimesheetBundle\Form\Type\CustomerType; +use TimesheetBundle\Repository\CustomerRepository; +use TimesheetBundle\Repository\Query\CustomerQuery; use TimesheetBundle\Repository\Query\ProjectQuery; /** @@ -21,7 +23,7 @@ use TimesheetBundle\Repository\Query\ProjectQuery; * * @author Kevin Papst */ -class ProjectToolbarForm extends CustomerToolbarForm +class ProjectToolbarForm extends VisibilityToolbarForm { /** @@ -29,13 +31,17 @@ class ProjectToolbarForm extends CustomerToolbarForm */ public function buildForm(FormBuilderInterface $builder, array $options) { - /** @var ProjectQuery $query */ - $query = $options['data']; - parent::buildForm($builder, $options); + $builder ->add('customer', CustomerType::class, [ '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); + }, ]) ; } diff --git a/src/TimesheetBundle/Form/TimesheetToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/TimesheetToolbarForm.php similarity index 55% rename from src/TimesheetBundle/Form/TimesheetToolbarForm.php rename to src/TimesheetBundle/Form/Toolbar/TimesheetToolbarForm.php index 1653429b..bf061fba 100644 --- a/src/TimesheetBundle/Form/TimesheetToolbarForm.php +++ b/src/TimesheetBundle/Form/Toolbar/TimesheetToolbarForm.php @@ -9,16 +9,12 @@ * 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\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use TimesheetBundle\Form\Type\ActivityType; -use TimesheetBundle\Form\Type\CustomerType; -use TimesheetBundle\Form\Type\ProjectType; use TimesheetBundle\Repository\Query\TimesheetQuery; /** @@ -26,31 +22,15 @@ use TimesheetBundle\Repository\Query\TimesheetQuery; * * @author Kevin Papst */ -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) { - /** @var TimesheetQuery $query */ - $query = $options['data']; - $builder - ->add('pageSize', PageSizeType::class, [ - 'required' => false, - ]) ->add('state', ChoiceType::class, [ 'label' => 'label.entryState', 'choices' => [ @@ -59,35 +39,11 @@ class TimesheetToolbarForm extends AbstractType 'entryState.stopped' => TimesheetQuery::STATE_STOPPED ], ]) - ->add('customer', CustomerType::class, [ - 'required' => false, - ]) ; + parent::buildForm($builder, $options); + $this->addActivityChoice($builder, $options['data']); - $this->addProjectChoice($builder, $query); - $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, - ]); + $builder->remove('visibility'); } /** @@ -103,7 +59,6 @@ class TimesheetToolbarForm extends AbstractType $choices = []; foreach ($query->getProject()->getActivities() as $activity) { $choices[] = $activity; - //$choices[$activity->getName()] = $activity->getId(); } $builder diff --git a/src/TimesheetBundle/Form/Toolbar/VisibilityToolbarForm.php b/src/TimesheetBundle/Form/Toolbar/VisibilityToolbarForm.php new file mode 100644 index 00000000..0b69911c --- /dev/null +++ b/src/TimesheetBundle/Form/Toolbar/VisibilityToolbarForm.php @@ -0,0 +1,38 @@ + + * + * 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 + */ +class VisibilityToolbarForm extends PagedToolbarForm +{ + + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + parent::buildForm($builder, $options); + + $builder + ->add('visibility', VisibilityType::class, [ + 'required' => false, + ]) + ; + } +} diff --git a/src/TimesheetBundle/Form/Type/ActivityGroupedWithCustomerNameType.php b/src/TimesheetBundle/Form/Type/ActivityGroupedWithCustomerNameType.php index 5d3ea4d6..e66948a2 100644 --- a/src/TimesheetBundle/Form/Type/ActivityGroupedWithCustomerNameType.php +++ b/src/TimesheetBundle/Form/Type/ActivityGroupedWithCustomerNameType.php @@ -29,6 +29,15 @@ class ActivityGroupedWithCustomerNameType extends ActivityType */ 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(); } } diff --git a/src/TimesheetBundle/Form/Type/ActivityType.php b/src/TimesheetBundle/Form/Type/ActivityType.php index 4576448f..46e69e05 100644 --- a/src/TimesheetBundle/Form/Type/ActivityType.php +++ b/src/TimesheetBundle/Form/Type/ActivityType.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\OptionsResolver\OptionsResolver; use TimesheetBundle\Entity\Activity; use TimesheetBundle\Repository\ActivityRepository; -use TimesheetBundle\Repository\Query\ActivityQuery; /** * Custom form field type to select an activity. @@ -26,6 +25,22 @@ use TimesheetBundle\Repository\Query\ActivityQuery; 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} */ @@ -34,15 +49,10 @@ class ActivityType extends AbstractType $resolver->setDefaults([ 'label' => 'label.activity', 'class' => 'TimesheetBundle:Activity', - 'choice_label' => 'name', - 'group_by' => function (Activity $activity, $key, $index) { - return '[' . $activity->getProject()->getId() . '] ' . $activity->getProject()->getName(); - }, + 'choice_label' => [$this, 'choiceLabel'], + 'group_by' => [$this, 'groupBy'], 'query_builder' => function (ActivityRepository $repo) { - $query = new ActivityQuery(); - $query->setVisibility(ActivityQuery::SHOW_BOTH); - $query->setResultType(ActivityQuery::RESULT_TYPE_QUERYBUILDER); - return $repo->findByQuery($query); + return $repo->builderForEntityType(null); }, ]); } diff --git a/src/TimesheetBundle/Repository/ActivityRepository.php b/src/TimesheetBundle/Repository/ActivityRepository.php index 24d87fe8..13863049 100644 --- a/src/TimesheetBundle/Repository/ActivityRepository.php +++ b/src/TimesheetBundle/Repository/ActivityRepository.php @@ -50,6 +50,9 @@ class ActivityRepository extends AbstractRepository ->join('a.project', 'p') ->join('p.customer', 'c') ->where($qb->expr()->isNotNull('t.end')) + ->andWhere('a.visible = 1') + ->andWhere('p.visible = 1') + ->andWhere('c.visible = 1') ->groupBy('a.id') ->orderBy('t.end', 'DESC') ->setMaxResults(10) @@ -93,6 +96,20 @@ class ActivityRepository extends AbstractRepository 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 * @return \Doctrine\ORM\QueryBuilder|\Pagerfanta\Pagerfanta @@ -108,11 +125,19 @@ class ActivityRepository extends AbstractRepository ->orderBy('a.' . $query->getOrderBy(), $query->getOrder()); if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) { + if (!$query->isExclusiveVisibility()) { + $qb->andWhere('c.visible = 1'); + $qb->andWhere('p.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) { $qb->andWhere('a.visible = 0'); - // TODO check for visibility of customer and project } if ($query->getProject() !== null) { diff --git a/src/TimesheetBundle/Resources/views/admin/timesheet.html.twig b/src/TimesheetBundle/Resources/views/admin/timesheet.html.twig index c64cad5c..872a5235 100644 --- a/src/TimesheetBundle/Resources/views/admin/timesheet.html.twig +++ b/src/TimesheetBundle/Resources/views/admin/timesheet.html.twig @@ -36,8 +36,10 @@ ‐ ‐ {% endif %} - {{ widgets.label_activity(entry.activity.name) }} - {{ entry.user.username }} + + {{ widgets.label_activity(entry.activity) }} + + {{ widgets.label_user(entry.user) }} {{ entry.description }} {% if entry.end %} diff --git a/src/TimesheetBundle/Resources/views/timesheet/index.html.twig b/src/TimesheetBundle/Resources/views/timesheet/index.html.twig index 3c2701cf..14e55abe 100644 --- a/src/TimesheetBundle/Resources/views/timesheet/index.html.twig +++ b/src/TimesheetBundle/Resources/views/timesheet/index.html.twig @@ -35,7 +35,7 @@ {{ entry.duration|duration }} ‐ {% endif %} - {{ widgets.label_activity(entry.activity.name) }} + {{ widgets.label_activity(entry.activity) }} {{ entry.description }} {% if entry.end %}