use dropdown for entity actions on detail pages (#801)

This commit is contained in:
Kevin Papst
2019-05-21 23:21:26 +02:00
committed by GitHub
parent ec174a38a9
commit 871b2e52c7
12 changed files with 52 additions and 193 deletions

View File

@@ -29,7 +29,7 @@ export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
const self = this;
document.addEventListener('click', function(event) {
let target = event.target;
while (!target.matches('body')) {
while (target !== null && !target.matches('body')) {
if (target.classList.contains(self.selector)) {
const attributes = target.dataset;

View File

@@ -25,7 +25,7 @@ export default class KimaiClickHandlerReducedInTableRow extends KimaiPlugin {
// we don't want the table row event to be processed - so we intercept it
let target = event.target;
if (event.currentTarget.matches('tr')) {
while (!target.matches('body')) {
while (target !== null && !target.matches('body')) {
if (target.matches('a') || target.matches ('button')) {
return;
}

View File

@@ -26,7 +26,7 @@ export default class KimaiToolbarAction extends KimaiPlugin {
const self = this;
document.addEventListener('click', function(event) {
let target = event.target;
while (!target.matches('body')) {
while (target !== null && !target.matches('body')) {
if (target.classList.contains(self.selector)) {
const form = document.querySelector('div.toolbar form.navbar-form');
if (form === null) {

View File

@@ -5,6 +5,19 @@
* file that was distributed with this source code.
*/
span.label-activity,
span.label-project,
span.label-customer {
display: inline-block;
.dot {
height: 10px;
width: 10px;
background-color: $gray-lte;
border-radius: 50%;
display: inline-block;
}
}
table.dataTable {
/* action column */
.actions {
@@ -39,14 +52,6 @@ table.dataTable {
span.label-activity,
span.label-project,
span.label-customer {
display: inline-block;
.dot {
height: 10px;
width: 10px;
background-color: $gray-lte;
border-radius: 50%;
display: inline-block;
}
a {
color: unset;
padding-bottom: 2px;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"build/app.js": "./app.js?4d1c16b6cec885d40370",
"build/app.css": "./app.css?e4b4080f26821060103657b889a6b1cd",
"build/app.js": "./app.js?dad0cc8443da0d5789c7",
"build/app.css": "./app.css?954c34ace3717cfb9d9c80d2be5f8c68",
"build/fonts/fa-solid-900.woff2": "./fonts/fa-solid-900.woff2?e8a92a29",
"build/images/fa-solid-900.svg": "./images/fa-solid-900.svg?666a82cb",
"build/images/glyphicons-halflings-regular.svg": "./images/glyphicons-halflings-regular.svg?89889688",

View File

@@ -1,163 +0,0 @@
<?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\Twig;
use App\Entity\Activity;
use App\Entity\Customer;
use App\Entity\Project;
use App\Entity\User;
use App\Repository\ActivityRepository;
use App\Repository\CustomerRepository;
use App\Repository\ProjectRepository;
use App\Repository\UserRepository;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
/**
* Entity specific twig extensions.
* Should be used with caution, as they can trigger a lot of DB queries.
*/
class EntityExtensions extends AbstractExtension
{
private const UNKNOWN_NAME = '-unknown-';
/**
* @var UserRepository|null
*/
private $users = null;
/**
* @var CustomerRepository|null
*/
private $customers = null;
/**
* @var ProjectRepository|null
*/
private $projects = null;
/**
* @var ActivityRepository|null
*/
private $activities = null;
/**
* @param UserRepository $users
* @param CustomerRepository $customers
* @param ProjectRepository $projects
* @param ActivityRepository $activities
*/
public function __construct(UserRepository $users, CustomerRepository $customers, ProjectRepository $projects, ActivityRepository $activities)
{
$this->users = $users;
$this->customers = $customers;
$this->projects = $projects;
$this->activities = $activities;
}
/**
* {@inheritdoc}
*/
public function getFilters()
{
return [
new TwigFilter('user', [$this, 'getUser']),
new TwigFilter('customer', [$this, 'getCustomer']),
new TwigFilter('project', [$this, 'getProject']),
new TwigFilter('activity', [$this, 'getActivity']),
];
}
/**
* @param int|User $user
* @param bool $allowEmpty
* @return User|null
*/
public function getUser($user, $allowEmpty = true)
{
if ($user instanceof User) {
return $user;
}
$entity = $this->users->getById($user);
if (null === $entity) {
$entity = $this->users->loadUserByUsername($user);
}
if (null === $entity && false === $allowEmpty) {
$entity = new User();
$entity->setUsername(self::UNKNOWN_NAME);
}
return $entity;
}
/**
* @param int|Customer $customer
* @param bool $allowEmpty
* @return Customer|null
*/
public function getCustomer($customer, $allowEmpty = true)
{
if ($customer instanceof Customer) {
return $customer;
}
$entity = $this->customers->getById($customer);
if (null === $entity && false === $allowEmpty) {
$entity = new Customer();
$entity->setName(self::UNKNOWN_NAME);
}
return $entity;
}
/**
* @param int|Project $project
* @param bool $allowEmpty
* @return Project|null
*/
public function getProject($project, $allowEmpty = true)
{
if ($project instanceof Project) {
return $project;
}
$entity = $this->projects->getById($project);
if (null === $entity && false === $allowEmpty) {
$entity = new Project();
$entity->setName(self::UNKNOWN_NAME);
$entity->setCustomer((new Customer())->setName(self::UNKNOWN_NAME));
}
return $entity;
}
/**
* @param int|Activity $activity
* @param bool $allowEmpty
* @return Activity|null
*/
public function getActivity($activity, $allowEmpty = true)
{
if ($activity instanceof Activity) {
return $activity;
}
$entity = $this->activities->getById($activity);
if (null === $entity && false === $allowEmpty) {
$entity = new Activity();
$entity->setName(self::UNKNOWN_NAME);
}
return $entity;
}
}

View File

@@ -27,7 +27,7 @@
{% set actions = actions|merge({'timesheet': path('admin_timesheet', {'customer': activity.project ? activity.project.customer.id : null, 'project': activity.project ? activity.project.id : null, 'activity': activity.id})}) %}
{% endif %}
{% if is_granted('create_other_timesheet') %}
{% set actions = actions|merge({'create-timesheet': path('admin_timesheet_create', {'project': activity.project ? activity.project.id : null, 'activity': activity.id})}) %}
{% set actions = actions|merge({'create-timesheet': {'url': path('admin_timesheet_create', {'project': activity.project ? activity.project.id : null, 'activity': activity.id}), 'class': 'modal-ajax-form'}}) %}
{% endif %}
{% if view == 'index' and is_granted('delete', activity) %}
{% set actions = actions|merge({'trash': {'url': path('admin_activity_delete', {'id': activity.id}), 'class': 'modal-ajax-form'}}) %}
@@ -35,14 +35,14 @@
{% endif %}
{% if view != 'index' %}
{% set actions = actions|merge({'list': path('admin_activity')}) %}
{% set actions = actions|merge({'activity': path('admin_activity')}) %}
{% endif %}
{% set event = trigger('actions.activity', {'actions': actions, 'view': view, 'activity': activity}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}
@@ -84,7 +84,7 @@
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}
@@ -127,14 +127,14 @@
{% endif %}
{% if view != 'index' %}
{% set actions = actions|merge({'list': path('admin_project')}) %}
{% set actions = actions|merge({'project': path('admin_project')}) %}
{% endif %}
{% set event = trigger('actions.project', {'actions': actions, 'view': view, 'project': project}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}
@@ -180,14 +180,14 @@
{% endif %}
{% if view != 'index' %}
{% set actions = actions|merge({'list': path('admin_customer')}) %}
{% set actions = actions|merge({'customer': path('admin_customer')}) %}
{% endif %}
{% set event = trigger('actions.customer', {'actions': actions, 'view': view, 'customer': customer}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}
@@ -247,14 +247,14 @@
{% endif %}
{% if view != 'index' %}
{% set actions = actions|merge({'list': path('timesheet')}) %}
{% set actions = actions|merge({'timesheet': path('timesheet')}) %}
{% endif %}
{% set event = trigger('actions.timesheet', {'actions': actions, 'view': view, 'timesheet': timesheet}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{%- endfilter -%}
{% endmacro %}
@@ -302,14 +302,14 @@
{% endif %}
{% if view != 'index' %}
{% set actions = actions|merge({'list': path('admin_timesheet')}) %}
{% set actions = actions|merge({'timesheet': path('admin_timesheet')}) %}
{% endif %}
{% set event = trigger('actions.timesheet_team', {'actions': actions, 'view': view, 'timesheet': timesheet}) %}
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}
@@ -331,7 +331,7 @@
{% if view == 'index' %}
{{ widgets.table_actions(event.payload.actions) }}
{% else %}
{{ widgets.page_actions(event.payload.actions) }}
{{ widgets.entity_actions(event.payload.actions) }}
{% endif %}
{% endmacro %}

View File

@@ -11,6 +11,15 @@
</div>
{%- endmacro -%}
{%- macro entity_actions(tools) -%}
{% import _self as macro %}
<div class="breadcrumb">
<div class="box-tools">
{{ macro.table_actions(tools) }}
</div>
</div>
{%- endmacro -%}
{% macro page_header(title) %}
<h2 class="page-header">{{ title|trans }}</h2>
{% endmacro %}

View File

@@ -30,6 +30,10 @@
<source>timesheet</source>
<target>Stundenzettel</target>
</trans-unit>
<trans-unit id="customer">
<source>customer</source>
<target>Kunden</target>
</trans-unit>
<trans-unit id="project">
<source>project</source>
<target>Projekte</target>

View File

@@ -28,7 +28,11 @@
</trans-unit>
<trans-unit id="timesheet">
<source>timesheet</source>
<target>Timesheet</target>
<target>Timesheets</target>
</trans-unit>
<trans-unit id="customer">
<source>customer</source>
<target>Customers</target>
</trans-unit>
<trans-unit id="project">
<source>project</source>