nodebb-plugin-onekite-calendar 2.0.85 → 2.0.87

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
@@ -367,9 +367,9 @@ admin.listGroups = async function (req, res) {
367
367
  const Groups = require.main.require('./src/groups');
368
368
  const q = String((req.query && req.query.q) || '').trim().toLowerCase();
369
369
  const names = await Groups.getGroups('groups:createtime', 0, 500);
370
- const filtered = q
371
- ? (names || []).filter(n => n && String(n).toLowerCase().includes(q))
372
- : (names || []).filter(Boolean);
370
+ const filtered = (names || [])
371
+ .filter(n => n && !Groups.isPrivilegeGroup(n))
372
+ .filter(n => !q || String(n).toLowerCase().includes(q));
373
373
  res.json(filtered.slice(0, 100));
374
374
  } catch (e) {
375
375
  res.json([]);
package/lib/api.js CHANGED
@@ -1192,8 +1192,15 @@ api.getItems = async function (req, res) {
1192
1192
  maint = new Set((ids || []).map(String));
1193
1193
  } catch (e) {}
1194
1194
 
1195
+ const itemIds = normalized.map((it) => String(it.id));
1196
+ let locations = {};
1197
+ try {
1198
+ locations = await dbLayer.getMaintenanceLocations(itemIds);
1199
+ } catch (e) {}
1200
+
1195
1201
  const out = normalized.map((it) => Object.assign({}, it, {
1196
1202
  maintenance: maint.has(String(it.id)),
1203
+ location: locations[String(it.id)] || '',
1197
1204
  }));
1198
1205
 
1199
1206
  res.json(out);
@@ -1963,15 +1970,27 @@ api.setMaintenance = async function (req, res) {
1963
1970
  if (!ok) return res.status(403).json({ error: 'not-allowed' });
1964
1971
  const itemId = String(req.params.itemId || '').trim();
1965
1972
  if (!itemId) return res.status(400).json({ error: 'missing-itemId' });
1966
- const enabled = !!(req.body && (req.body.enabled === true || req.body.enabled === '1' || req.body.enabled === 1));
1967
- await dbLayer.setItemMaintenance(itemId, enabled);
1968
- await auditLog(enabled ? 'maintenance_on' : 'maintenance_off', uid, {
1969
- targetType: 'item',
1970
- targetId: itemId,
1971
- });
1972
- // Maintenance impacts availability; ask clients to refetch.
1973
- realtime.emitCalendarUpdated({ kind: 'maintenance', action: enabled ? 'on' : 'off', itemId });
1974
- return res.json({ ok: true, itemId, enabled });
1973
+
1974
+ const hasEnabled = req.body && 'enabled' in req.body;
1975
+ const hasLocation = req.body && 'location' in req.body;
1976
+ if (!hasEnabled && !hasLocation) return res.status(400).json({ error: 'missing-fields' });
1977
+
1978
+ if (hasLocation) {
1979
+ await dbLayer.setMaintenanceLocation(itemId, String(req.body.location || ''));
1980
+ }
1981
+
1982
+ if (hasEnabled) {
1983
+ const enabled = !!(req.body.enabled === true || req.body.enabled === '1' || req.body.enabled === 1);
1984
+ await dbLayer.setItemMaintenance(itemId, enabled);
1985
+ await auditLog(enabled ? 'maintenance_on' : 'maintenance_off', uid, {
1986
+ targetType: 'item',
1987
+ targetId: itemId,
1988
+ });
1989
+ // Maintenance impacts availability; ask clients to refetch.
1990
+ realtime.emitCalendarUpdated({ kind: 'maintenance', action: enabled ? 'on' : 'off', itemId });
1991
+ }
1992
+
1993
+ return res.json({ ok: true, itemId });
1975
1994
  };
1976
1995
 
1977
1996
  // Bulk toggle: enable/disable maintenance for ALL catalog items.
package/lib/db.js CHANGED
@@ -16,6 +16,7 @@ const KEY_OUTING_OBJ = (oid) => `calendar-onekite:outings:${oid}`;
16
16
 
17
17
  // Maintenance (simple ON/OFF per item, no dates)
18
18
  const KEY_MAINTENANCE_ZSET = 'calendar-onekite:maintenance:itemIds';
19
+ const KEY_MAINTENANCE_META = (itemId) => `calendar-onekite:maintenance:meta:${itemId}`;
19
20
 
20
21
  // Audit log (partitioned by year)
21
22
  const KEY_AUDIT_ZSET = (year) => `calendar-onekite:audit:${year}`;
@@ -103,6 +104,27 @@ async function setItemMaintenance(itemId, enabled) {
103
104
  }
104
105
  }
105
106
 
