0
0
Fork 0
mirror of https://github.com/kevinpapst/kimai2.git synced 2025-04-15 01:38:44 +00:00

Timesheet toolbar ()

* add toolbar to timesheet 
* add customer filter 
* add project filter 
* add activity filter 
* add page size selector 
* added state filter 
* fixed csrf token names
* fixed typo
This commit is contained in:
Kevin Papst 2018-01-05 09:30:22 +01:00 committed by GitHub
parent c9c82e767f
commit 80d0dc2369
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 742 additions and 46 deletions

View file

@ -22,6 +22,10 @@
<source>subtitle.amount</source>
<target> (insgesamt %count%)</target>
</trans-unit>
<trans-unit id="This is a mandatory field">
<source>This is a mandatory field</source>
<target>Pflichtfeld</target>
</trans-unit>
<!--
Login / Security
@ -478,6 +482,10 @@
<!--
ROLES
-->
<trans-unit id="ROLE_SUPER_ADMIN">
<source>ROLE_SUPER_ADMIN</source>
<target>System-Admin</target>
</trans-unit>
<trans-unit id="ROLE_ADMIN">
<source>ROLE_ADMIN</source>
<target>Administrator</target>

View file

@ -32,17 +32,6 @@
{% block avanzu_head %}
<link rel="stylesheet" href="{{ asset('css/kimai.css') }}">
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ asset('theme/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('js/kimai.js') }}"></script>
<script src="{{ asset('js/Chart.min.js') }}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.dropdown-toggle').dropdown();
$(document).kimai({imagePath: '{{ asset('images') }}'});
//$(document).kimai('pauseRecord', 'li.messages-menu ul.menu li');
});
</script>
{% endblock %}
{% block avanzu_footer %}
@ -91,5 +80,21 @@
{% block avanzu_breadcrumb %}{{ parent() }}{% endblock %}
{% block avanzu_control_sidebar %}{{ parent() }}{% endblock %}
{% block avanzu_javascripts %}{{ parent() }}{% endblock %}
{% block avanzu_javascripts_inline %}{{ parent() }}{% endblock %}
{% block avanzu_javascripts %}
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="{{ asset('theme/bootstrap/js/bootstrap.min.js') }}"></script>
<script src="{{ asset('js/kimai.js') }}"></script>
<script src="{{ asset('js/Chart.min.js') }}"></script>
{% block javascript_imports %}{% endblock %}
{% endblock %}
{% block avanzu_javascripts_inline %}
<script type="text/javascript">
$(document).ready(function () {
$('.dropdown-toggle').dropdown();
$(document).kimai({imagePath: '{{ asset('images') }}'});
//$(document).kimai('pauseRecord', 'li.messages-menu ul.menu li');
});
</script>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% import "macros/toolbar.html.twig" as toolbar %}
{{ toolbar.start() }}
{{ form_start(form) }}
<div class="box-body">
{{ form_widget(form) }}
</div>
{{ form_end(form) }}
{{ toolbar.end() }}

View file

@ -0,0 +1,11 @@
{% macro start(columns) %}
<div class="box toolbar">
<div class="box-header">
<div class="row">
{% endmacro %}
{% macro end() %}
</div>
</div>
</div>
{% endmacro %}

View file

