drag & drop to delete entries from the calendar (#2513)

This commit is contained in:
Kevin Papst
2021-04-20 14:50:23 +02:00
committed by GitHub
parent 7ddcde62dd
commit 08a144ac31
7 changed files with 126 additions and 86 deletions

View File

@@ -32,3 +32,18 @@
border-left: 1px solid; border-left: 1px solid;
} }
} }
.fc-bootstrap3 {
.table-bordered > tbody > tr > td,
.table-bordered > thead > tr > td,
.table-bordered > thead > tr > th {
border: 1px solid #ddd;
}
.fc-head {
background-color: #fafafa;
}
td.fc-today {
background-color: #fcf8e3!important;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@
"build/app.2ee3c27f.js" "build/app.2ee3c27f.js"
], ],
"css": [ "css": [
"build/app.8e8f1a48.css" "build/app.fb1d5bab.css"
] ]
}, },
"invoice": { "invoice": {
@@ -54,7 +54,7 @@
"build/0.9ec1fb96.js": "sha384-1dI1TIwKkV71L1OH+DnDqaG1su73sfoXwMVzfTuAEIg0HgVImtDf01RtbASXV7yK", "build/0.9ec1fb96.js": "sha384-1dI1TIwKkV71L1OH+DnDqaG1su73sfoXwMVzfTuAEIg0HgVImtDf01RtbASXV7yK",
"build/1.2890d91a.js": "sha384-r7OpYErcdJM7NmHiLm3n6J144cfkYc57YYAKn/QabksGh/Rd+tpcy6/kLwpVSD0b", "build/1.2890d91a.js": "sha384-r7OpYErcdJM7NmHiLm3n6J144cfkYc57YYAKn/QabksGh/Rd+tpcy6/kLwpVSD0b",
"build/app.2ee3c27f.js": "sha384-YyGA9sqAqi7lk0IYrAj5E2CQZGZbMQuSCv2Auz7fbjxcuRJvh9hOWkV6r3qOJKNA", "build/app.2ee3c27f.js": "sha384-YyGA9sqAqi7lk0IYrAj5E2CQZGZbMQuSCv2Auz7fbjxcuRJvh9hOWkV6r3qOJKNA",
"build/app.8e8f1a48.css": "sha384-k9l5JFdLXPYnXgp8zIzSKC49AvFX5wDYx5+Pc7/NVMnOvnFUC0BzArW8H3mmGJPJ", "build/app.fb1d5bab.css": "sha384-b8s0budBJh3JWWMyOZ08KKAx/Ukl0GWMX/o5yD87UL5SAq5datSu8vuzTS0cnA6T",
"build/invoice.74279541.js": "sha384-2BXic5Sgorf2tXai6zSAN4wLY2dbg06L03/xMKW6itMcszvtnRArKzfBh6DNcF3f", "build/invoice.74279541.js": "sha384-2BXic5Sgorf2tXai6zSAN4wLY2dbg06L03/xMKW6itMcszvtnRArKzfBh6DNcF3f",
"build/invoice.13d8ef4e.css": "sha384-B6RN/wZJToSBCZk2JeLokIqWEhbh+Eb9arYbt9dM+YoC2Z6PnCeTwTqSGyexWWJh", "build/invoice.13d8ef4e.css": "sha384-B6RN/wZJToSBCZk2JeLokIqWEhbh+Eb9arYbt9dM+YoC2Z6PnCeTwTqSGyexWWJh",
"build/invoice-pdf.0efd7a97.js": "sha384-bSdIeRCtEJiYYuc2reb0e5CpJ1Kbd1lQNEkElMTiq1SX0IINzdwJJYf6WnCcHrNC", "build/invoice-pdf.0efd7a97.js": "sha384-bSdIeRCtEJiYYuc2reb0e5CpJ1Kbd1lQNEkElMTiq1SX0IINzdwJJYf6WnCcHrNC",

View File

@@ -2,7 +2,7 @@
"build/0.9ec1fb96.js": "build/0.9ec1fb96.js", "build/0.9ec1fb96.js": "build/0.9ec1fb96.js",
"build/1.2890d91a.js": "build/1.2890d91a.js", "build/1.2890d91a.js": "build/1.2890d91a.js",
"build/2.42abdacc.js": "build/2.42abdacc.js", "build/2.42abdacc.js": "build/2.42abdacc.js",
"build/app.css": "build/app.8e8f1a48.css", "build/app.css": "build/app.fb1d5bab.css",
"build/app.js": "build/app.2ee3c27f.js", "build/app.js": "build/app.2ee3c27f.js",
"build/calendar.css": "build/calendar.1408f57e.css", "build/calendar.css": "build/calendar.1408f57e.css",
"build/calendar.js": "build/calendar.070aab88.js", "build/calendar.js": "build/calendar.070aab88.js",

View File

@@ -120,15 +120,6 @@
function renderEventPopoverContent(eventObj) function renderEventPopoverContent(eventObj)
{ {
{# https://stackoverflow.com/questions/26530076/fullcalendar-js-deleting-event-on-button-click #}
{#
$el.append('<div style="position: absolute; top: 0; right: 0;" class="pull-right closeon">X</div>');
$el.find('.closeon').on('click', function(closeEvent) {
console.log(closeEvent);
jQuery('{{ calendarSelector }}').fullCalendar('removeEvents',eventObj._id);
closeEvent.stopPropagation();
});
#}
return '<div class="calendar-entry">' + return '<div class="calendar-entry">' +
'<ul>' + '<ul>' +
'<li>' + '{{ 'label.customer'|trans }}: ' + eventObj.customer + '</li>' + '<li>' + '{{ 'label.customer'|trans }}: ' + eventObj.customer + '</li>' +
@@ -194,7 +185,7 @@
}); });
}); });
// convert HTML to draggable items {# convert HTML to draggable items #}
jQuery('.external-events .external-event').each(function () { jQuery('.external-events .external-event').each(function () {
{# FullCalendar 3 can only work with jQuery UI elements #} {# FullCalendar 3 can only work with jQuery UI elements #}
jQuery(this).draggable({ jQuery(this).draggable({
@@ -207,15 +198,17 @@
let kimai = event.detail.kimai; let kimai = event.detail.kimai;
let API = kimai.getPlugin('api'); let API = kimai.getPlugin('api');
jQuery('{{ calendarSelector }}').fullCalendar({ jQuery('{{ calendarSelector }}').fullCalendar({
themeSystem: 'bootstrap3',
defaultView: '{{ app.user.getPreferenceValue('calendar.initial_view') }}', defaultView: '{{ app.user.getPreferenceValue('calendar.initial_view') }}',
{% if google is not null %} {% if google is not null %}
googleCalendarApiKey: '{{ google.apiKey }}', googleCalendarApiKey: '{{ google.apiKey }}',
{% endif %} {% endif %}
header : { header : {
left : 'prev,next today', left : 'prev,next today{% if is_granted('delete_own_timesheet') %} deleteButton{% endif %}',
center: 'title', center: 'title',
right : 'month,agendaWeek,agendaDay' right : 'month,agendaWeek,agendaDay'
}, },
dragRevertDuration: 0,
eventLimit: {{ config.dayLimit }}, eventLimit: {{ config.dayLimit }},
weekNumbersWithinDays: true, weekNumbersWithinDays: true,
weekNumberCalculation: 'ISO', weekNumberCalculation: 'ISO',
@@ -224,12 +217,14 @@
navLinks: true, navLinks: true,
locale: kimai.getConfiguration().get('locale').replace('_', '-').toLowerCase(), locale: kimai.getConfiguration().get('locale').replace('_', '-').toLowerCase(),
firstDay: kimai.getConfiguration().get('first_dow_iso'), firstDay: kimai.getConfiguration().get('first_dow_iso'),
{# customButtons: {
// TODO calculate height properly instead of relying on the default aspectRatio deleteButton: {
height: function() { text: '{{ 'action.delete'|trans }}',
return 'parent'; click: function() {
kimai.getPlugin('alert').info('{{ 'calendar.drag_and_drop.delete'|trans }}');
}
}
}, },
#}
height: 'auto', height: 'auto',
nowIndicator: true, nowIndicator: true,
now: '{{ now|date_format('c') }}', now: '{{ now|date_format('c') }}',
@@ -344,11 +339,11 @@
{% endif %} {% endif %}
], ],
eventRender: function(eventObj, $el) { eventRender: function(eventObj, $el) {
// don't show popover for google calendar {# don't show popover for google calendar #}
if (eventObj.source.ajaxSettings !== undefined) { if (eventObj.source.ajaxSettings !== undefined) {
return; return;
} }
// or when an event is dragged or resized {# or when an event is dragged or resized #}
if (!showPopover()) { if (!showPopover()) {
return; return;
} }
@@ -364,9 +359,11 @@
}, },
{% if not is_punch_mode and is_granted('create_own_timesheet') %} {% if not is_punch_mode and is_granted('create_own_timesheet') %}
dayClick: function(date, jsEvent, view) { dayClick: function(date, jsEvent, view) {
{# day-clicks are always triggered, unless a selection was created. {#
Day-clicks are always triggered, unless a selection was created.
So clicking in a day (month view) or any slot (week and day view) will trigger a dayClick So clicking in a day (month view) or any slot (week and day view) will trigger a dayClick
BEFORE triggering a select - make sure not two create dialogs are requested #} BEFORE triggering a select - make sure not two create dialogs are requested
#}
if (view.type !== 'month') { if (view.type !== 'month') {
return; return;
} }
@@ -377,8 +374,10 @@
selectable: true, selectable: true,
select: function(start, end, jsEvent, view) { select: function(start, end, jsEvent, view) {
if(view.type === 'month') { if(view.type === 'month') {
{# multi-day clicks are NOT allowed in the month view, as simple day clicks would also trigger {#
a select - there is no way to distinguish a simple click and a two day selection #} Multi-day clicks are NOT allowed in the month view, as simple day clicks would also trigger
a select - there is no way to distinguish a simple click and a two day selection
#}
return; return;
} }
let createUrl = '{{ path('timesheet_create') }}' + '?from=' + start.format() + '&to=' + end.format(); let createUrl = '{{ path('timesheet_create') }}' + '?from=' + start.format() + '&to=' + end.format();
@@ -401,6 +400,24 @@
}, },
eventDragStop: function(event, jsEvent, ui, view) { eventDragStop: function(event, jsEvent, ui, view) {
activatePopover(); activatePopover();
{% if is_granted('delete_own_timesheet') %}
var trash = jQuery('.fc-deleteButton-button');
var offset = trash.offset();
if (jsEvent.pageX >= offset.left && jsEvent.pageX<= (offset.left + trash.outerWidth(true)) &&
jsEvent.pageY >= offset.top && jsEvent.pageY <= (offset.top + trash.outerHeight(true))) {
// FIXME confirm delete
API.delete(
'{{ path('delete_timesheet', {'id': '__xxx__'}) }}'.replace('__xxx__', event.id),
function () {
kimai.getPlugin('alert').success('action.delete.success');
jQuery('{{ calendarSelector }}').fullCalendar('removeEvents', event._id);
}, function () {
kimai.getPlugin('alert').success('action.delete.error');
}
);
}
{% endif %}
}, },
eventDrop: changeHandler, eventDrop: changeHandler,
eventResizeStart: function(event, jsEvent, ui, view) { eventResizeStart: function(event, jsEvent, ui, view) {
@@ -412,7 +429,9 @@
eventResize: changeHandler, eventResize: changeHandler,
{% endif %} {% endif %}
{% endif %} {% endif %}
}) });
var trashBtn = jQuery('.fc-deleteButton-button');
trashBtn.html('<span class="text-danger"><i class="{{ 'trash'|icon }} text-danger"></i> ' + trashBtn.text() + '</span>');
}); });
</script> </script>
{% endblock %} {% endblock %}

View File

@@ -595,6 +595,10 @@
<source>calendar.title</source> <source>calendar.title</source>
<target>Kalender</target> <target>Kalender</target>
</trans-unit> </trans-unit>
<trans-unit id="calendar.drag_and_drop.delete">
<source>calendar.drag_and_drop.delete</source>
<target>Wenn Sie einen Eintrag löschen wollen, müssen Sie ihn auf die Schaltfläche ziehen.</target>
</trans-unit>
<!-- <!--
Admin: Timesheet Admin: Timesheet
--> -->

View File

@@ -603,7 +603,10 @@
<source>calendar.title</source> <source>calendar.title</source>
<target>Calendar</target> <target>Calendar</target>
</trans-unit> </trans-unit>
<trans-unit id="calendar.drag_and_drop.delete">
<source>calendar.drag_and_drop.delete</source>
<target>If you want to delete an entry, you must drag it onto the button.</target>
</trans-unit>
<!-- <!--
Admin: Timesheet Admin: Timesheet
--> -->
@@ -611,7 +614,6 @@
<source>admin_timesheet.title</source> <source>admin_timesheet.title</source>
<target>Timesheets</target> <target>Timesheets</target>
</trans-unit> </trans-unit>
<!-- <!--
Admin: Projects Admin: Projects
--> -->