Developer improvements, PhpCs, PhpUnit #42 (#43)

* improved dev fixtures with more diversity, more data, better testcases, user avatars #42
* added customer stats to dashboard, fixed column length for 3 widgets #42
* fixed empty alias - display empty message for new user #42
* unified-ui for "new" toolbar icon #42
* use kimai2_ as database prefix #42
* added customer stats to dashboard, fixed column length for 3 widgets #42
* fix long project/customer names in "currently active" navbar flyout" #42
* added services config for dev environment #42
* added command to run unit tests #42
* added command to run integration tests #42
* added command to run code sniffer #42
* added phpcs and phpunit to composer #42
* created tests directory #42
* fixed code sniffer warnings #42
* added function to switch result type from Pagerfanta to QueryBuilder #42
* dramatically reduced database calls by using custom joined query #42
* added command to install kimai dependencies #42
* added dev:reset command #42
This commit is contained in:
Kevin Papst
2018-01-07 15:11:03 +01:00
committed by GitHub
parent fa8e976e76
commit f8b390cbe2
63 changed files with 2424 additions and 302 deletions

View File

@@ -464,7 +464,7 @@
</trans-unit>
<trans-unit id="admin_user.subtitle">
<source>admin_user.subtitle</source>
<target>Alle registrierten Nutzer</target>
<target>Alle registrierten Benutzer der Zeitverwaltung</target>
</trans-unit>
<trans-unit id="label.alias">
<source>label.alias</source>
@@ -546,9 +546,9 @@
<source>stats.userActiveEver</source>
<target>Aktive Benutzer jemals</target>
</trans-unit>
<trans-unit id="stats.userActiveNow">
<source>stats.userActiveNow</source>
<target>Momentan aktiv</target>
<trans-unit id="stats.activeRecordings">
<source>stats.activeRecordings</source>
<target>Momentan aktive Zeitmessungen</target>
</trans-unit>
<trans-unit id="stats.activitiesTotal">
<source>stats.activitiesTotal</source>
@@ -558,6 +558,10 @@
<source>stats.projectsTotal</source>
<target>Anzahl Projekte</target>
</trans-unit>
<trans-unit id="stats.customerTotal">
<source>stats.customerTotal</source>
<target>Anzahl Kunden</target>
</trans-unit>
<!--
Month names

View File