@ -21,7 +21,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Form\TimesheetEditForm;
use TimesheetBundle\Repository\TimesheetRepository;
/**
* Controller used to manage timesheet contents in the public part of the site.
@ -33,13 +32,7 @@ use TimesheetBundle\Repository\TimesheetRepository;
*/
class TimesheetController extends AbstractController
{
/**
* @return TimesheetRepository
*/
protected function getRepository()
{
return $this->getDoctrine()->getRepository(Timesheet::class);
}
use TimesheetControllerTrait;
/**
* @Route("/", defaults={"page": 1}, name="timesheet")
@ -47,15 +40,20 @@ class TimesheetController extends AbstractController
* @Method("GET")
* @Cache(smaxage="10")
*/
public function indexAction($page)
public function indexAction($page, Request $request)
{
$user = $this->getUser();
$query = $this->getQueryForRequest($request);
$query->setUser($this->getUser());
$query->setPage($page);
/* @var $entries Pagerfanta */
$entries = $this->getRepository()->findLatest($user, $page);
$entries = $this->getRepository()->findByQuery($query);
return $this->render('TimesheetBundle:timesheet:index.html.twig', [
'entries' => $entries,
'page' => $page
'page' => $page,
'query' => $query,
'toolbarForm' => $this->getToolbarForm($query)->createView(),
]);
}

View file

@ -0,0 +1,108 @@
<?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\Controller;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
use TimesheetBundle\Entity\Timesheet;
use Symfony\Component\HttpFoundation\Request;
use TimesheetBundle\Form\TimesheetToolbarForm;
use TimesheetBundle\Repository\TimesheetRepository;
use TimesheetBundle\Model\Query\Timesheet as TimesheetQuery;
/**
* Helper functions for Timesheet controller
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
trait TimesheetControllerTrait
{
/**
* @return TimesheetRepository
*/
protected function getRepository()
{
return $this->getDoctrine()->getRepository(Timesheet::class);
}
/**
* @param Request $request
* @return TimesheetQuery
*/
protected function getQueryForRequest(Request $request)
{
$activity = $request->get('activity');
$activity = !empty(trim($activity)) ? trim($activity) : null;
$project = $request->get('project');
$project = !empty(trim($project)) ? trim($project) : null;
$customer = $request->get('customer');
$customer = !empty(trim($customer)) ? trim($customer) : null;
$state = $request->get('state');
$state = !empty(trim($state)) ? trim($state) : null;
$pageSize = (int) $request->get('pageSize');
if ($activity !== null) {
$repo = $this->getDoctrine()->getRepository(Activity::class);
$activity = $repo->getById($activity);
if ($activity !== null) {
$project = $activity->getProject();
if ($project !== null) {
$customer = $project->getCustomer();
}
} else {
$customer = null;
$project = null;
}
} elseif ($project !== null) {
$repo = $this->getDoctrine()->getRepository(Project::class);
$project = $repo->getById($project);
if ($project !== null) {
$customer = $project->getCustomer();
} else {
$customer = null;
}
} else if ($customer !== null) {
$repo = $this->getDoctrine()->getRepository(Customer::class);
$customer = $repo->getById($customer);
}
$query = new TimesheetQuery();
$query
->setActivity($activity)
->setProject($project)
->setCustomer($customer)
->setPageSize($pageSize)
->setState($state);
return $query ;
}
/**
* @param TimesheetQuery $query
* @param string $route
* @return mixed
*/
protected function getToolbarForm(TimesheetQuery $query, $route = 'timesheet')
{
return $this->createForm(
TimesheetToolbarForm::class,
$query,
[
'action' => $this->generateUrl($route, [
'page' => $query->getPage(),
]),
'method' => 'GET',
]
);
}
}

View file

@ -283,7 +283,7 @@ class LoadFixtures extends AppBundleLoadFixtures
'Customer Relations',
'Infrastructure',
'Software Upgrade',
'Office Managemenr',
'Office Management',
];
}

View file

@ -133,7 +133,7 @@ class CustomerEditForm extends AbstractType
'data_class' => Customer::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'admin_activity_edit',
'csrf_token_id' => 'admin_customer_edit',
]);
}
}

View file

@ -80,7 +80,7 @@ class ProjectEditForm extends AbstractType
'data_class' => Project::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'admin_activity_edit',
'csrf_token_id' => 'admin_project_edit',
'currency' => Customer::DEFAULT_CURRENCY,
]);
}

View file

@ -19,6 +19,7 @@ use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Timesheet;
use TimesheetBundle\Form\Type\ActivityGroupedWithCustomerNameType;
/**
* Defines the form used to manipulate Timesheet entries.
@ -47,18 +48,15 @@ class TimesheetEditForm extends AbstractType
])
// integer
/*
->add('duration', RangeType::class, [
'label' => 'label.duration',
])
// User
->add('user', UserType::class, [
'label' => 'label.user',
])
*/
// Activity
->add('activity', ActivityType::class, [
->add('activity', ActivityGroupedWithCustomerNameType::class, [
'label' => 'label.activity',
])
*/
// customer
->add('description', TextareaType::class, [
'label' => 'label.description',
@ -81,7 +79,7 @@ class TimesheetEditForm extends AbstractType
'data_class' => Timesheet::class,
'csrf_protection' => true,
'csrf_field_name' => '_token',
'csrf_token_id' => 'admin_timsheet_edit',
'csrf_token_id' => 'timesheet_edit',
'currency' => Customer::DEFAULT_CURRENCY,
]);
}

View file

@ -0,0 +1,131 @@
<?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 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\Model\Query\Timesheet as TimesheetQuery;
/**
* Defines the form used for filtering the timesheet.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class TimesheetToolbarForm 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 TimesheetQuery $query */
$query = $options['data'];
$builder
->add('pageSize', ChoiceType::class, [
'label' => 'label.pageSize',
'choices' => [10 => 10, 25 => 25, 50 => 50, 75 => 75, 100 => 100],
'required' => false,
])
->add('state', ChoiceType::class, [
'label' => 'label.entryState',
'choices' => [
'entryState.all' => TimesheetQuery::STATE_ALL,
'entryState.running' => TimesheetQuery::STATE_RUNNING,
'entryState.stopped' => TimesheetQuery::STATE_STOPPED
],
])
->add('customer', CustomerType::class, [
'label' => 'label.customer',
'required' => false,
])
;
$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;
//$choices[$project->getName()] = $project->getId();
}
$builder
->add('project', ProjectType::class, [
'label' => 'label.project',
'required' => false,
'choices' => $choices,
]);
}
/**
* @param FormBuilderInterface $builder
* @param TimesheetQuery $query
*/
protected function addActivityChoice(FormBuilderInterface $builder, TimesheetQuery $query)
{
if ($query->getProject() === null) {
return;
}
$choices = [];
foreach ($query->getProject()->getActivities() as $activity) {
$choices[] = $activity;
//$choices[$activity->getName()] = $activity->getId();
}
$builder
->add('activity', ActivityType::class, [
'label' => 'label.activity',
'required' => false,
'choices' => $choices,
]);
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => TimesheetQuery::class,
'csrf_protection' => false,
]);
}
}

