Edit and create timesheet records in modal (#603)

- added loading indicator for datatables
- fix multiple reloads of datatable content
This commit is contained in:
Kevin Papst
2019-03-03 19:43:12 +01:00
committed by GitHub
parent 86832fb703
commit bea4be881b
23 changed files with 382 additions and 211 deletions

View File

@@ -39,11 +39,6 @@ $(function() {
// set the current locale for all javascript components
moment.locale($.kimai.settings['locale']);
// ask before a delete call is executed
$('body').on('click', 'a.btn-trash', function (event) {
return confirm($.kimai.settings['confirmDelete']);
});
// activate the dropdown functionality
$('.dropdown-toggle').dropdown();
@@ -58,90 +53,24 @@ $(function() {
);
}
// ==== compound field in toolbar ====
$('input[data-daterangepickerenable="on"]').each(function(index) {
var localeFormat = $(this).data('format');
var separator = $(this).data('separator');
var rangesList = {};
rangesList[$.kimai.settings['today']] = [moment(), moment()];
rangesList[$.kimai.settings['yesterday']] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
rangesList[$.kimai.settings['thisWeek']] = [moment().startOf('week'), moment().endOf('week')];
rangesList[$.kimai.settings['lastWeek']] = [moment().subtract(1, 'week').startOf('week'), moment().subtract(1, 'week').endOf('week')];
rangesList[$.kimai.settings['thisMonth']] = [moment().startOf('month'), moment().endOf('month')];
rangesList[$.kimai.settings['lastMonth']] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
rangesList[$.kimai.settings['thisYear']] = [moment().startOf('year'), moment().endOf('year')];
rangesList[$.kimai.settings['lastYear']] = [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')];
$(this).daterangepicker({
showDropdowns: true,
autoUpdateInput: false,
autoApply: false,
linkedCalendars: false,
locale: {
separator: separator,
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
},
ranges: rangesList,
alwaysShowCalendars: true
});
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat) + ' - ' + picker.endDate.format(localeFormat));
$(this).trigger("change");
});
// ask before a delete call is executed
$('body').on('click', 'a.btn-trash', function (event) {
return confirm($.kimai.settings['confirmDelete']);
});
// ==== single select boxes in toolbars ====
$('input[data-datepickerenable="on"]').each(function(index) {
var localeFormat = $(this).data('format');
$(this).daterangepicker({
singleDatePicker: true,
showDropdowns: true,
autoUpdateInput: false,
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
}
});
// compound field in toolbar
this.activateDateRangePicker('.content-wrapper');
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat));
$(this).trigger("change");
});
});
// single select boxes in toolbars
this.activateDatePicker('.content-wrapper');
// ==== edit timesheet - date with time ====
$('input[data-datetimepicker="on"]').each(function(index) {
var localeFormat = $(this).data('format');
$(this).daterangepicker({
singleDatePicker: true,
timePicker: true,
timePicker24Hour: true,
showDropdowns: true,
autoUpdateInput: false,
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
}
});
// edit timesheet - date with time
this.activateDateTimePicker('.content-wrapper');
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat));
$(this).trigger("change");
});
});
// some actions can be performed in a modal for a better UX
this.activateAjaxFormInModal('a.modal-ajax-form');
$('select[data-related-select]').change(function() {
$('body').on('change', 'select[data-related-select]', function(event) {
var apiUrl = $(this).attr('data-api-url').replace('-s-', $(this).val());
var targetSelect = $(this).attr('data-related-select');
@@ -187,6 +116,25 @@ $(function() {
$(this).find('a.anchor').hide();
});
},
reloadDatatableWithToolbarFilter: function()
{
var $form = $('.toolbar form');
var loading = '<div class="overlay"><i class="fas fa-sync fa-spin"></i></div>';
$('section.content').append(loading);
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(html) {
$('section.content').replaceWith(
$(html).find('section.content')
);
},
error: function(xhr, err) {
$form.submit();
}
});
},
pauseRecord: function(selector) {
$(selector + ' .pull-left i').hover(function () {
var link = $(this).parents('a');
@@ -197,6 +145,163 @@ $(function() {
link.attr('href', link.attr('href').replace('/pause', '/stop'));
$(this).removeClass('fa-pause-circle').removeClass('text-orange').addClass('fa-stop-circle');
});
},
activateDatePicker: function(selector) {
$(selector + ' input[data-datepickerenable="on"]').each(function(index) {
var localeFormat = $(this).data('format');
$(this).daterangepicker({
singleDatePicker: true,
showDropdowns: true,
autoUpdateInput: false,
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
}
});
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat));
$(this).trigger("change");
});
});
},
activateDateTimePicker: function(selector) {
$(selector + ' input[data-datetimepicker="on"]').each(function(index) {
var localeFormat = $(this).data('format');
$(this).daterangepicker({
singleDatePicker: true,
timePicker: true,
timePicker24Hour: true,
showDropdowns: true,
autoUpdateInput: false,
locale: {
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
}
});
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat));
$(this).trigger("change");
});
});
},
activateDateRangePicker: function(selector) {
$(selector + ' input[data-daterangepickerenable="on"]').each(function(index) {
var localeFormat = $(this).data('format');
var separator = $(this).data('separator');
var rangesList = {};
rangesList[$.kimai.settings['today']] = [moment(), moment()];
rangesList[$.kimai.settings['yesterday']] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
rangesList[$.kimai.settings['thisWeek']] = [moment().startOf('week'), moment().endOf('week')];
rangesList[$.kimai.settings['lastWeek']] = [moment().subtract(1, 'week').startOf('week'), moment().subtract(1, 'week').endOf('week')];
rangesList[$.kimai.settings['thisMonth']] = [moment().startOf('month'), moment().endOf('month')];
rangesList[$.kimai.settings['lastMonth']] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
rangesList[$.kimai.settings['thisYear']] = [moment().startOf('year'), moment().endOf('year')];
rangesList[$.kimai.settings['lastYear']] = [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')];
$(this).daterangepicker({
showDropdowns: true,
autoUpdateInput: false,
autoApply: false,
linkedCalendars: false,
locale: {
separator: separator,
format: localeFormat,
firstDay: 1,
applyLabel: $.kimai.settings['apply'],
cancelLabel: $.kimai.settings['cancel'],
customRangeLabel: $.kimai.settings['customRange']
},
ranges: rangesList,
alwaysShowCalendars: true
});
$(this).on('apply.daterangepicker', function(ev, picker) {
$(this).val(picker.startDate.format(localeFormat) + ' - ' + picker.endDate.format(localeFormat));
$(this).trigger("change");
});
});
},
ajaxFormInModal: function(html) {
// the modal that we use to render the form in
var formIdentifier = '#remote_form_modal .modal-content form';
var flashErrorIdentifier = 'div.alert-error';
var $form = $(formIdentifier);
var $modal = $('#remote_form_modal');
// will be (re-)activated later
$form.off('submit');
// load new form from given content
if ($(html).find('#form_modal .modal-content').length > 0 ) {
// TODO cleanup widgets before replacing the content?
$('#remote_form_modal .modal-content').replaceWith(
$(html).find('#form_modal .modal-content')
);
// activate new loaded widgets
$.kimai.activateDateTimePicker(formIdentifier);
}
// show error flash messages
if ($(html).find(flashErrorIdentifier).length > 0) {
$('#remote_form_modal .modal-body').prepend(
$(html).find(flashErrorIdentifier)
);
}
$modal.modal('show');
// the new form that was loaded via ajax
$form = $(formIdentifier);
// click handler for modal save button, to send forms via ajax
$form.on('submit', function(event){
var btn = $(formIdentifier + ' button[type=submit]').button('loading');
event.preventDefault();
event.stopPropagation();
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(html) {
btn.button('reset');
if ($(html).find('#form_modal .modal-content .has-error').length > 0 || $(html).find(flashErrorIdentifier).length > 0) {
$.kimai.ajaxFormInModal(html);
} else {
$.kimai.reloadDatatableWithToolbarFilter();
$modal.modal('hide');
}
return false;
},
error: function(xhr, err) {
// 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();
}
});
});
},
activateAjaxFormInModal: function(selector) {
$('body').on('click', selector, function(event) {
event.preventDefault();
event.stopPropagation();
$.ajax({
url: $(this).attr('href'),
success: function(html) {
$.kimai.ajaxFormInModal(html);
},
error: function(xhr, err) {
window.location = $(this).attr('href');
}
});
});
}
};

