added config for initial calendar view (#363)
This commit is contained in:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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')
|
||||
|
||||
52
src/Form/Type/CalendarViewType.php
Normal file
52
src/Form/Type/CalendarViewType.php
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
});
|
||||
|
||||
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user