added toolbar to customer screen #28 (#49)

* fixed filter query #28
* fixed annotation #28
* merge message files #28
* added page size type #28
* added visibility type #28
* added filter toolbar to customer screen #28
This commit is contained in:
Kevin Papst
2018-01-07 21:42:27 +01:00
committed by GitHub
parent c5c9f37de7
commit 79e87ecdbe
17 changed files with 289 additions and 87 deletions

View File

@@ -639,6 +639,54 @@
<target>Neue Zeitmessung starten</target> <target>Neue Zeitmessung starten</target>
</trans-unit> </trans-unit>
<!--
TOOLBARS
-->
<trans-unit id="label.pageSize">
<source>label.pageSize</source>
<target>Anzahl Einträge</target>
</trans-unit>
<trans-unit id="label.entryState">
<source>label.entryState</source>
<target>Zeiten</target>
</trans-unit>
<trans-unit id="entryState.all">
<source>entryState.all</source>
<target>Alle</target>
</trans-unit>
<trans-unit id="entryState.running">
<source>entryState.running</source>
<target>Laufende</target>
</trans-unit>
<trans-unit id="entryState.stopped">
<source>entryState.stopped</source>
<target>Beendete</target>
</trans-unit>
<trans-unit id="0">
<source>0</source>
<target>0</target>
</trans-unit>
<trans-unit id="10">
<source>10</source>
<target>10</target>
</trans-unit>
<trans-unit id="25">
<source>25</source>
<target>25</target>
</trans-unit>
<trans-unit id="50">
<source>50</source>
<target>50</target>
</trans-unit>
<trans-unit id="75">
<source>75</source>
<target>75</target>
</trans-unit>
<trans-unit id="100">
<source>100</source>
<target>100</target>
</trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@@ -0,0 +1,44 @@
<?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 AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Custom form field type to select a page size.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class PageSizeType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'label' => 'label.pageSize',
'choices' => [10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100],
]);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
}

View File

@@ -0,0 +1,48 @@
<?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 AppBundle\Form\Type;
use AppBundle\Repository\Query\VisibilityInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* Custom form field type to select a visibility.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class VisibilityType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'label' => 'label.visible',
'choices' => [
'yes' => VisibilityInterface::SHOW_VISIBLE,
'no' => VisibilityInterface::SHOW_HIDDEN,
],
]);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
}

View File