View file

@ -0,0 +1,34 @@
<?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\Type;
use TimesheetBundle\Entity\Activity;
/**
* Custom form field type to select an activity which are grouped by their Projects, preceeded by their customer names.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class ActivityGroupedWithCustomerNameType extends ActivityType
{
/**
* @param Activity $activity
* @param $key
* @param $index
* @return string
*/
public function groupBy(Activity $activity, $key, $index)
{
return $activity->getProject()->getCustomer()->getName() . ': ' . $activity->getProject()->getName();
}
}

View file

@ -0,0 +1,58 @@
<?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\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Activity;
/**
* Custom form field type to select an activity.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class ActivityType extends AbstractType
{
/**
* @param Activity $activity
* @param $key
* @param $index
* @return string
*/
public function groupBy(Activity $activity, $key, $index)
{
return $activity->getProject()->getName();
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'class' => 'TimesheetBundle:Activity',
'choice_label' => 'name',
'choice_value' => 'id',
'group_by' => array($this, 'groupBy'),
]);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return EntityType::class;
}
}

View file

@ -11,9 +11,10 @@
namespace TimesheetBundle\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use TimesheetBundle\Entity\Project;
/**
* Custom form field type to select a project.
@ -30,14 +31,10 @@ class ProjectType extends AbstractType
{
$resolver->setDefaults([
'class' => 'TimesheetBundle:Project',
'choice_label' => function ($project) {
/* @var $project Project */
return
//'[' . $project->getId() . '] ' .
$project->getName() .
' (' .
$project->getCustomer()->getName() .
')';
'choice_label' => 'name',
'choice_value' => 'id',
'group_by' => function(Project $project, $key, $index) {
return $project->getCustomer()->getName();
},
]);
}
@ -47,6 +44,6 @@ class ProjectType extends AbstractType
*/
public function getParent()
{
return EntityType::class;
return ChoiceType::class;
}
}

View file

@ -0,0 +1,201 @@
<?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\Model\Query;
use AppBundle\Entity\User;
use TimesheetBundle\Entity\Activity;
use TimesheetBundle\Entity\Customer;
use TimesheetBundle\Entity\Project;
/**
* Can be used for advanced timesheet repository queries.
*
* @author Kevin Papst <kevin@kevinpapst.de>
*/
class Timesheet
{
const DEFAULT_PAGESIZE = 25;
const DEFAULT_PAGE = 1;
const STATE_ALL = 0;
const STATE_RUNNING = 1;
const STATE_STOPPED = 2;
/**
* @var User
*/
protected $user;
/**
* @var Activity
*/
protected $activity;
/**
* @var Project
*/
protected $project;
/**
* @var Customer
*/
protected $customer;
/**
* @var int
*/
protected $page = self::DEFAULT_PAGE;
/**
* @var int
*/
protected $pageSize = self::DEFAULT_PAGESIZE;
/**
* @var int
*/
protected $state = self::STATE_ALL;
/**
* @return User
*/
public function getUser()
{
return $this->user;
}
/**
* @param User $user
* @return Timesheet
*/
public function setUser(User $user = null)
{
$this->user = $user;
return $this;
}
/**
* Activity overwrites: setProject() and setCustomer()
*
* @return Activity
*/
public function getActivity()
{
return $this->activity;
}
/**
* @param Activity $activity
* @return Timesheet
*/
public function setActivity(Activity $activity = null)
{
$this->activity = $activity;
return $this;
}
/**
* @return Project
*/
public function getProject()
{
return $this->project;
}
/**
* Project overwrites: setCustomer()
* Is overwritten by: setActivity()
*
* @param Project $project
* @return Timesheet
*/
public function setProject(Project $project = null)
{
$this->project = $project;
return $this;
}
/**
* @return Customer
*/
public function getCustomer()
{
return $this->customer;
}
/**
* Project overwrites: none
* Is overwritten by: setActivity() and setProject()
*
* @param Customer $customer
* @return Timesheet
*/
public function setCustomer(Customer $customer = null)
{
$this->customer = $customer;
return $this;
}
/**
* @return int
*/
public function getPage()
{
return $this->page;
}
/**
* @param int $page
* @return Timesheet
*/
public function setPage($page)
{
$this->page = $page;
return $this;
}
/**
* @return int
*/
public function getPageSize()
{
return $this->pageSize;
}
/**
* @param int $pageSize
* @return Timesheet
*/
public function setPageSize($pageSize)
{
if (!empty($pageSize) && (int) $pageSize > 0) {
$this->pageSize = (int) $pageSize;
}
return $this;
}
/**
* @return int
*/
public function getState()
{
return $this->state;
}
/**
* @param int $state
* @return Timesheet
*/
public function setState($state)
{
if (in_array($state, [self::STATE_ALL, self::STATE_RUNNING, self::STATE_STOPPED])) {
$this->state = $state;
}
return $this;
}
}