View File

@@ -28,30 +28,28 @@ $(document).ready(function () {
default:
$('.toolbar form input#page').val(1);
}
toolbarLoadDataAfterChange();
$.kimai.reloadDatatableWithToolbarFilter();
});
$('.toolbar form select').change(function (event) {
var reload = true;
switch (event.target.id) {
case 'customer':
if ($('.toolbar form select#project').length > 0) {
reload = false;
}
break;
case 'project':
if ($('.toolbar form select#activity').length > 0) {
reload = false;
}
break;
}
$('.toolbar form input#page').val(1);
toolbarLoadDataAfterChange();
if (reload) {
$.kimai.reloadDatatableWithToolbarFilter();
}
});
function toolbarLoadDataAfterChange()
{
var $form = $('.toolbar form');
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
data: $form.serialize(),
success: function(html) {
$('section.content').replaceWith(
$(html).find('section.content')
);
},
error: function(xhr, err) {
$form.submit();
}
});
}
});

View File

@@ -5,6 +5,43 @@
* file that was distributed with this source code.
*/
/* Loading indicator: overwritten from AdminLTE for positioning and supporting fas classes */
.box .overlay > .fas,
section.content .overlay > .fas,
.overlay-wrapper .overlay > .fas {
position: absolute;
top: 50vh;
left: 50vw;
margin-left: -15px;
margin-top: -15px;
color: #000;
font-size: 30px;
}
.box > .overlay,
.overlay-wrapper > .overlay,
section.content > .overlay,
.box > .loading-img,
.overlay-wrapper > .loading-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.box .overlay,
section.content .overlay,
.overlay-wrapper .overlay {
z-index: 50;
background: rgba(255, 255, 255, 0.7);
border-radius: 3px;
}
.box .overlay.dark,
section.content .overlay.dark,
.overlay-wrapper .overlay.dark {
background: rgba(0, 0, 0, 0.5);
}
/*
dataTables.bootstrap.css
*/
@@ -244,6 +281,8 @@ table.dataTable {
}
.label {
font-size: 85%;
font-weight: 500;
padding: .3em .6em .3em;
}
}
}