nodebb-plugin-calendar-onekite 11.1.46 → 11.1.47
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 +18 -1
- package/lib/api.js +28 -3
- package/lib/helloasso.js +6 -0
- package/package.json +1 -1
- package/public/admin.js +6 -3
- package/public/client.js +4 -2
- package/templates/emails/calendar-onekite_approved.tpl +6 -1
package/lib/admin.js
CHANGED
|
@@ -25,7 +25,8 @@ async function sendEmail(template, toEmail, subject, data) {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
if (emailer.send.length === 3) {
|
|
28
|
-
|
|
28
|
+
const dataWithSubject = Object.assign({}, data || {}, subject ? { subject } : {});
|
|
29
|
+
await emailer.send(template, toEmail, dataWithSubject);
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
await emailer.send(template, toEmail, subject, data);
|
|
@@ -35,6 +36,19 @@ async function sendEmail(template, toEmail, subject, data) {
|
|
|
35
36
|
}
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
function normalizeCallbackUrl(configured, meta) {
|
|
40
|
+
const base = (meta && meta.config && (meta.config.url || meta.config['url'])) ? (meta.config.url || meta.config['url']) : '';
|
|
41
|
+
let url = (configured || '').trim();
|
|
42
|
+
if (!url) {
|
|
43
|
+
url = base ? `${base}/helloasso` : '';
|
|
44
|
+
}
|
|
45
|
+
if (url && url.startsWith('/') && base) {
|
|
46
|
+
url = `${base}${url}`;
|
|
47
|
+
}
|
|
48
|
+
return url;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
38
52
|
const dbLayer = require('./db');
|
|
39
53
|
const helloasso = require('./helloasso');
|
|
40
54
|
|
|
@@ -89,6 +103,9 @@ admin.approveReservation = async function (req, res) {
|
|
|
89
103
|
clientId: settings.helloassoClientId,
|
|
90
104
|
clientSecret: settings.helloassoClientSecret,
|
|
91
105
|
});
|
|
106
|
+
if (!token) {
|
|
107
|
+
console.warn('[calendar-onekite] HelloAsso access token not obtained (approve ACP)', { rid: r && r.rid });
|
|
108
|
+
}
|
|
92
109
|
|
|
93
110
|
let paymentUrl = null;
|
|
94
111
|
if (token) {
|
package/lib/api.js
CHANGED
|
@@ -27,8 +27,10 @@ async function sendEmail(template, toEmail, subject, data) {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
// Some builds: (template, email, data)
|
|
30
|
+
// In that case, subject is expected inside `data.subject`.
|
|
30
31
|
if (emailer.send.length === 3) {
|
|
31
|
-
|
|
32
|
+
const dataWithSubject = Object.assign({}, data || {}, subject ? { subject } : {});
|
|
33
|
+
await emailer.send(template, toEmail, dataWithSubject);
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
// Fallback: try 4-args anyway
|
|
@@ -41,6 +43,20 @@ async function sendEmail(template, toEmail, subject, data) {
|
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
function normalizeCallbackUrl(configured, meta) {
|
|
47
|
+
const base = (meta && meta.config && (meta.config.url || meta.config['url'])) ? (meta.config.url || meta.config['url']) : '';
|
|
48
|
+
let url = (configured || '').trim();
|
|
49
|
+
if (!url) {
|
|
50
|
+
url = base ? `${base}/helloasso` : '';
|
|
51
|
+
}
|
|
52
|
+
// If relative, prefix with forum base url
|
|
53
|
+
if (url && url.startsWith('/') && base) {
|
|
54
|
+
url = `${base}${url}`;
|
|
55
|
+
}
|
|
56
|
+
return url;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
44
60
|
function overlap(aStart, aEnd, bStart, bEnd) {
|
|
45
61
|
return aStart < bEnd && bStart < aEnd;
|
|
46
62
|
}
|
|
@@ -168,6 +184,9 @@ api.getItems = async function (req, res) {
|
|
|
168
184
|
clientId: settings.helloassoClientId,
|
|
169
185
|
clientSecret: settings.helloassoClientSecret,
|
|
170
186
|
});
|
|
187
|
+
if (!token) {
|
|
188
|
+
console.warn('[calendar-onekite] HelloAsso access token not obtained (approve API)', { rid });
|
|
189
|
+
}
|
|
171
190
|
|
|
172
191
|
if (!token) {
|
|
173
192
|
return res.json([]);
|
|
@@ -321,11 +340,17 @@ api.approveReservation = async function (req, res) {
|
|
|
321
340
|
formType: settings2.helloassoFormType,
|
|
322
341
|
formSlug: settings2.helloassoFormSlug,
|
|
323
342
|
// r.total is stored as an estimated total in euros; HelloAsso expects cents.
|
|
324
|
-
totalAmount:
|
|
343
|
+
totalAmount: (() => {
|
|
344
|
+
const cents = Math.max(0, Math.round((Number(r.total) || 0) * 100));
|
|
345
|
+
if (!cents) {
|
|
346
|
+
console.warn('[calendar-onekite] HelloAsso totalAmount is 0 (approve API)', { rid, total: r.total });
|
|
347
|
+
}
|
|
348
|
+
return cents;
|
|
349
|
+
})(),
|
|
325
350
|
payerEmail: payer && payer.email ? payer.email : '',
|
|
326
351
|
// By default, point to the forum base url so the webhook hits this NodeBB instance.
|
|
327
352
|
// Can be overridden via ACP setting `helloassoCallbackUrl`.
|
|
328
|
-
callbackUrl: (settings2.helloassoCallbackUrl
|
|
353
|
+
callbackUrl: normalizeCallbackUrl(settings2.helloassoCallbackUrl, meta),
|
|
329
354
|
itemName: 'Réservation matériel OneKite',
|
|
330
355
|
containsDonation: false,
|
|
331
356
|
metadata: { reservationId: String(rid) },
|
package/lib/helloasso.js
CHANGED
|
@@ -194,9 +194,15 @@ async function createCheckoutIntent({ env, token, organizationSlug, formType, fo
|
|
|
194
194
|
if (status >= 200 && status < 300 && json) {
|
|
195
195
|
return json.redirectUrl || json.checkoutUrl || json.url || null;
|
|
196
196
|
}
|
|
197
|
+
// Log the error payload to help diagnose configuration issues (slug, env, urls, amount, etc.)
|
|
198
|
+
try {
|
|
199
|
+
// eslint-disable-next-line no-console
|
|
200
|
+
console.warn('[calendar-onekite] HelloAsso checkout-intent failed', { status, json });
|
|
201
|
+
} catch (e) { /* ignore */ }
|
|
197
202
|
return null;
|
|
198
203
|
}
|
|
199
204
|
|
|
205
|
+
|
|
200
206
|
module.exports = {
|
|
201
207
|
getAccessToken,
|
|
202
208
|
listItems,
|
package/package.json
CHANGED
package/public/admin.js
CHANGED
|
@@ -77,7 +77,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
77
77
|
for (const r of list) {
|
|
78
78
|
const created = r.createdAt ? fmtFR(r.createdAt) : '';
|
|
79
79
|
const itemNames = Array.isArray(r.itemNames) && r.itemNames.length ? r.itemNames : [r.itemName || r.itemId].filter(Boolean);
|
|
80
|
-
const itemsHtml = itemNames.map(n => `<
|
|
80
|
+
const itemsHtml = `<ul style="margin: 0 0 10px 18px;">${itemNames.map(n => `<li>${escapeHtml(String(n))}</li>`).join('')}</ul>`;
|
|
81
81
|
const div = document.createElement('div');
|
|
82
82
|
div.className = 'list-group-item';
|
|
83
83
|
div.innerHTML = `
|
|
@@ -107,9 +107,12 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
107
107
|
});
|
|
108
108
|
|
|
109
109
|
approveBtn.addEventListener('click', async () => {
|
|
110
|
+
const itemNamesModal = Array.isArray(r.itemNames) && r.itemNames.length ? r.itemNames : [r.itemName || r.itemId].filter(Boolean);
|
|
111
|
+
const itemsHtmlModal = `<ul style="margin: 0 0 10px 18px;">${itemNamesModal.map(n => `<li>${escapeHtml(String(n))}</li>`).join('')}</ul>`;
|
|
112
|
+
|
|
110
113
|
const opts = (() => {
|
|
111
114
|
const out = [];
|
|
112
|
-
for (let h =
|
|
115
|
+
for (let h = 7; h < 24; h++) {
|
|
113
116
|
for (let m = 0; m < 60; m += 5) {
|
|
114
117
|
out.push(`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`);
|
|
115
118
|
}
|
|
@@ -162,7 +165,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
162
165
|
function timeOptions(stepMinutes) {
|
|
163
166
|
const step = stepMinutes || 5;
|
|
164
167
|
const out = [];
|
|
165
|
-
for (let h =
|
|
168
|
+
for (let h = 7; h < 24; h++) {
|
|
166
169
|
for (let m = 0; m < 60; m += step) {
|
|
167
170
|
const hh = String(h).padStart(2, '0');
|
|
168
171
|
const mm = String(m).padStart(2, '0');
|
package/public/client.js
CHANGED
|
@@ -339,9 +339,11 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
|
|
|
339
339
|
label: 'Valider',
|
|
340
340
|
className: 'btn-success',
|
|
341
341
|
callback: async () => {
|
|
342
|
+
const itemNames = Array.isArray(p.itemNames) && p.itemNames.length ? p.itemNames : String(itemsLabel || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
343
|
+
const itemsHtml = itemNames.map(n => `<li>${String(n).replace(/</g, '<').replace(/>/g, '>')}</li>`).join('');
|
|
342
344
|
const opts = (() => {
|
|
343
345
|
const out = [];
|
|
344
|
-
for (let h =
|
|
346
|
+
for (let h = 7; h < 24; h++) {
|
|
345
347
|
for (let m = 0; m < 60; m += 5) {
|
|
346
348
|
out.push(`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`);
|
|
347
349
|
}
|
|
@@ -416,4 +418,4 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
|
|
|
416
418
|
return {
|
|
417
419
|
init,
|
|
418
420
|
};
|
|
419
|
-
});
|
|
421
|
+
});
|
|
@@ -19,5 +19,10 @@
|
|
|
19
19
|
<!-- ENDIF pickupTime -->
|
|
20
20
|
|
|
21
21
|
<!-- IF paymentUrl -->
|
|
22
|
-
<p
|
|
22
|
+
<p>
|
|
23
|
+
<a href="{paymentUrl}" style="display:inline-block;padding:12px 18px;border-radius:6px;text-decoration:none;border:1px solid #333;">
|
|
24
|
+
Payer maintenant
|
|
25
|
+
</a>
|
|
26
|
+
</p>
|
|
27
|
+
<p style="font-size: 12px; color: #666;">Si le bouton ne fonctionne pas, utilisez ce lien : <a href="{paymentUrl}">{paymentUrl}</a></p>
|
|
23
28
|
<!-- ENDIF paymentUrl -->
|