@@ -59,7 +59,7 @@ class BaseQuery
/** /**
* @param int $page * @param int $page
* @return BaseQuery * @return $this
*/ */
public function setPage($page) public function setPage($page)
{ {
@@ -77,7 +77,7 @@ class BaseQuery
/** /**
* @param int $pageSize * @param int $pageSize
* @return BaseQuery * @return $this
*/ */
public function setPageSize($pageSize) public function setPageSize($pageSize)
{ {
@@ -99,7 +99,7 @@ class BaseQuery
* You need to validate carefully if this value is used from a user-input. * You need to validate carefully if this value is used from a user-input.
* *
* @param string $orderBy * @param string $orderBy
* @return BaseQuery * @return $this
*/ */
public function setOrderBy($orderBy) public function setOrderBy($orderBy)
{ {
@@ -117,7 +117,7 @@ class BaseQuery
/** /**
* @param string $order * @param string $order
* @return BaseQuery * @return $this
*/ */
public function setOrder($order) public function setOrder($order)
{ {
@@ -137,7 +137,7 @@ class BaseQuery
/** /**
* @param string $resultType * @param string $resultType
* @return BaseQuery * @return $this
*/ */
public function setResultType($resultType) public function setResultType($resultType)
{ {

View File

@@ -30,11 +30,13 @@ trait VisibilityTrait
/** /**
* @param int $visibility * @param int $visibility
* @return ProjectQuery * @return self
*/ */
public function setVisibility($visibility) public function setVisibility($visibility)
{ {
$this->visibility = $visibility; if (in_array($visibility, [self::SHOW_BOTH, self::SHOW_VISIBLE, self::SHOW_HIDDEN])) {
$this->visibility = $visibility;
}
return $this; return $this;
} }
} }

View File

@@ -20,6 +20,7 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use TimesheetBundle\Form\CustomerEditForm; use TimesheetBundle\Form\CustomerEditForm;
use TimesheetBundle\Form\CustomerToolbarForm;
use TimesheetBundle\Repository\Query\CustomerQuery; use TimesheetBundle\Repository\Query\CustomerQuery;
/** /**
@@ -32,22 +33,49 @@ use TimesheetBundle\Repository\Query\CustomerQuery;
*/ */
class CustomerController extends AbstractController class CustomerController extends AbstractController
{ {
/**
* @param Request $request
* @return CustomerQuery
*/
protected function getQueryForRequest(Request $request)
{
$visibility = $request->get('visibility');
if (strlen($visibility) == 0 || (int)$visibility != $visibility) {
$visibility = CustomerQuery::SHOW_BOTH;
}
$pageSize = (int) $request->get('pageSize');
$query = new CustomerQuery();
$query
->setPageSize($pageSize)
->setVisibility($visibility);
return $query ;
}
/** /**
* @Route("/", defaults={"page": 1}, name="admin_customer") * @Route("/", defaults={"page": 1}, name="admin_customer")
* @Route("/page/{page}", requirements={"page": "[1-9]\d*"}, name="admin_customer_paginated") * @Route("/page/{page}", requirements={"page": "[1-9]\d*"}, name="admin_customer_paginated")
* @Method("GET") * @Method("GET")
* @Cache(smaxage="10") * @Cache(smaxage="10")
*/ */
public function indexAction($page) public function indexAction($page, Request $request)
{ {
$query = new CustomerQuery(); $query = $this->getQueryForRequest($request);
$query->setVisibility(CustomerQuery::SHOW_BOTH);
$query->setPage($page); $query->setPage($page);
/* @var $entries Pagerfanta */ /* @var $entries Pagerfanta */
$entries = $this->getDoctrine()->getRepository(Customer::class)->findByQuery($query); $entries = $this->getDoctrine()->getRepository(Customer::class)->findByQuery($query);
return $this->render('TimesheetBundle:admin:customer.html.twig', ['entries' => $entries]); return $this->render(
'TimesheetBundle:admin:customer.html.twig',
[
'entries' => $entries,
'query' => $query,
'toolbarForm' => $this->getToolbarForm($query)->createView(),
]
);
} }
/** /**
@@ -99,6 +127,24 @@ class CustomerController extends AbstractController
); );
} }
/**
* @param CustomerQuery $query
* @return \Symfony\Component\Form\FormInterface
*/
protected function getToolbarForm(CustomerQuery $query)
{
return $this->createForm(
CustomerToolbarForm::class,
$query,
[
'action' => $this->generateUrl('admin_customer_paginated', [
'page' => $query->getPage(),
]),
'method' => 'GET',
]
);
}
/** /**
* @param Customer $customer * @param Customer $customer
* @return \Symfony\Component\Form\FormInterface * @return \Symfony\Component\Form\FormInterface

View File

@@ -11,7 +11,7 @@
namespace TimesheetBundle\Form; namespace TimesheetBundle\Form;
use AppBundle\Form\Type\YesNoType; use AppBundle\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType; use Symfony\Component\Form\Extension\Core\Type\TextType;
@@ -48,7 +48,7 @@ class ActivityEditForm extends AbstractType
'label' => 'label.project', 'label' => 'label.project',
]) ])
// boolean // boolean
->add('visible', YesNoType::class, [ ->add('visible', VisibilityType::class, [
'label' => 'label.visible', 'label' => 'label.visible',
]) ])
; ;

View File

@@ -11,7 +11,7 @@
namespace TimesheetBundle\Form; namespace TimesheetBundle\Form;
use AppBundle\Form\Type\YesNoType; use AppBundle\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CountryType; use Symfony\Component\Form\Extension\Core\Type\CountryType;
use Symfony\Component\Form\Extension\Core\Type\CurrencyType; use Symfony\Component\Form\Extension\Core\Type\CurrencyType;
@@ -61,7 +61,7 @@ class CustomerEditForm extends AbstractType
]) ])
*/ */
// boolean // boolean
->add('visible', YesNoType::class, [ ->add('visible', VisibilityType::class, [
'label' => 'label.visible', 'label' => 'label.visible',
]) ])
// string - length 255 // string - length 255

View File

@@ -0,0 +1,67 @@
<?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,
]);
}
}

View File

@@ -11,7 +11,7 @@
namespace TimesheetBundle\Form; namespace TimesheetBundle\Form;
use AppBundle\Form\Type\YesNoType; use AppBundle\Form\Type\VisibilityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType; use Symfony\Component\Form\Extension\Core\Type\MoneyType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\Extension\Core\Type\TextareaType;
@@ -49,7 +49,7 @@ class ProjectEditForm extends AbstractType
'label' => 'label.customer', 'label' => 'label.customer',
]) ])
// boolean // boolean
->add('visible', YesNoType::class, [ ->add('visible', VisibilityType::class, [
'label' => 'label.visible', 'label' => 'label.visible',
]) ])
// string // string

View File

@@ -11,6 +11,7 @@
namespace TimesheetBundle\Form; namespace TimesheetBundle\Form;
use AppBundle\Form\Type\PageSizeType;
use Symfony\Component\Form\AbstractType; 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;
@@ -47,9 +48,7 @@ class TimesheetToolbarForm extends AbstractType
$query = $options['data']; $query = $options['data'];
$builder $builder
->add('pageSize', ChoiceType::class, [ ->add('pageSize', PageSizeType::class, [
'label' => 'label.pageSize',
'choices' => [10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100],
'required' => false, 'required' => false,
]) ])
->add('state', ChoiceType::class, [ ->add('state', ChoiceType::class, [

View File

@@ -107,10 +107,10 @@ class ActivityRepository extends AbstractRepository
->join('p.customer', 'c') ->join('p.customer', 'c')
->orderBy('a.' . $query->getOrderBy(), $query->getOrder()); ->orderBy('a.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() === ActivityQuery::SHOW_VISIBLE) { if ($query->getVisibility() == ActivityQuery::SHOW_VISIBLE) {
$qb->andWhere('a.visible = 1'); $qb->andWhere('a.visible = 1');
// TODO check for visibility of customer and project // TODO check for visibility of customer and project
} 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 // TODO check for visibility of customer and project
} }

View File

@@ -62,9 +62,9 @@ class CustomerRepository extends AbstractRepository
->from('TimesheetBundle:Customer', 'c') ->from('TimesheetBundle:Customer', 'c')
->orderBy('c.' . $query->getOrderBy(), $query->getOrder()); ->orderBy('c.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() === CustomerQuery::SHOW_VISIBLE) { if ($query->getVisibility() == CustomerQuery::SHOW_VISIBLE) {
$qb->andWhere('c.visible = 1'); $qb->andWhere('c.visible = 1');
} elseif ($query->getVisibility() === CustomerQuery::SHOW_HIDDEN) { } elseif ($query->getVisibility() == CustomerQuery::SHOW_HIDDEN) {
$qb->andWhere('c.visible = 0'); $qb->andWhere('c.visible = 0');
} }

View File

@@ -65,10 +65,10 @@ class ProjectRepository extends AbstractRepository
->join('p.customer', 'c') ->join('p.customer', 'c')
->orderBy('p.' . $query->getOrderBy(), $query->getOrder()); ->orderBy('p.' . $query->getOrderBy(), $query->getOrder());
if ($query->getVisibility() === ProjectQuery::SHOW_VISIBLE) { if ($query->getVisibility() == ProjectQuery::SHOW_VISIBLE) {
$qb->andWhere('p.visible = 1'); $qb->andWhere('p.visible = 1');
// TODO check for visibility of customer // TODO check for visibility of customer
} elseif ($query->getVisibility() === ProjectQuery::SHOW_HIDDEN) { } elseif ($query->getVisibility() == ProjectQuery::SHOW_HIDDEN) {
$qb->andWhere('p.visible = 0'); $qb->andWhere('p.visible = 0');
// TODO check for visibility of customer // TODO check for visibility of customer
} }

View File

@@ -1,60 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file date="2016-10-19T21:46:45Z" source-language="en" target-language="de" datatype="plaintext" original="not.available">
<body>
<!--
TIMESHEET TOOLBAR
-->
<trans-unit id="label.pageSize">
<source>label.pageSize</source>
<target>Anzahl Einträge</target>
</trans-unit>
<trans-unit id="timesheet.toolbar.submit">
<source>timesheet.toolbar.submit</source>
<target>Einträge filtern</target>
</trans-unit>
<trans-unit id="label.entryState">
<source>label.entryState</source>
<target>Zeiten</target>
</trans-unit>
<trans-unit id="entryState.all">
<source>entryState.all</source>
<target>Alle</target>
</trans-unit>
<trans-unit id="entryState.running">
<source>entryState.running</source>
<target>Laufende</target>
</trans-unit>
<trans-unit id="entryState.stopped">
<source>entryState.stopped</source>
<target>Beendete</target>
</trans-unit>
<trans-unit id="0">
<source>0</source>
<target>0</target>
</trans-unit>
<trans-unit id="10">
<source>10</source>
<target>10</target>
</trans-unit>
<trans-unit id="25">
<source>25</source>
<target>25</target>
</trans-unit>
<trans-unit id="50">
<source>50</source>
<target>50</target>
</trans-unit>
<trans-unit id="75">
<source>75</source>
<target>75</target>
</trans-unit>
<trans-unit id="100">
<source>100</source>
<target>100</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -4,6 +4,7 @@
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %} {% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %} {% block page_subtitle %}{{ 'admin_customer.subtitle'|trans }} {{ 'subtitle.amount'|trans({'%count%': entries.count}) }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/toolbar.js') }}"></script>{% endblock %}
{% block main %} {% block main %}
{% if entries.count == 0 %} {% if entries.count == 0 %}
@@ -21,7 +22,7 @@
'label.currency': 'hidden-xs', 'label.currency': 'hidden-xs',
'label.visible': '', 'label.visible': '',
'label.actions': '', 'label.actions': '',
}, null, {'plus-square': path('admin_customer_create')}) }} }, toolbarForm, {'plus-square': path('admin_customer_create')}) }}
{% for entry in entries %} {% for entry in entries %}
<tr> <tr>

7
web/js/toolbar.js Normal file
View File

@@ -0,0 +1,7 @@
$(document).ready(function () {
$('.toolbar form select').change(function (event) {
$('.toolbar form').submit();
});
});