@@ -6,21 +6,20 @@
{% block main %}
{# blue / yellow / purple / green / black #}
{# bar-chart / line-chart / calendar / clock-o #}
{% for settings in dashboard_widgets %}
{% if settings.header %}
{{ widgets.page_header(settings.header) }}
{% endif %}
{% set columnWidth = 12 / (settings.widgets|length) %}
{% set width = settings.widgets|length %}
{% set rawWidth = 12 / width %}
{% set columnWidth = rawWidth|round(0, 'floor') %}
<div class="row">
{% for widgetTemplate in settings.widgets %}
<div class="col-md-{{ columnWidth }} col-sm-{{ columnWidth * 2 }} col-xs-{{ columnWidth * 4 }}">
{% set widgetString = '{% import "macros/widgets.html.twig" as widgets %}' ~ widgetTemplate %}
{{ include(template_from_string(widgetString)) }}
</div>
<div class="col-md-{{ columnWidth }} col-sm-{{ columnWidth * 2 }} col-xs-{{ columnWidth * 4 }}">
{% set widgetString = '{% import "macros/widgets.html.twig" as widgets %}' ~ widgetTemplate %}
{{ include(template_from_string(widgetString)) }}
</div>
{% endfor %}
</div>
{% endfor %}

View File

@@ -60,13 +60,20 @@
</div>
{% endmacro %}
{% macro info_box_counter(title, amount, icon, color) %}
{% macro info_box_counter(title, amount, icon, color, url) %}
<div class="info-box">
<span class="info-box-icon bg-{{ color|default(kimai_context.box_color) }}"><i class="fa fa-{{ icon|default('flag-o') }}"></i></span>
<div class="info-box-content">
{# this is a ugly hack, make me look nicely (dashboard widget with link) #}
{% if url %}
<a href="{{ url }}" class="small-box-footer">
{% endif %}
<span class="info-box-text">{{ title|trans }}</span>
<span class="info-box-number">{{ amount }}</span>
{% if url %}
</a>
{% endif %}
</div>
</div>
{% endmacro %}

View File

@@ -4,12 +4,13 @@
{% block page_subtitle %}{{ 'profile.subtitle'|trans }}{% endblock %}
{% block main %}
{% import _self as widgets %}
{% import _self as macro %}
{% import "macros/widgets.html.twig" as widgets %}
<div class="row">
<div class="col-md-3">
{{ widgets.profile_box(user, stats) }}
{{ widgets.profile_infos(user, stats) }}
{{ macro.profile_box(user, stats) }}
{{ macro.profile_infos(user, stats) }}
</div>
<div class="col-md-9">
@@ -28,6 +29,10 @@
</ul>
<div class="tab-content">
<div class="tab-pane {% if tab == "charts" %}active{% endif %}" id="charts">
{% if years is empty %}
{{ widgets.callout('warning', 'error.no_entries_found') }}
{% endif %}
<script type="text/javascript">
var barChartOptions = {
scaleBeginAtZero: true,
@@ -148,7 +153,7 @@
<div class="box box-primary">
<div class="box-body box-profile">
{{ macro.avatar(user.avatar, user.username, 'profile-user-img img-responsive img-circle') }}
<h3 class="profile-username text-center">{{ user.alias }}</h3>
<h3 class="profile-username text-center">{{ user.alias|default(user.username) }}</h3>
<p class="text-muted text-center">{{ user.title }}</p>
@@ -188,7 +193,7 @@
{{ macro.avatar(user.avatar, user.username) }}
</div>
<!-- /.widget-user-image -->
<h3 class="widget-user-username">{{ user.alias }} ({{ user.username }})</h3>
<h3 class="widget-user-username">{{ user.alias|default(user.username) }}</h3>
<h5 class="widget-user-desc">{{ user.title }}</h5>
</div>
<div class="box-footer no-padding">
@@ -207,7 +212,7 @@
<div class="box box-widget widget-user">
<div class="widget-user-header bg-{{ color|default(kimai_context.box_color) }}">
<h3 class="widget-user-username">{{ user.alias }} ({{ user.username }})</h3>
<h3 class="widget-user-username">{{ user.alias|default(user.username) }}</h3>
<h5 class="widget-user-desc">{{ user.title }}</h5>
</div>
<div class="widget-user-image">

View File

@@ -1,5 +1,6 @@
imports:
- { resource: config.yml }
- { resource: services_dev.yml }
framework:
router:

View File

@@ -11,7 +11,7 @@ parameters:
# database_url: 'mysql://root:pass@127.0.0.1:3306/timesheet'
# You can prefix all your tables to pevent collision with other software
database_prefix: kimai_
database_prefix: kimai2_
# You can create the database and load the sample data from the command line:
#

View File

@@ -6,20 +6,19 @@ security:
providers:
# in this example, users are stored via Doctrine in the database
# To see the users at src/AppBundle/DataFixtures/ORM/LoadFixtures.php
# To load users from somewhere else: http://symfony.com/doc/current/cookbook/security/custom_provider.html
# demo users can be found at src/AppBundle/DataFixtures/ORM/LoadFixtures.php
database_users:
entity: { class: AppBundle:User, property: username }
# http://symfony.com/doc/current/book/security.html#firewalls-authentication
firewalls:
secured_area:
# this firewall applies to all URLs
pattern: ^/
# does what it says
logout_on_user_change: true
# this firewall applies to all URLs
pattern: ^/
# but the firewall does not require login on every page
# denying access is done in access_control or in your controllers
anonymous: ~

View File

@@ -1,12 +1,12 @@
services:
# ================================================================================
# TWIG
# ================================================================================
markdown:
class: AppBundle\Utils\Markdown
# ================================================================================
# TWIG
# ================================================================================
app.twig.app_extension:
public: false
class: AppBundle\Twig\Extensions
@@ -26,9 +26,9 @@ services:
tags:
- { name: twig.extension }
# ================================================================================
# SECURITY
# ================================================================================
# ================================================================================
# SECURITY
# ================================================================================
# security voter to check user-profile access
app.voter.user:
@@ -58,9 +58,9 @@ services:
tags:
- { name: security.voter }
# ================================================================================
# FORMS
# ================================================================================
# ================================================================================
# FORMS
# ================================================================================
# form to edit user roles
app.admin.user_profile_roles:
@@ -76,9 +76,9 @@ services:
tags:
- { name: kernel.event_listener, event: theme.sidebar_setup_menu, method: onSetupNavbar }
# ================================================================================
# DATABASE
# ================================================================================
# ================================================================================
# DATABASE
# ================================================================================
# service that prefixes every database table
app.tableprefix_subscriber:
@@ -94,18 +94,18 @@ services:
# app.post_repository:
# class: Doctrine\ORM\EntityRepository
# factory: ['@doctrine.orm.entity_manager', getRepository]
# arguments: [AppBundle\Entity\Post]
# arguments: [AppBundle\Entity\User]
#
# // traditional code inside a controller
# $entityManager = $this->getDoctrine()->getManager();
# $posts = $entityManager->getRepository('AppBundle:Post')->findAll();
# $posts = $entityManager->getRepository('AppBundle:User')->findAll();
#
# // same code using repository services
# $posts = $this->get('app.post_repository')->findAll();
# $posts = $this->get('app.user_repository')->findAll();
# ================================================================================
# THEME
# ================================================================================
# ================================================================================
# THEME
# ================================================================================
avanzu_admin_theme.navbar_user_listener:
class: AppBundle\EventListener\NavbarShowUserListener
@@ -114,30 +114,30 @@ services:
- { 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 }
# 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 }
# ================================================================================
# APPLICATION CORE
# ================================================================================
# ================================================================================
# APPLICATION CORE
# ================================================================================
# a route listener, that injects the locale through a URL directory
app.redirect_to_preferred_locale_listener:
@@ -153,9 +153,10 @@ services:
- { name: kernel.event_listener, event: app.main_menu_configure, method: onMainMenuConfigure }
- { name: kernel.event_listener, event: app.admin_menu_configure, method: onAdminMenuConfigure }
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
app.command.create_user:
class: AppBundle\Command\CreateUserCommand
arguments: ["@security.password_encoder", "@doctrine", "@validator"]

View File

@@ -0,0 +1,32 @@
imports:
- { resource: services.yml }
services:
# ================================================================================
# CONSOLE COMMANDS
# ================================================================================
app.command.run_phpcs:
class: AppBundle\Command\RunCodeSnifferCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:phpcs }
app.command.run_unit_tests:
class: AppBundle\Command\RunUnitTestsCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:test-unit }
app.command.run_integration_tests:
class: AppBundle\Command\RunIntegrationTestsCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:test-integration }
app.command.dev_reset:
class: AppBundle\Command\DevResetCommand
arguments: ["%kernel.root_dir%"]
tags:
- { name: console.command, command: kimai:dev:reset }