nodebb-plugin-calendar-onekite 10.0.18 → 11.1.0

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-calendar-onekite",
3
- "version": "10.0.18",
3
+ "version": "11.1.0",
4
4
  "description": "Calendar & equipment booking workflow for NodeBB (FullCalendar + HelloAsso)",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
@@ -3,175 +3,201 @@
3
3
  /* global $, app, bootbox */
4
4
 
5
5
  (function () {
6
- async function getSettings() {
6
+ function getSettings() {
7
7
  return $.getJSON('/api/calendar-onekite/settings');
8
8
  }
9
9
 
10
- async function saveSettings(data) {
10
+ function saveSettings(data) {
11
11
  return $.ajax({
12
12
  url: '/api/admin/calendar-onekite/settings',
13
13
  method: 'POST',
14
14
  contentType: 'application/json',
15
- data: JSON.stringify(data)
15
+ data: JSON.stringify(data || {})
16
16
  });
17
17
  }
18
18
 
19
- async function syncItems() {
19
+ function syncItems() {
20
20
  return $.ajax({
21
21
  url: '/api/admin/calendar-onekite/sync-items',
22
22
  method: 'POST'
23
23
  });
24
24
  }
25
25
 
26
- async function purge(year) {
26
+ function purgeYear(year) {
27
27
  return $.ajax({
28
28
  url: '/api/admin/calendar-onekite/purge',
29
- method: 'POST',
30
- contentType: 'application/json',
31
- data: JSON.stringify({ year })
29
+ method: 'POST'
30
+ , contentType: 'application/json',
31
+ data: JSON.stringify({ year: year })
32
32
  });
33
33
  }
34
34
 
35
- async function listPending() {
35
+ function listPending() {
36
36
  return $.getJSON('/api/admin/calendar-onekite/pending');
37
37
  }
38
38
 
39
- async function approve(id) {
40
- return $.ajax({ url: `/api/admin/calendar-onekite/reservations/${id}/approve`, method: 'PUT' });
39
+ function approve(id) {
40
+ return $.ajax({
41
+ url: '/api/admin/calendar-onekite/reservations/' + id + '/approve',
42
+ method: 'PUT'
43
+ });
44
+ }
45
+
46
+ function refuse(id) {
47
+ return $.ajax({
48
+ url: '/api/admin/calendar-onekite/reservations/' + id + '/refuse',
49
+ method: 'PUT'
50
+ });
41
51
  }
42
52
 
43
- async function refuse(id) {
44
- return $.ajax({ url: `/api/admin/calendar-onekite/reservations/${id}/refuse`, method: 'PUT' });
53
+ function safeErr(e) {
54
+ try {
55
+ if (e && e.responseJSON && e.responseJSON.error) return e.responseJSON.error;
56
+ } catch (err) {}
57
+ return 'Erreur';
58
+ }
59
+
60
+ function fillForm(settings) {
61
+ var $form = $('.calendar-onekite-settings');
62
+ Object.keys(settings || {}).forEach(function (k) {
63
+ $form.find('[name="' + k + '"]').val(settings[k]);
64
+ });
45
65
  }
46
66
 
47
67
  function readForm() {
48
- const data = {};
49
- $('.calendar-onekite-settings').find('input, select, textarea').each(function () {
50
- const $el = $(this);
51
- const name = $el.attr('name');
68
+ var data = {};
69
+ $('.calendar-onekite-settings').find('input,select,textarea').each(function () {
70
+ var $el = $(this);
71
+ var name = $el.attr('name');
52
72
  if (!name) return;
53
73
  data[name] = $el.val();
54
74
  });
55
75
  return data;
56
76
  }
57
77
 
58
- function fillForm(settings) {
59
- Object.keys(settings || {}).forEach((key) => {
60
- const $el = $(`.calendar-onekite-settings [name="${key}"]`);
61
- if ($el.length) $el.val(settings[key]);
62
- });
63
- }
64
-
65
78
  function renderPending(list) {
66
- if (!list || !list.length) {
67
- $('#onekite-pending').html('<div class="text-muted">Aucune demande en attente.</div>');
68
- return;
79
+ var $p = $('#onekite-pending');
80
+ $p.empty();
81
+
82
+ function row(r, type) {
83
+ var btns = '';
84
+ if (type === 'pending') {
85
+ btns = ''
86
+ + '<button class="btn btn-sm btn-success me-1" data-approve="' + r.id + '"><i class="fa fa-check"></i> Approve</button>'
87
+ + '<button class="btn btn-sm btn-outline-danger" data-refuse="' + r.id + '"><i class="fa fa-times"></i> Refuse</button>';
88
+ } else {
89
+ btns = r.paymentUrl ? ('<a class="btn btn-sm btn-outline-primary" href="' + r.paymentUrl + '" target="_blank" rel="noopener"><i class="fa fa-credit-card"></i> Lien paiement</a>') : '';
90
+ }
91
+
92
+ return ''
93
+ + '<tr>'
94
+ + '<td>#' + r.id + '</td>'
95
+ + '<td>' + (r.itemName || '') + '</td>'
96
+ + '<td>' + (new Date(Number(r.start))).toLocaleString() + '</td>'
97
+ + '<td>' + (new Date(Number(r.end))).toLocaleString() + '</td>'
98
+ + '<td>' + (r.username || '') + '</td>'
99
+ + '<td><code>' + (r.status || '') + '</code></td>'
100
+ + '<td class="text-end">' + btns + '</td>'
101
+ + '</tr>';
69
102
  }
70
103
 
71
- const rows = list.map(r => {
72
- const start = new Date(parseInt(r.start, 10)).toLocaleString();
73
- const end = new Date(parseInt(r.end, 10)).toLocaleString();
74
- const expires = r.expiresAt ? new Date(parseInt(r.expiresAt, 10)).toLocaleString() : '';
75
-
76
- return `
77
- <tr>
78
- <td>${r.id}</td>
79
- <td>${$('<div>').text(r.username || '').html()}</td>
80
- <td>${$('<div>').text(r.itemName || '').html()}</td>
81
- <td>${start} → ${end}</td>
82
- <td>${expires}</td>
83
- <td class="text-end">
84
- <button class="btn btn-sm btn-success" data-action="approve" data-id="${r.id}"><i class="fa fa-check"></i></button>
85
- <button class="btn btn-sm btn-danger" data-action="refuse" data-id="${r.id}"><i class="fa fa-times"></i></button>
86
- </td>
87
- </tr>
88
- `;
89
- }).join('');
90
-
91
- $('#onekite-pending').html(`
92
- <div class="table-responsive">
93
- <table class="table table-sm">
94
- <thead>
95
- <tr>
96
- <th>ID</th>
97
- <th>Membre</th>
98
- <th>Matériel</th>
99
- <th>Plage</th>
100
- <th>Expire</th>
101
- <th></th>
102
- </tr>
103
- </thead>
104
- <tbody>${rows}</tbody>
105
- </table>
106
- </div>
107
- `);
104
+ var html = '';
105
+ var pending = (list && list.pending) ? list.pending : [];
106
+ var awaiting = (list && list.awaiting_payment) ? list.awaiting_payment : [];
107
+
108
+ html += '<h5 class="mt-4">Demandes en attente</h5>';
109
+ html += '<div class="table-responsive"><table class="table table-sm">'
110
+ + '<thead><tr><th>ID</th><th>Matériel</th><th>Début</th><th>Fin</th><th>Utilisateur</th><th>Statut</th><th></th></tr></thead><tbody>';
111
+ if (!pending.length) html += '<tr><td colspan="7" class="text-muted">Aucune</td></tr>';
112
+ pending.forEach(function (r) { html += row(r, 'pending'); });
113
+ html += '</tbody></table></div>';
114
+
115
+ html += '<h5 class="mt-4">Validées (en attente de paiement)</h5>';
116
+ html += '<div class="table-responsive"><table class="table table-sm">'
117
+ + '<thead><tr><th>ID</th><th>Matériel</th><th>Début</th><th>Fin</th><th>Utilisateur</th><th>Statut</th><th></th></tr></thead><tbody>';
118
+ if (!awaiting.length) html += '<tr><td colspan="7" class="text-muted">Aucune</td></tr>';
119
+ awaiting.forEach(function (r) { html += row(r, 'awaiting'); });
120
+ html += '</tbody></table></div>';
121
+
122
+ $p.html(html);
123
+
124
+ $p.find('[data-approve]').off('click').on('click', function () {
125
+ var id = $(this).attr('data-approve');
126
+ approve(id).done(function (resp) {
127
+ if (resp && resp.paymentUrl) {
128
+ app.alertSuccess('Validé. Lien de paiement créé.');
129
+ } else {
130
+ app.alertSuccess('Validé.');
131
+ }
132
+ refreshPending();
133
+ }).fail(function (e) {
134
+ app.alertError(safeErr(e));
135
+ });
136
+ });
137
+
138
+ $p.find('[data-refuse]').off('click').on('click', function () {
139
+ var id = $(this).attr('data-refuse');
140
+ refuse(id).done(function () {
141
+ app.alertSuccess('Refusé.');
142
+ refreshPending();
143
+ }).fail(function (e) {
144
+ app.alertError(safeErr(e));
145
+ });
146
+ });
108
147
  }
109
148
 
110
- async function refreshPending() {
111
- const list = await listPending();
112
- renderPending(list);
149
+ function refreshPending() {
150
+ listPending().done(function (list) {
151
+ renderPending(list);
152
+ }).fail(function () {
153
+ $('#onekite-pending').html('<div class="text-danger">Impossible de charger la liste.</div>');
154
+ });
113
155
  }
114
156
 
115
- async function init() {
116
- try {
117
- const settings = await getSettings();
157
+ function boot() {
158
+ getSettings().done(function (settings) {
118
159
  fillForm(settings);
119
- await refreshPending();
120
- } catch (e) {
121
- app.alertError(e && e.responseJSON && e.responseJSON.error ? e.responseJSON.error : 'Erreur');
122
- }
160
+ });
123
161
 
124
- $('#onekite-save').on('click', async function () {
125
- try {
126
- const data = readForm();
127
- await saveSettings(data);
128
- app.alertSuccess('Enregistré');
129
- } catch (e) {
130
- app.alertError(e && e.responseJSON && e.responseJSON.error ? e.responseJSON.error : 'Erreur');
131
- }
162
+ // Save settings
163
+ $('#onekite-save').on('click', function () {
164
+ var data = readForm();
165
+ saveSettings(data).done(function () {
166
+ app.alertSuccess('Paramètres enregistrés.');
167
+ }).fail(function (e) {
168
+ app.alertError(safeErr(e));
169
+ });
132
170
  });
133
171
 
134
- $('#onekite-sync-items').on('click', async function (ev) {
135
- ev.preventDefault();
136
- try {
137
- await syncItems();
138
- app.alertSuccess('Items synchronisés depuis HelloAsso');
139
- } catch (e) {
140
- app.alertError(e && e.responseJSON && e.responseJSON.error ? e.responseJSON.error : 'Erreur sync');
141
- }
172
+ // Sync items
173
+ $('#onekite-sync-items').on('click', function () {
174
+ syncItems().done(function (resp) {
175
+ app.alertSuccess('Synchronisation OK (' + (resp.count || 0) + ' items).');
176
+ }).fail(function (e) {
177
+ app.alertError(safeErr(e));
178
+ });
142
179
  });
143
180
 
144
- $('#onekite-purge').on('click', async function () {
145
- const year = parseInt($('[name="purgeYear"]').val(), 10);
146
- if (!year || year < 1970) {
181
+ // Purge
182
+ $('#onekite-purge').on('click', function () {
183
+ var year = parseInt($('#onekite-purge-year').val(), 10);
184
+ if (!year) {
147
185
  app.alertError('Année invalide');
148
186
  return;
149
187
  }
150
- bootbox.confirm(`Confirmer la purge de l'année ${year} ?`, async function (ok) {
188
+ bootbox.confirm('Purger toutes les réservations de ' + year + ' ?', function (ok) {
151
189
  if (!ok) return;
152
- try {
153
- await purge(year);
154
- app.alertSuccess('Purge effectuée');
155
- await refreshPending();
156
- } catch (e) {
157
- app.alertError(e && e.responseJSON && e.responseJSON.error ? e.responseJSON.error : 'Erreur purge');
158
- }
190
+ purgeYear(year).done(function (resp) {
191
+ app.alertSuccess('Purge OK (' + (resp.purged || 0) + ').');
192
+ refreshPending();
193
+ }).fail(function (e) {
194
+ app.alertError(safeErr(e));
195
+ });
159
196
  });
160
197
  });
161
198
 
162
- $('#onekite-pending').on('click', 'button[data-action]', async function () {
163
- const id = $(this).attr('data-id');
164
- const action = $(this).attr('data-action');
165
- try {
166
- if (action === 'approve') await approve(id);
167
- if (action === 'refuse') await refuse(id);
168
- app.alertSuccess('OK');
169
- await refreshPending();
170
- } catch (e) {
171
- app.alertError(e && e.responseJSON && e.responseJSON.error ? e.responseJSON.error : 'Erreur');
172
- }
173
- });
199
+ refreshPending();
174
200
  }
175
201
 
176
- $(document).ready(init);
202
+ $(boot);
177
203
  })();