diff --git a/README.md b/README.md index 9f776993..a9bd50d8 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ $ composer install Lets prepare the environment ```bash -$ php bin/console assets:install --symlink -$ php bin/console avanzu:admin:fetch-vendor +$ php bin/console assets:install --symlink --relative +$ php bin/console avanzu:admin:initialize --symlink --relative ``` diff --git a/app/Resources/AvanzuAdminThemeBundle/views/Navbar/user.html.twig b/app/Resources/AvanzuAdminThemeBundle/views/Navbar/user.html.twig new file mode 100644 index 00000000..e89d5475 --- /dev/null +++ b/app/Resources/AvanzuAdminThemeBundle/views/Navbar/user.html.twig @@ -0,0 +1,38 @@ + +{% import "AvanzuAdminThemeBundle:layout:macros.html.twig" as macro %} + diff --git a/app/Resources/translations/AvanzuAdminTheme.de.xliff b/app/Resources/translations/AvanzuAdminTheme.de.xliff new file mode 100644 index 00000000..b076b38b --- /dev/null +++ b/app/Resources/translations/AvanzuAdminTheme.de.xliff @@ -0,0 +1,19 @@ + + + + + + Member since %date% + Mitglied seit %date% + + + Profile + Profil + + + Sign out + Abmelden + + + + diff --git a/app/Resources/translations/messages.de.xliff b/app/Resources/translations/messages.de.xliff index 3b33e011..1a103c44 100644 --- a/app/Resources/translations/messages.de.xliff +++ b/app/Resources/translations/messages.de.xliff @@ -2,6 +2,9 @@ + browser.title Kimai - Time Tracking @@ -11,6 +14,57 @@ Kimai + + + security.title.login + Anmelden + + + security.label.username + Benutzername + + + security.label.password + Passwort + + + security.action.sign_in + Los geht's + + + + + menu.homepage + Dashboard + + + menu.admin + Administration + + + menu.logout + Abmelden + + + menu.timesheet + Zeiterfassung + + + + + footer.license + Alle Rechte vorbehalten. + + + http_error.name Error @@ -48,58 +102,34 @@ Error - - action.browse_admin - Zum Backend + + + label.date + Datum - - help.browse_admin - Zum Backend + + label.starttime + Begin - - action.browse_app - Zum Frontend + + label.endtime + Ende - - help.browse_app - Zum Frontend - - - title.login - Anmelden + + label.duration + Dauer label.username - Benutzername + Benutzer - - label.password - Passwort - - - action.sign_in - Los geht's - - - menu.logout - Abmelden - - - menu.admin - Backend - - - menu.timesheet - Zeiterfassung - - - kimai.license - Copyright Kevin Papst. Alle Rechte vorbehalten. - - - kimai.footer - Kimai Time-Tracking + + label.description + Beschreibung + diff --git a/app/Resources/views/base.html.twig b/app/Resources/views/base.html.twig index 05dda3e6..7c5e35eb 100644 --- a/app/Resources/views/base.html.twig +++ b/app/Resources/views/base.html.twig @@ -1,18 +1,68 @@ -{% extends 'AvanzuAdminThemeBundle:layout:base-layout.html.twig' %} +{% extends 'AvanzuAdminThemeBundle:layout:default-layout.html.twig' %} -{% block page_content %} - {% block main %} - {% endblock %} +{% block avanzu_page_content %} + {% block main %}{% endblock %} +{% endblock %} + +{% block avanzu_document_title %} + {% block title %}{{ 'browser.title'|trans }}{% endblock %} +{% endblock %} + +{% block avanzu_sidebar_search %} + +{% endblock %} + +{% block avanzu_page_title %} + {% block page_title %}{% endblock %} +{% endblock %} + +{% block avanzu_page_subtitle %} + {% block page_subtitle %}{% endblock %} +{% endblock %} + +{% block avanzu_logo_path %} + {{ path('dashboard') }} +{% endblock %} + +{% block avanzu_logo_mini %} + KTT +{% endblock %} + +{% block avanzu_logo_lg %} + Kimai - Time Tracking {% endblock %} {% block flash_messages %} {{ include('default/_flash_messages.html.twig') }} {% endblock %} +{% block avanzu_footer %} + {% block footer %} + + {% endblock %} +{% endblock %} {# - {% block title %}{{ 'browser.title'|trans }}{% endblock %} - + +avanzu_head +avanzu_navbar_toggle +avanzu_navbar_messages +avanzu_navbar_notifications +avanzu_navbar_tasks +avanzu_navbar_user +avanzu_navbar_control_sidebar_toggle +avanzu_sidebar_user +avanzu_sidebar_nav +avanzu_breadcrumb +avanzu_control_sidebar +avanzu_javascripts +avanzu_javascripts_inline - - -

© {{ 'now'|date('Y') }} - {{ 'kimai.footer'|trans }}

-

{{ 'kimai.license'|trans }}

- #} \ No newline at end of file diff --git a/app/Resources/views/dashboard/index.html.twig b/app/Resources/views/dashboard/index.html.twig index 4635af83..61d09c59 100644 --- a/app/Resources/views/dashboard/index.html.twig +++ b/app/Resources/views/dashboard/index.html.twig @@ -1,7 +1,53 @@ {% extends 'base.html.twig' %} +{% import "macros/widgets.html.twig" as widgets %} {% block page_title %}Dashboard{% endblock %} {% block page_subtitle %}Welcome!{% endblock %} {% block main %} + +
+
+ {{ widgets.info_box_counter('Bla blub', 300, 'bar-chart', 'blue') }} +
+
+ {{ widgets.info_box_counter('Steigerungsrate', 80, 'line-chart', 'red') }} +
+
+ {{ widgets.info_box_counter('Anzahl Tage', 27, 'calendar', 'yellow') }} +
+
+ {{ widgets.info_box_counter('Stunden total / Monat', 460, 'clock-o', 'green') }} +
+
+ +
+
+ {{ widgets.info_box_progress('Bewilligte Stunden', 'Stunden zur Abrechnung bewilligt', 120, 10, 'star-o') }} +
+
+ {{ widgets.info_box_progress('Umsatz / Monat', '70% Increase in 30 Days', 6830, 30, 'credit-card', 'black') }} +
+
+ {{ widgets.info_box_progress('Stunden persönlich', 'Das ist noch nicht genug', 135, 60, 'hourglass-o') }} +
+
+ {{ widgets.info_box_progress('Anzahl Benutzer', 'Mehr ist besser!', 5, 90, 'user') }} +
+
+ +
+
+ {{ widgets.info_box_more('Bewilligte Stunden', 120, 'h', 'star-o', 'purple') }} +
+
+ {{ widgets.info_box_more('Umsatz / Monat', 6830, '$', '', 'yellow') }} +
+
+ {{ widgets.info_box_more('Stunden persönlich', 135, '€', 'hourglass-o', 'red') }} +
+
+ {{ widgets.info_box_more('Anzahl Benutzer', 5, '', 'user') }} +
+
{% endblock %} diff --git a/app/Resources/views/macros/widgets.html.twig b/app/Resources/views/macros/widgets.html.twig new file mode 100644 index 00000000..4482f743 --- /dev/null +++ b/app/Resources/views/macros/widgets.html.twig @@ -0,0 +1,94 @@ + +{% macro profile_list(user, items, color) %} + {% import "AvanzuAdminThemeBundle:layout:macros.html.twig" as macro %} +
+ +
+
+ {{ macro.avatar(user.avatar, user.username) }} +
+ +

{{ user.alias }} ({{ user.username }})

+
{{ user.title }}
+
+ +
+{% endmacro %} + +{% macro profile_box(user, items) %} + {% import "AvanzuAdminThemeBundle:layout:macros.html.twig" as macro %} + +
+ +
+

{{ user.alias }} ({{ user.username }})

+
{{ user.title }}
+
+
+ {{ macro.avatar(user.avatar, user.username) }} +
+ +
+{% endmacro %} + +{% macro info_box_counter(title, amount, icon, color) %} +
+ + +
+ {{ title|trans }} + {{ amount }} +
+
+{% endmacro %} + +{% macro info_box_progress(title, description, amount, percentage, icon, color) %} +
+ + +
+ {{ title|trans }} + {{ amount }} + +
+
+
+ + {{ description }} + +
+ +
+{% endmacro %} + +{% macro info_box_more(title, amount, unit, icon, color) %} +
+
+

{{ amount }}{{ unit|default('%') }}

+

{{ title|trans }}

+
+
+ +
+ + {{ 'more.info.link'|trans }} + +
+{% endmacro %} diff --git a/app/Resources/views/security/login.html.twig b/app/Resources/views/security/login.html.twig index fdad8b35..3b8d47cf 100644 --- a/app/Resources/views/security/login.html.twig +++ b/app/Resources/views/security/login.html.twig @@ -15,18 +15,18 @@
- {{ 'title.login'|trans }} + {{ 'security.title.login'|trans }}
- +
- +
diff --git a/app/Resources/views/user/profile.html.twig b/app/Resources/views/user/profile.html.twig new file mode 100644 index 00000000..1bac09df --- /dev/null +++ b/app/Resources/views/user/profile.html.twig @@ -0,0 +1,10 @@ +{% extends 'base.html.twig' %} +{% import "macros/widgets.html.twig" as widgets %} + +{% block page_title %}Profile{% endblock %} +{% block page_subtitle %}manage your settings{% endblock %} + +{% block main %} + {{ widgets.profile_list(user, items, 'aqua-active') }} + {{ widgets.profile_box(user, items, 'aqua-active') }} +{% endblock %} \ No newline at end of file diff --git a/app/config/config.yml b/app/config/config.yml index b5442ff5..1a778cc6 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -58,7 +58,9 @@ twig: - "bootstrap_3_layout.html.twig" - "form/fields.html.twig" globals: - admin_skin: skin-blue + kimai_context: + date_1: "d.m.Y" # used for display in timesheets + box_color: "green" # Assetic Configuration (used for managing web assets: CSS, JavaScript, Sass, etc.) assetic: @@ -89,5 +91,13 @@ swiftmailer: password: "%mailer_password%" spool: { type: memory } -#avanzu_admin_theme: -# use_assetic: false +avanzu_admin_theme: + use_twig : true + theme: + default_avatar : avatars/default.png + skin : skin-blue + fixed_layout : false + boxed_layout : false + collapsed_sidebar: true + mini_sidebar : true + control_sidebar : false diff --git a/app/config/config_dev.yml b/app/config/config_dev.yml index cd62ce1f..19cd023c 100644 --- a/app/config/config_dev.yml +++ b/app/config/config_dev.yml @@ -7,9 +7,9 @@ framework: strict_requirements: true profiler: { only_exceptions: false } -web_profiler: - toolbar: '%kernel.debug%' - intercept_redirects: false +#web_profiler: +# toolbar: '%kernel.debug%' +# intercept_redirects: false monolog: handlers: @@ -40,3 +40,6 @@ services: class: Twig_Extensions_Extension_Text tags: - name: twig.extension + +avanzu_admin_theme: + enable_demo: false diff --git a/app/config/routing.yml b/app/config/routing.yml index 3c6fe41b..230e6565 100644 --- a/app/config/routing.yml +++ b/app/config/routing.yml @@ -34,6 +34,6 @@ homepage: permanent: true avanzu_admin_profile: - path: /profile/{userid}/ -avanzu_admin_logout: - path: /logout + path: /{_locale}/profile/{ident}/ + options: + avanzu_admin_route: profile diff --git a/app/config/routing_dev.yml b/app/config/routing_dev.yml index fbaae995..252828ee 100644 --- a/app/config/routing_dev.yml +++ b/app/config/routing_dev.yml @@ -1,17 +1,18 @@ # this imports the routes used to display the web debug toolbar at the bottom of each page -_wdt: - resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" - prefix: /_wdt +#_wdt: +# resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml" +# prefix: /_wdt # this imports the routes needed to display the Symfony Profiler information -_profiler: - resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" - prefix: /_profiler +#_profiler: +# resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml" +# prefix: /_profiler # this imports the route used to test error pages. Just browse the following URL: # /{_locale}/_error/{status_code}.{format} # (e.g. /en/_error/404, /en/_error/403.json, /fr/_error/500.xml) # See http://symfony.com/doc/current/cookbook/controller/error_pages.html#testing-error-pages-during-development + _errors: resource: "@TwigBundle/Resources/config/routing/errors.xml" prefix: /{_locale}/_error @@ -20,6 +21,76 @@ _errors: defaults: _locale: '%locale%' + +# ====================================================================== +# Template routes, that we need once we use those features +# ====================================================================== + +#avanzu_admin_login: +# path: /{_locale}/login +# options: +# avanzu_admin_route: login +# +#avanzu_admin_logout: +# path: /logout +# options: +# avanzu_admin_route: logout +# +#avanzu_admin_all_tasks: +# path: /tasks/ +# options: +# avanzu_admin_route: all_tasks +# +#avanzu_admin_show_task: +# path: /tasks/{ident}/ +# options: +# avanzu_admin_route: task +# +#avanzu_admin_all_notifications: +# path: /notifications/ +# options: +# avanzu_admin_route: all_notifications +# +#avanzu_admin_show_notification: +# path: /notifications/{ident}/ +# options: +# avanzu_admin_route: notification +# +#avanzu_admin_all_messages: +# path: /messages/ +# options: +# avanzu_admin_route: all_messages +# +#avanzu_admin_show_message: +# path: /messages/{ident}/ +# options: +# avanzu_admin_route: message + +# ====================================================================== +# Template demo screen +# Activate full demo mode by setting "enable_demo" in config_dev.xml +# ====================================================================== + +avanzu_admin_home: + path: /{_locale}/demo-admin/ + defaults: {_controller: AvanzuAdminThemeBundle:Default:index} + options: + avanzu_admin_route: welcome + +avanzu_admin_form_demo: + path: /{_locale}/demo-admin/form-demo/ + defaults: {_controller: AvanzuAdminThemeBundle:Default:form} + +avanzu_admin_login_demo: + path: /{_locale}/demo-admin/login/ + defaults: {_controller: AvanzuAdminThemeBundle:Default:login} + +avanzu_admin_dash_demo: + path: /{_locale}/demo-admin/dashboard/ + defaults: {_controller: AvanzuAdminThemeBundle:Default:dashboard} + +# ====================================================================== + # this loads the main routing file, which usually defines the routes available # in any environment (production, development, etc.) _main: diff --git a/app/config/security.yml b/app/config/security.yml index 10b2fe03..bdd29fc2 100644 --- a/app/config/security.yml +++ b/app/config/security.yml @@ -37,7 +37,7 @@ security: # The route name the user can go to in order to logout path: security_logout # The name of the route to redirect to after logging out - target: timesheet + target: homepage role_hierarchy: ROLE_USER: ROLE_CUSTOMER diff --git a/app/config/services.yml b/app/config/services.yml index f0295c81..c0b7dd1d 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -61,3 +61,31 @@ services: # # // same code using repository services # $posts = $this->get('app.post_repository')->findAll(); + + avanzu_admin_theme.navbar_user_listener: + class: AppBundle\EventListener\NavbarShowUserListener + arguments: ["@security.token_storage"] + tags: + - { name: kernel.event_listener, event: theme.navbar_user, method: onShowUser } + - { name: kernel.event_listener, event: theme.sidebar_user, method: onShowUser } + +# avanzu_admin_theme.navbar_task_listener: +# class: "%avanzu_admin_theme.navbar_task_listener.class%" +# tags: +# - { name: kernel.event_listener, event: theme.tasks, method: onListTasks } +# +# avanzu_admin_theme.navbar_notify_listener: +# class: "%avanzu_admin_theme.navbar_notify_listener.class%" +# tags: +# - { name: kernel.event_listener, event: theme.notifications, method: onListNotifications } +# +# avanzu_admin_theme.navbar_msg_listener: +# class: "%avanzu_admin_theme.navbar_msg_listener.class%" +# tags: +# - { name: kernel.event_listener, event: theme.messages, method: onListMessages } +# +# avanzu_admin_theme.setup_menu_listener: +# class: "%avanzu_admin_theme.setup_menu_listener.class%" +# tags: +# - { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupMenu } +# - { name: kernel.event_listener, event: theme.breadcrumb, method: onSetupMenu } diff --git a/composer.json b/composer.json index e73d63fc..d2dd0062 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ "symfony/symfony": "^3.1", "twig/extensions": "^1.3", "white-october/pagerfanta-bundle": "^1.0", - "avanzu/admin-theme-bundle": "^1.3" + "avanzu/admin-theme-bundle": "dev-feature/2.0" }, "require-dev": { "sensio/generator-bundle": "~3.0", diff --git a/src/AppBundle/Controller/ProfileController.php b/src/AppBundle/Controller/ProfileController.php new file mode 100644 index 00000000..5a076619 --- /dev/null +++ b/src/AppBundle/Controller/ProfileController.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace AppBundle\Controller; + +use TimesheetBundle\Entity\Timesheet; +use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security; +use Sensio\Bundle\FrameworkExtraBundle\Configuration\Cache; + +/** + * User profile controller + * + * @Route("/profile") + * @Security("has_role('ROLE_USER')") + * + * @author Kevin Papst + */ +class ProfileController extends Controller +{ + /** + * @Route("/", defaults={"ident": null}, name="user_profile") + * @Route("/{ident}/", requirements={"ident": "[a-zA-Z0-9\-].*"}, name="user_profile_ident") + * @Method("GET") + */ + public function indexAction($ident) + { + // FIXME fetch values dynamically and add trans filter to macros + $items = [ + [ + 'title' => 'Projects', + 'url' => '#', + 'color' => 'blue', + 'amount' => 12 + ], + [ + 'title' => 'Tasks', + 'url' => '#', + 'color' => 'aqua', + 'amount' => 5 + ], + [ + 'title' => 'Projects', + 'url' => '#', + 'color' => 'red', + 'amount' => 27 + ], + [ + 'title' => 'Einträge', + 'url' => '#', + 'color' => 'green', + 'amount' => 842 + ], + ]; + + return $this->render( + 'user/profile.html.twig', + ['user' => $this->getUser(), 'items' => $items] + ); + } +} diff --git a/src/AppBundle/Controller/SecurityController.php b/src/AppBundle/Controller/SecurityController.php index bf2b7dd3..74e513bd 100644 --- a/src/AppBundle/Controller/SecurityController.php +++ b/src/AppBundle/Controller/SecurityController.php @@ -31,6 +31,7 @@ class SecurityController extends Controller { $helper = $this->get('security.authentication_utils'); + //return $this->render('AvanzuAdminThemeBundle:Security:login.html.twig', [ return $this->render('security/login.html.twig', [ // last username entered by the user (if any) 'last_username' => $helper->getLastUsername(), diff --git a/src/AppBundle/DataFixtures/ORM/LoadFixtures.php b/src/AppBundle/DataFixtures/ORM/LoadFixtures.php index d86a1959..02053385 100644 --- a/src/AppBundle/DataFixtures/ORM/LoadFixtures.php +++ b/src/AppBundle/DataFixtures/ORM/LoadFixtures.php @@ -41,6 +41,8 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface $passwordEncoder = $this->container->get('security.password_encoder'); $claraCustomer = new User(); + $claraCustomer->setAlias('Clara Haynes'); + $claraCustomer->setTitle('CFO'); $claraCustomer->setUsername('clara_customer'); $claraCustomer->setEmail('clara_customer@example.com'); $claraCustomer->setRoles(['ROLE_CUSTOMER']); @@ -49,6 +51,8 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface $manager->persist($claraCustomer); $johnUser = new User(); + $johnUser->setAlias('John Doe'); + $johnUser->setTitle('Lead Developer'); $johnUser->setUsername('john_user'); $johnUser->setEmail('john_user@example.com'); $johnUser->setRoles(['ROLE_USER']); @@ -57,6 +61,8 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface $manager->persist($johnUser); $tonyTeamlead = new User(); + $tonyTeamlead->setAlias('Tony Maier'); + $tonyTeamlead->setTitle('Head of Development'); $tonyTeamlead->setUsername('tony_teamlead'); $tonyTeamlead->setEmail('tony_teamlead@example.com'); $tonyTeamlead->setRoles(['ROLE_TEAMLEAD']); @@ -65,6 +71,8 @@ class LoadFixtures implements FixtureInterface, ContainerAwareInterface $manager->persist($tonyTeamlead); $annaAdmin = new User(); + $annaAdmin->setAlias('Anna Smith'); + $annaAdmin->setTitle('Administrator'); $annaAdmin->setUsername('anna_admin'); $annaAdmin->setEmail('anna_admin@example.com'); $annaAdmin->setRoles(['ROLE_ADMIN']); diff --git a/src/AppBundle/Entity/User.php b/src/AppBundle/Entity/User.php index c0fbd49a..19ad2fb1 100644 --- a/src/AppBundle/Entity/User.php +++ b/src/AppBundle/Entity/User.php @@ -7,7 +7,7 @@ use Symfony\Component\Security\Core\User\UserInterface; /** - * KimaiUsers + * User * * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository") * @ORM\Table(name="users", uniqueConstraints={@ORM\UniqueConstraint(name="name", columns={"name"}), @ORM\UniqueConstraint(name="apikey", columns={"apikey"})}) @@ -46,6 +46,8 @@ class User implements UserInterface private $alias; /** + * FIXME remove me + * * @var boolean * * @ORM\Column(name="trash", type="boolean", nullable=false) @@ -67,6 +69,8 @@ class User implements UserInterface private $passwordresethash; /** + * FIXME remove me + * * @var integer * * @ORM\Column(name="ban", type="integer", nullable=false) @@ -74,6 +78,7 @@ class User implements UserInterface private $ban = '0'; /** + * FIXME remove me * @var integer * * @ORM\Column(name="banTime", type="integer", nullable=false) @@ -88,7 +93,7 @@ class User implements UserInterface private $secure = '0'; /** - * FIXME + * FIXME manytoone relation * * @var integer * @@ -97,7 +102,7 @@ class User implements UserInterface private $lastproject = '1'; /** - * FIXME + * FIXME manytoone * * @var integer * @@ -133,17 +138,32 @@ class User implements UserInterface */ private $apikey; + // ======= new columns for kimai 2 ======= /** * @ORM\Column(type="json_array") */ private $roles = []; + /** + * @var string + * + * @ORM\Column(name="title", type="string", length=50, nullable=true) + */ + private $title; + + /** + * @var string + * + * @ORM\Column(name="avatar", type="string", length=50, nullable=true) + */ + private $avatar; + /** * Set alias * * @param string $alias * - * @return KimaiUsers + * @return User */ public function setAlias($alias) { @@ -167,7 +187,7 @@ class User implements UserInterface * * @param boolean $trash * - * @return KimaiUsers + * @return User */ public function setTrash($trash) { @@ -191,7 +211,7 @@ class User implements UserInterface * * @param boolean $active * - * @return KimaiUsers + * @return User */ public function setActive($active) { @@ -215,7 +235,7 @@ class User implements UserInterface * * @param string $password * - * @return KimaiUsers + * @return User */ public function setPassword($password) { @@ -239,7 +259,7 @@ class User implements UserInterface * * @param string $passwordresethash * - * @return KimaiUsers + * @return User */ public function setPasswordresethash($passwordresethash) { @@ -263,7 +283,7 @@ class User implements UserInterface * * @param integer $ban * - * @return KimaiUsers + * @return User */ public function setBan($ban) { @@ -287,7 +307,7 @@ class User implements UserInterface * * @param integer $bantime * - * @return KimaiUsers + * @return User */ public function setBantime($bantime) { @@ -311,7 +331,7 @@ class User implements UserInterface * * @param string $secure * - * @return KimaiUsers + * @return User */ public function setSecure($secure) { @@ -335,7 +355,7 @@ class User implements UserInterface * * @param integer $lastproject * - * @return KimaiUsers + * @return User */ public function setLastproject($lastproject) { @@ -359,7 +379,7 @@ class User implements UserInterface * * @param integer $lastactivity * - * @return KimaiUsers + * @return User */ public function setLastactivity($lastactivity) { @@ -383,7 +403,7 @@ class User implements UserInterface * * @param integer $lastrecord * - * @return KimaiUsers + * @return User */ public function setLastrecord($lastrecord) { @@ -407,7 +427,7 @@ class User implements UserInterface * * @param string $timeframebegin * - * @return KimaiUsers + * @return User */ public function setTimeframebegin($timeframebegin) { @@ -431,7 +451,7 @@ class User implements UserInterface * * @param string $timeframeend * - * @return KimaiUsers + * @return User */ public function setTimeframeend($timeframeend) { @@ -455,7 +475,7 @@ class User implements UserInterface * * @param string $apikey * - * @return KimaiUsers + * @return User */ public function setApikey($apikey) { @@ -474,30 +494,6 @@ class User implements UserInterface return $this->apikey; } - /** - * Set globalroleid - * - * @param integer $globalroleid - * - * @return KimaiUsers - */ - public function setGlobalroleid($globalroleid) - { - $this->globalroleid = $globalroleid; - - return $this; - } - - /** - * Get globalroleid - * - * @return integer - */ - public function getGlobalroleid() - { - return $this->globalroleid; - } - public function getId() { return $this->id; @@ -565,8 +561,40 @@ class User implements UserInterface // $this->plainPassword = null; } + /** + * @return string + */ + public function getTitle() + { + return $this->title; + } + + /** + * @param string $title + */ + public function setTitle($title) + { + $this->title = $title; + } + + /** + * @return string + */ + public function getAvatar() + { + return $this->avatar; + } + + /** + * @param string $avatar + */ + public function setAvatar($avatar) + { + $this->avatar = $avatar; + } + public function __toString() { - return $this->getUsername(); + return $this->getAlias() ?: $this->getUsername(); } } \ No newline at end of file diff --git a/src/AppBundle/EventListener/MenuBuilder.php b/src/AppBundle/EventListener/MenuBuilder.php index 327be64f..33ad75f5 100644 --- a/src/AppBundle/EventListener/MenuBuilder.php +++ b/src/AppBundle/EventListener/MenuBuilder.php @@ -75,7 +75,7 @@ class MenuBuilder if ($isAdmin) { $event->addItem( - new MenuItemModel('admin', 'menu.admin_dashboard', '', [], 'fa fa-dashboard') + new MenuItemModel('admin', 'menu.admin', '', [], 'fa fa-dashboard') ); $this->eventDispatcher->dispatch( diff --git a/src/AppBundle/EventListener/NavbarShowUserListener.php b/src/AppBundle/EventListener/NavbarShowUserListener.php new file mode 100644 index 00000000..29b06c2c --- /dev/null +++ b/src/AppBundle/EventListener/NavbarShowUserListener.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace AppBundle\EventListener; + +use AppBundle\Entity\User; +use Avanzu\AdminThemeBundle\Event\ShowUserEvent; +use Avanzu\AdminThemeBundle\Model\UserModel; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\User\UserInterface; + +/** + * Class NavbarShowUserListener + * + * @author Kevin Papst + */ +class NavbarShowUserListener +{ + /** + * @var TokenStorageInterface + */ + protected $storage; + + public function __construct(TokenStorageInterface $tokenStorage) + { + $this->storage = $tokenStorage; + } + + public function onShowUser(ShowUserEvent $event) + { + /* @var $myUser User */ + $myUser = $this->storage->getToken()->getUser(); + + $titles = []; + $roles = $this->storage->getToken()->getRoles(); + foreach ($roles as $role) { + $titles[] = ucfirst(strtolower(str_replace('ROLE_', '', $role->getRole()))); + } + + $user = new UserModel(); + $user->setName($myUser->getAlias() ?: $myUser->getUsername()) + ->setUsername($myUser->getUsername()) + ->setIsOnline(true) + ->setTitle($myUser->getTitle()) + ->setAvatar($myUser->getAvatar()) + ->setMemberSince(new \DateTime()) // FIXME add column to entity + ; + + $event->setUser($user); + } +} \ No newline at end of file diff --git a/src/TimesheetBundle/Controller/Admin/TimesheetController.php b/src/TimesheetBundle/Controller/Admin/TimesheetController.php index 8d9ce632..30083c17 100644 --- a/src/TimesheetBundle/Controller/Admin/TimesheetController.php +++ b/src/TimesheetBundle/Controller/Admin/TimesheetController.php @@ -36,7 +36,7 @@ class TimesheetController extends Controller */ public function indexAction($page) { - $entries = $this->getDoctrine()->getRepository(Timesheet::class)->findLatest($page); + $entries = $this->getDoctrine()->getRepository(Timesheet::class)->findAll($page); return $this->render('TimesheetBundle:timesheet:index.html.twig', ['entries' => $entries]); } diff --git a/src/TimesheetBundle/Controller/TimesheetController.php b/src/TimesheetBundle/Controller/TimesheetController.php index 584f5c6e..2d3e98f6 100644 --- a/src/TimesheetBundle/Controller/TimesheetController.php +++ b/src/TimesheetBundle/Controller/TimesheetController.php @@ -30,13 +30,14 @@ class TimesheetController extends Controller { /** * @Route("/", defaults={"page": 1}, name="timesheet") - * @Route("/timesheet/{page}", requirements={"page": "[1-9]\d*"}, name="timesheet_paginated") + * @Route("/page/{page}", requirements={"page": "[1-9]\d*"}, name="timesheet_paginated") * @Method("GET") * @Cache(smaxage="10") */ public function indexAction($page) { - $entries = $this->getDoctrine()->getRepository(Timesheet::class)->findLatest($page); + $user = $this->getUser(); + $entries = $this->getDoctrine()->getRepository(Timesheet::class)->findLatest($user, $page); return $this->render('TimesheetBundle:timesheet:index.html.twig', ['entries' => $entries]); } diff --git a/src/TimesheetBundle/Repository/TimesheetRepository.php b/src/TimesheetBundle/Repository/TimesheetRepository.php index a7cfaebd..de405fdf 100644 --- a/src/TimesheetBundle/Repository/TimesheetRepository.php +++ b/src/TimesheetBundle/Repository/TimesheetRepository.php @@ -11,6 +11,7 @@ namespace TimesheetBundle\Repository; +use AppBundle\Entity\User; use TimesheetBundle\Entity\Timesheet; use Doctrine\ORM\EntityRepository; use Doctrine\ORM\Query; @@ -26,16 +27,33 @@ class TimesheetRepository extends EntityRepository { /** + * @param User $user * @return Query */ - public function queryLatest() + public function queryLatest(User $user = null) { - return $this->getEntityManager() - ->createQuery(' - SELECT p - FROM TimesheetBundle:Timesheet p - ORDER BY p.start DESC - '); + $qb = $this->getEntityManager()->createQueryBuilder(); + + $qb->select('p') + ->from('TimesheetBundle:Timesheet', 'p') + ->orderBy('p.start', 'DESC'); + + if (null !== $user) { + $qb->where('p.user = :user') + ->setParameter('user', $user); + } + + return $qb->getQuery(); + } + + /** + * @param User $user + * @param int $page + * @return Pagerfanta + */ + public function findLatest(User $user, $page = 1) + { + return $this->getPager($this->queryLatest($user), $page); } /** @@ -43,9 +61,19 @@ class TimesheetRepository extends EntityRepository * * @return Pagerfanta */ - public function findLatest($page = 1) + public function findAll($page = 1) { - $paginator = new Pagerfanta(new DoctrineORMAdapter($this->queryLatest(), false)); + return $this->getPager($this->queryLatest(), $page); + } + + /** + * @param Query $query + * @param int $page + * @return Pagerfanta + */ + protected function getPager(Query $query, $page = 1) + { + $paginator = new Pagerfanta(new DoctrineORMAdapter($query, false)); $paginator->setMaxPerPage(25); $paginator->setCurrentPage($page); diff --git a/src/TimesheetBundle/Resources/views/timesheet/index.html.twig b/src/TimesheetBundle/Resources/views/timesheet/index.html.twig index f53dcf02..7f45b4ff 100644 --- a/src/TimesheetBundle/Resources/views/timesheet/index.html.twig +++ b/src/TimesheetBundle/Resources/views/timesheet/index.html.twig @@ -9,17 +9,17 @@ {{ 'label.date'|trans }} - {{ 'label.start'|trans }} - {{ 'label.end'|trans }} + {{ 'label.starttime'|trans }} + {{ 'label.endtime'|trans }} {{ 'label.duration'|trans }} - {{ 'label.user'|trans }} - {{ 'label.description'|trans }} + {{ 'label.username'|trans }} + {{ 'label.description'|trans }} {% for entry in entries %} - {{ entry.start|date("m/d/Y") }} + {{ entry.start|date(kimai_context.date_1) }} {{ entry.start|date("H:i") }} {{ entry.end|date("H:i") }} {{ entry.duration|gmdate }} diff --git a/web/avatars/default.png b/web/avatars/default.png new file mode 100644 index 00000000..277c9f78 Binary files /dev/null and b/web/avatars/default.png differ