nodebb-plugin-equipment-calendar 9.0.0 → 9.0.2

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-equipment-calendar",
3
- "version": "9.0.0",
3
+ "version": "9.0.2",
4
4
  "description": "Equipment reservation calendar for NodeBB (FullCalendar, approvals, HelloAsso payments)",
5
5
  "main": "library.js",
6
6
  "scripts": {
package/plugin.json CHANGED
@@ -25,6 +25,6 @@
25
25
  "scripts": [
26
26
  "public/js/client.js"
27
27
  ],
28
- "version": "3.0.0-stable4p-admin-save-alert",
28
+ "version": "3.0.0-stable4q-acp-save-calendar-fixes",
29
29
  "minver": "4.7.1"
30
30
  }
@@ -1,4 +1,4 @@
1
- require(['jquery', 'bootstrap', 'bootbox'], function ($, bootstrap, bootbox) {
1
+ require(['jquery', 'bootstrap'], function ($, bootstrap) {
2
2
  'use strict';
3
3
  /* global window, document, FullCalendar */
4
4
 
@@ -54,38 +54,6 @@ require(['jquery', 'bootstrap', 'bootbox'], function ($, bootstrap, bootbox) {
54
54
  } catch (e) { return iso; }
55
55
  }
56
56
 
57
-
58
- function escapeHtml(str) {
59
- return String(str || '').replace(/[&<>"']/g, function (c) {
60
- return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[c];
61
- });
62
- }
63
-
64
- function ecDoAction(rid, action, eventObj) {
65
- try {
66
- const csrf = window.EC_CSRF || (window.config && window.config.csrf_token) || '';
67
- return fetch((config.relative_path || '') + '/api/equipment/reservations/' + encodeURIComponent(rid) + '/action', {
68
- method: 'POST',
69
- headers: { 'Content-Type': 'application/json', 'x-csrf-token': csrf },
70
- body: JSON.stringify({ action: action })
71
- }).then(function (r) {
72
- return r.json().catch(function () { return {}; }).then(function (j) { return { ok: r.ok, json: j }; });
73
- }).then(function (res) {
74
- if (!res.ok || (res.json && res.json.error)) {
75
- if (window.app && app.alertError) app.alertError((res.json && res.json.error) ? res.json.error : 'Erreur');
76
- return false;
77
- }
78
- if (action === 'delete') {
79
- try { eventObj.remove(); } catch (e) {}
80
- } else {
81
- try { eventObj.setExtendedProp('status', action === 'approve' ? 'approved' : 'rejected'); } catch (e) {}
82
- }
83
- if (window.app && app.alertSuccess) app.alertSuccess('OK');
84
- return true;
85
- });
86
- } catch (e) { return false; }
87
- }
88
-
89
57
  function updateTotalPrice() {
90
58
  try {
91
59
  const sel = document.getElementById('ec-item-ids');
@@ -172,6 +140,7 @@ function updateTotalPrice() {
172
140
  dayMaxEventRows: true,
173
141
  displayEventTime: false,
174
142
  timeZone: 'UTC',
143
+ locale: 'fr',
175
144
  events: events,
176
145
  select: function (info) {
177
146
  if (!window.EC_CAN_CREATE) return;
@@ -182,34 +151,15 @@ function updateTotalPrice() {
182
151
  },
183
152
  dateClick: function (info) {
184
153
  if (!window.EC_CAN_CREATE) return;
185
- openCreateModal(String(info.dateStr||'').slice(0,10), String(info.dateStr||'').slice(0,10));
154
+ openCreateModal(info.dateStr, info.dateStr);
186
155
  },
187
156
  eventClick: function (info) {
188
- try {
189
- info.jsEvent && info.jsEvent.preventDefault && info.jsEvent.preventDefault();
190
- const ep = info.event.extendedProps || {};
191
- const rid = ep.rid || info.event.id;
192
- const status = ep.status || 'pending';
193
- const title = info.event.title || 'Reservation';
194
- const start = String(info.event.startStr || '').slice(0,10);
195
- const end = String(info.event.endStr || '').slice(0,10);
196
- const total = ep.total || 0;
197
-
198
- let msg = '<div><strong>' + escapeHtml(title) + '</strong></div>';
199
- msg += '<div>Periode: ' + escapeHtml(start) + ' -> ' + escapeHtml(end) + '</div>';
200
- msg += '<div>Statut: ' + escapeHtml(status) + '</div>';
201
- if (total) msg += '<div>Total: ' + escapeHtml(String(total)) + ' EUR</div>';
202
-
203
- const buttons = { close: { label: 'Fermer', className: 'btn-secondary' } };
204
-
205
- if (window.EC_IS_APPROVER) {
206
- buttons.approve = { label: 'Valider', className: 'btn-success', callback: function () { return ecDoAction(rid, 'approve', info.event); } };
207
- buttons.reject = { label: 'Rejeter', className: 'btn-warning', callback: function () { return ecDoAction(rid, 'reject', info.event); } };
208
- buttons.delete = { label: 'Supprimer', className: 'btn-danger', callback: function () { return ecDoAction(rid, 'delete', info.event); } };
209
- }
210
-
211
- bootbox.dialog({ title: 'Reservation', message: msg, buttons: buttons });
212
- } catch (e) {}
157
+ // simple details popup
158
+ const r = info.event.extendedProps || {};
159
+ const title = info.event.title || 'Réservation';
160
+ const start = info.event.startStr || '';
161
+ const end = info.event.endStr ? addDaysIsoLocal(info.event.endStr, -1) : '';
162
+ bootbox.alert(`<strong>${title}</strong><br>Du ${start} au ${end}<br>Statut: ${r.status || ''}`);
213
163
  },
214
164
  });
215
165
 
@@ -1,3 +1,4 @@
1
+
1
2
  <div class="acp-page-container">
2
3
  <div class="d-flex align-items-center justify-content-between flex-wrap gap-2">
3
4
  <h1 class="mb-0">Equipment Calendar</h1>
@@ -25,34 +26,26 @@
25
26
  </div>
26
27
  </div>
27
28
 
28
- <div class="card card-body mb-3">
29
- <h5>Paiement</h5>
30
- <div class="mb-0">
31
- <label class="form-label">Timeout paiement (minutes)</label>
32
- <input class="form-control" type="number" min="1" name="paymentTimeoutMinutes" data-field="paymentTimeoutMinutes" value="{settings.paymentTimeoutMinutes}">
33
- </div>
34
- </div>
35
-
36
29
  <div class="card card-body mb-3">
37
30
  <h5>HelloAsso</h5>
38
- <div class="mb-3">
39
- <label class="form-label">API Base URL (prod/sandbox)</label>
40
- <input class="form-control" type="text" name="ha_apiBaseUrl" data-field="ha_apiBaseUrl" value="{settings.ha_apiBaseUrl}">
41
- <div class="form-text">Prod: <code>https://api.helloasso.com</code> — Sandbox: <code>https://api.helloasso-sandbox.com</code></div>
42
- </div>
43
- <div class="mb-3">
44
- <label class="form-label">Organization slug</label>
45
- <input class="form-control" type="text" name="ha_organizationSlug" data-field="ha_organizationSlug" value="{settings.ha_organizationSlug}">
46
- </div>
47
- <div class="mb-3">
48
- <label class="form-label">Client ID</label>
49
- <input class="form-control" type="text" name="ha_clientId" data-field="ha_clientId" value="{settings.ha_clientId}">
50
- </div>
51
- <div class="mb-3">
52
- <label class="form-label">Client Secret</label>
53
- <input class="form-control" type="password" name="ha_clientSecret" data-field="ha_clientSecret" value="{settings.ha_clientSecret}">
54
- </div>
55
31
  <div class="row g-3">
32
+ <div class="col-md-6">
33
+ <label class="form-label">Client ID</label>
34
+ <input class="form-control" type="text" name="ha_clientId" data-field="ha_clientId" value="{settings.ha_clientId}">
35
+ </div>
36
+ <div class="col-md-6">
37
+ <label class="form-label">Client Secret</label>
38
+ <input class="form-control" type="password" name="ha_clientSecret" data-field="ha_clientSecret" value="{settings.ha_clientSecret}">
39
+ </div>
40
+ <div class="col-md-6">
41
+ <label class="form-label">Organization slug</label>
42
+ <input class="form-control" type="text" name="ha_organizationSlug" data-field="ha_organizationSlug" value="{settings.ha_organizationSlug}">
43
+ </div>
44
+ <div class="col-md-6">
45
+ <label class="form-label">Return URL base (callback)</label>
46
+ <input class="form-control" type="text" name="ha_returnUrl" data-field="ha_returnUrl" value="{settings.ha_returnUrl}" placeholder="https://www.onekite.com">
47
+ <div class="form-text">Le plugin ajoutera automatiquement le chemin de callback.</div>
48
+ </div>
56
49
  <div class="col-md-6">
57
50
  <label class="form-label">Form Type</label>
58
51
  <input class="form-control" type="text" name="ha_itemsFormType" data-field="ha_itemsFormType" value="{settings.ha_itemsFormType}" placeholder="shop">
@@ -62,14 +55,30 @@
62
55
  <input class="form-control" type="text" name="ha_itemsFormSlug" data-field="ha_itemsFormSlug" value="{settings.ha_itemsFormSlug}" placeholder="locations-materiel-2026">
63
56
  </div>
64
57
  </div>
65
- <div class="mb-0 mt-3">
66
- <label class="form-label">Préfixe itemName (checkout)</label>
67
- <input class="form-control" type="text" name="ha_calendarItemNamePrefix" data-field="ha_calendarItemNamePrefix" value="{settings.ha_calendarItemNamePrefix}">
58
+ </div>
59
+
60
+ <div class="card card-body mb-3">
61
+ <h5>Calendrier</h5>
62
+ <div class="row g-3">
63
+ <div class="col-md-6">
64
+ <label class="form-label">Vue par défaut</label>
65
+ <select class="form-select" name="defaultView" data-field="defaultView">
66
+ <option value="dayGridMonth">Mois</option>
67
+ <option value="timeGridWeek">Semaine</option>
68
+ <option value="listWeek">Liste</option>
69
+ </select>
70
+ </div>
71
+ <div class="col-md-6">
72
+ <label class="form-label">Timezone</label>
73
+ <input class="form-control" type="text" name="timezone" data-field="timezone" value="{settings.timezone}">
74
+ </div>
75
+ <div class="col-md-6">
76
+ <label class="form-label">Timeout paiement (minutes)</label>
77
+ <input class="form-control" type="number" min="1" name="paymentTimeoutMinutes" data-field="paymentTimeoutMinutes" value="{settings.paymentTimeoutMinutes}">
78
+ </div>
68
79
  </div>
69
80
  </div>
70
81
 
71
82
  <button id="save" class="btn btn-primary" type="button">Enregistrer</button>
72
83
  </div>
73
-
74
-
75
84
  </div>