* 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:
Kevin Papst
2022-02-25 20:41:56 +01:00
committed by GitHub
parent 34649d809e
commit c0168ecc5b
53 changed files with 1222 additions and 611 deletions

View File

@@ -37,7 +37,11 @@ export default class KimaiActiveRecordsDuration extends KimaiPlugin {
if (activeRecords.length === 0) {
if (this.updateBrowserTitle) {
document.title = document.querySelector('body').dataset['title'];
if (document.body.dataset['title'] === undefined) {
this.updateBrowserTitle = false;
} else {
document.title = document.body.dataset['title'];
}
}
return;
}

View File

@@ -18,6 +18,14 @@ export default class KimaiDateUtils extends KimaiPlugin {
return 'date';
}
/**
* @param {string} dateTime
* @returns {string}
*/
getFormattedDate(dateTime) {
return moment(dateTime).format(this.getConfiguration('formatDate'));
}
getWeekDaysShort() {
return moment.localeData().weekdaysShort();
}

View File

@@ -161,18 +161,25 @@ export default class KimaiFormSelect extends KimaiPlugin {
let emptyOpts = [];
let options = [];
let titlePattern = null;
if (select[0].dataset['optionPattern'] !== undefined) {
titlePattern = select[0].dataset['optionPattern'];
}
if (titlePattern === null || titlePattern === '') {
titlePattern = '{name}';
}
for (const [key, value] of Object.entries(data)) {
if (key === '__empty__') {
for (const entity of value) {
emptyOpts.push(this._createOption(entity.name, entity.id));
emptyOpts.push(this._createOption(this._getTitleFromPattern(titlePattern, entity), entity.id));
}
continue;
}
let optGroup = this._createOptgroup(key);
for (const entity of value) {
optGroup.appendChild(this._createOption(entity.name, entity.id));
optGroup.appendChild(this._createOption(this._getTitleFromPattern(titlePattern, entity), entity.id));
}
options.push(optGroup);
}
@@ -192,6 +199,46 @@ export default class KimaiFormSelect extends KimaiPlugin {
}
}
/**
* @param {string} pattern
* @param {array} entity
* @private
*/
_getTitleFromPattern(pattern, entity) {
const DATE_UTILS = this.getPlugin('date');
const regexp = new RegExp('{[^}]*?}','g');
let title = pattern;
let match = null;
while ((match = regexp.exec(pattern)) !== null) {
const field = match[0].substr(1, match[0].length - 2);
let value = entity[field] === undefined ? null : entity[field];
if ((field === 'start' || field === 'end')) {
if (value === null) {
value = '?';
} else {
value = DATE_UTILS.getFormattedDate(value);
}
}
title = title.replace(new RegExp('{' + field + '}', 'g'), value ?? '');
}
title = title.replace(/- \?-\?/, '');
const chars = '- ';
let start = 0, end = title.length;
while(start < end && chars.indexOf(title[start]) >= 0) {
++start;
}
while(end > start && chars.indexOf(title[end - 1]) >= 0) {
--end;
}
return (start > 0 || end < title.length) ? title.substring(start, end) : title;
}
/**
* @param {string} label
* @param {string} value

View File

@@ -142,7 +142,9 @@ export default class KimaiSelectDataAPI extends KimaiPlugin {
ordered[key] = options[key];
});
this.getContainer().getPlugin('form-select').updateOptions(selectName, ordered);
/** @var {KimaiFormSelect} select */
const select = this.getContainer().getPlugin('form-select');
select.updateOptions(selectName, ordered);
}
}