nodebb-plugin-onekite-calendar 2.0.12 → 2.0.13
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/package.json +1 -1
- package/pkg/package/CHANGELOG.md +4 -0
- package/pkg/package/package.json +1 -1
- package/pkg/package/plugin.json +1 -1
- package/pkg/package/public/admin.js +9 -2
- package/pkg/package/public/client.js +52 -9
- package/pkg/package/templates/admin/plugins/calendar-onekite.tpl +11 -0
- package/plugin.json +1 -1
- package/public/admin.js +9 -2
- package/public/client.js +52 -9
- package/templates/admin/plugins/calendar-onekite.tpl +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog – calendar-onekite
|
|
2
2
|
|
|
3
|
+
## 1.3.6
|
|
4
|
+
- ACP Comptabilisation : ajout d’un tableau séparé « Détails des sorties gratuites » (avec le nom du matériel).
|
|
5
|
+
- Mobile FAB : la modale utilise maintenant des champs date avec calendrier (type="date") et empêche toute réservation pour le jour même ou dans le passé.
|
|
6
|
+
|
|
3
7
|
## 1.3.5
|
|
4
8
|
- ACP : ajout d’un paramètre « Location longue durée (jours) pour validateurs ». Si une réservation faite par un validateur dépasse ce nombre de jours, elle redevient payante et suit le workflow normal (demande → validation → paiement HelloAsso). Mets 0 pour conserver le comportement « toujours gratuit ».
|
|
5
9
|
|
package/package.json
CHANGED
package/pkg/package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog – calendar-onekite
|
|
2
2
|
|
|
3
|
+
## 1.3.6
|
|
4
|
+
- ACP Comptabilisation : ajout d’un tableau séparé « Détails des sorties gratuites » (avec le nom du matériel).
|
|
5
|
+
- Mobile FAB : la modale utilise maintenant des champs date avec calendrier (type="date") et empêche toute réservation pour le jour même ou dans le passé.
|
|
6
|
+
|
|
3
7
|
## 1.3.5
|
|
4
8
|
- ACP : ajout d’un paramètre « Location longue durée (jours) pour validateurs ». Si une réservation faite par un validateur dépasse ce nombre de jours, elle redevient payante et suit le workflow normal (demande → validation → paiement HelloAsso). Mets 0 pour conserver le comportement « toujours gratuit ».
|
|
5
9
|
|
package/pkg/package/package.json
CHANGED
package/pkg/package/plugin.json
CHANGED
|
@@ -1170,6 +1170,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1170
1170
|
const accPurge = document.getElementById('onekite-acc-purge');
|
|
1171
1171
|
const accSummary = document.querySelector('#onekite-acc-summary tbody');
|
|
1172
1172
|
const accRows = document.querySelector('#onekite-acc-rows tbody');
|
|
1173
|
+
const accFreeRows = document.querySelector('#onekite-acc-free-rows tbody');
|
|
1173
1174
|
|
|
1174
1175
|
function ymd(d) {
|
|
1175
1176
|
const yyyy = d.getUTCFullYear();
|
|
@@ -1188,6 +1189,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1188
1189
|
function renderAccounting(payload) {
|
|
1189
1190
|
if (accSummary) accSummary.innerHTML = '';
|
|
1190
1191
|
if (accRows) accRows.innerHTML = '';
|
|
1192
|
+
if (accFreeRows) accFreeRows.innerHTML = '';
|
|
1191
1193
|
if (!payload || !payload.ok) {
|
|
1192
1194
|
return;
|
|
1193
1195
|
}
|
|
@@ -1207,8 +1209,13 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1207
1209
|
const user = r.username ? `<a href="/user/${encodeURIComponent(r.username)}" target="_blank">${escapeHtml(r.username)}</a>${r.isFree ? ' <em>(gratuit)</em>' : ''}` : (r.isFree ? '<em>(gratuit)</em>' : '');
|
|
1208
1210
|
const items = Array.isArray(r.items) ? r.items.map((x) => escapeHtml(x)).join('<br>') : '';
|
|
1209
1211
|
const totalCell = r.isFree ? '-' : escapeHtml((Number(r.total) || 0).toFixed(2));
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
+
if (r.isFree) {
|
|
1213
|
+
tr.innerHTML = `<td>${escapeHtml(r.startDate)} → ${escapeHtml(r.endDate)}</td><td>${user}</td><td>${items}</td><td><code>${escapeHtml(r.rid)}</code></td>`;
|
|
1214
|
+
accFreeRows && accFreeRows.appendChild(tr);
|
|
1215
|
+
} else {
|
|
1216
|
+
tr.innerHTML = `<td>${escapeHtml(r.startDate)} → ${escapeHtml(r.endDate)}</td><td>${user}</td><td>${items}</td><td>${totalCell}</td><td><code>${escapeHtml(r.rid)}</code></td>`;
|
|
1217
|
+
accRows && accRows.appendChild(tr);
|
|
1218
|
+
}
|
|
1212
1219
|
});
|
|
1213
1220
|
}
|
|
1214
1221
|
|
|
@@ -2033,20 +2033,22 @@ function toDatetimeLocalValue(date) {
|
|
|
2033
2033
|
async function openFabDatePicker() {
|
|
2034
2034
|
if (!lockAction('fab-date-picker', 700)) return;
|
|
2035
2035
|
|
|
2036
|
-
// Defaults:
|
|
2036
|
+
// Defaults: tomorrow -> tomorrow (cannot book today or past)
|
|
2037
2037
|
const today = new Date();
|
|
2038
2038
|
today.setHours(0, 0, 0, 0);
|
|
2039
|
+
const minStart = new Date(today);
|
|
2040
|
+
minStart.setDate(minStart.getDate() + 1);
|
|
2039
2041
|
|
|
2040
2042
|
const html = `
|
|
2041
2043
|
<div class="onekite-fab-dates">
|
|
2042
2044
|
<div class="mb-2">
|
|
2043
2045
|
<label class="form-label">Date de début</label>
|
|
2044
|
-
<input class="form-control" type="
|
|
2046
|
+
<input class="form-control" type="date" id="onekite-fab-start" autocomplete="off" />
|
|
2045
2047
|
</div>
|
|
2046
2048
|
<div class="mb-2">
|
|
2047
2049
|
<label class="form-label">Date de fin (incluse)</label>
|
|
2048
|
-
<input class="form-control" type="
|
|
2049
|
-
<div class="form-text">
|
|
2050
|
+
<input class="form-control" type="date" id="onekite-fab-end" autocomplete="off" />
|
|
2051
|
+
<div class="form-text">Sélectionne une période (la date de fin est incluse).</div>
|
|
2050
2052
|
</div>
|
|
2051
2053
|
</div>
|
|
2052
2054
|
`;
|
|
@@ -2060,10 +2062,18 @@ function toDatetimeLocalValue(date) {
|
|
|
2060
2062
|
label: 'Continuer',
|
|
2061
2063
|
className: 'btn-primary',
|
|
2062
2064
|
callback: function () {
|
|
2063
|
-
const
|
|
2064
|
-
const
|
|
2065
|
+
const sStr = String(document.getElementById('onekite-fab-start').value || '');
|
|
2066
|
+
const eStr = String(document.getElementById('onekite-fab-end').value || '');
|
|
2067
|
+
const s = parseYmdDate(sStr);
|
|
2068
|
+
const e = parseYmdDate(eStr);
|
|
2065
2069
|
if (!s || !e) {
|
|
2066
|
-
alerts.error('Dates invalides.
|
|
2070
|
+
alerts.error('Dates invalides.');
|
|
2071
|
+
return false;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
// Cannot book today or past
|
|
2075
|
+
if (s < minStart || e < minStart) {
|
|
2076
|
+
alerts.error('Impossible de réserver pour le jour même ou dans le passé.');
|
|
2067
2077
|
return false;
|
|
2068
2078
|
}
|
|
2069
2079
|
if (e < s) {
|
|
@@ -2118,13 +2128,46 @@ function toDatetimeLocalValue(date) {
|
|
|
2118
2128
|
try {
|
|
2119
2129
|
const startEl = document.getElementById('onekite-fab-start');
|
|
2120
2130
|
const endEl = document.getElementById('onekite-fab-end');
|
|
2121
|
-
|
|
2122
|
-
if (
|
|
2131
|
+
const minStr = toLocalYmd(minStart);
|
|
2132
|
+
if (startEl) {
|
|
2133
|
+
startEl.min = minStr;
|
|
2134
|
+
startEl.value = minStr;
|
|
2135
|
+
}
|
|
2136
|
+
if (endEl) {
|
|
2137
|
+
endEl.min = minStr;
|
|
2138
|
+
endEl.value = minStr;
|
|
2139
|
+
}
|
|
2140
|
+
if (startEl && endEl) {
|
|
2141
|
+
startEl.addEventListener('change', () => {
|
|
2142
|
+
try {
|
|
2143
|
+
const d = parseYmdDate(String(startEl.value || ''));
|
|
2144
|
+
if (!d) return;
|
|
2145
|
+
const minEnd = new Date(d);
|
|
2146
|
+
const minEndStr = toLocalYmd(minEnd);
|
|
2147
|
+
endEl.min = minEndStr;
|
|
2148
|
+
if (String(endEl.value || '') < minEndStr) endEl.value = minEndStr;
|
|
2149
|
+
} catch (e) {}
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2123
2152
|
if (startEl) startEl.focus();
|
|
2124
2153
|
} catch (e) {}
|
|
2125
2154
|
});
|
|
2126
2155
|
}
|
|
2127
2156
|
|
|
2157
|
+
function parseYmdDate(ymdStr) {
|
|
2158
|
+
// Expect YYYY-MM-DD (from <input type="date">)
|
|
2159
|
+
if (!ymdStr || typeof ymdStr !== 'string') return null;
|
|
2160
|
+
const m = /^\s*(\d{4})-(\d{2})-(\d{2})\s*$/.exec(ymdStr);
|
|
2161
|
+
if (!m) return null;
|
|
2162
|
+
const y = parseInt(m[1], 10);
|
|
2163
|
+
const mo = parseInt(m[2], 10);
|
|
2164
|
+
const d = parseInt(m[3], 10);
|
|
2165
|
+
if (!y || !mo || !d) return null;
|
|
2166
|
+
const dt = new Date(y, mo - 1, d);
|
|
2167
|
+
dt.setHours(0, 0, 0, 0);
|
|
2168
|
+
return dt;
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2128
2171
|
function mountMobileFab() {
|
|
2129
2172
|
try {
|
|
2130
2173
|
unmountMobileFab();
|
|
@@ -219,6 +219,17 @@
|
|
|
219
219
|
<tbody></tbody>
|
|
220
220
|
</table>
|
|
221
221
|
</div>
|
|
222
|
+
|
|
223
|
+
<h5 class="mt-4">Détails des sorties gratuites</h5>
|
|
224
|
+
<div class="form-text mb-2">Réservations gratuites (validateurs) : comptées séparément (hors chiffre d’affaires).</div>
|
|
225
|
+
<div class="table-responsive">
|
|
226
|
+
<table class="table table-sm" id="onekite-acc-free-rows">
|
|
227
|
+
<thead>
|
|
228
|
+
<tr><th>Date</th><th>Utilisateur</th><th>Matériel</th><th>RID</th></tr>
|
|
229
|
+
</thead>
|
|
230
|
+
<tbody></tbody>
|
|
231
|
+
</table>
|
|
232
|
+
</div>
|
|
222
233
|
</div>
|
|
223
234
|
|
|
224
235
|
<div class="tab-pane fade" id="onekite-tab-maintenance" role="tabpanel">
|
package/plugin.json
CHANGED
package/public/admin.js
CHANGED
|
@@ -1170,6 +1170,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1170
1170
|
const accPurge = document.getElementById('onekite-acc-purge');
|
|
1171
1171
|
const accSummary = document.querySelector('#onekite-acc-summary tbody');
|
|
1172
1172
|
const accRows = document.querySelector('#onekite-acc-rows tbody');
|
|
1173
|
+
const accFreeRows = document.querySelector('#onekite-acc-free-rows tbody');
|
|
1173
1174
|
|
|
1174
1175
|
function ymd(d) {
|
|
1175
1176
|
const yyyy = d.getUTCFullYear();
|
|
@@ -1188,6 +1189,7 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1188
1189
|
function renderAccounting(payload) {
|
|
1189
1190
|
if (accSummary) accSummary.innerHTML = '';
|
|
1190
1191
|
if (accRows) accRows.innerHTML = '';
|
|
1192
|
+
if (accFreeRows) accFreeRows.innerHTML = '';
|
|
1191
1193
|
if (!payload || !payload.ok) {
|
|
1192
1194
|
return;
|
|
1193
1195
|
}
|
|
@@ -1207,8 +1209,13 @@ define('admin/plugins/calendar-onekite', ['alerts', 'bootbox'], function (alerts
|
|
|
1207
1209
|
const user = r.username ? `<a href="/user/${encodeURIComponent(r.username)}" target="_blank">${escapeHtml(r.username)}</a>${r.isFree ? ' <em>(gratuit)</em>' : ''}` : (r.isFree ? '<em>(gratuit)</em>' : '');
|
|
1208
1210
|
const items = Array.isArray(r.items) ? r.items.map((x) => escapeHtml(x)).join('<br>') : '';
|
|
1209
1211
|
const totalCell = r.isFree ? '-' : escapeHtml((Number(r.total) || 0).toFixed(2));
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
+
if (r.isFree) {
|
|
1213
|
+
tr.innerHTML = `<td>${escapeHtml(r.startDate)} → ${escapeHtml(r.endDate)}</td><td>${user}</td><td>${items}</td><td><code>${escapeHtml(r.rid)}</code></td>`;
|
|
1214
|
+
accFreeRows && accFreeRows.appendChild(tr);
|
|
1215
|
+
} else {
|
|
1216
|
+
tr.innerHTML = `<td>${escapeHtml(r.startDate)} → ${escapeHtml(r.endDate)}</td><td>${user}</td><td>${items}</td><td>${totalCell}</td><td><code>${escapeHtml(r.rid)}</code></td>`;
|
|
1217
|
+
accRows && accRows.appendChild(tr);
|
|
1218
|
+
}
|
|
1212
1219
|
});
|
|
1213
1220
|
}
|
|
1214
1221
|
|
package/public/client.js
CHANGED
|
@@ -2033,20 +2033,22 @@ function toDatetimeLocalValue(date) {
|
|
|
2033
2033
|
async function openFabDatePicker() {
|
|
2034
2034
|
if (!lockAction('fab-date-picker', 700)) return;
|
|
2035
2035
|
|
|
2036
|
-
// Defaults:
|
|
2036
|
+
// Defaults: tomorrow -> tomorrow (cannot book today or past)
|
|
2037
2037
|
const today = new Date();
|
|
2038
2038
|
today.setHours(0, 0, 0, 0);
|
|
2039
|
+
const minStart = new Date(today);
|
|
2040
|
+
minStart.setDate(minStart.getDate() + 1);
|
|
2039
2041
|
|
|
2040
2042
|
const html = `
|
|
2041
2043
|
<div class="onekite-fab-dates">
|
|
2042
2044
|
<div class="mb-2">
|
|
2043
2045
|
<label class="form-label">Date de début</label>
|
|
2044
|
-
<input class="form-control" type="
|
|
2046
|
+
<input class="form-control" type="date" id="onekite-fab-start" autocomplete="off" />
|
|
2045
2047
|
</div>
|
|
2046
2048
|
<div class="mb-2">
|
|
2047
2049
|
<label class="form-label">Date de fin (incluse)</label>
|
|
2048
|
-
<input class="form-control" type="
|
|
2049
|
-
<div class="form-text">
|
|
2050
|
+
<input class="form-control" type="date" id="onekite-fab-end" autocomplete="off" />
|
|
2051
|
+
<div class="form-text">Sélectionne une période (la date de fin est incluse).</div>
|
|
2050
2052
|
</div>
|
|
2051
2053
|
</div>
|
|
2052
2054
|
`;
|
|
@@ -2060,10 +2062,18 @@ function toDatetimeLocalValue(date) {
|
|
|
2060
2062
|
label: 'Continuer',
|
|
2061
2063
|
className: 'btn-primary',
|
|
2062
2064
|
callback: function () {
|
|
2063
|
-
const
|
|
2064
|
-
const
|
|
2065
|
+
const sStr = String(document.getElementById('onekite-fab-start').value || '');
|
|
2066
|
+
const eStr = String(document.getElementById('onekite-fab-end').value || '');
|
|
2067
|
+
const s = parseYmdDate(sStr);
|
|
2068
|
+
const e = parseYmdDate(eStr);
|
|
2065
2069
|
if (!s || !e) {
|
|
2066
|
-
alerts.error('Dates invalides.
|
|
2070
|
+
alerts.error('Dates invalides.');
|
|
2071
|
+
return false;
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
// Cannot book today or past
|
|
2075
|
+
if (s < minStart || e < minStart) {
|
|
2076
|
+
alerts.error('Impossible de réserver pour le jour même ou dans le passé.');
|
|
2067
2077
|
return false;
|
|
2068
2078
|
}
|
|
2069
2079
|
if (e < s) {
|
|
@@ -2118,13 +2128,46 @@ function toDatetimeLocalValue(date) {
|
|
|
2118
2128
|
try {
|
|
2119
2129
|
const startEl = document.getElementById('onekite-fab-start');
|
|
2120
2130
|
const endEl = document.getElementById('onekite-fab-end');
|
|
2121
|
-
|
|
2122
|
-
if (
|
|
2131
|
+
const minStr = toLocalYmd(minStart);
|
|
2132
|
+
if (startEl) {
|
|
2133
|
+
startEl.min = minStr;
|
|
2134
|
+
startEl.value = minStr;
|
|
2135
|
+
}
|
|
2136
|
+
if (endEl) {
|
|
2137
|
+
endEl.min = minStr;
|
|
2138
|
+
endEl.value = minStr;
|
|
2139
|
+
}
|
|
2140
|
+
if (startEl && endEl) {
|
|
2141
|
+
startEl.addEventListener('change', () => {
|
|
2142
|
+
try {
|
|
2143
|
+
const d = parseYmdDate(String(startEl.value || ''));
|
|
2144
|
+
if (!d) return;
|
|
2145
|
+
const minEnd = new Date(d);
|
|
2146
|
+
const minEndStr = toLocalYmd(minEnd);
|
|
2147
|
+
endEl.min = minEndStr;
|
|
2148
|
+
if (String(endEl.value || '') < minEndStr) endEl.value = minEndStr;
|
|
2149
|
+
} catch (e) {}
|
|
2150
|
+
});
|
|
2151
|
+
}
|
|
2123
2152
|
if (startEl) startEl.focus();
|
|
2124
2153
|
} catch (e) {}
|
|
2125
2154
|
});
|
|
2126
2155
|
}
|
|
2127
2156
|
|
|
2157
|
+
function parseYmdDate(ymdStr) {
|
|
2158
|
+
// Expect YYYY-MM-DD (from <input type="date">)
|
|
2159
|
+
if (!ymdStr || typeof ymdStr !== 'string') return null;
|
|
2160
|
+
const m = /^\s*(\d{4})-(\d{2})-(\d{2})\s*$/.exec(ymdStr);
|
|
2161
|
+
if (!m) return null;
|
|
2162
|
+
const y = parseInt(m[1], 10);
|
|
2163
|
+
const mo = parseInt(m[2], 10);
|
|
2164
|
+
const d = parseInt(m[3], 10);
|
|
2165
|
+
if (!y || !mo || !d) return null;
|
|
2166
|
+
const dt = new Date(y, mo - 1, d);
|
|
2167
|
+
dt.setHours(0, 0, 0, 0);
|
|
2168
|
+
return dt;
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2128
2171
|
function mountMobileFab() {
|
|
2129
2172
|
try {
|
|
2130
2173
|
unmountMobileFab();
|
|
@@ -219,6 +219,17 @@
|
|
|
219
219
|
<tbody></tbody>
|
|
220
220
|
</table>
|
|
221
221
|
</div>
|
|
222
|
+
|
|
223
|
+
<h5 class="mt-4">Détails des sorties gratuites</h5>
|
|
224
|
+
<div class="form-text mb-2">Réservations gratuites (validateurs) : comptées séparément (hors chiffre d’affaires).</div>
|
|
225
|
+
<div class="table-responsive">
|
|
226
|
+
<table class="table table-sm" id="onekite-acc-free-rows">
|
|
227
|
+
<thead>
|
|
228
|
+
<tr><th>Date</th><th>Utilisateur</th><th>Matériel</th><th>RID</th></tr>
|
|
229
|
+
</thead>
|
|
230
|
+
<tbody></tbody>
|
|
231
|
+
</table>
|
|
232
|
+
</div>
|
|
222
233
|
</div>
|
|
223
234
|
|
|
224
235
|
<div class="tab-pane fade" id="onekite-tab-maintenance" role="tabpanel">
|