nodebb-plugin-onekite-calendar 2.0.39 → 2.0.40
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/CHANGELOG.md +4 -0
- package/lib/group-helpers.js +31 -0
- package/lib/realtime.js +0 -4
- package/lib/widgets.js +13 -32
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/public/admin.js +17 -33
- package/public/client.js +24 -31
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.0.38
|
|
2
|
+
- Refactor : factorisation du code client (helpers headers/CSRF) et simplification du widget.
|
|
3
|
+
- Widget : suppression des fallbacks de polling/visibilitychange (mise à jour via sockets uniquement) + conservation du no-cache pour éviter les 304.
|
|
4
|
+
|
|
1
5
|
## 2.0.37
|
|
2
6
|
- Les rappels validateurs et notifications d’expiration ne sont envoyés qu’aux membres du/des groupe(s) "personnes notifiées" (notifyGroups).
|
|
3
7
|
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const groups = require.main.require('./src/groups');
|
|
4
|
+
|
|
5
|
+
async function getGroupNameBySlug(slug) {
|
|
6
|
+
const fn = groups && groups.getGroupNameByGroupSlug;
|
|
7
|
+
if (typeof fn !== 'function') return null;
|
|
8
|
+
|
|
9
|
+
const id = String(slug || '').trim();
|
|
10
|
+
if (!id) return null;
|
|
11
|
+
|
|
12
|
+
try {
|
|
13
|
+
const maybe = fn(id);
|
|
14
|
+
if (maybe && typeof maybe.then === 'function') {
|
|
15
|
+
return await maybe;
|
|
16
|
+
}
|
|
17
|
+
if (typeof maybe === 'string') {
|
|
18
|
+
return maybe;
|
|
19
|
+
}
|
|
20
|
+
} catch (e) {
|
|
21
|
+
// fall through to callback form
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return await new Promise((resolve) => {
|
|
25
|
+
try {
|
|
26
|
+
fn(id, (err, name) => resolve(err ? null : name));
|
|
27
|
+
} catch (e) {
|
|
28
|
+
resolve(null);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
package/lib/realtime.js
CHANGED
|
@@ -24,10 +24,6 @@ function emitCalendarUpdated(payload) {
|
|
|
24
24
|
|
|
25
25
|
// New event name (generic).
|
|
26
26
|
server.sockets.emit('event:calendar-onekite.calendarUpdated', payload || {});
|
|
27
|
-
|
|
28
|
-
// Backwards compatible event name (older clients only listened to this).
|
|
29
|
-
// Keep it emitted for *any* calendar mutation, not just reservation status.
|
|
30
|
-
server.sockets.emit('event:calendar-onekite.reservationUpdated', payload || {});
|
|
31
27
|
} catch (e) {}
|
|
32
28
|
}
|
|
33
29
|
|
package/lib/widgets.js
CHANGED
|
@@ -392,19 +392,19 @@ dateClick: function() { window.location.href = calUrl; },
|
|
|
392
392
|
calendar.render();
|
|
393
393
|
|
|
394
394
|
// Real-time refresh for the widget (same server events as the main calendar)
|
|
395
|
+
// We intentionally rely on sockets only (no periodic polling fallback):
|
|
396
|
+
// - keeps the widget lightweight
|
|
397
|
+
// - avoids pointless API traffic
|
|
398
|
+
// - updates are already broadcast server-side across NodeBB instances
|
|
395
399
|
try {
|
|
396
400
|
// Debounce per widget instance
|
|
397
401
|
let tRefetch = null;
|
|
398
402
|
const refetch = function () {
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
tRefetch =
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
calendar.refetchEvents();
|
|
405
|
-
} catch (e) {}
|
|
406
|
-
}, 200);
|
|
407
|
-
} catch (e) {}
|
|
403
|
+
if (tRefetch) return;
|
|
404
|
+
tRefetch = setTimeout(() => {
|
|
405
|
+
tRefetch = null;
|
|
406
|
+
try { calendar.refetchEvents(); } catch (e) {}
|
|
407
|
+
}, 200);
|
|
408
408
|
};
|
|
409
409
|
|
|
410
410
|
// Register refetcher and bind socket listeners once per page
|
|
@@ -414,34 +414,15 @@ dateClick: function() { window.location.href = calUrl; },
|
|
|
414
414
|
if (!window.__oneKiteWidgetSocketBound && typeof socket !== 'undefined' && socket && typeof socket.on === 'function') {
|
|
415
415
|
window.__oneKiteWidgetSocketBound = true;
|
|
416
416
|
const triggerAll = function () {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
422
|
-
} catch (e) {}
|
|
417
|
+
const list = window.__oneKiteWidgetRefetchers || [];
|
|
418
|
+
for (let i = 0; i < list.length; i += 1) {
|
|
419
|
+
try { list[i](); } catch (e) {}
|
|
420
|
+
}
|
|
423
421
|
};
|
|
424
422
|
socket.on('event:calendar-onekite.calendarUpdated', triggerAll);
|
|
425
|
-
socket.on('event:calendar-onekite.reservationUpdated', triggerAll);
|
|
426
423
|
}
|
|
427
424
|
} catch (e) {}
|
|
428
425
|
|
|
429
|
-
// Fallback refresh: in case sockets are unavailable or blocked by proxies,
|
|
430
|
-
// refetch periodically and when the tab becomes visible.
|
|
431
|
-
try {
|
|
432
|
-
window.__oneKiteWidgetIntervals = window.__oneKiteWidgetIntervals || {};
|
|
433
|
-
if (!window.__oneKiteWidgetIntervals[containerId]) {
|
|
434
|
-
window.__oneKiteWidgetIntervals[containerId] = setInterval(() => {
|
|
435
|
-
try { calendar.refetchEvents(); } catch (e) {}
|
|
436
|
-
}, 60000);
|
|
437
|
-
}
|
|
438
|
-
document.addEventListener('visibilitychange', () => {
|
|
439
|
-
try {
|
|
440
|
-
if (!document.hidden) calendar.refetchEvents();
|
|
441
|
-
} catch (e) {}
|
|
442
|
-
}, { passive: true });
|
|
443
|
-
} catch (e) {}
|
|
444
|
-
|
|
445
426
|
// Mobile swipe (left/right) to navigate weeks
|
|
446
427
|
try {
|
|
447
428
|
let touchStartX = null;
|
package/package.json
CHANGED
package/plugin.json
CHANGED
package/public/admin.js
CHANGED
|
@@ -109,48 +109,32 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
async function fetchJson(url, opts) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
116
|
-
const token =
|
|
112
|
+
const getCsrfToken = () => {
|
|
113
|
+
try {
|
|
114
|
+
return (
|
|
117
115
|
(window.config && (window.config.csrf_token || window.config.csrfToken)) ||
|
|
118
116
|
(window.ajaxify && window.ajaxify.data && window.ajaxify.data.csrf_token) ||
|
|
119
117
|
(document.querySelector('meta[name="csrf-token"]') && document.querySelector('meta[name="csrf-token"]').getAttribute('content')) ||
|
|
120
118
|
(document.querySelector('meta[name="csrf_token"]') && document.querySelector('meta[name="csrf_token"]').getAttribute('content')) ||
|
|
121
119
|
(typeof app !== 'undefined' && app && app.csrfToken) ||
|
|
122
|
-
null
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
null
|
|
121
|
+
);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const headers = { 'Content-Type': 'application/json' };
|
|
128
|
+
const token = getCsrfToken();
|
|
129
|
+
if (token) headers['x-csrf-token'] = token;
|
|
130
|
+
|
|
131
|
+
const res = await fetch(url, {
|
|
132
|
+
credentials: 'same-origin',
|
|
133
|
+
headers,
|
|
126
134
|
...opts,
|
|
127
135
|
});
|
|
128
136
|
|
|
129
|
-
|
|
130
137
|
if (!res.ok) {
|
|
131
|
-
// NodeBB versions differ: some expose admin APIs under /api/admin instead of /api/v3/admin
|
|
132
|
-
if (res.status === 404 && typeof url === 'string' && url.includes('/api/v3/admin/')) {
|
|
133
|
-
const altUrl = url.replace('/api/v3/admin/', '/api/admin/');
|
|
134
|
-
const res2 = await fetch(altUrl, {
|
|
135
|
-
credentials: 'same-origin',
|
|
136
|
-
headers: (() => {
|
|
137
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
138
|
-
const token =
|
|
139
|
-
(window.config && (window.config.csrf_token || window.config.csrfToken)) ||
|
|
140
|
-
(window.ajaxify && window.ajaxify.data && window.ajaxify.data.csrf_token) ||
|
|
141
|
-
(document.querySelector('meta[name="csrf-token"]') && document.querySelector('meta[name="csrf-token"]').getAttribute('content')) ||
|
|
142
|
-
(document.querySelector('meta[name="csrf_token"]') && document.querySelector('meta[name="csrf_token"]').getAttribute('content')) ||
|
|
143
|
-
(typeof app !== 'undefined' && app && app.csrfToken) ||
|
|
144
|
-
null;
|
|
145
|
-
if (token) headers['x-csrf-token'] = token;
|
|
146
|
-
return headers;
|
|
147
|
-
})(),
|
|
148
|
-
...opts,
|
|
149
|
-
});
|
|
150
|
-
if (res2.ok) {
|
|
151
|
-
return await res2.json();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
138
|
const text = await res.text().catch(() => '');
|
|
155
139
|
throw new Error(`${res.status} ${text}`);
|
|
156
140
|
}
|
package/public/client.js
CHANGED
|
@@ -138,6 +138,28 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
|
|
|
138
138
|
.replace(/'/g, ''');
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
function getCsrfToken() {
|
|
142
|
+
try {
|
|
143
|
+
return (
|
|
144
|
+
(window.config && (window.config.csrf_token || window.config.csrfToken)) ||
|
|
145
|
+
(window.ajaxify && window.ajaxify.data && window.ajaxify.data.csrf_token) ||
|
|
146
|
+
(document.querySelector('meta[name="csrf-token"]') && document.querySelector('meta[name="csrf-token"]').getAttribute('content')) ||
|
|
147
|
+
(document.querySelector('meta[name="csrf_token"]') && document.querySelector('meta[name="csrf_token"]').getAttribute('content')) ||
|
|
148
|
+
(typeof app !== 'undefined' && app && app.csrfToken) ||
|
|
149
|
+
null
|
|
150
|
+
);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function jsonHeaders(extra) {
|
|
157
|
+
const headers = Object.assign({ 'Content-Type': 'application/json' }, extra || {});
|
|
158
|
+
const token = getCsrfToken();
|
|
159
|
+
if (token) headers['x-csrf-token'] = token;
|
|
160
|
+
return headers;
|
|
161
|
+
}
|
|
162
|
+
|
|
141
163
|
function pad2(n) { return String(n).padStart(2, '0'); }
|
|
142
164
|
|
|
143
165
|
function toDateInputValue(d) {
|
|
@@ -502,18 +524,7 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
|
|
|
502
524
|
async function fetchJson(url, opts) {
|
|
503
525
|
const res = await fetch(url, {
|
|
504
526
|
credentials: 'same-origin',
|
|
505
|
-
headers: (()
|
|
506
|
-
const headers = { 'Content-Type': 'application/json' };
|
|
507
|
-
const token =
|
|
508
|
-
(window.config && (window.config.csrf_token || window.config.csrfToken)) ||
|
|
509
|
-
(window.ajaxify && window.ajaxify.data && window.ajaxify.data.csrf_token) ||
|
|
510
|
-
(document.querySelector('meta[name="csrf-token"]') && document.querySelector('meta[name="csrf-token"]').getAttribute('content')) ||
|
|
511
|
-
(document.querySelector('meta[name="csrf_token"]') && document.querySelector('meta[name="csrf_token"]').getAttribute('content')) ||
|
|
512
|
-
(typeof app !== 'undefined' && app && app.csrfToken) ||
|
|
513
|
-
null;
|
|
514
|
-
if (token) headers['x-csrf-token'] = token;
|
|
515
|
-
return headers;
|
|
516
|
-
})(),
|
|
527
|
+
headers: jsonHeaders((opts && opts.headers) || {}),
|
|
517
528
|
...opts,
|
|
518
529
|
});
|
|
519
530
|
if (!res.ok) {
|
|
@@ -563,19 +574,7 @@ define('forum/calendar-onekite', ['alerts', 'bootbox', 'hooks'], function (alert
|
|
|
563
574
|
try {
|
|
564
575
|
res = await fetch(url, {
|
|
565
576
|
credentials: 'same-origin',
|
|
566
|
-
headers: (
|
|
567
|
-
// reuse csrf header builder (fetchJson) by calling it indirectly
|
|
568
|
-
const base = { 'Content-Type': 'application/json' };
|
|
569
|
-
const token =
|
|
570
|
-
(window.config && (window.config.csrf_token || window.config.csrfToken)) ||
|
|
571
|
-
(window.ajaxify && window.ajaxify.data && window.ajaxify.data.csrf_token) ||
|
|
572
|
-
(document.querySelector('meta[name="csrf-token"]') && document.querySelector('meta[name="csrf-token"]').getAttribute('content')) ||
|
|
573
|
-
(document.querySelector('meta[name="csrf_token"]') && document.querySelector('meta[name="csrf_token"]').getAttribute('content')) ||
|
|
574
|
-
(typeof app !== 'undefined' && app && app.csrfToken) ||
|
|
575
|
-
null;
|
|
576
|
-
if (token) base['x-csrf-token'] = token;
|
|
577
|
-
return Object.assign(base, headers);
|
|
578
|
-
})(),
|
|
577
|
+
headers: jsonHeaders(headers),
|
|
579
578
|
...opts,
|
|
580
579
|
});
|
|
581
580
|
} catch (e) {
|
|
@@ -2383,12 +2382,6 @@ try {
|
|
|
2383
2382
|
scheduleRefetch(cal);
|
|
2384
2383
|
} catch (e) {}
|
|
2385
2384
|
});
|
|
2386
|
-
socket.on('event:calendar-onekite.reservationUpdated', function () {
|
|
2387
|
-
try {
|
|
2388
|
-
const cal = window.oneKiteCalendar;
|
|
2389
|
-
scheduleRefetch(cal);
|
|
2390
|
-
} catch (e) {}
|
|
2391
|
-
});
|
|
2392
2385
|
}
|
|
2393
2386
|
} catch (e) {}
|
|
2394
2387
|
|