nodebb-plugin-onekite-calendar 1.0.10 → 1.0.11

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/api.js CHANGED
@@ -137,12 +137,18 @@ function buildHelloAssoItemName(baseLabel, itemNames, start, end) {
137
137
  const base = String(baseLabel || '').trim();
138
138
  const items = Array.isArray(itemNames) ? itemNames.map((s) => String(s || '').trim()).filter(Boolean) : [];
139
139
  const range = (start && end) ? ('Du ' + formatFR(start) + ' au ' + formatFR(end)) : '';
140
- const lines = [];
141
- if (base) lines.push(base);
142
- items.forEach((it) => lines.push('• ' + it));
143
- if (range) lines.push(range);
144
- if (!lines.length) lines.push('Réservation matériel');
145
- let out = lines.join('\n').trim();
140
+
141
+ // IMPORTANT:
142
+ // On the public HelloAsso checkout page, line breaks are not always rendered consistently.
143
+ // Build a single-line label using bullet separators.
144
+ let out = '';
145
+ if (base) out += base;
146
+ if (items.length) out += (out ? ' — ' : '') + items.map((it) => '• ' + it).join(' ');
147
+ if (range) out += (out ? ' — ' : '') + range;
148
+
149
+ out = String(out || '').trim();
150
+ if (!out) out = 'Réservation matériel';
151
+
146
152
  // HelloAsso constraint: itemName max 250 chars
147
153
  if (out.length > 250) {
148
154
  out = out.slice(0, 249).trimEnd() + '…';
package/lib/widgets.js CHANGED
@@ -137,9 +137,19 @@ widgets.renderTwoWeeksWidget = async function (data) {
137
137
  tip.style.display = 'none';
138
138
  }
139
139
 
140
- document.addEventListener('click', (e) => {
140
+ // Client-side escaping (the server-side helper is not in scope here)
141
+ function escapeHtml(s) {
142
+ return String(s || '')
143
+ .replace(/&/g, '&')
144
+ .replace(/</g, '&lt;')
145
+ .replace(/>/g, '&gt;')
146
+ .replace(/"/g, '&quot;')
147
+ .replace(/'/g, '&#39;');
148
+ }
149
+
150
+ document.addEventListener('pointerdown', (e) => {
141
151
  // Close when clicking outside an event
142
- if (!e.target || !e.target.closest || !e.target.closest('.fc-event')) {
152
+ if (!e.target || !e.target.closest || (!e.target.closest('.fc-event') && !e.target.closest('.onekite-cal-tooltip'))) {
143
153
  hideTip();
144
154
  }
145
155
  }, { passive: true });
@@ -229,6 +239,21 @@ widgets.renderTwoWeeksWidget = async function (data) {
229
239
  eventDidMount: function(info) {
230
240
  try {
231
241
  const ev = info.event;
242
+ // Improve centering for single-day dots by centering the harness,
243
+ // same visual behavior as rentals.
244
+ try {
245
+ const cls = (info.el && info.el.classList) ? info.el.classList : null;
246
+ const isSingle = cls && cls.contains('onekite-singleday');
247
+ const harness = info.el && info.el.closest ? info.el.closest('.fc-daygrid-event-harness') : null;
248
+ if (harness && harness.classList) {
249
+ if (isSingle) {
250
+ harness.classList.add('onekite-harness-dot');
251
+ } else {
252
+ harness.classList.remove('onekite-harness-dot');
253
+ }
254
+ }
255
+ } catch (e) {}
256
+
232
257
  const ep = ev.extendedProps || {};
233
258
  const title = (ep.itemNameLine || ep.title || ev.title || '').toString();
234
259
  const status = (ep.status || ep.type || '').toString();
@@ -243,22 +268,36 @@ widgets.renderTwoWeeksWidget = async function (data) {
243
268
  (status ? ('<div style="opacity:.75; margin-top:2px; font-size:.85em;">' + escapeHtml(status) + '</div>') : '');
244
269
 
245
270
  // Hover (desktop)
246
- info.el.addEventListener('mouseenter', (e) => {
271
+ info.el.addEventListener('pointerenter', () => {
272
+ // Only show on devices that actually hover
273
+ if (window.matchMedia && window.matchMedia('(hover: hover)').matches === false) return;
247
274
  setTipContent(html);
248
275
  const rect = info.el.getBoundingClientRect();
249
- showTipAt(rect.left + window.scrollX, rect.top + window.scrollY);
276
+ showTipAt(rect.left + rect.width / 2 + window.scrollX, rect.top + window.scrollY);
250
277
  }, { passive: true });
251
- info.el.addEventListener('mouseleave', hideTip, { passive: true });
278
+ info.el.addEventListener('pointerleave', hideTip, { passive: true });
252
279
 
253
- // Tap/click (mobile)
254
- info.el.addEventListener('click', (e) => {
255
- e.preventDefault();
256
- e.stopPropagation();
280
+ // Tap (mobile) / click (fallback)
281
+ const openTipFromPoint = (pt) => {
257
282
  setTipContent(html);
258
- const pt = (e.touches && e.touches[0]) ? e.touches[0] : e;
259
283
  showTipAt((pt.clientX || 0) + window.scrollX, (pt.clientY || 0) + window.scrollY);
284
+ };
285
+
286
+ info.el.addEventListener('pointerdown', (e) => {
287
+ // On touch devices, FullCalendar can swallow click events during swipe;
288
+ // pointerdown is more reliable.
289
+ if (e && e.preventDefault) e.preventDefault();
290
+ if (e && e.stopPropagation) e.stopPropagation();
291
+ openTipFromPoint(e);
260
292
  });
261
- } catch (e) {}
293
+
294
+ info.el.addEventListener('touchstart', (e) => {
295
+ const t = e.touches && e.touches[0];
296
+ if (!t) return;
297
+ if (e && e.stopPropagation) e.stopPropagation();
298
+ openTipFromPoint(t);
299
+ }, { passive: true });
300
+ } catch (e) {}
262
301
  },
263
302
  });
264
303
 
@@ -328,10 +367,15 @@ widgets.renderTwoWeeksWidget = async function (data) {
328
367
  .onekite-twoweeks .fc .fc-event.onekite-multiday .fc-event-time { display:none !important; }
329
368
 
330
369
  .onekite-twoweeks .fc .fc-daygrid-event-harness { margin-top: 2px; }
370
+ /* Center single-day dots inside the day cell (match rentals) */
371
+ .onekite-twoweeks .fc .fc-daygrid-event-harness.onekite-harness-dot {
372
+ display: flex;
373
+ justify-content: center;
374
+ }
331
375
  .onekite-twoweeks .fc .fc-daygrid-event { padding: 0 !important; }
332
376
  .onekite-twoweeks .fc .fc-event-main { color: inherit; }
333
377
  .onekite-twoweeks .fc .fc-event-title { display:none; }
334
- .onekite-dot-wrap { display:flex; align-items:center; justify-content:center; width: auto; }
378
+ .onekite-dot-wrap { display:flex; align-items:center; justify-content:center; width: 100%; }
335
379
  .onekite-dot { width: 10px; height: 10px; border-radius: 999px; display:inline-block; }
336
380
  .onekite-pill-spacer { display:block; height: 10px; line-height: 10px; }
337
381
  .onekite-cal-tooltip {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-onekite-calendar",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
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
@@ -39,5 +39,5 @@
39
39
  "acpScripts": [
40
40
  "public/admin.js"
41
41
  ],
42
- "version": "1.0.10"
42
+ "version": "1.0.11"
43
43
  }