nodebb-plugin-equipment-calendar 0.8.0 → 0.8.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/library.js CHANGED
@@ -60,20 +60,23 @@ function parseLocationMap(locationMapJson) {
60
60
 
61
61
  let haTokenCache = null; // { accessToken, refreshToken, expMs }
62
62
 
63
- async function getHelloAssoAccessToken(settings) {
63
+ async function getHelloAssoAccessToken(settings, opts = {}) {
64
64
  const now = Date.now();
65
- if (haTokenCache && haTokenCache.accessToken && haTokenCache.expMs && now < haTokenCache.expMs - 30_000) {
65
+ if (!opts.force && haTokenCache && haTokenCache.accessToken && haTokenCache.expMs && now < haTokenCache.expMs - 30_000) {
66
66
  return haTokenCache.accessToken;
67
67
  }
68
68
 
69
69
  const tokenKey = 'equipmentCalendar:ha:token';
70
+ if (opts.clearStored) {
71
+ try { await db.delete(tokenKey); } catch (e) {}
72
+ }
70
73
  let stored = null;
71
74
  try {
72
75
  stored = await db.getObject(tokenKey);
73
76
  } catch (e) {}
74
77
 
75
78
  // If refresh token exists and not expired locally, try refresh flow first
76
- const canRefresh = stored && stored.refresh_token;
79
+ const canRefresh = !opts.force && stored && stored.refresh_token;
77
80
  const useRefresh = canRefresh && stored.refresh_expires_at && now < parseInt(stored.refresh_expires_at, 10);
78
81
 
79
82
  const formBody = new URLSearchParams();
@@ -796,10 +799,19 @@ async function handleHelloAssoTest(req, res) {
796
799
  let count = 0;
797
800
 
798
801
  try {
799
- await getHelloAssoAccessToken(settings);
802
+ const force = String(req.query.force || '') === '1';
803
+ const clear = String(req.query.clear || '') === '1';
804
+ // force=1 skips in-memory cache and refresh_token; clear=1 wipes stored refresh token
805
+ haTokenCache = null;
806
+ await getHelloAssoAccessToken(settings, { force, clearStored: clear });
800
807
  const items = await fetchHelloAssoItems(settings);
801
808
  const list = Array.isArray(items) ? items : (Array.isArray(items.data) ? items.data : []);
802
809
  count = list.length;
810
+ const sampleItems = list.slice(0, 10).map(it => ({
811
+ id: String(it.id || it.itemId || it.reference || it.slug || it.name || '').trim(),
812
+ name: String(it.name || it.label || it.title || '').trim(),
813
+ rawName: String(it.name || it.label || it.title || it.id || '').trim(),
814
+ }));
803
815
  ok = true;
804
816
  message = `OK: token valide. Items récupérés: ${count}.`;
805
817
  } catch (e) {
@@ -813,6 +825,8 @@ async function handleHelloAssoTest(req, res) {
813
825
  message,
814
826
  count,
815
827
  settings,
828
+ sampleItems,
829
+ hasSampleItems: sampleItems && sampleItems.length > 0,
816
830
  });
817
831
  }
818
832
 
@@ -1368,6 +1382,10 @@ async function handleAdminSave(req, res) {
1368
1382
  approverGroup: String(req.body.approverGroup || DEFAULT_SETTINGS.approverGroup),
1369
1383
  notifyGroup: String(req.body.notifyGroup || DEFAULT_SETTINGS.notifyGroup),
1370
1384
  itemsJson: String(req.body.itemsJson || DEFAULT_SETTINGS.itemsJson),
1385
+ itemsSource: String(req.body.itemsSource || DEFAULT_SETTINGS.itemsSource),
1386
+ ha_itemsFormType: String(req.body.ha_itemsFormType || DEFAULT_SETTINGS.ha_itemsFormType),
1387
+ ha_itemsFormSlug: String(req.body.ha_itemsFormSlug || DEFAULT_SETTINGS.ha_itemsFormSlug),
1388
+ ha_locationMapJson: String(req.body.ha_locationMapJson || DEFAULT_SETTINGS.ha_locationMapJson),
1371
1389
  ha_clientId: String(req.body.ha_clientId || ''),
1372
1390
  ha_clientSecret: String(req.body.ha_clientSecret || ''),
1373
1391
  ha_organizationSlug: String(req.body.ha_organizationSlug || ''),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-equipment-calendar",
3
- "version": "0.8.0",
3
+ "version": "0.8.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
@@ -3,7 +3,6 @@
3
3
  "name": "Equipment Calendar",
4
4
  "description": "Calendar-based equipment reservations with group approvals and HelloAsso payments.",
5
5
  "url": "https://example.invalid",
6
- "library": "./library.js",
7
6
  "hooks": [
8
7
  {
9
8
  "hook": "static:app.load",
@@ -26,6 +25,6 @@
26
25
  "scripts": [
27
26
  "public/js/client.js"
28
27
  ],
29
- "version": "0.4.4",
28
+ "version": "0.4.8",
30
29
  "minver": "4.7.1"
31
30
  }
@@ -9,6 +9,11 @@
9
9
  </div>
10
10
 
11
11
  <div class="card card-body mt-3">
12
+ <div class="d-flex flex-wrap gap-2 mb-2">
13
+ <a class="btn btn-outline-primary" href="/admin/plugins/equipment-calendar/helloasso-test">Test (cache OK)</a>
14
+ <a class="btn btn-outline-primary" href="/admin/plugins/equipment-calendar/helloasso-test?force=1">Test (forcer nouveau token)</a>
15
+ <a class="btn btn-outline-danger" href="/admin/plugins/equipment-calendar/helloasso-test?force=1&clear=1" onclick="return confirm('Supprimer le token stocké et retester ?');">Vider token + retester</a>
16
+ </div>
12
17
  {{{ if ok }}}
13
18
  <div class="alert alert-success">{message}</div>
14
19
  {{{ else }}}
@@ -18,5 +23,32 @@
18
23
  <div class="small text-muted">
19
24
  Form: <code>{settings.ha_itemsFormType}</code> / <code>{settings.ha_itemsFormSlug}</code> — Orga: <code>{settings.ha_organizationSlug}</code>
20
25
  </div>
26
+ {{{ if hasSampleItems }}}
27
+ <div class="card card-body mt-3">
28
+ <div class="d-flex flex-wrap gap-2 mb-2">
29
+ <a class="btn btn-outline-primary" href="/admin/plugins/equipment-calendar/helloasso-test">Test (cache OK)</a>
30
+ <a class="btn btn-outline-primary" href="/admin/plugins/equipment-calendar/helloasso-test?force=1">Test (forcer nouveau token)</a>
31
+ <a class="btn btn-outline-danger" href="/admin/plugins/equipment-calendar/helloasso-test?force=1&clear=1" onclick="return confirm('Supprimer le token stocké et retester ?');">Vider token + retester</a>
32
+ </div>
33
+ <h5 class="mb-2">Aperçu (10 premiers articles)</h5>
34
+ <div class="table-responsive">
35
+ <table class="table table-striped align-middle">
36
+ <thead>
37
+ <tr>
38
+ <th>ID</th>
39
+ <th>Nom</th>
40
+ </tr>
41
+ </thead>
42
+ <tbody>
43
+ {{{ each sampleItems }}}
44
+ <tr>
45
+ <td><code>{sampleItems.id}</code></td>
46
+ <td>{sampleItems.rawName}</td>
47
+ </tr>
48
+ {{{ end }}}
49
+ </tbody>
50
+ </table>
51
+ </div>
21
52
  </div>
53
+ {{{ end }}}
22
54
  </div>