added multi-select for customer, project and activity (#1557)

This commit is contained in:
Kevin Papst
2020-03-16 14:06:26 +01:00
committed by GitHub
parent 6eeb01ad48
commit 4b1cfa5840
74 changed files with 1262 additions and 754 deletions

View File

@@ -9,6 +9,7 @@
namespace App\Form\Toolbar;
use App\Entity\Activity;
use App\Form\Type\ActivityType;
use App\Form\Type\CustomerType;
use App\Form\Type\DateRangeType;
@@ -70,25 +71,47 @@ abstract class AbstractToolbarForm extends AbstractType
]);
}
protected function addCustomerChoice(FormBuilderInterface $builder, array $options = [])
protected function addCustomerChoice(FormBuilderInterface $builder, array $options = [], bool $multiProject = false)
{
$this->addCustomerSelect($builder, $options, false, $multiProject);
}
protected function addCustomerMultiChoice(FormBuilderInterface $builder, array $options = [], bool $multiProject = false)
{
$this->addCustomerSelect($builder, $options, true, $multiProject);
}
private function addCustomerSelect(FormBuilderInterface $builder, array $options, bool $multiCustomer, bool $multiProject)
{
$name = 'customer';
if ($multiCustomer) {
$name = 'customers';
}
// just a fake field for having this field at the right position in the frontend
$builder->add('customer', HiddenType::class);
$builder->add($name, HiddenType::class);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($builder, $options) {
function (FormEvent $event) use ($builder, $options, $name, $multiCustomer, $multiProject) {
$data = $event->getData();
$event->getForm()->add('customer', CustomerType::class, array_merge([
$event->getForm()->add($name, CustomerType::class, array_merge([
'multiple' => $multiCustomer,
'required' => false,
'project_enabled' => true,
'project_enabled' => $multiCustomer ? 'customers' : 'customer',
'project_select' => $multiProject ? 'projects' : 'project',
'end_date_param' => '%daterange%',
'start_date_param' => '%daterange%',
'query_builder' => function (CustomerRepository $repo) use ($builder, $data) {
'query_builder' => function (CustomerRepository $repo) use ($builder, $data, $name, $multiCustomer) {
$query = new CustomerFormTypeQuery();
$query->setUser($builder->getOption('user'));
if (isset($data['customer']) && !empty($data['customer'])) {
$query->setCustomer($data['customer']);
if (isset($data[$name]) && !empty($data[$name])) {
if ($multiCustomer) {
$query->setCustomers($data[$name]);
} else {
$query->addCustomer($data[$name]);
}
}
return $repo->getQueryBuilderForFormType($query);
@@ -131,28 +154,56 @@ abstract class AbstractToolbarForm extends AbstractType
]);
}
protected function addProjectChoice(FormBuilderInterface $builder, array $options = [])
protected function addProjectChoice(FormBuilderInterface $builder, array $options = [], bool $multiCustomer = false, bool $multiActivity = false)
{
$this->addProjectSelect($builder, $options, false, $multiCustomer, $multiActivity);
}
protected function addProjectMultiChoice(FormBuilderInterface $builder, array $options = [], bool $multiCustomer = false, bool $multiActivity = false)
{
$this->addProjectSelect($builder, $options, true, $multiCustomer, $multiActivity);
}
private function addProjectSelect(FormBuilderInterface $builder, array $options, bool $multiProject, bool $multiCustomer, bool $multiActivity)
{
$name = 'project';
if ($multiProject) {
$name = 'projects';
}
// just a fake field for having this field at the right position in the frontend
$builder->add('project', HiddenType::class);
$builder->add($name, HiddenType::class);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) use ($builder, $options) {
function (FormEvent $event) use ($builder, $options, $name, $multiCustomer, $multiProject, $multiActivity) {
$data = $event->getData();
$event->getForm()->add('project', ProjectType::class, array_merge([
$event->getForm()->add($name, ProjectType::class, array_merge([
'multiple' => $multiProject,
'required' => false,
'activity_enabled' => true,
'query_builder' => function (ProjectRepository $repo) use ($builder, $data, $options) {
'activity_enabled' => $multiProject ? 'projects' : 'project',
'activity_select' => $multiActivity ? 'activities' : 'activity',
'query_builder' => function (ProjectRepository $repo) use ($builder, $data, $options, $multiCustomer, $multiProject) {
$query = new ProjectFormTypeQuery();
$query->setUser($builder->getOption('user'));
if (isset($data['customer']) && !empty($data['customer'])) {
$query->setCustomer($data['customer']);
$name = $multiCustomer ? 'customers' : 'customer';
if (isset($data[$name]) && !empty($data[$name])) {
if (is_array($data[$name])) {
$query->setCustomers($data[$name]);
} else {
$query->addCustomer($data[$name]);
}
}
if (isset($data['project']) && !empty($data['project'])) {
$query->setProject($data['project']);
$name = $multiProject ? 'projects' : 'project';
if (isset($data[$name]) && !empty($data[$name])) {
if (is_array($data[$name])) {
$query->setProjects($data[$name]);
} else {
$query->addProject($data[$name]);
}
}
if (isset($options['ignore_date']) && true === $options['ignore_date']) {
$query->setIgnoreDate(true);
}
@@ -164,30 +215,62 @@ abstract class AbstractToolbarForm extends AbstractType
);
}
protected function addActivityChoice(FormBuilderInterface $builder)
protected function addActivityChoice(FormBuilderInterface $builder, array $options = [], bool $multiProject = false)
{
$this->addActivitySelect($builder, $options, false, $multiProject);
}
protected function addActivityMultiChoice(FormBuilderInterface $builder, array $options = [], bool $multiProject = false)
{
$this->addActivitySelect($builder, $options, true, $multiProject);
}
private function addActivitySelect(FormBuilderInterface $builder, array $options = [], bool $multiActivity = false, bool $multiProject = false)
{
$name = 'activity';
if ($multiActivity) {
$name = 'activities';
}
// just a fake field for having this field at the right position in the frontend
$builder->add('activity', HiddenType::class);
$builder->add($name, HiddenType::class);
$builder->addEventListener(
FormEvents::PRE_SUBMIT,
function (FormEvent $event) {
function (FormEvent $event) use ($name, $multiActivity, $multiProject) {
$data = $event->getData();
$event->getForm()->add('activity', ActivityType::class, [
$event->getForm()->add($name, ActivityType::class, [
'multiple' => $multiActivity,
'required' => false,
'query_builder' => function (ActivityRepository $repo) use ($data) {
'query_builder' => function (ActivityRepository $repo) use ($data, $multiActivity, $multiProject) {
$query = new ActivityFormTypeQuery();
if (isset($data['activity']) && !empty($data['activity'])) {
$activity = $data['activity'];
if (is_string($data['activity'])) {
$activity = $repo->find($data['activity']);
$name = $multiActivity ? 'activities' : 'activity';
if (isset($data[$name]) && !empty($data[$name])) {
// we need to pre-fetch the activities to see if they are global, see ActivityFormTypeQuery::isGlobalsOnly()
$activities = $data[$name];
if (!is_array($activities)) {
$activities = [$activities];
}
foreach ($activities as $activity) {
if ($activity instanceof Activity) {
$query->addActivity($activity);
} elseif ($activity !== null) {
$tmp = $repo->find($activity);
if (null !== $tmp) {
$query->addActivity($tmp);
}
}
}
$query->setActivity($activity);
}
if (isset($data['project']) && !empty($data['project'])) {
$query->setProject($data['project']);
$name = $multiProject ? 'projects' : 'project';
if (isset($data[$name]) && !empty($data[$name])) {
if ($multiProject) {
$query->setProjects($data[$name]);
} else {
$query->addProject($data[$name]);
}
}
return $repo->getQueryBuilderForFormType($query);

View File

@@ -25,8 +25,8 @@ class ActivityToolbarForm extends AbstractToolbarForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->addSearchTermInputField($builder);
$this->addCustomerChoice($builder);
$this->addProjectChoice($builder);
$this->addCustomerMultiChoice($builder, [], true);
$this->addProjectMultiChoice($builder, [], true, false);
$builder->add('globalsOnly', ChoiceType::class, [
'choices' => [
'yes' => 1,

View File

@@ -31,9 +31,9 @@ class ExportToolbarForm extends AbstractToolbarForm
$this->addTimesheetStateChoice($builder);
$this->addUsersChoice($builder);
$this->addDateRangeChoice($builder);
$this->addCustomerChoice($builder, ['start_date_param' => null, 'end_date_param' => null, 'ignore_date' => true]);
$this->addProjectChoice($builder, ['ignore_date' => true]);
$this->addActivityChoice($builder);
$this->addCustomerMultiChoice($builder, ['start_date_param' => null, 'end_date_param' => null, 'ignore_date' => true], true);
$this->addProjectMultiChoice($builder, ['ignore_date' => true], true, true);
$this->addActivityMultiChoice($builder, [], true);
$this->addExportType($builder);
$this->addTagInputField($builder);
$builder->add('markAsExported', CheckboxType::class, [

View File

@@ -27,7 +27,7 @@ class InvoiceToolbarForm extends InvoiceToolbarSimpleForm
if ($options['include_user']) {
$this->addUsersChoice($builder);
}
$this->addActivityChoice($builder);
$this->addActivityMultiChoice($builder, $options, true);
$this->addTagInputField($builder);
$this->addExportStateChoice($builder);
}

View File

@@ -28,8 +28,8 @@ class InvoiceToolbarSimpleForm extends AbstractToolbarForm
{
$this->addTemplateChoice($builder);
$this->addDateRangeChoice($builder);
$this->addCustomerChoice($builder, ['required' => true, 'start_date_param' => null, 'end_date_param' => null, 'ignore_date' => true, 'placeholder' => '']);
$this->addProjectChoice($builder, ['ignore_date' => true]);
$this->addCustomerChoice($builder, ['required' => true, 'start_date_param' => null, 'end_date_param' => null, 'ignore_date' => true, 'placeholder' => ''], true);
$this->addProjectMultiChoice($builder, ['ignore_date' => true], false, true);
$builder->add('markAsExported', CheckboxType::class, [
'label' => 'label.mark_as_exported',
'required' => false,

View File

@@ -24,7 +24,7 @@ class ProjectToolbarForm extends AbstractToolbarForm
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->addSearchTermInputField($builder);
$this->addCustomerChoice($builder);
$this->addCustomerMultiChoice($builder, [], false);
$this->addVisibilityChoice($builder);
$this->addPageSizeChoice($builder);
$this->addHiddenPagination($builder);

View File

@@ -20,6 +20,7 @@ class TeamToolbarForm extends AbstractToolbarForm
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$this->addUsersChoice($builder);
$this->addSearchTermInputField($builder);
$this->addPageSizeChoice($builder);
$this->addHiddenPagination($builder);

View File

@@ -28,9 +28,9 @@ class TimesheetToolbarForm extends AbstractToolbarForm
$this->addUsersChoice($builder);
}
$this->addDateRangeChoice($builder);
$this->addCustomerChoice($builder);
$this->addProjectChoice($builder);
$this->addActivityChoice($builder);
$this->addCustomerMultiChoice($builder, [], true);
$this->addProjectMultiChoice($builder, [], true, true);
$this->addActivityMultiChoice($builder, [], true);
$this->addTagInputField($builder);
$this->addTimesheetStateChoice($builder);
$this->addExportStateChoice($builder);

View File

@@ -39,6 +39,7 @@ class CustomerType extends AbstractType
'choice_label' => 'name',
'query_builder_for_user' => true,
'project_enabled' => false,
'project_select' => 'project',
'start_date_param' => '%begin%',
'end_date_param' => '%end%',
'ignore_date' => false,
@@ -57,8 +58,9 @@ class CustomerType extends AbstractType
});
$resolver->setDefault('api_data', function (Options $options) {
if (true === $options['project_enabled']) {
$routeParams = ['customer' => '%customer%', 'visible' => $options['project_visibility']];
if (false !== $options['project_enabled']) {
$name = is_string($options['project_enabled']) ? $options['project_enabled'] : 'customer';
$routeParams = [$name => '%' . $name . '%', 'visible' => $options['project_visibility']];
$emptyRouteParams = ['visible' => $options['project_visibility']];
if (!$options['ignore_date']) {
@@ -77,7 +79,7 @@ class CustomerType extends AbstractType
}
return [
'select' => 'project',
'select' => $options['project_select'],
'route' => 'get_projects',
'route_params' => $routeParams,
'empty_route_params' => $emptyRouteParams,

View File

@@ -64,6 +64,7 @@ class ProjectType extends AbstractType
},
'query_builder_for_user' => true,
'activity_enabled' => false,
'activity_select' => 'activity',
'activity_visibility' => ActivityQuery::SHOW_VISIBLE,
'ignore_date' => false,
]);
@@ -83,11 +84,13 @@ class ProjectType extends AbstractType
});
$resolver->setDefault('api_data', function (Options $options) {
if (true === $options['activity_enabled']) {
if (false !== $options['activity_enabled']) {
$name = is_string($options['activity_enabled']) ? $options['activity_enabled'] : 'project';
return [
'select' => 'activity',
'select' => $options['activity_select'],
'route' => 'get_activities',
'route_params' => ['project' => '%project%', 'visible' => $options['activity_visibility']],
'route_params' => [$name => '%' . $name . '%', 'visible' => $options['activity_visibility']],
'empty_route_params' => ['globals' => 'true', 'visible' => $options['activity_visibility']],
];
}