weekly quick-entry form (#2793)
This commit is contained in:
@@ -8,6 +8,23 @@
|
||||
{{ parent() }}
|
||||
{% endblock form_label %}
|
||||
|
||||
{% block quick_entry_week_row %}
|
||||
<tr{% with {attr: row_attr|merge({class: (row_attr.class|default('') ~ ' form-group qe-entry-week-row' ~ (not valid ? ' has-error'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||
<td>
|
||||
{{ form_row(form.project) }}
|
||||
</td>
|
||||
<td>
|
||||
{{ form_row(form.activity) }}
|
||||
</td>
|
||||
{% for timesheet in form.timesheets %}
|
||||
<td class="text-center{% if timesheet.vars.data.begin is weekend %} weekend{% endif %}{% if timesheet.vars.data.begin is today %} today{% endif %}">
|
||||
{{ form_row(timesheet) }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
<td class="text-nowrap text-center total qe-totals-row"></td>
|
||||
</tr>
|
||||
{% endblock %}
|
||||
|
||||
{% block _team_edit_form_members_entry_user_widget %}
|
||||
{# this will convert the select box into a hidden field, which are exchangable from an HTML perspective #}
|
||||
{%- set type = 'hidden' -%}
|
||||
@@ -47,7 +64,7 @@
|
||||
{% endblock daterange_widget %}
|
||||
|
||||
{% block duration_widget %}
|
||||
{% if form.vars.duration_presets is defined and form.vars.duration_presets is not empty %}
|
||||
{% if (form.vars.duration_presets is defined and form.vars.duration_presets is not empty) and (form.vars.disabled is same as (false)) %}
|
||||
<div class="input-group">
|
||||
{{ block('form_widget_simple') }}
|
||||
<div class="input-group-btn">
|
||||
@@ -55,7 +72,7 @@
|
||||
<ul class="dropdown-menu dropdown-menu-right pre-scrollable">
|
||||
{% for value in form.vars.duration_presets %}
|
||||
<li class="text-center">
|
||||
<a href="#" onclick="$('#{{ form.vars.id }}').val('{{ value }}');$('#{{ form.vars.id }}').trigger('change');return false;">{{ value }}</a>
|
||||
<a href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ value }}').trigger('change');return false;">{{ value }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
@@ -69,7 +86,7 @@
|
||||
{% block datetime_widget -%}
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<a href="#" onclick="if (!$('#{{ id }}').is(':disabled')) { $('#{{ id }}').val(moment().format('{{ attr['data-format'] }}')).change(); }return false;"><i class="{{ 'calendar'|icon }}"></i></a>
|
||||
<a href="#" onclick="if (!jQuery('#{{ id }}').is(':disabled')) { jQuery('#{{ id }}').val(moment().format('{{ attr['data-format'] }}')).change(); }return false;"><i class="{{ 'calendar'|icon }}"></i></a>
|
||||
</div>
|
||||
{{ block('form_widget_simple') }}
|
||||
</div>
|
||||
@@ -78,7 +95,7 @@
|
||||
{% block date_widget -%}
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">
|
||||
<a href="#" onclick="if (!$('#{{ id }}').is(':disabled')) { $('#{{ id }}').val(moment().format('{{ attr['data-format'] }}')).change(); }return false;"><i class="{{ 'calendar'|icon }}"></i></a>
|
||||
<a href="#" onclick="if (!jQuery('#{{ id }}').is(':disabled')) { jQuery('#{{ id }}').val(moment().format('{{ attr['data-format'] }}')).change(); }return false;"><i class="{{ 'calendar'|icon }}"></i></a>
|
||||
</div>
|
||||
{{ block('form_widget_simple') }}
|
||||
</div>
|
||||
@@ -99,7 +116,7 @@
|
||||
|
||||
{% block yearpicker_widget -%}
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="$('#{{ form.vars.id }}').val('{{ previousYear|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ previousYear|date_short }}">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ previousYear|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ previousYear|date_short }}">
|
||||
<i class="{{ 'left'|icon }}"></i>
|
||||
</a>
|
||||
<a class="btn btn-default" href="#" onclick="return false;">
|
||||
@@ -111,7 +128,7 @@
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
<a class="btn btn-default btn-right" href="#" onclick="$('#{{ form.vars.id }}').val('{{ nextYear|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ nextYear|date_short }}">
|
||||
<a class="btn btn-default btn-right" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ nextYear|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ nextYear|date_short }}">
|
||||
<i class="{{ 'right'|icon }}"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -120,13 +137,13 @@
|
||||
|
||||
{% block monthpicker_widget -%}
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="$('#{{ form.vars.id }}').val('{{ previousMonth|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ previousMonth|month_name(true) }}">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ previousMonth|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ previousMonth|month_name(true) }}">
|
||||
<i class="{{ 'left'|icon }}"></i>
|
||||
</a>
|
||||
<a class="btn btn-default" href="#" onclick="return false;">
|
||||
<span id="{{ form.vars.id }}_month_name">{{ month|month_name(true) }}</span>
|
||||
</a>
|
||||
<a class="btn btn-default btn-right" href="#" onclick="$('#{{ form.vars.id }}').val('{{ nextMonth|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ nextMonth|month_name(true) }}">
|
||||
<a class="btn btn-default btn-right" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ nextMonth|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ nextMonth|month_name(true) }}">
|
||||
<i class="{{ 'right'|icon }}"></i>
|
||||
</a>
|
||||
</div>
|
||||
@@ -134,14 +151,14 @@
|
||||
{%- endblock monthpicker_widget %}
|
||||
|
||||
{% block weekpicker_widget -%}
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="$('#{{ form.vars.id }}').val('{{ previousWeek|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ 'stats.workingTimeWeek'|trans({'%week%': previousWeek|date_format('W')}) }}">
|
||||
<div class="btn-group week-picker-btn-group">
|
||||
<a class="btn btn-default btn-left" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ previousWeek|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ 'stats.workingTimeWeek'|trans({'%week%': previousWeek|date_format('W')}) }}">
|
||||
<i class="{{ 'left'|icon }}"></i>
|
||||
</a>
|
||||
<a class="btn btn-default" href="#" onclick="return false;">
|
||||
<span id="{{ form.vars.id }}_week_number">{{ 'stats.workingTimeWeek'|trans({'%week%': week|date_format('W')}) }}</span>
|
||||
</a>
|
||||
<a class="btn btn-default btn-right" href="#" onclick="$('#{{ form.vars.id }}').val('{{ nextWeek|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ 'stats.workingTimeWeek'|trans({'%week%': nextWeek|date_format('W')}) }}">
|
||||
<a class="btn btn-default btn-right" href="#" onclick="jQuery('#{{ form.vars.id }}').val('{{ nextWeek|report_date }}').change()" data-toggle="tooltip" data-placement="top" title="{{ 'stats.workingTimeWeek'|trans({'%week%': nextWeek|date_format('W')}) }}">
|
||||
<i class="{{ 'right'|icon }}"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
5
templates/quick-entry/actions.html.twig
Normal file
5
templates/quick-entry/actions.html.twig
Normal file
@@ -0,0 +1,5 @@
|
||||
{% macro quickEntries(view) %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% set event = actions(app.user, 'weekly_times', view, {}) %}
|
||||
{{ widgets.page_actions(event.actions) }}
|
||||
{% endmacro %}
|
||||
127
templates/quick-entry/index.html.twig
Normal file
127
templates/quick-entry/index.html.twig
Normal file
@@ -0,0 +1,127 @@
|
||||
{% extends app.request.xmlHttpRequest ? 'form.html.twig' : 'base.html.twig' %}
|
||||
{% import "quick-entry/actions.html.twig" as actions %}
|
||||
|
||||
{% block page_title %}{{ 'quick_entry.title'|trans }}{% endblock %}
|
||||
{% block page_actions %}{{ actions.quickEntries('index') }}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% block box_attributes %}id="quick_entry_box"{% endblock %}
|
||||
{% block box_before %}{{ form_start(form, {attr: {class: 'form-dataTable'}}) }}{% endblock %}
|
||||
{% block box_after %}{{ form_end(form) }}{% endblock %}
|
||||
{% block box_title %}
|
||||
{{ form_widget(form.date) }}
|
||||
{% endblock %}
|
||||
{% block box_body_class %}no-padding{% endblock %}
|
||||
{% block box_footer %}
|
||||
<input type="submit" value="{{ 'action.save'|trans }}" class="btn btn-primary" />
|
||||
<button type="button" class="btn btn-success add-item-link" data-collection-prototype="{{ form.rows.vars.id }}" data-collection-holder="ts-collection">
|
||||
<i class="{{ 'create'|icon }}"></i>
|
||||
{{ 'action.add'|trans }}
|
||||
</button>
|
||||
{% endblock %}
|
||||
{% block box_body %}
|
||||
<table class="table dataTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ 'label.project'|trans }}</th>
|
||||
<th>{{ 'label.activity'|trans }}</th>
|
||||
{% for id, week in days %}
|
||||
<th class="text-center{% if week.day is weekend %} weekend{% endif %}{% if week.day is today %} today{% endif %}">
|
||||
{{ week.day|day_name(true) }}<br>
|
||||
{{ week.day|format_date('short') }}
|
||||
</th>
|
||||
{% endfor %}
|
||||
<th class="summary">{{ 'label.duration'|trans }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="ts-collection" data-index="{{ form.rows.children|length }}">
|
||||
{{ form(form) }}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="summary">
|
||||
<td>{{ 'stats.durationTotal'|trans }}</td>
|
||||
<td></td>
|
||||
{% for id, week in days %}
|
||||
<td class="text-center" id="qe-totals-day-{{ loop.index0 }}"></td>
|
||||
{% endfor %}
|
||||
<td class="text-center" id="qe-totals-week"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
document.addEventListener('kimai.initialized', function(event) {
|
||||
const kimai = event.detail.kimai;
|
||||
const DATES = kimai.getPlugin('date');
|
||||
const FORMS = kimai.getPlugin('form-select');
|
||||
|
||||
const recalculateTotals = function(e) {
|
||||
const allFields = document.getElementsByClassName('duration-input');
|
||||
let totalsPerDay = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0};
|
||||
let fullTotals = 0;
|
||||
for (let durationInput of allFields) {
|
||||
let id = durationInput.id.replace(/_duration/, '').substr(-1);
|
||||
totalsPerDay[id] += DATES.getSecondsFromDurationString(durationInput.value);
|
||||
}
|
||||
for (const [id, total] of Object.entries(totalsPerDay)) {
|
||||
document.getElementById('qe-totals-day-' + id).innerText = DATES.formatSeconds(total);
|
||||
fullTotals += total;
|
||||
}
|
||||
document.getElementById('qe-totals-week').innerText = DATES.formatSeconds(fullTotals);
|
||||
|
||||
const allRows = document.getElementsByClassName('qe-entry-week-row');
|
||||
for (let qeWeekRow of allRows) {
|
||||
let qeWeekRowFields = qeWeekRow.getElementsByClassName('duration-input');
|
||||
let totalsRow = 0;
|
||||
for (let durationInput of qeWeekRowFields) {
|
||||
totalsRow += DATES.getSecondsFromDurationString(durationInput.value);
|
||||
}
|
||||
qeWeekRow.getElementsByClassName('qe-totals-row')[0].innerText = DATES.formatSeconds(totalsRow);
|
||||
}
|
||||
};
|
||||
recalculateTotals();
|
||||
|
||||
{% if form.user is defined %}
|
||||
jQuery('#{{ form.user.vars.id }}').on('change', function(ev) {
|
||||
jQuery(this).closest('form').submit();
|
||||
});
|
||||
{% endif %}
|
||||
|
||||
jQuery('#{{ form.date.vars.id }}').on('change', function(ev) {
|
||||
location.href = '{{ path('quick_entry', {'begin': '__BEGIN__'}) }}'.replace('__BEGIN__', jQuery(this).val());
|
||||
});
|
||||
|
||||
jQuery('body').on('change', '.duration-input', recalculateTotals);
|
||||
|
||||
const addFormToCollection = function(e) {
|
||||
const collectionHolder = document.getElementById(e.currentTarget.dataset.collectionHolder);
|
||||
const collectionPrototype = document.getElementById(e.currentTarget.dataset.collectionPrototype);
|
||||
|
||||
const node = document.createElement('tr');
|
||||
node.innerHTML = collectionPrototype
|
||||
.dataset
|
||||
.prototype
|
||||
.replace(
|
||||
/__name__/g,
|
||||
collectionHolder.dataset.index
|
||||
);
|
||||
collectionHolder.appendChild(node);
|
||||
|
||||
jQuery(node).find('.selectpicker').each(function(i, el) {
|
||||
FORMS.activateSelectPickerByElement(el, 'body');
|
||||
});
|
||||
|
||||
collectionHolder.dataset.index++;
|
||||
};
|
||||
|
||||
document.querySelectorAll('.add-item-link').forEach(btn => btn.addEventListener("click", addFormToCollection));
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -30,7 +30,7 @@
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
{% for day in days.dateTimes %}
|
||||
<th class="text-center text-nowrap{% if day is weekend %} weekend{% endif %}">
|
||||
<th class="text-center text-nowrap{% if day is weekend %} weekend{% endif %}{% if day is today %} today{% endif %}">
|
||||
{{ day|day_name(true) }}<br>
|
||||
{{ day|format_date('short') }}
|
||||
</th>
|
||||
@@ -55,7 +55,7 @@
|
||||
</td>
|
||||
<th class="text-nowrap text-center total">{{ project.duration|duration }}</th>
|
||||
{% for day in project.days.days %}
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}">
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}{% if day.date is today %} today{% endif %}">
|
||||
{% if day.duration > 0 %}
|
||||
{% set totals = totals|merge({(day.date|report_date): (totals[day.date|report_date] + day.duration)}) %}
|
||||
<strong>{{ day.duration|duration }}</strong>
|
||||
@@ -70,7 +70,7 @@
|
||||
</td>
|
||||
<th class="text-nowrap text-center total">{{ activity.duration|duration }}</th>
|
||||
{% for day in activity.days.days %}
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}">
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}{% if day.date is today %} today{% endif %}">
|
||||
{% if day.duration > 0 %}
|
||||
{{ day.duration|duration }}
|
||||
{% endif %}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<th> </th>
|
||||
<th> </th>
|
||||
{% for day in stats.0.getDateTimes() %}
|
||||
<th class="text-center text-nowrap{% if day is weekend %} weekend{% endif %}">
|
||||
<th class="text-center text-nowrap{% if day is weekend %} weekend{% endif %}{% if day is today %} today{% endif %}">
|
||||
{{ day|day_name(true) }}<br>
|
||||
{{ day|format_date('short') }}
|
||||
</th>
|
||||
@@ -54,7 +54,7 @@
|
||||
<a href="{{ path(subReportRoute, {'date': subReportDate|report_date, 'user': userDay.user.id}) }}">{{ usersTotalDuration|duration }}</a>
|
||||
</th>
|
||||
{% for day in userDay.days %}
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}">
|
||||
<td class="text-nowrap text-center day-total{% if day.date is weekend %} weekend{% endif %}{% if day.date is today %} today{% endif %}">
|
||||
{% if day.totalDuration > 0 %}
|
||||
{{ day.totalDuration|duration }}
|
||||
{% endif %}
|
||||
|
||||
Reference in New Issue
Block a user