nodebb-plugin-calendar-onekite 1.4.5 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/plugin.json
CHANGED
package/static/js/calendar.js
CHANGED
|
@@ -1,301 +1,42 @@
|
|
|
1
|
-
'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
checkPermissions: function () {
|
|
17
|
-
$.get('/api/calendar/permissions/book').then(res => {
|
|
18
|
-
CalendarPage.canBook = !!(res && res.allow);
|
|
19
|
-
});
|
|
20
|
-
},
|
|
21
|
-
|
|
22
|
-
prepareModals: function () {
|
|
23
|
-
$('.calendar-modal').hide();
|
|
24
|
-
$('.calendar-modal .calendar-close').on('click', function () {
|
|
25
|
-
$(this).closest('.calendar-modal').fadeOut();
|
|
26
|
-
});
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
initCalendar: function () {
|
|
30
|
-
const calendarEl = document.getElementById('calendar');
|
|
31
|
-
|
|
32
|
-
const calendar = new FullCalendar.Calendar(calendarEl, {
|
|
33
|
-
themeSystem: 'bootstrap5',
|
|
34
|
-
initialView: 'dayGridMonth',
|
|
35
|
-
locale: 'fr',
|
|
36
|
-
height: 'auto',
|
|
37
|
-
selectable: true,
|
|
38
|
-
headerToolbar: {
|
|
39
|
-
left: 'prev,next today',
|
|
40
|
-
center: 'title',
|
|
41
|
-
right: 'dayGridMonth,timeGridWeek,listWeek'
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
events: (info, success, fail) => {
|
|
45
|
-
$.get('/api/calendar/events', { start: info.startStr, end: info.endStr })
|
|
46
|
-
.then(events => {
|
|
47
|
-
success(events.map(ev => ({
|
|
48
|
-
id: ev.eid,
|
|
49
|
-
title: ev.title,
|
|
50
|
-
start: ev.start,
|
|
51
|
-
end: ev.end,
|
|
52
|
-
allDay: ev.allDay == 1,
|
|
53
|
-
extendedProps: ev
|
|
54
|
-
})));
|
|
55
|
-
})
|
|
56
|
-
.catch(fail);
|
|
57
|
-
},
|
|
58
|
-
|
|
59
|
-
dateClick: info => {
|
|
60
|
-
CalendarPage.openCreateEventModal(info.dateStr);
|
|
61
|
-
},
|
|
62
|
-
|
|
63
|
-
eventClick: info => {
|
|
64
|
-
CalendarPage.openEventModal(info.event.extendedProps);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
calendar.render();
|
|
69
|
-
|
|
70
|
-
// bouton nouvel event
|
|
71
|
-
$.get('/api/calendar/permissions/create').then(res => {
|
|
72
|
-
if (!res || !res.allow) {
|
|
73
|
-
$('#calendar-new-event').hide();
|
|
74
|
-
} else {
|
|
75
|
-
$('#calendar-new-event').on('click', () => {
|
|
76
|
-
CalendarPage.openCreateEventModal();
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
/* -------- MODAL EVENT -------- */
|
|
83
|
-
|
|
84
|
-
openCreateEventModal: function (dateStr) {
|
|
85
|
-
const modal = $('#calendar-event-modal');
|
|
86
|
-
|
|
87
|
-
$('#event-modal-title').text('Créer un événement');
|
|
88
|
-
$('#event-title').val('');
|
|
89
|
-
$('#event-description').val('');
|
|
90
|
-
const base = dateStr || new Date().toISOString().slice(0, 10);
|
|
91
|
-
$('#event-start').val(base + 'T09:00');
|
|
92
|
-
$('#event-end').val(base + 'T11:00');
|
|
93
|
-
$('#event-allDay').prop('checked', false);
|
|
94
|
-
$('#event-location').val('');
|
|
95
|
-
$('#event-bookingEnabled').prop('checked', false);
|
|
96
|
-
$('#booking-items').empty();
|
|
97
|
-
|
|
98
|
-
$('#event-save').off('click').on('click', () => {
|
|
99
|
-
CalendarPage.saveEvent();
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
$('#event-delete').hide();
|
|
103
|
-
$('#event-reserve').hide();
|
|
104
|
-
|
|
105
|
-
$('#event-add-item').off('click').on('click', () => {
|
|
106
|
-
CalendarPage.addBookingItemRow();
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
modal.fadeIn();
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
openEventModal: function (eventData) {
|
|
113
|
-
const modal = $('#calendar-event-modal');
|
|
114
|
-
|
|
115
|
-
$('#event-modal-title').text('Événement : ' + eventData.title);
|
|
116
|
-
$('#event-title').val(eventData.title);
|
|
117
|
-
$('#event-description').val(eventData.description || '');
|
|
118
|
-
$('#event-start').val(eventData.start.replace('Z', ''));
|
|
119
|
-
$('#event-end').val(eventData.end.replace('Z', ''));
|
|
120
|
-
$('#event-allDay').prop('checked', eventData.allDay == 1);
|
|
121
|
-
$('#event-location').val(eventData.location || '');
|
|
122
|
-
$('#event-bookingEnabled').prop('checked', eventData.bookingEnabled == 1);
|
|
123
|
-
|
|
124
|
-
CalendarPage.renderBookingItems(eventData.bookingItems || []);
|
|
125
|
-
|
|
126
|
-
$('#event-add-item').off('click').on('click', () => {
|
|
127
|
-
CalendarPage.addBookingItemRow();
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
$('#event-save').off('click').on('click', () => {
|
|
131
|
-
CalendarPage.updateEvent(eventData.eid);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
$('#event-delete').show().off('click').on('click', () => {
|
|
135
|
-
bootbox.confirm('Supprimer cet événement ?', ok => {
|
|
136
|
-
if (!ok) return;
|
|
137
|
-
$.ajax({ url: '/api/calendar/event/' + eventData.eid, method: 'DELETE' })
|
|
138
|
-
.then(() => location.reload());
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
if (CalendarPage.canBook && Number(eventData.bookingEnabled)) {
|
|
143
|
-
$('#event-reserve').show().off('click').on('click', () => {
|
|
144
|
-
CalendarPage.openReserveModal(eventData.eid);
|
|
145
|
-
});
|
|
146
|
-
} else {
|
|
147
|
-
$('#event-reserve').hide();
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
modal.fadeIn();
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
saveEvent: function () {
|
|
154
|
-
const data = CalendarPage.collectEventForm();
|
|
155
|
-
$.ajax({
|
|
156
|
-
url: '/api/calendar/event',
|
|
157
|
-
method: 'POST',
|
|
158
|
-
contentType: 'application/json',
|
|
159
|
-
data: JSON.stringify(data),
|
|
160
|
-
}).then(() => location.reload())
|
|
161
|
-
.catch(err => app.alertError(err.responseJSON?.error || err.message));
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
updateEvent: function (eid) {
|
|
165
|
-
const data = CalendarPage.collectEventForm();
|
|
166
|
-
$.ajax({
|
|
167
|
-
url: '/api/calendar/event/' + eid,
|
|
168
|
-
method: 'PUT',
|
|
169
|
-
contentType: 'application/json',
|
|
170
|
-
data: JSON.stringify(data),
|
|
171
|
-
}).then(() => location.reload())
|
|
172
|
-
.catch(err => app.alertError(err.responseJSON?.error || err.message));
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
collectEventForm: function () {
|
|
176
|
-
const items = [];
|
|
177
|
-
$('#booking-items .booking-item-row').each(function () {
|
|
178
|
-
const row = $(this);
|
|
179
|
-
const total = Number(row.find('.item-total').val() || 0);
|
|
180
|
-
if (!total) return;
|
|
181
|
-
|
|
182
|
-
items.push({
|
|
183
|
-
id: row.find('.item-id').val(),
|
|
184
|
-
name: row.find('.item-name').val(),
|
|
185
|
-
total,
|
|
186
|
-
reserved: Number(row.find('.item-reserved').val() || 0),
|
|
187
|
-
reservedTemp: Number(row.find('.item-reservedTemp').val() || 0),
|
|
188
|
-
price: Number(row.find('.item-price').val() || 0),
|
|
189
|
-
pickupLocation: row.find('.item-pickup').val() || ''
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
title: $('#event-title').val(),
|
|
195
|
-
description: $('#event-description').val(),
|
|
196
|
-
start: $('#event-start').val(),
|
|
197
|
-
end: $('#event-end').val(),
|
|
198
|
-
allDay: $('#event-allDay').is(':checked'),
|
|
199
|
-
location: $('#event-location').val(),
|
|
200
|
-
bookingEnabled: $('#event-bookingEnabled').is(':checked'),
|
|
201
|
-
bookingItems: items
|
|
202
|
-
};
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
renderBookingItems: function (items) {
|
|
206
|
-
const container = $('#booking-items');
|
|
207
|
-
container.empty();
|
|
208
|
-
(items || []).forEach(item => CalendarPage.addBookingItemRow(item));
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
addBookingItemRow: function (item = {}) {
|
|
212
|
-
const row = $(`
|
|
213
|
-
<div class="booking-item-row">
|
|
214
|
-
<input type="text" class="item-id form-control" placeholder="ID" value="${item.id || ''}">
|
|
215
|
-
<input type="text" class="item-name form-control" placeholder="Nom matériel" value="${item.name || ''}">
|
|
216
|
-
<input type="number" class="item-total form-control" placeholder="Total" value="${item.total || 0}">
|
|
217
|
-
<input type="number" class="item-price form-control" placeholder="Prix €" step="0.01" value="${item.price || 0}">
|
|
218
|
-
<input type="text" class="item-pickup form-control" placeholder="Lieu retrait" value="${item.pickupLocation || ''}">
|
|
219
|
-
<input type="hidden" class="item-reserved" value="${item.reserved || 0}">
|
|
220
|
-
<input type="hidden" class="item-reservedTemp" value="${item.reservedTemp || 0}">
|
|
221
|
-
<button class="btn btn-danger btn-sm item-remove">✕</button>
|
|
222
|
-
</div>
|
|
223
|
-
`);
|
|
224
|
-
|
|
225
|
-
row.find('.item-remove').on('click', () => row.remove());
|
|
226
|
-
$('#booking-items').append(row);
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
/* -------- MODAL RÉSERVATION -------- */
|
|
230
|
-
|
|
231
|
-
openReserveModal: function (eid) {
|
|
232
|
-
$.get('/api/calendar/event/' + eid).then(eventData => {
|
|
233
|
-
const modal = $('#calendar-reserve-modal');
|
|
234
|
-
|
|
235
|
-
$('#reserve-title').text(eventData.title);
|
|
236
|
-
|
|
237
|
-
const items = eventData.bookingItems || [];
|
|
238
|
-
if (!items.length || !Number(eventData.bookingEnabled)) {
|
|
239
|
-
$('#reserve-items').html('<p>Aucun matériel réservable pour cet événement.</p>');
|
|
240
|
-
$('#reserve-confirm').hide();
|
|
241
|
-
} else {
|
|
242
|
-
let html = '<ul>';
|
|
243
|
-
items.forEach((item, index) => {
|
|
244
|
-
const pickup = item.pickupLocation || 'Lieu de retrait non précisé';
|
|
245
|
-
html += `
|
|
246
|
-
<li>
|
|
247
|
-
<label>
|
|
248
|
-
<input type="radio" name="reserve-item" value="${item.id}" ${index === 0 ? 'checked' : ''}>
|
|
249
|
-
<strong>${item.name}</strong>
|
|
250
|
-
${item.price ? `– ${item.price} €/jour` : ''}
|
|
251
|
-
<br><small>📍 Retrait : ${pickup}</small>
|
|
252
|
-
</label>
|
|
253
|
-
</li>`;
|
|
254
|
-
});
|
|
255
|
-
html += '</ul>';
|
|
256
|
-
$('#reserve-items').html(html);
|
|
257
|
-
$('#reserve-confirm').show();
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
261
|
-
$('#reserve-start').val(today);
|
|
262
|
-
$('#reserve-end').val(today);
|
|
263
|
-
$('#reserve-quantity').val(1);
|
|
264
|
-
|
|
265
|
-
$('#reserve-confirm').off('click').on('click', () => {
|
|
266
|
-
CalendarPage.sendReservation(eid);
|
|
267
|
-
});
|
|
1
|
+
define('plugins/nodebb-plugin-calendar-onekite/static/js/calendar', [
|
|
2
|
+
'api',
|
|
3
|
+
'alerts',
|
|
4
|
+
], function (api, alerts) {
|
|
5
|
+
'use strict';
|
|
6
|
+
|
|
7
|
+
function init() {
|
|
8
|
+
// jQuery est fourni par NodeBB sur les pages rendues via buildHeader
|
|
9
|
+
const $ = window.jQuery;
|
|
10
|
+
if (!$) {
|
|
11
|
+
// fallback: on évite le crash
|
|
12
|
+
console.error('[calendar-onekite] jQuery not found');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
268
15
|
|
|
269
|
-
|
|
16
|
+
// Exemple: bind bouton "nouvel événement"
|
|
17
|
+
$('#calendar-new-event')
|
|
18
|
+
.off('click.calendarOnekite')
|
|
19
|
+
.on('click.calendarOnekite', function () {
|
|
20
|
+
// TODO: ouvre ton modal / formulaire
|
|
21
|
+
alerts.success('Clique OK: handler actif ✅');
|
|
270
22
|
});
|
|
271
|
-
},
|
|
272
23
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
const quantity = Number($('#reserve-quantity').val() || 1);
|
|
276
|
-
const dateStart = $('#reserve-start').val();
|
|
277
|
-
const dateEnd = $('#reserve-end').val();
|
|
24
|
+
// Si tu as d'autres binds / initialisation calendrier, fais-les ici
|
|
25
|
+
}
|
|
278
26
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
27
|
+
// important: ajaxify SPA
|
|
28
|
+
$(window).on('action:ajaxify.end', function () {
|
|
29
|
+
// page /calendar
|
|
30
|
+
if (ajaxify?.data?.template?.includes('calendar')) {
|
|
31
|
+
init();
|
|
32
|
+
}
|
|
33
|
+
});
|
|
283
34
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
contentType: 'application/json',
|
|
288
|
-
data: JSON.stringify({ itemId, quantity, dateStart, dateEnd }),
|
|
289
|
-
})
|
|
290
|
-
.then(res => {
|
|
291
|
-
app.alertSuccess(res.message || 'Demande envoyée.');
|
|
292
|
-
$('#calendar-reserve-modal').fadeOut();
|
|
293
|
-
})
|
|
294
|
-
.catch(err => {
|
|
295
|
-
app.alertError(err.responseJSON?.error || err.message);
|
|
296
|
-
});
|
|
35
|
+
$(function () {
|
|
36
|
+
if (ajaxify?.data?.template?.includes('calendar')) {
|
|
37
|
+
init();
|
|
297
38
|
}
|
|
298
|
-
};
|
|
39
|
+
});
|
|
299
40
|
|
|
300
|
-
|
|
41
|
+
return { init };
|
|
301
42
|
});
|
|
@@ -26,4 +26,9 @@
|
|
|
26
26
|
</div>
|
|
27
27
|
|
|
28
28
|
<button id="calendar-onekite-save" class="btn btn-primary">Enregistrer</button>
|
|
29
|
-
</div>
|
|
29
|
+
</div>
|
|
30
|
+
<script>
|
|
31
|
+
require(['plugins/nodebb-plugin-calendar-onekite/static/js/calendar'], function (Calendar) {
|
|
32
|
+
Calendar.init && Calendar.init();
|
|
33
|
+
});
|
|
34
|
+
</script>
|
package/templates/calendar.tpl
CHANGED
|
@@ -84,5 +84,8 @@
|
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|
|
86
86
|
|
|
87
|
-
<
|
|
88
|
-
|
|
87
|
+
<script>
|
|
88
|
+
require(['plugins/nodebb-plugin-calendar-onekite/static/js/calendar'], function (Calendar) {
|
|
89
|
+
Calendar.init && Calendar.init();
|
|
90
|
+
});
|
|
91
|
+
</script>
|