nodebb-plugin-calendar-onekite 11.1.49 → 11.1.50

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/lib/admin.js CHANGED
@@ -3,6 +3,12 @@
3
3
  const meta = require.main.require('./src/meta');
4
4
  const user = require.main.require('./src/user');
5
5
  const emailer = require.main.require('./src/emailer');
6
+ const nconf = require.main.require('nconf');
7
+
8
+ function forumBaseUrl() {
9
+ const base = String(nconf.get('url') || '').trim().replace(/\/$/, '');
10
+ return base;
11
+ }
6
12
 
7
13
  function formatFR(tsOrIso) {
8
14
  const d = new Date(typeof tsOrIso === 'string' && /^[0-9]+$/.test(tsOrIso) ? parseInt(tsOrIso, 10) : tsOrIso);
@@ -119,6 +125,9 @@ admin.approveReservation = async function (req, res) {
119
125
  const requester = await user.getUserFields(r.uid, ['username', 'email']);
120
126
  // r.total is stored as an estimated total in euros; HelloAsso expects cents.
121
127
  const totalAmount = Math.max(0, Math.round((Number(r.total) || 0) * 100));
128
+ const base = forumBaseUrl();
129
+ const returnUrl = base ? `${base}/calendar` : '';
130
+ const webhookUrl = base ? `${base}/plugins/calendar-onekite/helloasso` : '';
122
131
  paymentUrl = await helloasso.createCheckoutIntent({
123
132
  env,
124
133
  token,
@@ -127,7 +136,9 @@ admin.approveReservation = async function (req, res) {
127
136
  formSlug: settings.helloassoFormSlug,
128
137
  totalAmount,
129
138
  payerEmail: requester && requester.email,
130
- callbackUrl: 'https://api.onekite.com/helloasso',
139
+ // User return/back/error URLs must be real pages; webhook uses the plugin endpoint.
140
+ callbackUrl: returnUrl,
141
+ webhookUrl: webhookUrl,
131
142
  itemName: 'Réservation matériel OneKite',
132
143
  containsDonation: false,
133
144
  metadata: { reservationId: String(rid) },
package/lib/api.js CHANGED
@@ -72,7 +72,8 @@ function normalizeCallbackUrl(configured, meta) {
72
72
  const base = normalizeBaseUrl(meta);
73
73
  let url = (configured || '').trim();
74
74
  if (!url) {
75
- url = base ? `${base}/helloasso` : '';
75
+ // Default webhook endpoint (recommended): namespaced under /plugins
76
+ url = base ? `${base}/plugins/calendar-onekite/helloasso` : '';
76
77
  }
77
78
  if (url && url.startsWith('/') && base) {
78
79
  url = `${base}${url}`;
package/library.js CHANGED
@@ -107,10 +107,14 @@ Plugin.init = async function (params) {
107
107
  },
108
108
  type: ['application/json', 'application/*+json'],
109
109
  });
110
+ // Accept webhook on both legacy root path and namespaced plugin path.
111
+ // Some reverse proxies block unknown root paths, so /plugins/... is recommended.
110
112
  router.post('/helloasso', helloassoJson, helloassoWebhook.handler);
113
+ router.post('/plugins/calendar-onekite/helloasso', helloassoJson, helloassoWebhook.handler);
111
114
 
112
- // Optional: keep GET for simple health-checks without exposing processing.
115
+ // Optional: health checks
113
116
  router.get('/helloasso', (req, res) => res.json({ ok: true }));
117
+ router.get('/plugins/calendar-onekite/helloasso', (req, res) => res.json({ ok: true }));
114
118
 
115
119
  scheduler.start();
116
120
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-calendar-onekite",
3
- "version": "11.1.49",
3
+ "version": "11.1.50",
4
4
  "description": "FullCalendar-based equipment reservation workflow with admin approval & HelloAsso payment for NodeBB",
5
5
  "main": "library.js",
6
6
  "license": "MIT",
package/plugin.json CHANGED
@@ -27,5 +27,5 @@
27
27
  "acpScripts": [
28
28
  "public/admin.js"
29
29
  ],
30
- "version": "0.0.18"
30
+ "version": "0.0.19"
31
31
  }
package/public/client.js CHANGED
@@ -309,9 +309,23 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
309
309
  const isOwner = uidNow && ownerUid && uidNow === ownerUid;
310
310
  const showModeration = canModerate && isPending;
311
311
  const showCancel = isOwner && ['pending', 'awaiting_payment'].includes(status);
312
+ const paymentUrl = String((p && p.paymentUrl) || '');
313
+ const showPay = isOwner && status === 'awaiting_payment' && /^https?:\/\//i.test(paymentUrl);
312
314
  const buttons = {
313
315
  close: { label: 'Fermer', className: 'btn-secondary' },
314
316
  };
317
+ if (showPay) {
318
+ buttons.pay = {
319
+ label: 'Payer maintenant',
320
+ className: 'btn-primary',
321
+ callback: () => {
322
+ try {
323
+ window.open(paymentUrl, '_blank', 'noopener');
324
+ } catch (e) {}
325
+ return false;
326
+ },
327
+ };
328
+ }
315
329
  if (showCancel) {
316
330
  buttons.cancel = {
317
331
  label: 'Annuler',
@@ -345,8 +359,12 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
345
359
  label: 'Valider',
346
360
  className: 'btn-success',
347
361
  callback: async () => {
348
- const itemNames = Array.isArray(p.itemNames) && p.itemNames.length ? p.itemNames : String(itemsLabel || '').split(',').map(s => s.trim()).filter(Boolean);
349
- const itemsHtml = itemNames.map(n => `<li>${String(n).replace(/</g, '&lt;').replace(/>/g, '&gt;')}</li>`).join('');
362
+ const itemNames = Array.isArray(p.itemNames) && p.itemNames.length
363
+ ? p.itemNames
364
+ : (p.itemName ? [p.itemName] : []);
365
+ const itemsListHtml = itemNames.length
366
+ ? `<div class="mb-2"><strong>Matériel</strong><ul style="margin:0.25rem 0 0 1.1rem; padding:0;">${itemNames.map(n => `<li>${String(n).replace(/</g, '&lt;').replace(/>/g, '&gt;')}</li>`).join('')}</ul></div>`
367
+ : '';
350
368
  const opts = (() => {
351
369
  const out = [];
352
370
  for (let h = 7; h < 24; h++) {
@@ -355,8 +373,9 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
355
373
  }
356
374
  }
357
375
  return out;
358
- })().map(t => `<option value="${t}">${t}</option>`).join('');
376
+ })().map(t => `<option value="${t}" ${t === '07:00' ? 'selected' : ''}>${t}</option>`).join('');
359
377
  const html = `
378
+ ${itemsListHtml}
360
379
  <div class="mb-3">
361
380
  <label class="form-label">Note (incluse dans l'email)</label>
362
381
  <textarea class="form-control" id="onekite-admin-note" rows="3" placeholder="Matériel à récupérer à l'adresse : ..."></textarea>