added tags for timesheets (#604)

This commit is contained in:
Mathias
2019-05-12 01:40:04 +02:00
committed by Kevin Papst
parent f31118292c
commit e29e183e84
84 changed files with 2132 additions and 158 deletions

View File

@@ -18,7 +18,7 @@ export default class KimaiAPI extends KimaiPlugin {
return 'api';
}
get(url, callback) {
get(url, data, callback) {
jQuery.ajax({
url: url,
headers: {
@@ -26,6 +26,7 @@ export default class KimaiAPI extends KimaiPlugin {
'Content-Type':'application/json'
},
method: 'GET',
data: data,
dataType: 'json',
success: callback
});
@@ -45,4 +46,18 @@ export default class KimaiAPI extends KimaiPlugin {
});
}
delete(url, callbackSuccess, callbackError) {
jQuery.ajax({
url: url,
headers: {
'X-AUTH-SESSION': true,
'Content-Type':'application/json'
},
method: 'DELETE',
dataType: 'json',
success: callbackSuccess,
error: callbackError
});
}
}

View File

@@ -5,15 +5,19 @@
* file that was distributed with this source code.
*/
/*!
* [KIMAI] KimaiAPILink
*
* allows to assign the given selector to any element, which then is used as click-handler
* calling an API method and trigger the event from data-event attribute afterwards
*/
import KimaiClickHandlerReducedInTableRow from "./KimaiClickHandlerReducedInTableRow";
/**
* Needs to be initialized with a class name.
*
* A link like <a href=# class=remoteLink> can be activated with:
* new KimaiAPILink('remoteLink')
*
* Allows to assign the given selector to any element, which then is used as click-handler
* calling an API method and trigger the event from data-event attribute afterwards.
*
* @param selector
*/
export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
constructor(selector) {
@@ -26,7 +30,7 @@ export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
document.addEventListener('click', function(event) {
let target = event.target;
while (!target.matches('body')) {
if (target.matches(self.selector)) {
if (target.classList.contains(self.selector)) {
const attributes = target.dataset;
let url = attributes['href'];
@@ -34,28 +38,12 @@ export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
url = target.getAttribute('href');
}
const method = attributes['method'];
const eventName = attributes['event'];
const api = self.getContainer().getPlugin('api');
const eventing = self.getContainer().getPlugin('event');
const alert = self.getContainer().getPlugin('alert');
if (method === 'PATCH') {
api.patch(url, function(result) {
eventing.trigger(eventName);
if (attributes.msgSuccess) {
alert.success(attributes.msgSuccess);
}
}, function(xhr, err) {
let message = 'action.update.error';
if (attributes.msgError) {
message = attributes.msgError;
}
if (xhr.responseJSON && xhr.responseJSON.message) {
err = xhr.responseJSON.message;
}
alert.error(message, err);
if (attributes.question !== undefined) {
self.getContainer().getPlugin('alert').question(attributes.question, function() {
self._callApi(url, attributes);
});
} else {
self._callApi(url, attributes);
}
event.preventDefault();
@@ -67,4 +55,35 @@ export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
});
}
_callApi(url, attributes)
{
const method = attributes['method'];
const eventName = attributes['event'];
const api = this.getContainer().getPlugin('api');
const eventing = this.getContainer().getPlugin('event');
const alert = this.getContainer().getPlugin('alert');
const successHandle = function(result) {
eventing.trigger(eventName);
if (attributes.msgSuccess) {
alert.success(attributes.msgSuccess);
}
};
const errorHandle = function(xhr, err) {
let message = 'action.update.error';
if (attributes.msgError) {
message = attributes.msgError;
}
if (xhr.responseJSON && xhr.responseJSON.message) {
err = xhr.responseJSON.message;
}
alert.error(message, err);
};
if (method === 'PATCH') {
api.patch(url, successHandle, errorHandle);
} else if (method === 'DELETE') {
api.delete(url, successHandle, errorHandle);
}
}
}

View File

@@ -105,7 +105,7 @@ export default class KimaiActiveRecords extends KimaiPlugin {
const self = this;
const apiService = this.getContainer().getPlugin('api');
apiService.get(this.attributes['api'], function(result) {
apiService.get(this.attributes['api'], {}, function(result) {
self.setEntries(result);
});
}

View File

@@ -72,6 +72,8 @@ export default class KimaiAjaxModalForm extends KimaiClickHandlerReducedInTableR
// activate new loaded widgets
self.getContainer().getPlugin('date-time-picker').activateDateTimePicker(formIdentifier);
self.getContainer().getPlugin('autocomplete').activateAutocomplete(formIdentifier + " .js-autocomplete");
// activate selectpicker if beta test is active
jQuery('.selectpicker').selectpicker('refresh');
}

View File

@@ -51,4 +51,30 @@ export default class KimaiAlert extends KimaiPlugin {
});
}
/**
* Callback receives a value and needs to decide what should happen with it
*
* @param message
* @param callback
*/
question(message, callback) {
const translation = this.getContainer().getTranslation();
if (translation.has(message)) {
message = translation.get(message);
}
Swal.fire({
title: message,
type: 'question',
showCancelButton: true,
confirmButtonText: translation.get('confirm'),
cancelButtonText: translation.get('cancel')
}).then((result) => {
if (result.value) {
callback(result.value);
}
});
}
}

View File

@@ -0,0 +1,93 @@
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import jQuery from 'jquery';
import KimaiPlugin from "../KimaiPlugin";
/**
* Supporting auto-complete fields via API.
* Currently used for timesheet tagging in toolbar and edit dialogs.
*/
export default class KimaiAutocomplete extends KimaiPlugin {
constructor(selector) {
super();
this.selector = selector;
}
init() {
this.activateAutocomplete(this.selector);
}
getId() {
return 'autocomplete';
}
splitTagList(val) {
return val.split(/,\s*/);
}
extractLastTag(term) {
return this.splitTagList(term).pop();
}
activateAutocomplete(selector)
{
const apiUrl = jQuery(selector).attr('data-autocomplete-url');
const self = this;
jQuery(selector)
// don't navigate away from the field on tab when selecting an item
.on("keydown", function (event) {
if (event.keyCode === jQuery.ui.keyCode.TAB &&
jQuery(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
source: function (request, response) {
const lastEntry = self.extractLastTag(request.term);
self.getContainer().getPlugin('api').get(apiUrl, {'name': lastEntry}, function(data){
response(data);
});
},
search: function () {
// custom minLength
var term = self.extractLastTag(this.value);
if (term.length < 2) {
return false;
}
},
focus: function () {
// prevent value inserted on focus
return false;
},
select: function (event, ui) {
var terms = self.splitTagList(this.value);
// remove the current input
terms.pop();
// check if selected tag is already in list
if (!terms.includes(ui.item.value)) {
// add the selected item
terms.push(ui.item.value);
}
// add placeholder to get the comma-and-space at the end
terms.push("");
this.value = terms.join(", ");
$(this).trigger('change');
return false;
}
}
);
}
}

View File

@@ -39,7 +39,7 @@ export default class KimaiDatePicker extends KimaiPlugin {
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: translator.get('apply'),
applyLabel: translator.get('confirm'),
cancelLabel: translator.get('cancel'),
customRangeLabel: translator.get('customRange'),
daysOfWeek: moment.weekdaysShort(),

View File

@@ -53,7 +53,7 @@ export default class KimaiDateRangePicker extends KimaiPlugin {
separator: separator,
format: localeFormat,
firstDay: 1,
applyLabel: translator.get('apply'),
applyLabel: translator.get('confirm'),
cancelLabel: translator.get('cancel'),
customRangeLabel: translator.get('customRange'),
daysOfWeek: moment.weekdaysShort(),

View File

@@ -43,7 +43,7 @@ export default class KimaiDateTimePicker extends KimaiPlugin {
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: translator.get('apply'),
applyLabel: translator.get('confirm'),
cancelLabel: translator.get('cancel'),
customRangeLabel: translator.get('customRange'),
daysOfWeek: moment.weekdaysShort(),

View File

@@ -74,7 +74,7 @@ export default class KimaiRecentActivities extends KimaiPlugin {
const self = this;
const apiService = this.getContainer().getPlugin('api');
apiService.get(this.attributes['api'], function(result) {
apiService.get(this.attributes['api'], {}, function(result) {
self.setEntries(result);
});
}