1.18 (#3158)
* bump version * fix translation ids * added css classes to modify form with custom css * improve export pdf file names * respect financial year in new report * added new InvoiceCalculator: price * upgrade packages and node-sass to v7 * title pattern for customer, project and activity via API * support negative money without currency * fix sub-locale in print export template * fix overbooking validation for monthly budget * fix copying entities with different set of custom-fields compared to the current configuration
This commit is contained in:
@@ -288,28 +288,8 @@
|
||||
|
||||
{% 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">
|
||||
window.addEventListener('load', function() {
|
||||
var loader = new KimaiWebLoader(
|
||||
{
|
||||
formatDuration: '{{ get_format_duration() }}',
|
||||
login: '{{ path('fos_user_security_login') }}',
|
||||
locale: '{{ app.request.locale }}',
|
||||
first_dow_iso: {{ iso_day_by_name(app.user.firstDayOfWeek) }},
|
||||
twentyFourHours: {{ app.user.is24Hour() ? 'true' : 'false' }},
|
||||
autoComplete: {{ kimai_config.themeAutocompleteCharacters }},
|
||||
defaultColor: '{{ constant('App\\Constants::DEFAULT_COLOR') }}',
|
||||
updateBrowserTitle: {% if app.user.preferenceValue('theme.update_browser_title') %}true{% else %}false{% endif %}
|
||||
},
|
||||
{
|
||||
{% for key, translation in javascript_translations() -%}
|
||||
'{{ key }}': '{{ translation.0|trans({}, translation.1)|escape('js') }}',
|
||||
{%- endfor %}
|
||||
}
|
||||
);
|
||||
window.kimai = loader.getKimai();
|
||||
});
|
||||
</script>
|
||||
{% import "macros/webloader.html.twig" as webloader %}
|
||||
{{ webloader.init_frontend_loader() }}
|
||||
{% set event = trigger(constant('App\\Event\\ThemeEvent::JAVASCRIPT')) %}
|
||||
{{ event.content|raw }}
|
||||
{% endblock %}
|
||||
|
||||
@@ -95,7 +95,11 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for button in group %}
|
||||
<li><a href="#" class="startExportBtn" data-type="{{ button.id }}">{{ (button.id)|trans({}, 'export') }}</a></li>
|
||||
{% set btnTitle = (button.id)|trans({}, 'export') %}
|
||||
{% if btnTitle == button.id %}
|
||||
{% set btnTitle = button.id|split('.')|first|replace({'-': ' ', '_': ' '})|split(' ')|map(t => t|capitalize)|join(' ') %}
|
||||
{% endif %}
|
||||
<li><a href="#" class="startExportBtn" data-type="{{ button.id }}">{{ btnTitle }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{% extends 'export/layout.html.twig' %}
|
||||
{% import "macros/widgets.html.twig" as widgets %}
|
||||
{% import "macros/datatables.html.twig" as tables %}
|
||||
{% extends 'export/layout.html.twig' %}
|
||||
{% import "macros/webloader.html.twig" as webloader %}
|
||||
|
||||
{% block document_title %}{{ 'export.title'|trans }}{% endblock %}
|
||||
|
||||
@@ -51,27 +52,25 @@
|
||||
}) %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ webloader.init_frontend_loader() }}
|
||||
<script type="text/javascript">
|
||||
let initialized = false;
|
||||
|
||||
window.addEventListener('load', function() {
|
||||
var loader = new KimaiWebLoader({
|
||||
formatDuration: '{{ get_format_duration() }}',
|
||||
locale: '{{ app.request.locale }}',
|
||||
}, {});
|
||||
var DATES = loader.getKimai().getPlugin('date');
|
||||
document.addEventListener('kimai.initialized', function(event) {
|
||||
const KIMAI = event.detail.kimai;
|
||||
const DATES = KIMAI.getPlugin('date');
|
||||
|
||||
document.getElementById('duration-decimal').addEventListener('click', function(event) {
|
||||
var spans = document.getElementsByClassName('duration-format');
|
||||
for (var span of spans) {
|
||||
var duration = span.dataset['duration'];
|
||||
let spans = document.getElementsByClassName('duration-format');
|
||||
for (let span of spans) {
|
||||
let duration = span.dataset['duration'];
|
||||
if (duration === undefined) {
|
||||
continue;
|
||||
}
|
||||
if (!event.target.checked) {
|
||||
span.innerHTML = DATES.formatSeconds(duration);
|
||||
} else {
|
||||
span.innerHTML = (new Intl.NumberFormat('{{ app.request.locale }}', {maximumFractionDigits: 2}).format(duration / 3600));
|
||||
span.innerHTML = (new Intl.NumberFormat('{{ app.request.locale|replace({'_': '-'}) }}', {maximumFractionDigits: 2}).format(duration / 3600));
|
||||
}
|
||||
}
|
||||
saveVisibility();
|
||||
@@ -96,36 +95,36 @@
|
||||
saveVisibility();
|
||||
});
|
||||
document.getElementById('summary-timeBudget').addEventListener('click', function(event) {
|
||||
var cells = document.getElementsByClassName('export-timeBudget');
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('export-timeBudget');
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = event.target.checked ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
});
|
||||
document.getElementById('summary-budget').addEventListener('click', function(event) {
|
||||
var cells = document.getElementsByClassName('export-budget');
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('export-budget');
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = event.target.checked ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
});
|
||||
document.getElementById('summary-duration').addEventListener('click', function(event) {
|
||||
var cells = document.getElementsByClassName('summary-duration');
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('summary-duration');
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = event.target.checked ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
});
|
||||
document.getElementById('summary-rate').addEventListener('click', function(event) {
|
||||
var cells = document.getElementsByClassName('summary-rate');
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('summary-rate');
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = event.target.checked ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
});
|
||||
document.getElementById('summary-rate-internal').addEventListener('click', function(event) {
|
||||
var cells = document.getElementsByClassName('summary-rate-internal');
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('summary-rate-internal');
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = event.target.checked ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
@@ -139,17 +138,17 @@
|
||||
saveVisibility();
|
||||
});
|
||||
|
||||
var columnCheckboxes = document.getElementsByClassName('column-visibility-changer');
|
||||
let columnCheckboxes = document.getElementsByClassName('column-visibility-changer');
|
||||
|
||||
for (var checkbox of columnCheckboxes) {
|
||||
for (let checkbox of columnCheckboxes) {
|
||||
checkbox.addEventListener('click', function(event) {
|
||||
changeVisibility(event.target.name, event.target.checked);
|
||||
});
|
||||
}
|
||||
|
||||
var editableTitles = document.querySelectorAll('[contenteditable=true]');
|
||||
let editableTitles = document.querySelectorAll('[contenteditable=true]');
|
||||
|
||||
for (var editable of editableTitles) {
|
||||
for (let editable of editableTitles) {
|
||||
editable.addEventListener('input', function(event) {
|
||||
if (event.target.innerText === '') {
|
||||
return;
|
||||
@@ -200,8 +199,8 @@
|
||||
|
||||
function changeVisibility(column, visible)
|
||||
{
|
||||
var cells = document.getElementsByClassName('column-' + column);
|
||||
for (var columnCell of cells) {
|
||||
let cells = document.getElementsByClassName('column-' + column);
|
||||
for (let columnCell of cells) {
|
||||
columnCell.style.display = visible ? 'table-cell' : 'none';
|
||||
}
|
||||
saveVisibility();
|
||||
@@ -209,9 +208,9 @@
|
||||
|
||||
function changedDateFormat(formatType, className)
|
||||
{
|
||||
var elements = document.getElementsByClassName(className);
|
||||
for (var elem of elements) {
|
||||
var formattedDate = elem.dataset[formatType];
|
||||
let elements = document.getElementsByClassName(className);
|
||||
for (let elem of elements) {
|
||||
let formattedDate = elem.dataset[formatType];
|
||||
if (formattedDate === undefined) {
|
||||
continue;
|
||||
}
|
||||
@@ -242,9 +241,9 @@
|
||||
|
||||
function resetExport()
|
||||
{
|
||||
var editableTitles = document.querySelectorAll('[contenteditable=true]');
|
||||
let editableTitles = document.querySelectorAll('[contenteditable=true]');
|
||||
|
||||
for (var editable of editableTitles) {
|
||||
for (let editable of editableTitles) {
|
||||
editable.innerText = editable.dataset['original'];
|
||||
}
|
||||
|
||||
@@ -252,7 +251,6 @@
|
||||
const form = document.getElementsByTagName('form')[0];
|
||||
form.reset();
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
31
templates/macros/webloader.html.twig
Normal file
31
templates/macros/webloader.html.twig
Normal file
@@ -0,0 +1,31 @@
|
||||
{% macro init_frontend_loader() %}
|
||||
{% set configurations = javascript_configurations(app.user)|merge({
|
||||
login: path('fos_user_security_login'),
|
||||
locale: app.request.locale,
|
||||
first_dow_iso: iso_day_by_name(app.user.firstDayOfWeek),
|
||||
autoComplete: kimai_config.themeAutocompleteCharacters,
|
||||
}) %}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function() {
|
||||
const loader = new KimaiWebLoader({
|
||||
{%- for name, value in configurations -%}
|
||||
{%- if value is same as (true) -%}
|
||||
{{ name }}:true
|
||||
{%- elseif value is same as (false) -%}
|
||||
{{ name }}:false
|
||||
{%- elseif value is number -%}
|
||||
{{ name }}:{{ value }}
|
||||
{%- else -%}
|
||||
{{ name }}:'{{ value }}'
|
||||
{%- endif -%}
|
||||
{%- if not loop.last %},{% endif -%}
|
||||
{%- endfor -%}
|
||||
},{
|
||||
{%- for key, translation in javascript_translations() -%}
|
||||
'{{ key }}': '{{ translation.0|trans({}, translation.1)|escape('js') }}'{% if not loop.last %},{% endif %}
|
||||
{%- endfor -%}
|
||||
});
|
||||
window.kimai = loader.getKimai();
|
||||
});
|
||||
</script>
|
||||
{% endmacro %}
|
||||
@@ -7,7 +7,7 @@
|
||||
{% embed '@AdminLTE/Widgets/box-widget.html.twig' %}
|
||||
{% from "macros/widgets.html.twig" import nothing_found %}
|
||||
{% block box_before %}
|
||||
{{ form_start(form, {'attr': {'class': 'form-inline kimai-1.17', 'id': 'user-list-filter-form'}}) }}
|
||||
{{ form_start(form, {'attr': {'class': 'form-inline', 'id': 'user-list-filter-form'}}) }}
|
||||
{% endblock %}
|
||||
{% block box_after %}
|
||||
{{ form_end(form) }}
|
||||
|
||||
@@ -43,22 +43,22 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if form.customer is defined %}
|
||||
{{ form_row(form.customer) }}
|
||||
{{ form_row(form.customer, {'row_attr': {'class': 'timesheet_edit_form_row_customer'}}) }}
|
||||
{% endif %}
|
||||
{% if form.project is defined %}
|
||||
{{ form_row(form.project) }}
|
||||
{{ form_row(form.project, {'row_attr': {'class': 'timesheet_edit_form_row_project'}}) }}
|
||||
{% endif %}
|
||||
{% if form.activity is defined %}
|
||||
{{ form_row(form.activity) }}
|
||||
{{ form_row(form.activity, {'row_attr': {'class': 'timesheet_edit_form_row_activity'}}) }}
|
||||
{% endif %}
|
||||
{% if form.description is defined %}
|
||||
{{ form_row(form.description) }}
|
||||
{{ form_row(form.description, {'row_attr': {'class': 'timesheet_edit_form_row_description'}}) }}
|
||||
{% endif %}
|
||||
{% if form.tags is defined %}
|
||||
{{ form_row(form.tags) }}
|
||||
{{ form_row(form.tags, {'row_attr': {'class': 'timesheet_edit_form_row_tags'}}) }}
|
||||
{% endif %}
|
||||
{% if form.user is defined %}
|
||||
{{ form_row(form.user) }}
|
||||
{{ form_row(form.user, {'row_attr': {'class': 'timesheet_edit_form_row_user'}}) }}
|
||||
{% endif %}
|
||||
{% if form.users is defined or form.teams is defined %}
|
||||
{% set uLength = 12 %}
|
||||
@@ -81,10 +81,10 @@
|
||||
{% if form.fixedRate is defined and form.hourlyRate is defined %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.fixedRate) }}
|
||||
{{ form_row(form.fixedRate, {'row_attr': {'class': 'timesheet_edit_form_row_fixedRate'}}) }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{ form_row(form.hourlyRate) }}
|
||||
{{ form_row(form.hourlyRate, {'row_attr': {'class': 'timesheet_edit_form_row_hourlyRate'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -98,12 +98,12 @@
|
||||
<div class="row">
|
||||
{% if form.exported is defined %}
|
||||
<div class="col-md-{{ ebLength }}">
|
||||
{{ form_row(form.exported) }}
|
||||
{{ form_row(form.exported, {'row_attr': {'class': 'timesheet_edit_form_row_exported'}}) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if form.billable is defined %}
|
||||
<div class="col-md-{{ ebLength }}">
|
||||
{{ form_row(form.billable) }}
|
||||
{{ form_row(form.billable, {'row_attr': {'class': 'timesheet_edit_form_row_billable'}}) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user