nodebb-plugin-equipment-calendar 8.8.9 → 8.9.1
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 +16 -23
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/public/js/client.js +23 -7
package/library.js
CHANGED
|
@@ -1324,31 +1324,23 @@ async function handleCreateReservation(req, res) {
|
|
|
1324
1324
|
return helpers.notAllowed(req, res);
|
|
1325
1325
|
}
|
|
1326
1326
|
|
|
1327
|
-
const startIsoInput = String(req.body.start || req.body.startDate || req.body.startIso || '').trim();
|
|
1328
|
-
const endIsoInput = String(req.body.end || req.body.endDate || req.body.endIso || '').trim();
|
|
1329
|
-
|
|
1330
1327
|
const itemIdsRaw = (req.body.itemIds !== undefined ? req.body.itemIds : req.body.itemId);
|
|
1331
1328
|
const itemIds = normalizeItemIds(itemIdsRaw);
|
|
1332
1329
|
if (!itemIds.length) return res.status(400).send('itemIds required');
|
|
1333
1330
|
|
|
1334
|
-
// Dates
|
|
1335
|
-
const
|
|
1336
|
-
const
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
const startIso = (/^\d{4}-\d{2}-\d{2}$/.test(startIsoInput) ? startIsoInput : `${start.getUTCFullYear()}-${String(start.getUTCMonth()+1).padStart(2,'0')}-${String(start.getUTCDate()).padStart(2,'0')}`);
|
|
1342
|
-
const endIso = (/^\d{4}-\d{2}-\d{2}$/.test(endIsoInput) ? endIsoInput : `${end.getUTCFullYear()}-${String(end.getUTCMonth()+1).padStart(2,'0')}-${String(end.getUTCDate()).padStart(2,'0')}`);
|
|
1343
|
-
|
|
1331
|
+
// Dates expected as YYYY-MM-DD (end inclusive in UI)
|
|
1332
|
+
const startIso = String(req.body.start || req.body.startDate || req.body.startIso || '').trim();
|
|
1333
|
+
const endIso = String(req.body.end || req.body.endDate || req.body.endIso || '').trim();
|
|
1334
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(startIso) || !/^\d{4}-\d{2}-\d{2}$/.test(endIso)) {
|
|
1335
|
+
return res.status(400).send('dates required');
|
|
1336
|
+
}
|
|
1344
1337
|
|
|
1345
|
-
const startMs = Date.
|
|
1346
|
-
|
|
1347
|
-
if (endMs
|
|
1338
|
+
const startMs = Date.parse(startIso + 'T00:00:00Z');
|
|
1339
|
+
const endMs = Date.parse(addDaysIso(endIso, 1) + 'T00:00:00Z'); // exclusive end
|
|
1340
|
+
if (!startMs || !endMs || endMs <= startMs) {
|
|
1341
|
+
return res.status(400).send('dates required');
|
|
1342
|
+
}
|
|
1348
1343
|
|
|
1349
|
-
const endMsInclusive = endMs;
|
|
1350
|
-
const endMsExclusive = endMsInclusive + 24 * 60 * 60 * 1000;
|
|
1351
|
-
endMs = endMsExclusive;
|
|
1352
1344
|
const days = Math.max(1, Math.round((endMs - startMs) / (24 * 60 * 60 * 1000)));
|
|
1353
1345
|
|
|
1354
1346
|
const items = await getActiveItems(settings);
|
|
@@ -1372,14 +1364,14 @@ async function handleCreateReservation(req, res) {
|
|
|
1372
1364
|
itemId,
|
|
1373
1365
|
startMs,
|
|
1374
1366
|
endMs,
|
|
1375
|
-
startIso
|
|
1376
|
-
endIso
|
|
1367
|
+
startIso,
|
|
1368
|
+
endIso,
|
|
1377
1369
|
days,
|
|
1378
1370
|
unitPrice,
|
|
1379
1371
|
total,
|
|
1380
1372
|
notesUser,
|
|
1381
1373
|
status: 'pending',
|
|
1382
|
-
createdAt:
|
|
1374
|
+
createdAt: Date.now(),
|
|
1383
1375
|
};
|
|
1384
1376
|
// eslint-disable-next-line no-await-in-loop
|
|
1385
1377
|
await saveReservation(r);
|
|
@@ -1388,10 +1380,11 @@ async function handleCreateReservation(req, res) {
|
|
|
1388
1380
|
return res.redirect(nconf.get('relative_path') + '/calendar?created=1');
|
|
1389
1381
|
} catch (err) {
|
|
1390
1382
|
winston.error('[equipment-calendar] create error: ' + (err && err.message ? err.message : ''), err);
|
|
1391
|
-
return res.status(500).send(
|
|
1383
|
+
return res.status(500).send('error');
|
|
1392
1384
|
}
|
|
1393
1385
|
}
|
|
1394
1386
|
|
|
1387
|
+
|
|
1395
1388
|
async function handleApproveReservation(req, res) {
|
|
1396
1389
|
try {
|
|
1397
1390
|
const settings = await getSettings();
|
package/package.json
CHANGED
package/plugin.json
CHANGED
package/public/js/client.js
CHANGED
|
@@ -143,26 +143,42 @@ function updateTotalPrice() {
|
|
|
143
143
|
eventContent: function(arg) {
|
|
144
144
|
try {
|
|
145
145
|
var status = (arg.event.extendedProps && arg.event.extendedProps.status) ? arg.event.extendedProps.status : '';
|
|
146
|
+
var iconTxt = '';
|
|
146
147
|
var iconClass = '';
|
|
147
|
-
if (status === 'pending') iconClass = 'fa-hourglass-half text-warning';
|
|
148
|
-
else if (status === 'paid') iconClass = 'fa-check-circle text-success';
|
|
149
|
-
else if (status === 'approved') iconClass = 'fa-check text-
|
|
150
|
-
else if (status === 'rejected' || status === 'cancelled') iconClass = 'fa-times
|
|
148
|
+
if (status === 'pending') { iconTxt = '⏳'; iconClass = 'fa fa-hourglass-half text-warning'; }
|
|
149
|
+
else if (status === 'paid') { iconTxt = '✅'; iconClass = 'fa fa-check-circle text-success'; }
|
|
150
|
+
else if (status === 'approved') { iconTxt = '✔️'; iconClass = 'fa fa-check text-success'; }
|
|
151
|
+
else if (status === 'rejected' || status === 'cancelled') { iconTxt = '❌'; iconClass = 'fa fa-times text-danger'; }
|
|
152
|
+
|
|
151
153
|
var wrap = document.createElement('div');
|
|
152
154
|
wrap.className = 'ec-event';
|
|
155
|
+
var icon = document.createElement('span');
|
|
156
|
+
icon.className = 'ec-icon';
|
|
157
|
+
// Prefer fontawesome if available, but keep emoji fallback
|
|
153
158
|
if (iconClass) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
159
|
+
icon.innerHTML = '<i class="' + iconClass + '"></i> <span class="visually-hidden">' + status + '</span>';
|
|
160
|
+
} else {
|
|
161
|
+
icon.textContent = '';
|
|
157
162
|
}
|
|
158
163
|
var t = document.createElement('span');
|
|
159
164
|
t.className = 'ec-title';
|
|
160
165
|
t.textContent = arg.event.title || '';
|
|
166
|
+
if (iconTxt && (!iconClass || !document.querySelector('link[href*="fontawesome"], style, script'))) {
|
|
167
|
+
// emoji fallback shown if needed
|
|
168
|
+
var em = document.createElement('span');
|
|
169
|
+
em.textContent = iconTxt + ' ';
|
|
170
|
+
wrap.appendChild(em);
|
|
171
|
+
} else if (iconClass) {
|
|
172
|
+
wrap.appendChild(icon);
|
|
173
|
+
}
|
|
161
174
|
wrap.appendChild(t);
|
|
162
175
|
return { domNodes: [wrap] };
|
|
163
176
|
} catch (e) {
|
|
164
177
|
return true;
|
|
165
178
|
}
|
|
179
|
+
} catch (e) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
166
182
|
},
|
|
167
183
|
timeZone: 'local',
|
|
168
184
|
events: events,
|