107
+ async function getMaintenanceLocations(itemIds) {
108
+ if (!Array.isArray(itemIds) || !itemIds.length) return {};
109
+ const keys = itemIds.map((id) => KEY_MAINTENANCE_META(String(id)));
110
+ let metas = [];
111
+ try {
112
+ metas = await db.getObjects(keys);
113
+ } catch (e) {}
114
+ const result = {};
115
+ itemIds.forEach((id, i) => {
116
+ const meta = metas && metas[i];
117
+ result[String(id)] = (meta && meta.location) ? String(meta.location) : '';
118
+ });
119
+ return result;
120
+ }
121
+
122
+ async function setMaintenanceLocation(itemId, location) {
123
+ const id = String(itemId || '').trim();
124
+ if (!id) return;
125
+ await db.setObjectField(KEY_MAINTENANCE_META(id), 'location', String(location || '').trim());
126
+ }
127
+
106
128
  async function setAllMaintenance(enabled, itemIds) {
107
129
  // Clear set first (fast)
108
130
  await db.delete(KEY_MAINTENANCE_ZSET);
@@ -242,6 +264,8 @@ module.exports = {
242
264
  isItemInMaintenance,
243
265
  setItemMaintenance,
244
266
  setAllMaintenance,
267
+ getMaintenanceLocations,
268
+ setMaintenanceLocation,
245
269
 
246
270
  // Audit
247
271
  addAuditEntry,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-onekite-calendar",
3
- "version": "2.0.85",
3
+ "version": "2.0.87",
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/public/admin.js CHANGED
@@ -1518,15 +1518,17 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
1518
1518
  const id = String(it.id);
1519
1519
  const name = String(it.name || '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1520
1520
  const checked = it.maintenance ? 'checked' : '';
1521
+ const location = String(it.location || '').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
1521
1522
  return `<tr data-itemid="${id}">
1522
1523
  <td>${name}</td>
1524
+ <td><input type="text" class="form-control form-control-sm onekite-maint-location" value="${location}" placeholder="Emplacement..." style="min-width:180px;"></td>
1523
1525
  <td>
1524
1526
  <div class="form-check form-switch">
1525
1527
  <input class="form-check-input onekite-maint-toggle" type="checkbox" ${checked} />
1526
1528
  </div>
1527
1529
  </td>
1528
1530
  </tr>`;
1529
- }).join('') || '<tr><td colspan="2" class="text-muted">Aucun matériel.</td></tr>';
1531
+ }).join('') || '<tr><td colspan="3" class="text-muted">Aucun matériel.</td></tr>';
1530
1532
  }
1531
1533
 
1532
1534
  async function refreshMaintenance() {
@@ -1585,6 +1587,33 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
1585
1587
  showAlert('error', 'Impossible de modifier la maintenance.');
1586
1588
  }
1587
1589
  });
1590
+
1591
+ maintTableBody.addEventListener('input', (ev) => {
1592
+ const el = ev && ev.target;
1593
+ if (!el || !el.classList || !el.classList.contains('onekite-maint-location')) return;
1594
+ const tr = el.closest('tr');
1595
+ const itemId = tr ? tr.getAttribute('data-itemid') : '';
1596
+ if (!itemId) return;
1597
+ // Keep cache in sync so re-renders preserve typed value
1598
+ maintItemsCache = maintItemsCache.map((it) => (String(it.id) === String(itemId) ? Object.assign({}, it, { location: el.value }) : it));
1599
+ });
1600
+
1601
+ maintTableBody.addEventListener('focusout', async (ev) => {
1602
+ const el = ev && ev.target;
1603
+ if (!el || !el.classList || !el.classList.contains('onekite-maint-location')) return;
1604
+ const tr = el.closest('tr');
1605
+ const itemId = tr ? tr.getAttribute('data-itemid') : '';
1606
+ if (!itemId) return;
1607
+ const location = String(el.value || '');
1608
+ try {
1609
+ await fetchJson(`/api/v3/plugins/calendar-onekite/maintenance/${encodeURIComponent(String(itemId))}`, {
1610
+ method: 'PUT',
1611
+ body: JSON.stringify({ location }),
1612
+ });
1613
+ } catch (e) {
1614
+ showAlert('error', 'Impossible de sauvegarder l\'emplacement.');
1615
+ }
1616
+ });
1588
1617
  }
1589
1618
 
1590
1619
  // Load once
@@ -314,7 +314,7 @@
314
314
  <div class="table-responsive">
315
315
  <table class="table table-sm" id="onekite-maint-table">
316
316
  <thead>
317
- <tr><th>Matériel</th><th style="width: 140px;">Maintenance</th></tr>
317
+ <tr><th>Matériel</th><th>Emplacement</th><th style="width: 140px;">Maintenance</th></tr>
318
318
  </thead>
319
319
  <tbody></tbody>
320
320
  </table>