added config for initial calendar view (#363)

This commit is contained in:
Kevin Papst
2018-10-21 15:43:16 +02:00
committed by GitHub
parent 3075276a52
commit 0165658659
8 changed files with 155 additions and 5 deletions

View File

@@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
/**
* Class ThemeOptionsSubscriber
* Allows dynamic injection of theme related options.
*/
class ThemeOptionsSubscriber implements EventSubscriberInterface
{
@@ -33,7 +33,6 @@ class ThemeOptionsSubscriber implements EventSubscriberInterface
protected $helper;
/**
* ThemeOptionsSubscriber constructor.
* @param TokenStorageInterface $storage
* @param ContextHelper $helper
*/

View File

@@ -12,6 +12,7 @@ namespace App\EventSubscriber;
use App\Entity\User;
use App\Entity\UserPreference;
use App\Event\UserPreferenceEvent;
use App\Form\Type\CalendarViewType;
use App\Form\Type\SkinType;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
@@ -95,6 +96,11 @@ class UserPreferenceSubscriber implements EventSubscriberInterface
->setValue(true)
->setType(CheckboxType::class),
(new UserPreference())
->setName('calendar.initial_view')
->setValue(CalendarViewType::DEFAULT_VIEW)
->setType(CalendarViewType::class),
/*
(new UserPreference())
->setName('language')

View File

@@ -0,0 +1,52 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\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 calendar view.
*/
class CalendarViewType extends AbstractType
{
public const DEFAULT_VIEW = 'month';
public const ALLOWED_VIEWS = [
'month',
'agendaWeek',
'agendaDay',
];
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$choices = [];
foreach (self::ALLOWED_VIEWS as $name) {
$choices[$name] = $name;
}
$resolver->setDefaults([
'required' => true,
'choices' => $choices,
]);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
return ChoiceType::class;
}
}

View File

@@ -24,6 +24,7 @@
<script>
$(function () {
$('#calendar').fullCalendar({
defaultView: '{{ app.user.getPreferenceValue('calendar.initial_view') }}',
{% if not google.apiKey is null %}
googleCalendarApiKey: '{{ google.apiKey }}',
{% endif %}
@@ -84,7 +85,7 @@
'</div>'
,
trigger: 'hover',
placement: 'top',
placement: 'auto',
container: 'body',
html: true
});

View File

@@ -11,6 +11,7 @@ namespace App\Tests\Controller;
use App\DataFixtures\UserFixtures;
use App\Entity\User;
use App\Entity\UserPreference;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
/**
@@ -206,4 +207,54 @@ class ProfileControllerTest extends ControllerBaseTest
$this->assertEquals(['ROLE_TEAMLEAD', 'ROLE_SUPER_ADMIN', 'ROLE_USER'], $user->getRoles());
}
public function testPreferencesAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_USER);
$this->request($client, '/profile/' . UserFixtures::USERNAME_USER . '/prefs');
/** @var User $user */
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$user = $this->getUserByRole($em, User::ROLE_USER);
$this->assertEquals(82, $user->getPreferenceValue(UserPreference::HOURLY_RATE));
$this->assertEquals('green', $user->getPreferenceValue(UserPreference::SKIN));
$this->assertEquals(true, $user->getPreferenceValue('theme.fixed_layout'));
$this->assertEquals(false, $user->getPreferenceValue('theme.boxed_layout'));
$this->assertEquals(false, $user->getPreferenceValue('theme.collapsed_sidebar'));
$this->assertEquals(true, $user->getPreferenceValue('theme.mini_sidebar'));
$this->assertEquals('month', $user->getPreferenceValue('calendar.initial_view'));
$form = $client->getCrawler()->filter('form[name=user_preferences_form]')->form();
$client->submit($form, [
'user_preferences_form' => [
'preferences' => [
['name' => UserPreference::HOURLY_RATE, 'value' => 37],
['name' => UserPreference::SKIN, 'value' => 'blue'],
['name' => 'theme.fixed_layout', 'value' => false],
['name' => 'theme.boxed_layout', 'value' => true],
['name' => 'theme.collapsed_sidebar', 'value' => true],
['name' => 'theme.mini_sidebar', 'value' => false],
['name' => 'calendar.initial_view', 'value' => 'agendaDay'],
]
]
]);
$this->assertIsRedirect($client, $this->createUrl('/profile/' . urlencode(UserFixtures::USERNAME_USER) . '/prefs'));
$client->followRedirect();
$this->assertTrue($client->getResponse()->isSuccessful());
$this->assertHasFlashSuccess($client);
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$user = $this->getUserByRole($em, User::ROLE_USER);
$this->assertEquals(37, $user->getPreferenceValue(UserPreference::HOURLY_RATE));
$this->assertEquals('blue', $user->getPreferenceValue(UserPreference::SKIN));
$this->assertEquals(false, $user->getPreferenceValue('theme.fixed_layout'));
$this->assertEquals(true, $user->getPreferenceValue('theme.boxed_layout'));
$this->assertEquals(true, $user->getPreferenceValue('theme.collapsed_sidebar'));
$this->assertEquals(false, $user->getPreferenceValue('theme.mini_sidebar'));
$this->assertEquals('agendaDay', $user->getPreferenceValue('calendar.initial_view'));
}
}

View File

@@ -383,6 +383,23 @@
<source>label.theme.mini_sidebar</source>
<target>Aktiviert die minimierte Version der linken Navigationsleiste</target>
</trans-unit>
<trans-unit id="label.calendar.initial_view">
<source>label.calendar.initial_view</source>
<target>Initiale Darstellung des Kalenders</target>
</trans-unit>
<!-- Options for user-preference label.calendar.initial_view -->
<trans-unit id="month">
<source>month</source>
<target>Monat</target>
</trans-unit>
<trans-unit id="agendaWeek">
<source>agendaWeek</source>
<target>Woche</target>
</trans-unit>
<trans-unit id="agendaDay">
<source>agendaDay</source>
<target>Tag</target>
</trans-unit>
<!--
Help - Manual

View File

@@ -383,6 +383,23 @@
<source>label.theme.mini_sidebar</source>
<target>Toggle the size of the left sidebar's header (full or collapse)</target>
</trans-unit>
<trans-unit id="label.calendar.initial_view">
<source>label.calendar.initial_view</source>
<target>Initial calendar view</target>
</trans-unit>
<!-- Options for user-preference label.calendar.initial_view -->
<trans-unit id="month">
<source>month</source>
<target>Month</target>
</trans-unit>
<trans-unit id="agendaWeek">
<source>agendaWeek</source>
<target>Week</target>
</trans-unit>
<trans-unit id="agendaDay">
<source>agendaDay</source>
<target>Day</target>
</trans-unit>
<!--
Help - Manual

View File

@@ -3,7 +3,7 @@
Kimai 2 provides a calendar view, which displays your timesheet entries in a easy readable format.
You can choose between a monthly, weekly and daily view.
The calendar view look and feel is configured with the config keys below `kimai.calendar` in `kimai.yaml`:
The calendar view look and feel is configured with the config keys below `kimai.calendar` in `kimai.yaml` / your [local.yaml](configurations.md):
```yaml
kimai:
@@ -22,7 +22,14 @@ kimai:
- `businessHours.begin` the start time of your working day, which will be highlighted in the weekly and daily view (default: 08:00 / 8am)
- `businessHours.end` the end time of your working day, which will be highlighted in the weekly and daily view (default: 20:00 / 8pm)
#### Integrating google calender
## Initial view
The initial view for the calendar is `month`.
It is a user specific setting and each user can configure it in his _User profile_ at _Preferences_.
Available options are: `month`, `agendaWeek`, `agendaDay`
## Integrating google calender
If you want to embed Google calendars e.g. to display regional holidays or company events you can import (multiple) Google calendars.