View file

@ -22,6 +22,7 @@ use Pagerfanta\Pagerfanta;
use TimesheetBundle\Model\Statistic\Month;
use TimesheetBundle\Model\Statistic\Year;
use TimesheetBundle\Model\TimesheetGlobalStatistic;
use TimesheetBundle\Model\Query\Timesheet as TimesheetQuery;
use TimesheetBundle\Model\TimesheetStatistic;
use DateTime;
@ -291,6 +292,42 @@ class TimesheetRepository extends EntityRepository
return $qb->getQuery();
}
public function findByQuery(TimesheetQuery $query)
{
$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('t', 'a')
->from('TimesheetBundle:Timesheet', 't')
->join('t.activity', 'a')
->orderBy('t.begin', 'DESC');
if ($query->getUser() !== null) {
$qb->andWhere('t.user = :user')
->setParameter('user', $query->getUser());
}
if ($query->getState() == TimesheetQuery::STATE_RUNNING) {
$qb->andWhere($qb->expr()->isNull('t.end'));
} elseif ($query->getState() == TimesheetQuery::STATE_STOPPED) {
$qb->andWhere($qb->expr()->isNotNull('t.end'));
}
if ($query->getActivity() !== null) {
$qb->andWhere('t.activity = :activity')
->setParameter('activity', $query->getActivity());
} elseif ($query->getProject() !== null) {
$qb->andWhere('a.project = :project')
->setParameter('project', $query->getProject());
} elseif ($query->getCustomer() !== null) {
$qb->join('a.project', 'p')
->join('p.customer', 'c')
->andWhere('p.customer = :customer')
->setParameter('customer', $query->getCustomer());
}
return $this->getPager($qb->getQuery(), $query->getPage(), $query->getPageSize());
}
/**
* @param User $user
* @param int $page
@ -314,12 +351,13 @@ class TimesheetRepository extends EntityRepository
/**
* @param Query $query
* @param int $page
* @param int $maxPerPage
* @return Pagerfanta
*/
protected function getPager(Query $query, $page = 1)
protected function getPager(Query $query, $page = 1, $maxPerPage = 25)
{
$paginator = new Pagerfanta(new DoctrineORMAdapter($query, false));
$paginator->setMaxPerPage(25);
$paginator->setMaxPerPage($maxPerPage);
$paginator->setCurrentPage($page);
return $paginator;

View file

@ -0,0 +1,60 @@
<?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,8 +4,13 @@
{% block page_title %}{{ 'timesheet.title'|trans }}{% endblock %}
{% block page_subtitle %}{{ 'timesheet.subtitle'|trans }}{% endblock %}
{% block javascript_imports %}<script src="{{ asset('js/timesheet.js') }}"></script>{% endblock %}
{% block main %}
{% if toolbarForm %}
{{ include('default/_toolbar_form.html.twig', {'form': toolbarForm}) }}
{% endif %}
{% if entries.count > 0 %}
{{ datatables.data_table_header({
'label.date': '',

View file

@ -31,6 +31,17 @@ li.open .ticktac i.running{
}
*/
/* ================================ TOOLBAR ================================ */
.toolbar form input,
.toolbar form select {
display: inline-block;
width: inherit;
}
.toolbar form .form-group {
display: inline;
}
/* ================================ SIDEBAR ================================ */

24
web/js/timesheet.js Normal file
View file

@ -0,0 +1,24 @@
$(document).ready(function () {
$('.toolbar form select').change(function (event) {
switch (event.target.id) {
case 'customer':
if ($(this).val() === '') {
$('.toolbar form select#project').parent().remove();
} else {
$('.toolbar form select#project').val('');
}
$('.toolbar form select#activity').parent().remove();
break;
case 'project':
if ($(this).val() === '') {
$('.toolbar form select#activity').parent().remove();
} else {
$('.toolbar form select#activity').val('');
}
break;
}
$('.toolbar form').submit();
});
});