javascript and api to stop and display active records (#772)
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
// ------------------- INLINED ADMIN-LTE DEFINITIONS -------------------
|
||||
// this was done to save around 300kb by:
|
||||
// require('../vendor/kevinpapst/adminlte-bundle/Resources/assets/admin-lte');
|
||||
// this was replaced to save around 300kb by:
|
||||
// - removing moment locales which are not used
|
||||
// - removing fullcalendar locales which are not used
|
||||
// - removing icheck which is not used
|
||||
|
||||
//require('../vendor/kevinpapst/adminlte-bundle/Resources/assets/admin-lte');
|
||||
// - removing jquery-ui which is not used?
|
||||
|
||||
const $ = require('jquery');
|
||||
global.$ = global.jQuery = $;
|
||||
|
||||
require('jquery-ui');
|
||||
require('bootstrap-sass');
|
||||
require('jquery-slimscroll');
|
||||
require('bootstrap-select');
|
||||
|
||||
@@ -25,8 +25,11 @@ import KimaiSelectDataAPI from "./plugins/KimaiSelectDataAPI";
|
||||
import KimaiDateTimePicker from "./plugins/KimaiDateTimePicker";
|
||||
import KimaiAlternativeLinks from "./plugins/KimaiAlternativeLinks";
|
||||
import KimaiAjaxModalForm from "./plugins/KimaiAjaxModalForm";
|
||||
import KimaiActiveRecords from "./plugins/KimaiActiveRecords";
|
||||
import KimaiRecentActivities from "./plugins/KimaiRecentActivities";
|
||||
import KimaiEvent from "./plugins/KimaiEvent";
|
||||
import KimaiAPILink from "./plugins/KimaiAPILink";
|
||||
import KimaiAlert from "./plugins/KimaiAlert";
|
||||
|
||||
export default class KimaiLoader {
|
||||
|
||||
@@ -64,19 +67,22 @@ export default class KimaiLoader {
|
||||
|
||||
kimai.registerPlugin(new KimaiEvent());
|
||||
kimai.registerPlugin(new KimaiAPI());
|
||||
kimai.registerPlugin(new KimaiAlert());
|
||||
kimai.registerPlugin(new KimaiActiveRecordsDuration('[data-since]'));
|
||||
kimai.registerPlugin(new KimaiDatatableColumnView('data-column-visibility'));
|
||||
kimai.registerPlugin(new KimaiThemeInitializer());
|
||||
kimai.registerPlugin(new KimaiJqueryPluginInitializer());
|
||||
kimai.registerPlugin(new KimaiDateRangePicker('.content-wrapper'));
|
||||
kimai.registerPlugin(new KimaiDateTimePicker('.content-wrapper'));
|
||||
kimai.registerPlugin(new KimaiDatatable());
|
||||
kimai.registerPlugin(new KimaiDatatable('table.dataTable'));
|
||||
kimai.registerPlugin(new KimaiToolbar());
|
||||
kimai.registerPlugin(new KimaiSelectDataAPI('select[data-related-select]'));
|
||||
kimai.registerPlugin(new KimaiAlternativeLinks('.alternative-link'));
|
||||
kimai.registerPlugin(new KimaiAjaxModalForm('.modal-ajax-form'));
|
||||
//kimai.registerPlugin(new KimaiPauseRecord('li.messages-menu ul.menu li'));
|
||||
kimai.registerPlugin(new KimaiRecentActivities('li.notifications-menu'));
|
||||
kimai.registerPlugin(new KimaiActiveRecords('li.messages-menu', 'li.messages-menu-empty'));
|
||||
kimai.registerPlugin(new KimaiAPILink('a.api-link'));
|
||||
//kimai.registerPlugin(new KimaiPauseRecord('li.messages-menu ul.menu li'));
|
||||
|
||||
// notify all listeners that Kimai plugins can now be registered
|
||||
kimai.getPlugin('event').trigger('kimai.pluginRegister');
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/*!
|
||||
* [KIMAI] KimaiToolbar: some event listener to handle the toolbar/data-table filter, toolbar and navigation
|
||||
* [KIMAI] KimaiAPI: easy access to API methods
|
||||
*/
|
||||
|
||||
import jQuery from 'jquery';
|
||||
@@ -31,4 +31,18 @@ export default class KimaiAPI extends KimaiPlugin {
|
||||
});
|
||||
}
|
||||
|
||||
patch(url, callbackSuccess, callbackError) {
|
||||
jQuery.ajax({
|
||||
url: url,
|
||||
headers: {
|
||||
'X-AUTH-SESSION': true,
|
||||
'Content-Type':'application/json'
|
||||
},
|
||||
method: 'PATCH',
|
||||
dataType: 'json',
|
||||
success: callbackSuccess,
|
||||
error: callbackError
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
70
assets/js/plugins/KimaiAPILink.js
Normal file
70
assets/js/plugins/KimaiAPILink.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* [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";
|
||||
|
||||
export default class KimaiAPILink extends KimaiClickHandlerReducedInTableRow {
|
||||
|
||||
constructor(selector) {
|
||||
super();
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
init() {
|
||||
const self = this;
|
||||
document.addEventListener('click', function(event) {
|
||||
let target = event.target;
|
||||
while (!target.matches('body')) {
|
||||
if (target.matches(self.selector)) {
|
||||
const attributes = target.dataset;
|
||||
|
||||
let url = attributes['href'];
|
||||
if (!url) {
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
target = target.parentNode;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
113
assets/js/plugins/KimaiActiveRecords.js
Normal file
113
assets/js/plugins/KimaiActiveRecords.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* [KIMAI] KimaiActiveRecords: responsible to display the users active records
|
||||
*/
|
||||
|
||||
import KimaiPlugin from '../KimaiPlugin';
|
||||
|
||||
export default class KimaiActiveRecords extends KimaiPlugin {
|
||||
|
||||
constructor(selector, selectorEmpty) {
|
||||
super();
|
||||
this.selector = selector;
|
||||
this.selectorEmpty = selectorEmpty;
|
||||
}
|
||||
|
||||
getId() {
|
||||
return 'active-records';
|
||||
}
|
||||
|
||||
init() {
|
||||
const menu = document.querySelector(this.selector);
|
||||
|
||||
// the menu can be hidden if user has no permissions to see it
|
||||
if (menu === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dropdown = menu.querySelector('ul.dropdown-menu');
|
||||
|
||||
this.attributes = dropdown.dataset;
|
||||
this.itemList = dropdown.querySelector('li > ul.menu');
|
||||
this.label = menu.querySelector('a > span.label');
|
||||
|
||||
const self = this;
|
||||
const handle = function() { self.reloadActiveRecords(); };
|
||||
|
||||
document.addEventListener('kimai.timesheetUpdate', handle);
|
||||
document.addEventListener('kimai.activityUpdate', handle);
|
||||
document.addEventListener('kimai.projectUpdate', handle);
|
||||
document.addEventListener('kimai.customerUpdate', handle);
|
||||
}
|
||||
|
||||
emptyList() {
|
||||
this.itemList.innerHTML = '';
|
||||
}
|
||||
|
||||
_toggleMenu(hasEntries) {
|
||||
const menu = document.querySelector(this.selector);
|
||||
const menuEmpty = document.querySelector(this.selectorEmpty);
|
||||
|
||||
menu.style.display = hasEntries ? 'inline-block' : 'none';
|
||||
if (menuEmpty !== null) {
|
||||
menuEmpty.style.display = !hasEntries ? 'inline-block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
setEntries(entries) {
|
||||
this._toggleMenu(entries.length > 0);
|
||||
|
||||
if (entries.length === 0) {
|
||||
this.label.innerText = '';
|
||||
this.emptyList();
|
||||
return;
|
||||
}
|
||||
|
||||
let htmlToInsert = '';
|
||||
const durations = this.getContainer().getPlugin('timesheet-duration');
|
||||
|
||||
for (let timesheet of entries) {
|
||||
htmlToInsert +=
|
||||
`<li>` +
|
||||
`<a href="${ this.attributes['href'].replace('000', timesheet.id) }" data-event="kimai.timesheetStop kimai.timesheetUpdate" class="api-link" data-method="PATCH" data-msg-error="timesheet.stop.error" data-msg-success="timesheet.stop.success">` +
|
||||
`<div class="pull-left">` +
|
||||
`<i class="${ this.attributes['icon'] } fa-2x"></i>` +
|
||||
`</div>` +
|
||||
`<h4>` +
|
||||
`<span>${ timesheet.activity.name }</span>` +
|
||||
`<small>` +
|
||||
`<span data-title="true" data-since="${ timesheet.begin }" data-format="${ this.attributes['format'] }">${ durations.formatDuration(timesheet.duration, this.attributes['format']) }</span>` +
|
||||
`</small>` +
|
||||
`</h4>` +
|
||||
`<p>${ timesheet.project.name } (${ timesheet.project.customer.name })</p>` +
|
||||
`</a>` +
|
||||
`</li>`;
|
||||
}
|
||||
|
||||
if (this.label.dataset.warning < entries.length) {
|
||||
this.label.classList = 'label label-danger';
|
||||
} else {
|
||||
this.label.classList = 'label label-warning';
|
||||
}
|
||||
this.label.innerText = entries.length;
|
||||
this.itemList.innerHTML = htmlToInsert;
|
||||
|
||||
durations.updateRecords();
|
||||
}
|
||||
|
||||
reloadActiveRecords() {
|
||||
const self = this;
|
||||
const apiService = this.getContainer().getPlugin('api');
|
||||
|
||||
apiService.get(this.attributes['api'], function(result) {
|
||||
self.setEntries(result);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,19 +19,17 @@ export default class KimaiActiveRecordsDuration extends KimaiPlugin {
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
init() {
|
||||
this.updateRecords();
|
||||
this.registerUpdates(10000);
|
||||
getId() {
|
||||
return 'timesheet-duration';
|
||||
}
|
||||
|
||||
registerUpdates(interval) {
|
||||
let self = this;
|
||||
this._updatesHandler = setInterval(
|
||||
function() {
|
||||
self.updateRecords();
|
||||
},
|
||||
interval
|
||||
);
|
||||
init() {
|
||||
this.updateRecords();
|
||||
const self = this;
|
||||
const handle = function() { self.updateRecords(); };
|
||||
this._updatesHandler = setInterval(handle, 10000);
|
||||
// this will probably not work as expected, as other event-handler might need longer to update the DOM
|
||||
document.addEventListener('kimai.timesheetUpdate', handle);
|
||||
}
|
||||
|
||||
unregisterUpdates() {
|
||||
@@ -40,10 +38,17 @@ export default class KimaiActiveRecordsDuration extends KimaiPlugin {
|
||||
|
||||
updateRecords() {
|
||||
let durations = [];
|
||||
for(let record of document.querySelectorAll(this.selector)) {
|
||||
const activeRecords = document.querySelectorAll(this.selector);
|
||||
|
||||
if (activeRecords.length === 0) {
|
||||
document.title = document.querySelector('body').dataset['title'];
|
||||
return;
|
||||
}
|
||||
|
||||
for(let record of activeRecords) {
|
||||
const since = record.getAttribute('data-since');
|
||||
const format = record.getAttribute('data-format');
|
||||
const duration = KimaiActiveRecordsDuration._getDuration(since, format);
|
||||
const duration = this.formatDuration(since, format);
|
||||
if (record.getAttribute('data-title') !== null) {
|
||||
durations.push(duration);
|
||||
}
|
||||
@@ -51,7 +56,7 @@ export default class KimaiActiveRecordsDuration extends KimaiPlugin {
|
||||
}
|
||||
|
||||
if (durations.length === 0) {
|
||||
return this;
|
||||
return;
|
||||
}
|
||||
|
||||
let title = durations.shift();
|
||||
@@ -61,11 +66,9 @@ export default class KimaiActiveRecordsDuration extends KimaiPlugin {
|
||||
title += prefix + duration;
|
||||
}
|
||||
document.title = title;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static _getDuration(since, format) {
|
||||
formatDuration(since, format) {
|
||||
const duration = moment.duration(moment(new Date()).diff(moment(since)));
|
||||
|
||||
let hours = parseInt(duration.asHours()).toString();
|
||||
|
||||
@@ -67,8 +67,13 @@ export default class KimaiAjaxModalForm extends KimaiClickHandlerReducedInTableR
|
||||
jQuery(html).find('#form_modal .modal-content')
|
||||
);
|
||||
|
||||
// TODO these should be handled with Events, probably using Custom Events
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
|
||||
|
||||
// activate new loaded widgets
|
||||
self.getContainer().getPlugin('date-time-picker').activateDateTimePicker(formIdentifier);
|
||||
// activate selectpicker if beta test is active
|
||||
jQuery('.selectpicker').selectpicker('refresh');
|
||||
}
|
||||
|
||||
// show error flash messages
|
||||
@@ -100,9 +105,10 @@ export default class KimaiAjaxModalForm extends KimaiClickHandlerReducedInTableR
|
||||
|
||||
// click handler for modal save button, to send forms via ajax
|
||||
form.on('submit', function(event){
|
||||
let btn = jQuery(formIdentifier + ' button[type=submit]').button('loading');
|
||||
let eventName = form.attr('data-form-event');
|
||||
let events = self.getContainer().getPlugin('event');
|
||||
const btn = jQuery(formIdentifier + ' button[type=submit]').button('loading');
|
||||
const eventName = form.attr('data-form-event');
|
||||
const events = self.getContainer().getPlugin('event');
|
||||
const alert = self.getContainer().getPlugin('alert');
|
||||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
@@ -121,16 +127,40 @@ export default class KimaiAjaxModalForm extends KimaiClickHandlerReducedInTableR
|
||||
self._openFormInModal(html);
|
||||
} else {
|
||||
events.trigger(eventName);
|
||||
self.getContainer().getPlugin('datatable').reload();
|
||||
|
||||
// try to find form defined messages first ...
|
||||
let msg = form.attr('data-msg-success');
|
||||
if (msg === null || msg === undefined) {
|
||||
// ... but if none was available, check the response to find server rendered flash-message
|
||||
let flashMessage = jQuery(html).find('section.content div.row div.alert.alert-success');
|
||||
if (flashMessage.length > 0) {
|
||||
let flashContent = flashMessage.contents();
|
||||
if (flashContent.length === 3) {
|
||||
msg = flashContent[2].textContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ... and if even that is not available, we use a generic fallback message
|
||||
if (msg === null || msg === undefined) {
|
||||
msg = 'action.update.success';
|
||||
}
|
||||
remoteModal.modal('hide');
|
||||
alert.success(msg);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
error: function(xhr, err) {
|
||||
// FIXME problem in google and 500 error, keeps on submitting...
|
||||
// what else could we do? submitting again at least gives us the opportunity to see errors,
|
||||
// which maybe would be hidden otherwise... this one is totally up for discussion!
|
||||
form.submit();
|
||||
let message = form.attr('data-msg-error');
|
||||
if (message === null || message === undefined) {
|
||||
message = 'action.update.error';
|
||||
}
|
||||
if (xhr.responseJSON && xhr.responseJSON.message) {
|
||||
err = xhr.responseJSON.message;
|
||||
} else if (xhr.status && xhr.statusText) {
|
||||
err = '[' + xhr.status +'] ' + xhr.statusText;
|
||||
}
|
||||
alert.error(message, err);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
54
assets/js/plugins/KimaiAlert.js
Normal file
54
assets/js/plugins/KimaiAlert.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* [KIMAI] KimaiAlert: notifications for Kimai
|
||||
*/
|
||||
|
||||
import Swal from 'sweetalert2'
|
||||
import KimaiPlugin from "../KimaiPlugin";
|
||||
|
||||
export default class KimaiAlert extends KimaiPlugin {
|
||||
|
||||
getId() {
|
||||
return 'alert';
|
||||
}
|
||||
|
||||
error(title, message) {
|
||||
const translation = this.getContainer().getTranslation();
|
||||
if (translation.has(title)) {
|
||||
title = translation.get(title);
|
||||
}
|
||||
if (translation.has(message)) {
|
||||
message = translation.get(message);
|
||||
}
|
||||
Swal.fire({
|
||||
type: 'error',
|
||||
title: title.replace('%reason%', ''),
|
||||
text: message,
|
||||
});
|
||||
}
|
||||
|
||||
success(message) {
|
||||
const translation = this.getContainer().getTranslation();
|
||||
|
||||
if (translation.has(message)) {
|
||||
message = translation.get(message);
|
||||
}
|
||||
|
||||
Swal.fire({
|
||||
//toast: true,
|
||||
//timer: 3000,
|
||||
timer: 1500,
|
||||
position: 'top-end',
|
||||
showConfirmButton: false,
|
||||
type: 'success',
|
||||
title: message,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,12 +14,42 @@ import KimaiPlugin from "../KimaiPlugin";
|
||||
|
||||
export default class KimaiDatatable extends KimaiPlugin {
|
||||
|
||||
constructor(selector) {
|
||||
super();
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
getId() {
|
||||
return 'datatable';
|
||||
}
|
||||
|
||||
reload() {
|
||||
let form = jQuery('.toolbar form');
|
||||
init() {
|
||||
const dataTable = document.querySelector(this.selector);
|
||||
|
||||
// not every page contains a dataTable
|
||||
if (dataTable === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const attributes = dataTable.dataset;
|
||||
const events = attributes['reloadEvent'];
|
||||
|
||||
if (events === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
const self = this;
|
||||
const handle = function() { self.reloadDatatable(); };
|
||||
|
||||
for (let eventName of events.split(' ')) {
|
||||
document.addEventListener(eventName, handle);
|
||||
}
|
||||
}
|
||||
|
||||
reloadDatatable() {
|
||||
// FIXME remove query
|
||||
const durations = this.getContainer().getPlugin('timesheet-duration');
|
||||
const form = jQuery('.toolbar form');
|
||||
let loading = '<div class="overlay"><i class="fas fa-sync fa-spin"></i></div>';
|
||||
jQuery('section.content').append(loading);
|
||||
|
||||
@@ -38,6 +68,7 @@ export default class KimaiDatatable extends KimaiPlugin {
|
||||
jQuery('section.content').replaceWith(
|
||||
jQuery(html).find('section.content')
|
||||
);
|
||||
durations.updateRecords();
|
||||
},
|
||||
error: function(xhr, err) {
|
||||
form.submit();
|
||||
|
||||
@@ -18,11 +18,13 @@ export default class KimaiEvent extends KimaiPlugin {
|
||||
}
|
||||
|
||||
trigger(name) {
|
||||
if (name === null) {
|
||||
if (name === null || name === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
document.dispatchEvent(new Event(name));
|
||||
for(let event of name.split(' ')) {
|
||||
document.dispatchEvent(new Event(event));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,11 +35,12 @@ export default class KimaiRecentActivities extends KimaiPlugin {
|
||||
this.itemList = dropdown.querySelector('li > ul.menu');
|
||||
|
||||
const self = this;
|
||||
const handle = function() { self.reload(); };
|
||||
const handle = function() { self.reloadRecentActivities(); };
|
||||
|
||||
// don't block initial browser rendering
|
||||
setTimeout(handle, 500);
|
||||
|
||||
document.addEventListener('kimai.timesheetStop', handle);
|
||||
document.addEventListener('kimai.activityUpdate', handle);
|
||||
document.addEventListener('kimai.projectUpdate', handle);
|
||||
document.addEventListener('kimai.customerUpdate', handle);
|
||||
@@ -63,13 +64,13 @@ export default class KimaiRecentActivities extends KimaiPlugin {
|
||||
.replace('%project%', timesheet.project.name)
|
||||
.replace('%activity%', timesheet.activity.name);
|
||||
|
||||
htmlToInsert += `<li><a href="${ this.attributes['url'].replace('000', timesheet.id) }"><i class="${ this.attributes['icon'] }"></i> ${ label }</a></li>`;
|
||||
htmlToInsert += `<li><a href="${ this.attributes['href'].replace('000', timesheet.id) }"><i class="${ this.attributes['icon'] }"></i> ${ label }</a></li>`;
|
||||
}
|
||||
|
||||
this.itemList.innerHTML = htmlToInsert;
|
||||
}
|
||||
|
||||
reload() {
|
||||
reloadRecentActivities() {
|
||||
const self = this;
|
||||
const apiService = this.getContainer().getPlugin('api');
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import KimaiPlugin from "../KimaiPlugin";
|
||||
export default class KimaiToolbar extends KimaiPlugin {
|
||||
|
||||
init() {
|
||||
const self = this;
|
||||
const datatable = this.getContainer().getPlugin('datatable');
|
||||
|
||||
// This catches all clicks on the pagination and prevents the default action, as we want to relad the page via JS
|
||||
jQuery('body').on('click', 'div.navigation ul.pagination li a', function(event) {
|
||||
@@ -41,7 +41,7 @@ export default class KimaiToolbar extends KimaiPlugin {
|
||||
default:
|
||||
jQuery('.toolbar form input#page').val(1);
|
||||
}
|
||||
self._reloadDatatable();
|
||||
datatable.reloadDatatable();
|
||||
});
|
||||
|
||||
jQuery('.toolbar form select').change(function (event) {
|
||||
@@ -61,13 +61,9 @@ export default class KimaiToolbar extends KimaiPlugin {
|
||||
}
|
||||
jQuery('.toolbar form input#page').val(1);
|
||||
if (reload) {
|
||||
self._reloadDatatable();
|
||||
datatable.reloadDatatable();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_reloadDatatable() {
|
||||
this.getContainer().getPlugin('datatable').reload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,3 +21,4 @@
|
||||
@import 'navbar';
|
||||
@import 'daterangepicker';
|
||||
@import 'skins';
|
||||
@import 'sweetalert';
|
||||
|
||||
@@ -25,9 +25,6 @@
|
||||
.messages-menu>.dropdown-menu>li .menu>li>a>h4>span {
|
||||
margin-right: 55px;
|
||||
}
|
||||
.start_record {
|
||||
text-align: center;
|
||||
}
|
||||
.dropdown-menu {
|
||||
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
max-width: 90vw;
|
||||
|
||||
3
assets/sass/sweetalert.scss
Normal file
3
assets/sass/sweetalert.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
.swal2-popup {
|
||||
font-size: unset;
|
||||
}
|
||||
Reference in New Issue
Block a user