detail pages for customers and projects (#1371)
This commit is contained in:
@@ -28,6 +28,9 @@
|
||||
{% if is_granted('budget', activity) %}
|
||||
{% set actions = actions|merge({'report': {'url': path('admin_activity_budget', {'id': activity.id})}}) %}
|
||||
{% endif %}
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_other_timesheet') %}
|
||||
{% 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 %}
|
||||
@@ -39,12 +42,12 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if view != 'index' %}
|
||||
{% if view != 'index' and view != 'custom' %}
|
||||
{% set actions = actions|merge({'back': path('admin_activity')}) %}
|
||||
{% endif %}
|
||||
|
||||
{% set event = trigger('actions.activity', {'actions': actions, 'view': view, 'activity': activity}) %}
|
||||
{% if view == 'index' %}
|
||||
{% if view == 'index' or view == 'custom' %}
|
||||
{{ widgets.table_actions(event.payload.actions) }}
|
||||
{% else %}
|
||||
{{ widgets.entity_actions(event.payload.actions) }}
|
||||
|
||||
@@ -4,19 +4,23 @@
|
||||
{% import "macros/toolbar.html.twig" as toolbar %}
|
||||
{% import "activity/actions.html.twig" as actions %}
|
||||
|
||||
{% set showVisibility = query.visibility != 1 %}
|
||||
{% set columns = {
|
||||
'name': 'alwaysVisible',
|
||||
'customer': 'hidden-xs',
|
||||
'project': 'hidden-xs',
|
||||
'comment': 'hidden-xs hidden-sm',
|
||||
'comment': {'class': 'hidden-xs hidden-sm', 'title': 'label.description'|trans},
|
||||
} %}
|
||||
{% for field in metaColumns %}
|
||||
{% set columns = columns|merge({
|
||||
('mf_' ~ field.name): {'title': field.label, 'class': 'hidden-xs hidden-sm', 'orderBy': false}
|
||||
}) %}
|
||||
{% endfor %}
|
||||
{% if showVisibility %}
|
||||
{% set columns = columns|merge({
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
}) %}
|
||||
{% endif %}
|
||||
{% set columns = columns|merge({
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
'actions': 'actions alwaysVisible',
|
||||
}) %}
|
||||
|
||||
@@ -40,16 +44,16 @@
|
||||
{% for entry in entries %}
|
||||
<tr{% if is_granted('edit', entry) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_activity_edit', {'id': entry.id}) }}"{% endif %}>
|
||||
<td>{{ widgets.label_color_dot('activity', true, entry.name, null, entry.color) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'customer') }}">
|
||||
{% if entry.project and entry.project.customer %}
|
||||
{# only none-global activities have a project and customer assigned #}
|
||||
{{ widgets.label_customer(entry.project.customer) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'project') }}">
|
||||
{# only none-global activities have a project and customer assigned #}
|
||||
{% if entry.project %}
|
||||
{# only none-global activities have a project and customer assigned #}
|
||||
{{ widgets.label_project(entry.project) }}
|
||||
{% if entry.project.customer %}
|
||||
<br>
|
||||
<small>
|
||||
{{ widgets.label_customer(entry.project.customer) }}
|
||||
</small>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">{{ entry.comment|comment2html }}</td>
|
||||
@@ -58,7 +62,9 @@
|
||||
{{ tables.datatable_meta_column(entry, field) }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% if showVisibility %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% endif %}
|
||||
<td class="actions">
|
||||
{{ actions.activity(entry, 'index') }}
|
||||
</td>
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
{% block javascripts %}
|
||||
{# no call to parent(), as we use a custom built for the frontend assets and don't want the default <script> #}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
window.addEventListener('load', function() {
|
||||
var loader = new KimaiWebLoader(
|
||||
{
|
||||
login: '{{ path('fos_user_security_login') }}',
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
{% set actions = {} %}
|
||||
|
||||
{% if customer.id is not empty %}
|
||||
{% if view != 'details' and is_granted('view', customer) %}
|
||||
{% set actions = actions|merge({'details': path('customer_details', {'id': customer.id})}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('edit', customer) %}
|
||||
{% set class = '' %}
|
||||
{% if view != 'edit' %}
|
||||
@@ -25,13 +28,17 @@
|
||||
{% endif %}
|
||||
{% set actions = actions|merge({'edit': {'url': path('admin_customer_edit', {'id': customer.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('budget', customer) %}
|
||||
{% set actions = actions|merge({'report': {'url': path('admin_customer_budget', {'id': customer.id})}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('permissions', customer) %}
|
||||
{% set actions = actions|merge({'permissions': {'url': path('admin_customer_permissions', {'id': customer.id})}}) %}
|
||||
{% set class = '' %}
|
||||
{% if view != 'permissions' %}
|
||||
{% set class = 'modal-ajax-form' %}
|
||||
{% endif %}
|
||||
{% set actions = actions|merge({'permissions': {'url': path('admin_customer_permissions', {'id': customer.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_project') %}
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_project') or is_granted('view_teamlead_project') or is_granted('view_team_project') %}
|
||||
{% set actions = actions|merge({'project': path('admin_project', {'customer': customer.id})}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_activity') %}
|
||||
@@ -48,12 +55,12 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if view != 'index' %}
|
||||
{% if view != 'index' and view != 'custom' %}
|
||||
{% set actions = actions|merge({'back': path('admin_customer')}) %}
|
||||
{% endif %}
|
||||
|
||||
{% set event = trigger('actions.customer', {'actions': actions, 'view': view, 'customer': customer}) %}
|
||||
{% if view == 'index' %}
|
||||
{% if view == 'index' or view == 'custom' %}
|
||||
{{ widgets.table_actions(event.payload.actions) }}
|
||||
{% else %}
|
||||
{{ widgets.entity_actions(event.payload.actions) }}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "customer/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.customer(customer, 'delete') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{% set params = {
|
||||
'%activity%': '<strong>' ~ stats.activityAmount ~ '</strong>',
|
||||
'%project%': '<strong>' ~ stats.projectAmount ~ '</strong>',
|
||||
'%customer%': '<strong>' ~ customer.name ~ '</strong>',
|
||||
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
|
||||
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>',
|
||||
'%rate%': '<strong>' ~ stats.recordRate|money ~ '</strong>'
|
||||
} %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_title %}{{ customer.name }}{% endblock %}
|
||||
{% block box_body %}
|
||||
<p>
|
||||
{{ 'admin_customer.short_stats'|trans(params)|raw }}
|
||||
</p>
|
||||
|
||||
{{ progress.progressbar(customer.budget, stats.recordRate, 'label.budget'|trans, stats.recordRate|money(customer.currency) ~ ' / ' ~ customer.budget|money(customer.currency) ) }}
|
||||
{{ progress.progressbar(customer.timeBudget, stats.recordDuration, 'label.timeBudget'|trans, stats.recordDuration|duration ~ ' / ' ~ customer.timeBudget|duration ) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% endblock %}
|
||||
174
templates/customer/details.html.twig
Normal file
174
templates/customer/details.html.twig
Normal file
@@ -0,0 +1,174 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "customer/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_actions %}{{ actions.customer(customer, 'details') }}{% endblock %}
|
||||
{% block page_title %}{{ 'admin_customer.title'|trans }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% set can_edit = is_granted('edit', customer) %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_attributes %}id="customer_details_box"{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ widgets.label_customer(customer) }}
|
||||
{% if customer.company is not empty %} – {{ customer.company }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{% if can_edit %}
|
||||
<a class="modal-ajax-form open-edit btn btn-box-tool" data-href="{{ path('admin_customer_edit', {'id': customer.id}) }}" data-toggle="tooltip" data-placement="top" title="{{ 'action.edit'|trans }}"><i class="{{ 'edit'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{% if customer.comment is not empty %}
|
||||
{{ customer.comment|comment2html(true) }}
|
||||
{% endif %}
|
||||
<table class="table table-hover">
|
||||
{% if not customer.visible %}
|
||||
<tr>
|
||||
<th>{{ 'label.visible'|trans }}</th>
|
||||
<td>
|
||||
{{ widgets.label_boolean(customer.visible) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.address is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.address'|trans }}</th>
|
||||
<td>
|
||||
{{ customer.address|nl2br }}
|
||||
|
||||
{% if customer.country is not empty %}
|
||||
<br>
|
||||
{{ customer.country|country }}
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.contact is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.contact'|trans }}</th>
|
||||
<td>{{ customer.contact }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.phone is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.phone'|trans }}</th>
|
||||
<td><a href="tel:{{ customer.phone }}">{{ customer.phone }}</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.mobile is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.mobile'|trans }}</th>
|
||||
<td><a href="tel:{{ customer.mobile }}">{{ customer.mobile }}</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.email is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.email'|trans }}</th>
|
||||
<td><a href="mailto:{{ customer.email }}">{{ customer.email }}</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.homepage is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.homepage'|trans }}</th>
|
||||
<td><a href="{{ customer.homepage }}" target="_blank">{{ customer.homepage|replace({'https://': '', 'http://': ''}) }}</a></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.fax is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.fax'|trans }}</th>
|
||||
<td>{{ customer.fax }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.timezone is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.timezone'|trans }}</th>
|
||||
<td><span data-toggle="tooltip" data-placement="top" title="{{ customer.timezone }}">{{ now|date_full(false) }}</span></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.currency is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.currency'|trans }}</th>
|
||||
<td>{{ customer.currency }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if is_granted('details', customer) %}
|
||||
{% if customer.number is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.number'|trans }}</th>
|
||||
<td>{{ customer.number }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if customer.vatId is not empty %}
|
||||
<tr>
|
||||
<th>{{ 'label.vat_id'|trans }}</th>
|
||||
<td>{{ customer.vatId }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if can_edit %}
|
||||
<tr>
|
||||
<th>{{ 'label.fixedRate'|trans }}</th>
|
||||
<td>
|
||||
{% if customer.fixedRate is not empty %}
|
||||
{{ customer.fixedRate|money(customer.currency) }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.hourlyRate'|trans }}</th>
|
||||
<td>
|
||||
{% if customer.hourlyRate is not empty %}
|
||||
{{ customer.hourlyRate|money(customer.currency) }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for metaField in customer.visibleMetaFields %}
|
||||
<tr>
|
||||
<th>{{ metaField.name }}</th>
|
||||
<td>{{ widgets.form_type_value(metaField.type, metaField.value, customer) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{{ render(controller('App\\Controller\\CustomerController::projectsAction', {'customer': customer.id, 'page': 1})) }}
|
||||
|
||||
{% if stats is not null %}
|
||||
{{ include('customer/embed_budget.html.twig', {'customer': customer, 'stats': stats}) }}
|
||||
{% endif %}
|
||||
|
||||
{% if teams is not null %}
|
||||
{% set options = {'teams': teams, 'team': team} %}
|
||||
{% if is_granted('permissions', customer) %}
|
||||
{% set options = options|merge({'route_create': path('customer_team_create', {'id': customer.id}), 'route_edit': path('admin_customer_permissions', {'id': customer.id})}) %}
|
||||
{% endif %}
|
||||
{{ include('embeds/teams.html.twig', options) }}
|
||||
{% endif %}
|
||||
|
||||
{% if comments is not null %}
|
||||
{% set options = {'form': commentForm, 'comments': comments} %}
|
||||
{% if can_edit %}
|
||||
{% set options = options|merge({'route_pin': 'customer_comment_pin', 'route_delete': 'customer_comment_delete'}) %}
|
||||
{% endif %}
|
||||
{{ include('embeds/comments.html.twig', options) }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function() {
|
||||
KimaiReloadPageWidget.create('kimai.customerTeamUpdate kimai.customerUpdate kimai.teamUpdate');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -23,65 +23,60 @@
|
||||
</div>
|
||||
</div>
|
||||
{{ form_row(form.comment) }}
|
||||
<fieldset>
|
||||
{#<legend>Company data</legend>#}
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
{{ form_row(form.company) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.vatId) }}
|
||||
</div>
|
||||
{{ form_row(form.address) }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.company) }}
|
||||
</div>
|
||||
{{ form_row(form.address) }}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.country) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.currency) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.timezone) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.number) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
{#<legend>Contact data</legend>#}
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.contact) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.email) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.homepage) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.vatId) }}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.mobile) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.phone) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.fax) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.country) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
{#<legend>Financial data</legend>#}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.fixedRate) }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.hourlyRate) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.currency) }}
|
||||
</div>
|
||||
{% if form.budget is defined %}
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.timezone) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.contact) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.email) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.homepage) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.mobile) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.phone) }}
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{{ form_row(form.fax) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.fixedRate) }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.hourlyRate) }}
|
||||
</div>
|
||||
</div>
|
||||
{% if form.budget is defined %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.budget) }}
|
||||
@@ -90,14 +85,10 @@
|
||||
{{ form_row(form.timeBudget) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
{% endif %}
|
||||
{{ form_row(form.visible) }}
|
||||
{% if form.metaFields is defined and form.metaFields is not empty %}
|
||||
<fieldset>
|
||||
{#<legend>Custom fields</legend>#}
|
||||
{{ form_row(form.metaFields) }}
|
||||
</fieldset>
|
||||
{{ form_row(form.metaFields) }}
|
||||
{% endif %}
|
||||
{{ form_widget(form) }}
|
||||
{% endblock %}
|
||||
|
||||
22
templates/customer/embed_budget.html.twig
Normal file
22
templates/customer/embed_budget.html.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'customer': customer, 'stats': stats} %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_title %}{{ 'label.budget'|trans }}{% endblock %}
|
||||
{% block box_attributes %}id="budget_box"{% endblock %}
|
||||
{% block box_body %}
|
||||
{% set params = {
|
||||
'%activity%': '<strong>' ~ stats.activityAmount ~ '</strong>',
|
||||
'%project%': '<strong>' ~ stats.projectAmount ~ '</strong>',
|
||||
'%customer%': '<strong>' ~ customer.name ~ '</strong>',
|
||||
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
|
||||
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>',
|
||||
'%rate%': '<strong>' ~ stats.recordRate|money ~ '</strong>'
|
||||
} %}
|
||||
|
||||
<p>
|
||||
{{ 'admin_customer.short_stats'|trans(params)|raw }}
|
||||
</p>
|
||||
|
||||
{{ progress.progressbar(customer.budget, stats.recordRate, 'label.budget'|trans, stats.recordRate|money(customer.currency) ~ ' / ' ~ customer.budget|money(customer.currency) ) }}
|
||||
{{ progress.progressbar(customer.timeBudget, stats.recordDuration, 'label.timeBudget'|trans, stats.recordDuration|duration ~ ' / ' ~ customer.timeBudget|duration ) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
30
templates/customer/embed_projects.html.twig
Normal file
30
templates/customer/embed_projects.html.twig
Normal file
@@ -0,0 +1,30 @@
|
||||
{% if projects|length > 0 %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'customer': customer, 'projects': projects, 'page': page} %}
|
||||
{% import "project/actions.html.twig" as actions %}
|
||||
{% block box_title %}{{ 'menu.admin_project'|trans }}{% endblock %}
|
||||
{% block box_attributes %}
|
||||
id="project_list_box" data-href="{{ path('customer_projects', {'id': customer.id}) }}" data-reload="kimai.projectUpdate"
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{{ pagerfanta(projects, 'twitter_bootstrap3_translated', { proximity: 1, css_container_class: 'pagination pagination-sm inline', routeName: 'customer_projects', routeParams: {'id': customer.id} }) }}
|
||||
{% endblock %}
|
||||
{% block box_body_class %}no-padding{% endblock %}
|
||||
{% block box_tools_attributes %}data-page="{{ page }}"{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table table-hover dataTable">
|
||||
<tbody>
|
||||
{% for project in projects %}
|
||||
<tr>
|
||||
<td>{{ project.name }}</td>
|
||||
<td>{{ project.comment|comment2html }}</td>
|
||||
<td class="actions">{{ actions.project(project, 'custom') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
<script type="text/javascript">
|
||||
KimaiPaginatedBoxWidget.create('#project_list_box');
|
||||
</script>
|
||||
{% endif %}
|
||||
@@ -4,11 +4,10 @@
|
||||
{% import "macros/toolbar.html.twig" as toolbar %}
|
||||
{% import "customer/actions.html.twig" as actions %}
|
||||
|
||||
{% set showVisibility = query.visibility != 1 %}
|
||||
{% set columns = {
|
||||
'name': 'alwaysVisible',
|
||||
'comment': 'hidden-xs',
|
||||
'country': 'hidden-xs hidden-sm',
|
||||
'number': 'hidden-xs',
|
||||
'comment': {'class': 'hidden-xs hidden-sm', 'title': 'label.description'|trans},
|
||||
} %}
|
||||
{% for field in metaColumns %}
|
||||
{% set columns = columns|merge({
|
||||
@@ -16,12 +15,14 @@
|
||||
}) %}
|
||||
{% endfor %}
|
||||
{% set columns = columns|merge({
|
||||
'email': {'class': 'text-center hidden hidden-xs', 'orderBy': false},
|
||||
'homepage': {'class': 'text-center hidden hidden-xs', 'orderBy': false},
|
||||
'mobile': {'class': 'text-center hidden hidden-xs', 'orderBy': false},
|
||||
'phone': {'class': 'text-center hidden hidden-xs', 'orderBy': false},
|
||||
'team': {'class': 'text-center', 'orderBy': false},
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
}) %}
|
||||
{% if showVisibility %}
|
||||
{% set columns = columns|merge({
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
}) %}
|
||||
{% endif %}
|
||||
{% set columns = columns|merge({
|
||||
'actions': 'actions alwaysVisible',
|
||||
}) %}
|
||||
|
||||
@@ -40,47 +41,21 @@
|
||||
{% if entries.count == 0 %}
|
||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||
{% else %}
|
||||
{{ tables.datatable_header(tableName, columns, query, {'reload': 'kimai.customerUpdate'}) }}
|
||||
{{ tables.datatable_header(tableName, columns, query, {'reload': 'kimai.customerUpdate kimai.customerTeamUpdate'}) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr{% if is_granted('edit', entry) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_customer_edit', {'id': entry.id}) }}"{% endif %}>
|
||||
<td>{{ widgets.label_color_dot('customer', true, entry.name, null, entry.color) }} {% if entry.company is not empty %}({{ entry.company }}){% endif %}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">{{ entry.comment|comment2html }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'country') }}">{{ entry.country|country }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'number') }}">{{ entry.number }}</td>
|
||||
<tr class="alternative-link open-edit" data-href="{{ path('customer_details', {'id': entry.id}) }}">
|
||||
<td>
|
||||
{{ widgets.label_color_dot('customer', true, entry.name, null, entry.color) }}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">
|
||||
{{ entry.comment|comment2html }}
|
||||
</td>
|
||||
{% for field in metaColumns %}
|
||||
<td class="text-nowrap {{ tables.data_table_column_class(tableName, columns, 'mf_' ~ field.name) }}">
|
||||
{{ tables.datatable_meta_column(entry, field) }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'email') }}">
|
||||
{% if entry.email is not empty %}
|
||||
<a href="mailto:{{ entry.email }}"><i class="{{ 'mail'|icon }}"></i></a>
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'homepage') }}">
|
||||
{% if entry.homepage is not empty %}
|
||||
<a href="{{ entry.homepage }}" target="_blank"><i class="{{ 'home'|icon }}"></i></a>
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'mobile') }}">
|
||||
{% if entry.mobile is not empty %}
|
||||
<a href="tel:{{ entry.mobile }}"><i class="{{ 'mobile'|icon }}"></i></a>
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'phone') }}">
|
||||
{% if entry.phone is not empty %}
|
||||
<a href="tel:{{ entry.phone }}"><i class="{{ 'phone'|icon }}"></i></a>
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'team') }}">
|
||||
{% if entry.teams|length > 0 %}
|
||||
{{ widgets.badge_counter(entry.teams|length) }}
|
||||
@@ -88,7 +63,9 @@
|
||||
{{ widgets.icon('unlocked') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% if showVisibility %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% endif %}
|
||||
<td class="actions">
|
||||
{{ actions.customer(entry, 'index') }}
|
||||
</td>
|
||||
|
||||
@@ -1,21 +1,30 @@
|
||||
<div class="box box-solid box-danger">
|
||||
<div class="box-header">
|
||||
<h3 class="box-title">{{ title|default('confirm.delete'|trans) }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{{ message|raw }}
|
||||
</div>
|
||||
{{ form_start(form) }}
|
||||
<div class="box-body">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'boxtype': 'danger'} %}
|
||||
{% block box_before %}
|
||||
{{ form_start(form) }}
|
||||
{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ title|default('confirm.delete'|trans) }}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{% block form_body %}
|
||||
{{ form_widget(form) }}
|
||||
{% if used is same as (false) %}
|
||||
{{ 'delete.not_in_use'|trans }}
|
||||
<div class="hidden">
|
||||
{{ form_widget(form) }}
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{{ message|raw }}</p>
|
||||
{{ form_widget(form) }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
<input type="submit" value="{{ 'action.delete'|trans }}" class="btn btn-danger" />
|
||||
{% if back %}
|
||||
<a href="{{ back }}" class="btn btn-link">{{ 'action.back'|trans }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block box_after %}
|
||||
{{ form_end(form) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
53
templates/embeds/comments.html.twig
Normal file
53
templates/embeds/comments.html.twig
Normal file
@@ -0,0 +1,53 @@
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'form': form, 'comments': comments, 'route_pin': route_pin|default(null), 'route_delete': route_delete|default(null)} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}{{ 'label.comment'|trans }}{% endblock %}
|
||||
{% block box_attributes %}id="comments_box"{% endblock %}
|
||||
{% block box_body_class %}box-comments{% endblock %}
|
||||
{% block box_body %}
|
||||
{% set replacer = {} %}
|
||||
{% for pref in app.user.preferences %}
|
||||
{% set replacer = replacer|merge({('{{user.' ~ pref.name ~ '}}'): pref.value}) %}
|
||||
{% endfor %}
|
||||
{% if comments|length == 0 %}
|
||||
{{ 'error.no_comments_found'|trans }}
|
||||
{% endif %}
|
||||
{% for comment in comments %}
|
||||
<div class="box-comment">
|
||||
{{ widgets.user_avatar(comment.createdBy, false, 'img-sm') }}
|
||||
<div class="comment-text">
|
||||
<span class="username">
|
||||
{{ widgets.username(comment.createdBy) }}
|
||||
<span class="text-muted pull-right">
|
||||
{% if route_pin is not null %}
|
||||
<a href="{{ path(route_pin, {'id': comment.id}) }}" class="btn btn-default btn-xs {% if comment.pinned %}active{% endif %}"><i class="{{ 'pin'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% if route_delete is not null %}
|
||||
<a href="{{ path(route_delete, {'id': comment.id}) }}" class="confirmation-link btn btn-default btn-xs" data-method="POST" data-question="confirm.delete" data-msg-error="action.delete.error" data-msg-success="action.delete.success"><i class="{{ 'delete'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{{ comment.createdAt|date_full }}
|
||||
</span>
|
||||
</span>
|
||||
{{ comment.message|replace(replacer)|md2html }}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
{% block box_footer -%}
|
||||
{% if form is not null %}
|
||||
{{ form_start(form) }}
|
||||
<div class="input-group">
|
||||
{{ widgets.user_avatar(app.user, false, 'img-responsive img-sm') }}
|
||||
<div class="img-push">
|
||||
{{ form_widget(form.message) }}
|
||||
</div>
|
||||
<span class="input-group-btn">
|
||||
<button type="submit" class="btn btn-default">
|
||||
{{ 'action.save'|trans }}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
{{ form_widget(form) }}
|
||||
{{ form_end(form) }}
|
||||
{% endif %}
|
||||
{%- endblock %}
|
||||
{% endembed %}
|
||||
32
templates/embeds/teams.html.twig
Normal file
32
templates/embeds/teams.html.twig
Normal file
@@ -0,0 +1,32 @@
|
||||
{%
|
||||
set options = {
|
||||
'teams': teams,
|
||||
'team': team|default(null),
|
||||
'route_create': route_create|default(null),
|
||||
'route_edit': route_edit|default(null),
|
||||
'empty_message': empty_message|default('team.visibility_global')
|
||||
}
|
||||
%}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with options %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_tools %}
|
||||
{% if teams|length == 0 and team is null and route_create is not null and is_granted('create_team') %}
|
||||
<a class="btn-box-tool" href="{{ route_create }}" data-toggle="tooltip" data-placement="top" title="{{ 'team.create_default'|trans({}, 'teams') }}"><i class="{{ 'create'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% if route_edit is not null %}
|
||||
<a class="modal-ajax-form open-edit btn btn-box-tool" href="{{ route_edit }}" data-toggle="tooltip" data-placement="top" title="{{ 'action.edit'|trans }}"><i class="{{ 'edit'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_attributes %}id="team_listing_box"{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ 'permissions'|trans({}, 'actions') }}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{% if teams|length > 0 %}
|
||||
<p>{{ 'team.visibility_restricted'|trans({}, 'teams') }}</p>
|
||||
{{ widgets.team_list(teams) }}
|
||||
{% else %}
|
||||
<p>{{ empty_message|default('team.visibility_global')|trans({}, 'teams') }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
@@ -15,7 +15,17 @@
|
||||
{% import _self as macro %}
|
||||
<div class="breadcrumb">
|
||||
<div class="box-tools">
|
||||
{{ macro.table_actions(tools) }}
|
||||
<div class="btn-group">
|
||||
{% set actions = {} %}
|
||||
{%- for icon, values in tools %}
|
||||
{% if icon == 'back' %}
|
||||
{{ macro.action_button(icon, values) }}
|
||||
{% else %}
|
||||
{% set actions = actions|merge({(icon): values}) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ macro.table_actions(actions, '') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{%- endmacro -%}
|
||||
@@ -69,11 +79,10 @@
|
||||
|
||||
{% macro user_avatar(user, tooltip, class) %}
|
||||
{% set avatar = avatar(user, admin_lte_context.default_avatar) %}
|
||||
{% set showTooltip = tooltip|default(true) %}
|
||||
{% if tooltip is not defined or tooltip is same as (false)%}
|
||||
<img src="{{ avatar }}" class="{{ class|default('img-circle') }}" alt="{{ user.displayName }}" />
|
||||
{% if tooltip is same as (false) %}
|
||||
<img src="{{ avatar }}" class="img-circle{% if class is not empty %} {{ class }}{% endif %}" alt="{{ user.displayName }}" />
|
||||
{% else %}
|
||||
<img src="{{ avatar }}" class="{{ class|default('img-circle') }}" data-toggle="tooltip" data-placement="top" alt="{{ user.displayName }}" title="{{ user.displayName }}" />
|
||||
<img src="{{ avatar }}" class="img-circle{% if class is not empty %} {{ class }}{% endif %}" data-toggle="tooltip" data-placement="top" alt="{{ user.displayName }}" title="{{ tooltip|default(user.displayName) }}" />
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
@@ -200,30 +209,50 @@
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro table_actions(actions) %}
|
||||
{% macro table_actions(actions, class) %}
|
||||
{%- import _self as macro -%}
|
||||
{% if actions|length >= 1 %}
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{ 'label.actions'|trans }}
|
||||
<span class="fa fa-caret-down"></span></button>
|
||||
{% if class is null %}
|
||||
{% set class = 'btn-sm' %}
|
||||
{% endif %}
|
||||
{% set trash = null %}
|
||||
{% set divider = false %}
|
||||
<div class="btn-group dropdown">
|
||||
<button type="button" class="btn btn-default {{ class }} dropdown-toggle" data-toggle="dropdown" aria-expanded="false">
|
||||
<span class="fa fa-chevron-down"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
{%- apply spaceless -%}
|
||||
{%- for icon,values in actions %}
|
||||
{% set class = '' %}
|
||||
{% if icon == 'trash' %}
|
||||
{% set class = 'delete' %}
|
||||
{% if actions|length > 1 %}
|
||||
<li class="divider"></li>
|
||||
{% if icon == 'divider' and values is null %}
|
||||
{% if not loop.last and divider is same as (false) %}
|
||||
<li class="divider"></li>
|
||||
{% endif %}
|
||||
{% set divider = true %}
|
||||
{% else %}
|
||||
{% if values is iterable %}
|
||||
{% set values = values|merge({'title': icon|trans({}, 'actions')}) %}
|
||||
{% else %}
|
||||
{% set values = {'url': values, 'title': icon|trans({}, 'actions')} %}
|
||||
{% endif %}
|
||||
{% if icon == 'trash' %}
|
||||
{% set trash = values %}
|
||||
{% else %}
|
||||
{% set divider = false %}
|
||||
<li>
|
||||
{{ macro.action_button(icon, values, false) }}
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<li class="{{ class }}">
|
||||
{% if values is iterable %}
|
||||
{{ macro.action_button(icon, values|merge({'title': icon|trans({}, 'actions')}), false) }}
|
||||
{% else %}
|
||||
{{ macro.action_button(icon, {'url': values, 'title': icon|trans({}, 'actions')}, false) }}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endfor -%}
|
||||
{%- if trash is not null %}
|
||||
{% if actions|length > 1 and divider is same as (false) %}
|
||||
<li class="divider"></li>
|
||||
{% endif %}
|
||||
<li class="delete">
|
||||
{{ macro.action_button('trash', trash, false) }}
|
||||
</li>
|
||||
{% endif -%}
|
||||
{% endapply %}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -371,3 +400,49 @@
|
||||
{{ value }}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro team_list(teams, showTitle) %}
|
||||
{% if showTitle is null %}
|
||||
{% set showTitle = true %}
|
||||
{% endif %}
|
||||
{% import _self as macro %}
|
||||
<table class="table table-hover dataTable" role="grid">
|
||||
{% if showTitle %}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'label.team'|trans }}</th>
|
||||
<th>{{ 'label.user'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
{% endif %}
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr{% if is_granted('edit', team) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_team_member', {'id': team.id}) }}"{% endif %}>
|
||||
<td>
|
||||
{{ team.name }}
|
||||
</td>
|
||||
<td class="avatars">
|
||||
{% set userTeamCount = team.users|length %}
|
||||
{{ macro.user_avatar(team.teamlead, ('label.teamlead'|trans ~ ': ' ~ team.teamlead.displayName), 'teamlead') }}
|
||||
{% set teamHiddenId = 'team_' ~ team.id ~ '_hiddenUser' ~ random() %}
|
||||
{% set counter = 0 %}
|
||||
{% for user in team.users %}
|
||||
{% if user != team.teamlead %}
|
||||
{{ macro.user_avatar(user) }}
|
||||
{% set counter = counter + 1 %}
|
||||
{% endif %}
|
||||
{% if userTeamCount > 5 and counter == 4 and not loop.last %}
|
||||
<a href="#" onclick="$('#{{ teamHiddenId }}').toggleClass('hidden');$(this).hide();return false;" class="badge">{{ 'label.plus_more'|trans({'%count%': (userTeamCount - 5)}) }}</a>
|
||||
<span class="hidden" id="{{ teamHiddenId }}">
|
||||
{% set counter = counter + 1 %}
|
||||
{% endif %}
|
||||
{% if userTeamCount > 5 and counter != 4 and loop.last %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
{% set actions = {} %}
|
||||
|
||||
{% if project.id is not empty %}
|
||||
{% if view != 'details' and is_granted('view', project) %}
|
||||
{% set actions = actions|merge({'details': path('project_details', {'id': project.id})}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('edit', project) %}
|
||||
{% set class = '' %}
|
||||
{% if view != 'edit' %}
|
||||
@@ -25,11 +28,15 @@
|
||||
{% endif %}
|
||||
{% set actions = actions|merge({'edit': {'url': path('admin_project_edit', {'id': project.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('budget', project) %}
|
||||
{% set actions = actions|merge({'report': {'url': path('admin_project_budget', {'id': project.id})}}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('permissions', project) %}
|
||||
{% set actions = actions|merge({'permissions': {'url': path('admin_project_permissions', {'id': project.id})}}) %}
|
||||
{% set class = '' %}
|
||||
{% if view != 'permissions' %}
|
||||
{% set class = 'modal-ajax-form' %}
|
||||
{% endif %}
|
||||
{% set actions = actions|merge({'permissions': {'url': path('admin_project_permissions', {'id': project.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_activity') %}
|
||||
{% set actions = actions|merge({'activity': path('admin_activity', {'customer': project.customer.id, 'project': project.id})}) %}
|
||||
@@ -45,12 +52,12 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if view != 'index' %}
|
||||
{% if view != 'index' and view != 'custom' %}
|
||||
{% set actions = actions|merge({'back': path('admin_project')}) %}
|
||||
{% endif %}
|
||||
|
||||
{% set event = trigger('actions.project', {'actions': actions, 'view': view, 'project': project}) %}
|
||||
{% if view == 'index' %}
|
||||
{% if view == 'index' or view == 'custom' %}
|
||||
{{ widgets.table_actions(event.payload.actions) }}
|
||||
{% else %}
|
||||
{{ widgets.entity_actions(event.payload.actions) }}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "project/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.project(project, 'delete') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
{% set params = {
|
||||
'%project%': '<strong>' ~ project.name ~ '</strong>',
|
||||
'%customer%': '<strong>' ~ project.customer.name ~ '</strong>',
|
||||
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
|
||||
'%activities%': '<strong>' ~ stats.activityAmount ~ '</strong>',
|
||||
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
|
||||
} %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_title %}{{ project.name }}{% endblock %}
|
||||
{% block box_body %}
|
||||
<p>
|
||||
{{ 'admin_project.short_stats'|trans(params)|raw }}
|
||||
</p>
|
||||
|
||||
{{ progress.progressbar(project.budget, stats.recordRate, 'label.budget'|trans, stats.recordRate|money(project.customer.currency) ~ ' / ' ~ project.budget|money(project.customer.currency) ) }}
|
||||
{{ progress.progressbar(project.timeBudget, stats.recordDuration, 'label.timeBudget'|trans, stats.recordDuration|duration ~ ' / ' ~ project.timeBudget|duration ) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% endblock %}
|
||||
151
templates/project/details.html.twig
Normal file
151
templates/project/details.html.twig
Normal file
@@ -0,0 +1,151 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "project/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'admin_project.title'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.project(project, 'details') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% set can_edit = is_granted('edit', project) %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "customer/actions.html.twig" as customerActions %}
|
||||
{% block box_attributes %}id="project_details_box"{% endblock %}
|
||||
{% block box_tools %}
|
||||
{% if can_edit %}
|
||||
<a class="modal-ajax-form open-edit btn btn-box-tool" data-href="{{ path('admin_project_edit', {'id': project.id}) }}" data-toggle="tooltip" data-placement="top" title="{{ 'action.edit'|trans }}"><i class="{{ 'edit'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ widgets.label_project(project) }}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{% if project.comment is not empty %}
|
||||
{{ project.comment|comment2html(true) }}
|
||||
{% endif %}
|
||||
<table class="table table-hover">
|
||||
{% if not project.visible %}
|
||||
<tr>
|
||||
<th>{{ 'label.visible'|trans }}</th>
|
||||
<td>
|
||||
{{ widgets.label_boolean(project.visible) }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>{{ 'label.customer'|trans }}</th>
|
||||
<td>
|
||||
{{ widgets.label_customer(project.customer) }}
|
||||
{% if project.customer.teams|length == 0 %}
|
||||
{{ widgets.icon('unlocked') }}
|
||||
{% endif %}
|
||||
|
||||
{{ customerActions.customer(project.customer, 'custom') }}
|
||||
</td>
|
||||
</tr>
|
||||
{% if is_granted('details', project) %}
|
||||
<tr>
|
||||
<th>{{ 'label.orderNumber'|trans }}</th>
|
||||
<td>
|
||||
{{ project.orderNumber }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.orderDate'|trans }}</th>
|
||||
<td>
|
||||
{% if project.orderDate is not empty %}
|
||||
{{ project.orderDate|date_full }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.project_start'|trans }}</th>
|
||||
<td>
|
||||
{% if project.start is not empty %}
|
||||
{{ project.start|date_full }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.project_end'|trans }}</th>
|
||||
<td>
|
||||
{% if project.end is not empty %}
|
||||
{{ project.end|date_full }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if can_edit %}
|
||||
<tr>
|
||||
<th>{{ 'label.fixedRate'|trans }}</th>
|
||||
<td>
|
||||
{% if project.fixedRate is not empty %}
|
||||
{{ project.fixedRate|money(project.customer.currency) }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.hourlyRate'|trans }}</th>
|
||||
<td>
|
||||
{% if project.hourlyRate is not empty %}
|
||||
{{ project.hourlyRate|money(project.customer.currency) }}
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% for metaField in project.visibleMetaFields %}
|
||||
<tr>
|
||||
<th>{{ metaField.name }}</th>
|
||||
<td>{{ widgets.form_type_value(metaField.type, metaField.value, project) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{{ render(controller('App\\Controller\\ProjectController::activitiesAction', {'project': project.id, 'page': 1})) }}
|
||||
|
||||
{% if stats is not null %}
|
||||
{{ include('project/embed_budget.html.twig', {'project': project, 'stats': stats}) }}
|
||||
{% endif %}
|
||||
|
||||
{% if teams is not null%}
|
||||
{% set options = {'teams': teams, 'team': team} %}
|
||||
{% if is_granted('permissions', project) %}
|
||||
{% set options = options|merge({'route_create': path('project_team_create', {'id': project.id}), 'route_edit': path('admin_project_permissions', {'id': project.id})}) %}
|
||||
{% endif %}
|
||||
{% if project.customer.teams|length > 0 %}
|
||||
{% set options = options|merge({'empty_message': 'team.project_visibility_inherited'}) %}
|
||||
{% endif %}
|
||||
{{ include('embeds/teams.html.twig', options) }}
|
||||
{% endif %}
|
||||
|
||||
{% if comments is not null %}
|
||||
{% set options = {'form': commentForm, 'comments': comments} %}
|
||||
{% if can_edit %}
|
||||
{% set options = options|merge({'route_pin': 'project_comment_pin', 'route_delete': 'project_comment_delete'}) %}
|
||||
{% endif %}
|
||||
{{ include('embeds/comments.html.twig', options) }}
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function() {
|
||||
KimaiReloadPageWidget.create('kimai.projectTeamUpdate kimai.projectUpdate kimai.teamUpdate kimai.customerUpdate ');
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
29
templates/project/embed_activities.html.twig
Normal file
29
templates/project/embed_activities.html.twig
Normal file
@@ -0,0 +1,29 @@
|
||||
{% if activities|length > 0 %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'project': project, 'activities': activities, 'page': page} %}
|
||||
{% import "activity/actions.html.twig" as actions %}
|
||||
{% block box_title %}{{ 'menu.admin_activity'|trans }}{% endblock %}
|
||||
{% block box_attributes %}
|
||||
id="activity_list_box" data-href="{{ path('project_activities', {'id': project.id}) }}" data-reload="kimai.activityUpdate"
|
||||
{% endblock %}
|
||||
{% block box_tools %}
|
||||
{{ pagerfanta(activities, 'twitter_bootstrap3_translated', { proximity: 1, css_container_class: 'pagination pagination-sm inline', routeName: 'project_activities', routeParams: {'id': project.id} }) }}
|
||||
{% endblock %}
|
||||
{% block box_body_class %}no-padding{% endblock %}
|
||||
{% block box_tools_attributes %}data-page="{{ page }}"{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table table-hover dataTable">
|
||||
<tbody>
|
||||
{% for activity in activities %}
|
||||
<tr>
|
||||
<td>{{ activity.name }}</td>
|
||||
<td class="actions">{{ actions.activity(activity, 'custom') }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
<script type="text/javascript">
|
||||
KimaiPaginatedBoxWidget.create('#activity_list_box');
|
||||
</script>
|
||||
{% endif %}
|
||||
21
templates/project/embed_budget.html.twig
Normal file
21
templates/project/embed_budget.html.twig
Normal file
@@ -0,0 +1,21 @@
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/progressbar.html.twig" as progress %}
|
||||
{% block box_title %}{{ 'label.budget'|trans }}{% endblock %}
|
||||
{% block box_attributes %}id="budget_box"{% endblock %}
|
||||
{% block box_body %}
|
||||
{% set params = {
|
||||
'%project%': '<strong>' ~ project.name ~ '</strong>',
|
||||
'%customer%': '<strong>' ~ project.customer.name ~ '</strong>',
|
||||
'%records%': '<strong>' ~ stats.recordAmount ~ '</strong>',
|
||||
'%activities%': '<strong>' ~ stats.activityAmount ~ '</strong>',
|
||||
'%duration%': '<strong>' ~ stats.recordDuration|duration ~ '</strong>'
|
||||
} %}
|
||||
|
||||
<p>
|
||||
{{ 'admin_project.short_stats'|trans(params)|raw }}
|
||||
</p>
|
||||
|
||||
{{ progress.progressbar(project.budget, stats.recordRate, 'label.budget'|trans, stats.recordRate|money(project.customer.currency) ~ ' / ' ~ project.budget|money(project.customer.currency) ) }}
|
||||
{{ progress.progressbar(project.timeBudget, stats.recordDuration, 'label.timeBudget'|trans, stats.recordDuration|duration ~ ' / ' ~ project.timeBudget|duration ) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
@@ -4,12 +4,11 @@
|
||||
{% import "macros/toolbar.html.twig" as toolbar %}
|
||||
{% import "project/actions.html.twig" as actions %}
|
||||
|
||||
{% set showVisibility = query.visibility != 1 %}
|
||||
{% set columns = {
|
||||
'name': 'alwaysVisible',
|
||||
'customer': 'hidden-xs',
|
||||
'comment': 'hidden-xs hidden-sm',
|
||||
'orderNumber': 'hidden-xs hidden-sm',
|
||||
'orderDate': 'hidden-xs hidden-sm',
|
||||
'comment': {'class': 'hidden-xs hidden-sm', 'title': 'label.description'|trans},
|
||||
} %}
|
||||
{% for field in metaColumns %}
|
||||
{% set columns = columns|merge({
|
||||
@@ -18,7 +17,13 @@
|
||||
{% endfor %}
|
||||
{% set columns = columns|merge({
|
||||
'team': {'class': 'text-center', 'orderBy': false},
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
}) %}
|
||||
{% if showVisibility %}
|
||||
{% set columns = columns|merge({
|
||||
'visible': {'class': 'text-center', 'orderBy': false},
|
||||
}) %}
|
||||
{% endif %}
|
||||
{% set columns = columns|merge({
|
||||
'actions': 'actions alwaysVisible',
|
||||
}) %}
|
||||
|
||||
@@ -37,21 +42,15 @@
|
||||
{% if entries.count == 0 %}
|
||||
{{ widgets.callout('warning', 'error.no_entries_found') }}
|
||||
{% else %}
|
||||
{{ tables.datatable_header(tableName, columns, query, {'reload': 'kimai.projectUpdate'}) }}
|
||||
{{ tables.datatable_header(tableName, columns, query, {'reload': 'kimai.projectUpdate kimai.projectTeamUpdate'}) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr{% if is_granted('edit', entry) %} class="modal-ajax-form open-edit" data-href="{{ path('admin_project_edit', {'id': entry.id}) }}"{% endif %}>
|
||||
<tr class="alternative-link open-edit" data-href="{{ path('project_details', {'id': entry.id}) }}">
|
||||
<td>{{ widgets.label_color_dot('project', true, entry.name, null, entry.color) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'customer') }}">
|
||||
{{ widgets.label_customer(entry.customer) }}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">{{ entry.comment|comment2html }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'orderNumber') }}">{{ entry.orderNumber }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'orderDate') }}">
|
||||
{% if entry.orderDate is not empty %}
|
||||
{{ entry.orderDate|date_short }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'comment') }}">{{ entry.comment|comment2html() }}</td>
|
||||
{% for field in metaColumns %}
|
||||
<td class="text-nowrap {{ tables.data_table_column_class(tableName, columns, 'mf_' ~ field.name) }}">
|
||||
{{ tables.datatable_meta_column(entry, field) }}
|
||||
@@ -64,7 +63,9 @@
|
||||
{{ widgets.icon('unlocked') }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% if showVisibility %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'visible') }}">{{ widgets.label_visible(entry.visible) }}</td>
|
||||
{% endif %}
|
||||
<td class="actions">
|
||||
{{ actions.project(entry, 'index') }}
|
||||
</td>
|
||||
|
||||
14
templates/team/edit_member.html.twig
Normal file
14
templates/team/edit_member.html.twig
Normal file
@@ -0,0 +1,14 @@
|
||||
{% extends app.request.xmlHttpRequest ? 'form.html.twig' : 'base.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "team/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'teams.title'|trans({}, 'teams') }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.team(team, 'edit') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{{ include(app.request.xmlHttpRequest ? 'default/_form_modal.html.twig' : 'default/_form.html.twig', {
|
||||
'title': team.name|default('create'|trans),
|
||||
'form': form,
|
||||
'back': path('admin_team')
|
||||
}) }}
|
||||
{% endblock %}
|
||||
@@ -46,6 +46,10 @@
|
||||
{% set actions = actions|merge({'edit': {'url': path('admin_timesheet_edit', {'id': timesheet.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if view == 'index' and is_granted('delete', timesheet) %}
|
||||
{% set actions = actions|merge({'trash': {'url': path('delete_timesheet', {'id' : timesheet.id}), 'class': 'api-link', 'attr': {'data-event': 'kimai.timesheetDelete kimai.timesheetUpdate', 'data-method': 'DELETE', 'data-question': 'confirm.delete', 'data-msg-error': 'action.delete.error', 'data-msg-success': 'action.delete.success'}}}) %}
|
||||
{% endif %}
|
||||
|
||||
@@ -47,6 +47,10 @@
|
||||
{% set actions = actions|merge({'edit': {'url': path('timesheet_edit', {'id': timesheet.id}), 'class': class}}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
|
||||
{% if view == 'index' and is_granted('delete', timesheet) %}
|
||||
{% set actions = actions|merge({'trash': {'url': path('delete_timesheet', {'id' : timesheet.id}), 'class': 'api-link', 'attr': {'data-event': 'kimai.timesheetDelete kimai.timesheetUpdate', 'data-method': 'DELETE', 'data-question': 'confirm.delete', 'data-msg-error': 'action.delete.error', 'data-msg-success': 'action.delete.success'}}}) %}
|
||||
{% endif %}
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
{% if is_granted('preferences', user) %}
|
||||
{% set actions = actions|merge({'settings': {'url': path('user_profile_preferences', {'username' : user.username})}}) %}
|
||||
{% endif %}
|
||||
{% if actions|length > 0 %}
|
||||
{% set actions = actions|merge({'divider': null}) %}
|
||||
{% endif %}
|
||||
{% if is_granted('view_other_timesheet') and user.enabled %}
|
||||
{% set actions = actions|merge({'timesheet': path('admin_timesheet', {'users': [user.id]})}) %}
|
||||
{% endif %}
|
||||
|
||||
@@ -4,21 +4,28 @@
|
||||
{% import "macros/toolbar.html.twig" as toolbar %}
|
||||
{% import "user/actions.html.twig" as actions %}
|
||||
|
||||
{% set showVisibility = query.visibility != 1 %}
|
||||
{% set columns = {
|
||||
'alias': 'alwaysVisible',
|
||||
'username': 'hidden-xs',
|
||||
'email': 'hidden-xs hidden-md hidden-sm',
|
||||
'title': 'hidden-xs hidden-sm',
|
||||
} %}
|
||||
{% set columns = columns|merge({
|
||||
'roles': {'class': 'hidden-xs hidden-sm', 'orderBy': false},
|
||||
}) %}
|
||||
{% for pref in preferences %}
|
||||
{% set columns = columns|merge({
|
||||
('mf_' ~ pref.name): {'title': pref.label, 'class': 'hidden-xs hidden-sm', 'orderBy': false}
|
||||
}) %}
|
||||
{% endfor %}
|
||||
{% set columns = columns|merge({
|
||||
'roles': {'class': 'hidden-xs hidden-sm', 'orderBy': false},
|
||||
'team': {'class': 'hidden-xs', 'orderBy': false},
|
||||
'active': {'class': '', 'orderBy': false},
|
||||
'team': {'class': 'text-center hidden-xs', 'orderBy': false},
|
||||
}) %}
|
||||
{% if showVisibility %}
|
||||
{% set columns = columns|merge({
|
||||
'active': {'class': '', 'orderBy': false},
|
||||
}) %}
|
||||
{% endif %}
|
||||
{% set columns = columns|merge({
|
||||
'actions': 'actions alwaysVisible',
|
||||
}) %}
|
||||
|
||||
@@ -40,19 +47,9 @@
|
||||
{{ tables.datatable_header(tableName, columns, query, {'reload': 'kimai.userUpdate'}) }}
|
||||
|
||||
{% for entry in entries %}
|
||||
<tr{% if is_granted('edit', entry) %} class="open-edit alternative-link" data-href="{{ path('user_profile_edit', {'username': entry.username}) }}"{% endif %}>
|
||||
<tr{% if is_granted('view', entry) %} class="open-edit alternative-link" data-href="{{ path('user_profile', {'username': entry.username}) }}"{% endif %}>
|
||||
<td>{{ widgets.user_avatar(entry) }} {{ widgets.username(entry) }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'username') }}">{{ entry.username }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'email') }}">{{ entry.email }}</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'title') }}">{{ entry.title }}</td>
|
||||
{% for pref in preferences %}
|
||||
<td class="text-nowrap {{ tables.data_table_column_class(tableName, columns, 'mf_' ~ pref.name) }}">
|
||||
{% set metaField = entry.preference(pref.name) %}
|
||||
{% if not metaField is null and metaField.value is not null and metaField.value is not empty %}
|
||||
{{ widgets.form_type_value(pref.type, metaField.value, entry) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'roles') }}">
|
||||
{% set showUserRole = entry.roles|length == 1 %}
|
||||
{% for role in entry.roles %}
|
||||
@@ -61,16 +58,22 @@
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'team') }}">
|
||||
{% for team in entry.teams %}
|
||||
{% if entry.isTeamleadOf(team) %}
|
||||
{{ widgets.label_team(team, 'success') }}
|
||||
{% else %}
|
||||
{{ widgets.label_team(team) }}
|
||||
{% for pref in preferences %}
|
||||
<td class="text-nowrap {{ tables.data_table_column_class(tableName, columns, 'mf_' ~ pref.name) }}">
|
||||
{% set metaField = entry.preference(pref.name) %}
|
||||
{% if not metaField is null and metaField.value is not null and metaField.value is not empty %}
|
||||
{{ widgets.form_type_value(pref.type, metaField.value, entry) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td class="text-center {{ tables.data_table_column_class(tableName, columns, 'team') }}">
|
||||
{% if entry.teams|length > 0 %}
|
||||
{{ widgets.badge_counter(entry.teams|length) }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'active') }}">{{ widgets.label_visible(entry.enabled) }}</td>
|
||||
{% if showVisibility %}
|
||||
<td class="{{ tables.data_table_column_class(tableName, columns, 'active') }}">{{ widgets.label_visible(entry.enabled) }}</td>
|
||||
{% endif %}
|
||||
<td class="actions">
|
||||
{{ actions.user(entry, 'index') }}
|
||||
</td>
|
||||
|
||||
@@ -6,81 +6,104 @@
|
||||
{% block page_actions %}{{ actions.user(user, tab) }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% import _self as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
|
||||
<div class="col-md-8">
|
||||
{% block profile_content %}{% endblock %}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
{{ macro.profile_box(user, stats) }}
|
||||
{{ macro.profile_infos(user, stats) }}
|
||||
<div class="col-md-4">
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_body_class %}box-profile{% endblock %}
|
||||
{% block box_body %}
|
||||
<div class="text-center">
|
||||
{{ widgets.user_avatar(user) }}
|
||||
<h3 class="profile-username">{{ widgets.username(user) }}</h3>
|
||||
<p class="text-muted">{{ user.title }}</p>
|
||||
</div>
|
||||
{% set seeOwnRate = is_granted('view_rate_own_timesheet') %}
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>{{ 'stats.durationMonth'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ stats.durationThisMonth|duration }}</td>
|
||||
</tr>
|
||||
{% if seeOwnRate %}
|
||||
<tr>
|
||||
<th>{{ 'stats.amountMonth'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ stats.amountThisMonth|money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<th>{{ 'stats.durationTotal'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ stats.durationTotal|duration }}</td>
|
||||
</tr>
|
||||
{% if seeOwnRate %}
|
||||
<tr>
|
||||
<th>{{ 'stats.amountTotal'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ stats.amountTotal|money }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}{{ 'profile.about_me'|trans }}{% endblock %}
|
||||
{% block box_body %}
|
||||
{# colors = purple, blue, aqua, red, green #}
|
||||
<table class="table no-border">
|
||||
<tr>
|
||||
<th>{{ 'label.id'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ user.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'label.username'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ user.username }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{{ 'profile.first_entry'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ stats.firstEntry|date_short }}</td>
|
||||
</tr>
|
||||
{% if is_granted('hourly-rate', user) %}
|
||||
<tr>
|
||||
<th>{{ 'label.hourlyRate'|trans }}</th>
|
||||
<td class="text-nowrap pull-right">{{ user.preferenceValue('hourly_rate') }}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
{% if user.teams is not empty and (is_granted('teams', user) or (app.user == user and is_granted('view_team_member'))) %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}{{ 'label.my_teams'|trans }}{% endblock %}
|
||||
{% block box_tools %}
|
||||
{% if is_granted('roles', user) %}
|
||||
<a class="btn-box-tool" href="{{ path('user_profile_teams', {'username': user.username}) }}"><i class="{{ 'edit'|icon }}"></i></a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ widgets.team_list(user.teams) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% macro profile_infos(user, stats) %}
|
||||
<div class="box box-{{ admin_lte_context.widget.type }}">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'profile.about_me'|trans }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<ul class="nav nav-stacked">
|
||||
{# colors = purple, blue, aqua, red, green #}
|
||||
<li><a href="#">{{ 'label.id'|trans }} <span class="pull-right badge bg-aqua">{{ user.id }}</span></a></li>
|
||||
<li><a href="#">{{ 'label.username'|trans }} <span class="pull-right badge bg-blue">{{ user.username }}</span></a></li>
|
||||
<li><a href="#">{{ 'profile.first_entry'|trans }} <span class="pull-right badge bg-purple">{{ stats.firstEntry|date_short }}</span></a></li>
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li><a href="#">{{ 'label.hourlyRate'|trans }} <span class="pull-right badge bg-blue">{{ user.preferenceValue('hourly_rate') }}</span></a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function() {
|
||||
KimaiReloadPageWidget.create('kimai.teamUpdate', true);
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% macro profile_box(user, stats) %}
|
||||
{% import "@AdminLTE/Macros/default.html.twig" as macro %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
<div class="box box-{{ admin_lte_context.widget.type }}">
|
||||
<div class="box-body box-profile">
|
||||
<div class="text-center">
|
||||
{{ widgets.user_avatar(user) }}
|
||||
<h3 class="profile-username">{{ widgets.username(user) }}</h3>
|
||||
<p class="text-muted">{{ user.title }}</p>
|
||||
</div>
|
||||
|
||||
<ul class="list-group list-group-unbordered">
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationMonth'|trans }}</b> <a class="pull-right">{{ stats.durationThisMonth|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountMonth'|trans }}</b> <a class="pull-right">{{ stats.amountThisMonth|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.durationTotal'|trans }}</b> <a class="pull-right">{{ stats.durationTotal|duration }}</a>
|
||||
</li>
|
||||
|
||||
{% if is_granted('view_rate_own_timesheet') %}
|
||||
<li class="list-group-item">
|
||||
<b>{{ 'stats.amountTotal'|trans }}</b> <a class="pull-right">{{ stats.amountTotal|money }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{# -------------------------------- UNUSED FOR NOW -------------------------------- #}
|
||||
{% macro profile_list_unused(user, items) %}
|
||||
|
||||
@@ -53,8 +53,6 @@
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.userRoleUpdate', function() {
|
||||
document.location.reload();
|
||||
});
|
||||
KimaiReloadPageWidget.create('kimai.userRoleUpdate');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,99 +1,39 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box">
|
||||
{% if not title is empty %}
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ title|trans }}</h3>
|
||||
{#
|
||||
<div class="box-tools pull-right">
|
||||
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i>
|
||||
</button>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="fa fa-wrench"></i></button>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" class="btn btn-box-tool" data-widget="remove"><i class="fa fa-times"></i></button>
|
||||
</div>
|
||||
#}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="box-body">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{ render_widget(widgets.0) }}
|
||||
</div>
|
||||
{#
|
||||
<div class="col-md-4">
|
||||
<p class="text-center">
|
||||
<strong>Goal Completion</strong>
|
||||
</p>
|
||||
<div class="progress-group">
|
||||
<span class="progress-text">Add Products to Cart</span>
|
||||
<span class="progress-number"><b>160</b>/200</span>
|
||||
|
||||
<div class="progress sm">
|
||||
<div class="progress-bar progress-bar-aqua" style="width: 80%"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block box_footer %}
|
||||
{% if widgets|length > 1 %}
|
||||
<div class="row">
|
||||
{% set width = (widgets|length) - 1 %}
|
||||
{% set rawWidth = 12 / width %}
|
||||
{% set columnWidth = rawWidth|round(0, 'floor') %}
|
||||
{% for widget in widgets|slice(1, width) %}
|
||||
{% set data = widget.data %}
|
||||
{% if widget.option('dataType') == 'duration' %}
|
||||
{% set data = widget.data|duration %}
|
||||
{% elseif widget.option('dataType') == 'money' %}
|
||||
{% set data = widget.data|money %}
|
||||
{% endif %}
|
||||
<div class="col-sm-{{ columnWidth }} col-xs-{{ columnWidth * 2 }}">
|
||||
<div class="description-block border-right">
|
||||
<h5 class="description-header">{{ data }}</h5>
|
||||
<span class="description-text">{{ widget.title|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-group">
|
||||
<span class="progress-text">Complete Purchase</span>
|
||||
<span class="progress-number"><b>310</b>/400</span>
|
||||
<div class="progress sm">
|
||||
<div class="progress-bar progress-bar-red" style="width: 80%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-group">
|
||||
<span class="progress-text">Visit Premium Page</span>
|
||||
<span class="progress-number"><b>480</b>/800</span>
|
||||
<div class="progress sm">
|
||||
<div class="progress-bar progress-bar-green" style="width: 80%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-group">
|
||||
<span class="progress-text">Send Inquiries</span>
|
||||
<span class="progress-number"><b>250</b>/500</span>
|
||||
<div class="progress sm">
|
||||
<div class="progress-bar progress-bar-yellow" style="width: 80%"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
#}
|
||||
</div>
|
||||
</div>
|
||||
{% if widgets|length > 1 %}
|
||||
<div class="box-footer">
|
||||
<div class="row">
|
||||
{% set width = (widgets|length) - 1 %}
|
||||
{% set rawWidth = 12 / width %}
|
||||
{% set columnWidth = rawWidth|round(0, 'floor') %}
|
||||
{% for widget in widgets|slice(1, width) %}
|
||||
{% set data = widget.data %}
|
||||
{% if widget.option('dataType') == 'duration' %}
|
||||
{% set data = widget.data|duration %}
|
||||
{% elseif widget.option('dataType') == 'money' %}
|
||||
{% set data = widget.data|money %}
|
||||
{% endif %}
|
||||
<div class="col-sm-{{ columnWidth }} col-xs-{{ columnWidth * 2 }}">
|
||||
<div class="description-block border-right">
|
||||
{#<span class="description-percentage text-green"><i class="fa fa-caret-up"></i> 17%</span>#}
|
||||
{#<span class="description-percentage text-yellow"><i class="fa fa-caret-left"></i> 0%</span>#}
|
||||
{#<span class="description-percentage text-green"><i class="fa fa-caret-up"></i> 20%</span>#}
|
||||
{#<span class="description-percentage text-red"><i class="fa fa-caret-down"></i> 18%</span>#}
|
||||
<h5 class="description-header">{{ data }}</h5>
|
||||
<span class="description-text">{{ widget.title|trans }}</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,18 +8,17 @@
|
||||
{% if projectStats|length > 0 %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box box-{{ admin_lte_context.widget.type }} WidgetUserTeamProjects" id="{{ widgetId }}">
|
||||
{% if not title is empty %}
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ title|trans }}</h3>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="box-body">
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% block box_attributes %}id="{{ widgetId }}"{% endblock %}
|
||||
{% block box_title %}
|
||||
{% if not title is empty %}{{ title|trans }}{% endif %}
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table table-hover dataTable" role="grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'label.project'|trans }}</th>
|
||||
<th class="hidden-xs">{{ 'label.team'|trans }}</th>
|
||||
<th class="hidden-xs hidden-sm hidden-md">{{ 'label.team'|trans }}</th>
|
||||
<th style="width:50%">{{ 'label.progress'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -32,7 +31,7 @@
|
||||
<br>
|
||||
<small>{{ widgets.label_customer(stats.project.customer) }}</small>
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<td class="hidden-xs hidden-sm hidden-md">
|
||||
{% for team in project.teams %}
|
||||
{% if app.user.isInTeam(team) %}
|
||||
{{ widgets.label_team(team) }}
|
||||
@@ -51,10 +50,9 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -1,58 +1,21 @@
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
|
||||
{% set teams = data %}
|
||||
{% set title = options.title|default('label.my_teams') %}
|
||||
{% set title = options.title|default(title|default('label.teams')) %}
|
||||
{% set widgetId = options.id %}
|
||||
|
||||
|
||||
{% if teams|length > 0 %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="box box-{{ admin_lte_context.widget.type }} WidgetUserTeams" id="{{ widgetId }}">
|
||||
{% if not title is empty %}
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ title|trans }}</h3>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="box-body">
|
||||
<table class="table table-hover dataTable" role="grid">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'label.team'|trans }}</th>
|
||||
<th class="text-center">{{ 'label.teamlead'|trans }}</th>
|
||||
<th>{{ 'label.user'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for team in teams %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ team.name }}
|
||||
</td>
|
||||
<td class="text-center">
|
||||
{{ widgets.user_avatar(team.teamlead) }}
|
||||
</td>
|
||||
<td class="avatars">
|
||||
{% set userTeamCount = team.users|length %}
|
||||
{% for user in team.users %}
|
||||
{% set teamHiddenId = widgetId ~ '_' ~ team.id ~ '_hiddenUser' %}
|
||||
{{ widgets.user_avatar(user) }}
|
||||
{% if userTeamCount > 5 and loop.index == 5 and not loop.last %}
|
||||
<a href="#" onclick="$('#{{ teamHiddenId }}').toggleClass('hidden');$(this).hide();return false;" class="badge">{{ 'label.plus_more'|trans({'%count%': (userTeamCount - 5)}) }}</a>
|
||||
<span class="hidden" id="{{ teamHiddenId }}">
|
||||
{% endif %}
|
||||
{% if userTeamCount > 5 and loop.index != 5 and loop.last %}
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' with {'border': false} %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_title %}{{ title|trans }}{% endblock %}
|
||||
{% block box_attributes %}id="{{ widgetId }}"{% endblock %}
|
||||
{% block box_body_class %}no-padding{% endblock %}
|
||||
{% block box_body %}
|
||||
{{ widgets.team_list(teams, false) }}
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
Reference in New Issue
Block a user