nodebb-plugin-onekite-calendar 1.0.12 → 1.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/lib/admin.js +568 -0
- package/lib/api.js +941 -0
- package/lib/controllers.js +11 -0
- package/lib/db.js +110 -0
- package/lib/discord.js +163 -0
- package/lib/helloasso.js +352 -0
- package/lib/helloassoWebhook.js +390 -0
- package/lib/scheduler.js +182 -0
- package/lib/widgets.js +425 -0
- package/package.json +1 -1
- package/plugin.json +1 -1
package/lib/widgets.js
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const nconf = require.main.require('nconf');
|
|
4
|
+
|
|
5
|
+
function forumBaseUrl() {
|
|
6
|
+
return String(nconf.get('url') || '').trim().replace(/\/$/, '');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function escapeHtml(s) {
|
|
10
|
+
return String(s || '')
|
|
11
|
+
.replace(/&/g, '&')
|
|
12
|
+
.replace(/</g, '<')
|
|
13
|
+
.replace(/>/g, '>')
|
|
14
|
+
.replace(/"/g, '"')
|
|
15
|
+
.replace(/'/g, ''');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function makeDomId() {
|
|
19
|
+
const r = Math.floor(Math.random() * 1e9);
|
|
20
|
+
return `onekite-twoweeks-${Date.now()}-${r}`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function widgetCalendarUrl() {
|
|
24
|
+
// Per request, keep the public URL fixed (even if forum base differs)
|
|
25
|
+
return 'https://www.onekite.com/calendar';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const widgets = {};
|
|
29
|
+
|
|
30
|
+
widgets.defineWidgets = async function (widgetData) {
|
|
31
|
+
// NodeBB versions differ:
|
|
32
|
+
// - Some pass an object: { widgets: [...] }
|
|
33
|
+
// - Others pass the array directly
|
|
34
|
+
const list = Array.isArray(widgetData)
|
|
35
|
+
? widgetData
|
|
36
|
+
: (widgetData && Array.isArray(widgetData.widgets) ? widgetData.widgets : null);
|
|
37
|
+
|
|
38
|
+
if (!list) {
|
|
39
|
+
return widgetData;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
list.push({
|
|
43
|
+
widget: 'calendar-onekite-twoweeks',
|
|
44
|
+
name: 'Calendrier',
|
|
45
|
+
description: 'Affiche la semaine courante + la semaine suivante (FullCalendar via CDN).',
|
|
46
|
+
content: '',
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return widgetData;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
widgets.renderTwoWeeksWidget = async function (data) {
|
|
53
|
+
// data: { widget, ... }
|
|
54
|
+
const id = makeDomId();
|
|
55
|
+
const calUrl = widgetCalendarUrl();
|
|
56
|
+
const apiBase = forumBaseUrl();
|
|
57
|
+
const eventsEndpoint = `${apiBase}/api/v3/plugins/calendar-onekite/events`;
|
|
58
|
+
|
|
59
|
+
const idJson = JSON.stringify(id);
|
|
60
|
+
const calUrlJson = JSON.stringify(calUrl);
|
|
61
|
+
const eventsEndpointJson = JSON.stringify(eventsEndpoint);
|
|
62
|
+
|
|
63
|
+
const html = `
|
|
64
|
+
<div class="onekite-twoweeks">
|
|
65
|
+
<div class="d-flex justify-content-between align-items-center mb-1">
|
|
66
|
+
<div style="font-weight: 600;">Calendrier</div>
|
|
67
|
+
<a href="${escapeHtml(calUrl)}" class="btn btn-sm btn-outline-secondary" style="line-height: 1.1;">Ouvrir</a>
|
|
68
|
+
</div>
|
|
69
|
+
<div id="${escapeHtml(id)}"></div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fullcalendar@latest/main.min.css" />
|
|
73
|
+
<script>
|
|
74
|
+
(function(){
|
|
75
|
+
const containerId = ${idJson};
|
|
76
|
+
const calUrl = ${calUrlJson};
|
|
77
|
+
const eventsEndpoint = ${eventsEndpointJson};
|
|
78
|
+
|
|
79
|
+
function loadOnce(tag, attrs) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
try {
|
|
82
|
+
const key = attrs && (attrs.id || attrs.href || attrs.src);
|
|
83
|
+
if (key && document.querySelector((attrs.id ? ('#' + attrs.id) : (attrs.href ? ('link[href="' + attrs.href + '"]') : ('script[src="' + attrs.src + '"]'))))) {
|
|
84
|
+
resolve();
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const el = document.createElement(tag);
|
|
88
|
+
Object.keys(attrs || {}).forEach((k) => el.setAttribute(k, attrs[k]));
|
|
89
|
+
el.onload = () => resolve();
|
|
90
|
+
el.onerror = () => reject(new Error('load-failed'));
|
|
91
|
+
document.head.appendChild(el);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
reject(e);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async function ensureFullCalendar() {
|
|
99
|
+
if (window.FullCalendar && window.FullCalendar.Calendar) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
await loadOnce('script', {
|
|
103
|
+
id: 'onekite-fullcalendar-global',
|
|
104
|
+
src: 'https://cdn.jsdelivr.net/npm/fullcalendar@latest/index.global.min.js',
|
|
105
|
+
async: 'true'
|
|
106
|
+
});
|
|
107
|
+
await loadOnce('script', {
|
|
108
|
+
id: 'onekite-fullcalendar-locales',
|
|
109
|
+
src: 'https://cdn.jsdelivr.net/npm/@fullcalendar/core@latest/locales-all.global.min.js',
|
|
110
|
+
async: 'true'
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function init() {
|
|
115
|
+
const el = document.getElementById(containerId);
|
|
116
|
+
if (!el) return;
|
|
117
|
+
|
|
118
|
+
await ensureFullCalendar();
|
|
119
|
+
|
|
120
|
+
// Basic lightweight tooltip (no dependencies, works on hover + tap)
|
|
121
|
+
const tip = document.createElement('div');
|
|
122
|
+
tip.className = 'onekite-cal-tooltip';
|
|
123
|
+
tip.style.display = 'none';
|
|
124
|
+
document.body.appendChild(tip);
|
|
125
|
+
|
|
126
|
+
function setTipContent(html) {
|
|
127
|
+
tip.innerHTML = html;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function showTipAt(x, y) {
|
|
131
|
+
tip.style.left = Math.max(8, x + 12) + 'px';
|
|
132
|
+
tip.style.top = Math.max(8, y + 12) + 'px';
|
|
133
|
+
tip.style.display = 'block';
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function hideTip() {
|
|
137
|
+
tip.style.display = 'none';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Client-side escaping (the server-side helper is not in scope here)
|
|
141
|
+
function escapeHtml(s) {
|
|
142
|
+
return String(s || '')
|
|
143
|
+
.replace(/&/g, '&')
|
|
144
|
+
.replace(/</g, '<')
|
|
145
|
+
.replace(/>/g, '>')
|
|
146
|
+
.replace(/"/g, '"')
|
|
147
|
+
.replace(/'/g, ''');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
document.addEventListener('pointerdown', (e) => {
|
|
151
|
+
// Close when clicking outside an event
|
|
152
|
+
if (!e.target || !e.target.closest || (!e.target.closest('.fc-event') && !e.target.closest('.onekite-cal-tooltip'))) {
|
|
153
|
+
hideTip();
|
|
154
|
+
}
|
|
155
|
+
}, { passive: true });
|
|
156
|
+
|
|
157
|
+
// Define a 2-week dayGrid view
|
|
158
|
+
const calendar = new window.FullCalendar.Calendar(el, {
|
|
159
|
+
initialView: 'dayGridTwoWeek',
|
|
160
|
+
views: {
|
|
161
|
+
dayGridTwoWeek: {
|
|
162
|
+
type: 'dayGrid',
|
|
163
|
+
duration: { weeks: 2 },
|
|
164
|
+
buttonText: '2 semaines',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
locale: 'fr',
|
|
168
|
+
firstDay: 1,
|
|
169
|
+
height: 'auto',
|
|
170
|
+
headerToolbar: {
|
|
171
|
+
left: 'prev,next',
|
|
172
|
+
// No range/title in the widget: it becomes redundant and, when the
|
|
173
|
+
// view crosses months, FullCalendar displays a start/end range.
|
|
174
|
+
center: '',
|
|
175
|
+
right: '',
|
|
176
|
+
},
|
|
177
|
+
navLinks: false,
|
|
178
|
+
eventTimeFormat: { hour: '2-digit', minute: '2-digit', hour12: false },
|
|
179
|
+
// Hide date numbers in column headers (keep only weekday)
|
|
180
|
+
dayHeaderFormat: { weekday: 'short' },
|
|
181
|
+
// Force day number to be numeric only (avoid '1 janvier' style labels)
|
|
182
|
+
dayCellContent: function(arg) {
|
|
183
|
+
try {
|
|
184
|
+
const t = String(arg.dayNumberText || '');
|
|
185
|
+
const m = t.match(/^\d+/);
|
|
186
|
+
return { html: '<span class="fc-daygrid-day-number">' + (m ? m[0] : t) + '</span>' };
|
|
187
|
+
} catch (e) {
|
|
188
|
+
return { html: '<span class="fc-daygrid-day-number">' + String(arg.dayNumberText || '') + '</span>' };
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
eventClassNames: function(arg) {
|
|
192
|
+
try {
|
|
193
|
+
const ev = arg && arg.event;
|
|
194
|
+
if (!ev) return ['onekite-singleday'];
|
|
195
|
+
if (ev.extendedProps && (ev.extendedProps.multiDay === true || ev.extendedProps.days > 1)) return ['onekite-multiday'];
|
|
196
|
+
if (ev.start && ev.end) {
|
|
197
|
+
const diff = (new Date(ev.end)).getTime() - (new Date(ev.start)).getTime();
|
|
198
|
+
return [diff > 86400000 ? 'onekite-multiday' : 'onekite-singleday'];
|
|
199
|
+
}
|
|
200
|
+
} catch (e) {}
|
|
201
|
+
return ['onekite-singleday'];
|
|
202
|
+
},
|
|
203
|
+
// Render: dot for single-day, pill for multi-day
|
|
204
|
+
eventContent: function(arg) {
|
|
205
|
+
const ev = arg && arg.event;
|
|
206
|
+
const isMulti = (function(){
|
|
207
|
+
try {
|
|
208
|
+
if (!ev || !ev.start || !ev.end) return false;
|
|
209
|
+
if (ev.extendedProps && (ev.extendedProps.multiDay === true || ev.extendedProps.days > 1)) return true;
|
|
210
|
+
const s = new Date(ev.start);
|
|
211
|
+
const e = new Date(ev.end);
|
|
212
|
+
const diff = e.getTime() - s.getTime();
|
|
213
|
+
return diff > 86400000; // strictly more than 1 day
|
|
214
|
+
} catch (e) { return false; }
|
|
215
|
+
})();
|
|
216
|
+
|
|
217
|
+
if (isMulti) {
|
|
218
|
+
const spacer = document.createElement('span');
|
|
219
|
+
spacer.className = 'onekite-pill-spacer';
|
|
220
|
+
spacer.appendChild(document.createTextNode('\u00A0'));
|
|
221
|
+
return { domNodes: [spacer] };
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const bg = (ev.backgroundColor || (ev.extendedProps && ev.extendedProps.backgroundColor) || '').trim();
|
|
225
|
+
const border = (ev.borderColor || '').trim();
|
|
226
|
+
const color = bg || border || '#3788d8';
|
|
227
|
+
const wrap = document.createElement('span');
|
|
228
|
+
wrap.className = 'onekite-dot-wrap';
|
|
229
|
+
const dot = document.createElement('span');
|
|
230
|
+
dot.className = 'onekite-dot';
|
|
231
|
+
dot.style.backgroundColor = color;
|
|
232
|
+
wrap.appendChild(dot);
|
|
233
|
+
return { domNodes: [wrap] };
|
|
234
|
+
},
|
|
235
|
+
events: function(info, successCallback, failureCallback) {
|
|
236
|
+
const qs = new URLSearchParams({ start: info.startStr, end: info.endStr });
|
|
237
|
+
fetch(eventsEndpoint + '?' + qs.toString(), { credentials: 'same-origin' })
|
|
238
|
+
.then((r) => r.json())
|
|
239
|
+
.then((json) => successCallback(json || []))
|
|
240
|
+
.catch((e) => failureCallback(e));
|
|
241
|
+
},
|
|
242
|
+
eventDataTransform: function(ev) {
|
|
243
|
+
try {
|
|
244
|
+
if (ev && ev.extendedProps && String(ev.extendedProps.type) === 'special') {
|
|
245
|
+
// Unify rendering with rentals in the widget: use allDay layout
|
|
246
|
+
ev.allDay = true;
|
|
247
|
+
}
|
|
248
|
+
} catch (e) {}
|
|
249
|
+
return ev;
|
|
250
|
+
},
|
|
251
|
+
dateClick: function() { window.location.href = calUrl; },
|
|
252
|
+
eventDidMount: function(info) {
|
|
253
|
+
try {
|
|
254
|
+
const ev = info.event;
|
|
255
|
+
// Improve centering for single-day dots by centering the harness,
|
|
256
|
+
// same visual behavior as rentals.
|
|
257
|
+
try {
|
|
258
|
+
const cls = (info.el && info.el.classList) ? info.el.classList : null;
|
|
259
|
+
const isSingle = cls && cls.contains('onekite-singleday');
|
|
260
|
+
const harness = info.el && info.el.closest ? info.el.closest('.fc-daygrid-event-harness') : null;
|
|
261
|
+
if (harness && harness.classList) {
|
|
262
|
+
if (isSingle) {
|
|
263
|
+
harness.classList.add('onekite-harness-dot');
|
|
264
|
+
} else {
|
|
265
|
+
harness.classList.remove('onekite-harness-dot');
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} catch (e) {}
|
|
269
|
+
|
|
270
|
+
const ep = ev.extendedProps || {};
|
|
271
|
+
const title = (ep.itemNameLine || ep.title || ev.title || '').toString();
|
|
272
|
+
const statusLabel = (function(s){
|
|
273
|
+
const map = {
|
|
274
|
+
pending: 'En attente',
|
|
275
|
+
awaiting_payment: 'Validée – paiement en attente',
|
|
276
|
+
paid: 'Payée',
|
|
277
|
+
rejected: 'Rejetée',
|
|
278
|
+
expired: 'Expirée',
|
|
279
|
+
};
|
|
280
|
+
const k = String(s || '');
|
|
281
|
+
return map[k] || '';
|
|
282
|
+
});
|
|
283
|
+
const status = (String(ep.type || '') === 'reservation') ? statusLabel(ep.status) : '';
|
|
284
|
+
const start = ev.start ? new Date(ev.start) : null;
|
|
285
|
+
const end = ev.end ? new Date(ev.end) : null;
|
|
286
|
+
const pad2 = (n) => String(n).padStart(2, '0');
|
|
287
|
+
const fmt = (d) => d ? (pad2(d.getDate()) + '/' + pad2(d.getMonth() + 1) + '/' + String(d.getFullYear()).slice(-2)) : '';
|
|
288
|
+
const range = (start && end) ? ('Du ' + fmt(start) + ' au ' + fmt(end)) : '';
|
|
289
|
+
const html = '' +
|
|
290
|
+
'<div style="font-weight:600; margin-bottom:2px;">' + escapeHtml(title) + '</div>' +
|
|
291
|
+
(range ? ('<div style="opacity:.85">' + escapeHtml(range) + '</div>') : '') +
|
|
292
|
+
(status ? ('<div style="opacity:.75; margin-top:2px; font-size:.85em;">' + escapeHtml(status) + '</div>') : '');
|
|
293
|
+
|
|
294
|
+
// Hover (desktop)
|
|
295
|
+
info.el.addEventListener('pointerenter', () => {
|
|
296
|
+
// Only show on devices that actually hover
|
|
297
|
+
if (window.matchMedia && window.matchMedia('(hover: hover)').matches === false) return;
|
|
298
|
+
setTipContent(html);
|
|
299
|
+
const rect = info.el.getBoundingClientRect();
|
|
300
|
+
showTipAt(rect.left + rect.width / 2 + window.scrollX, rect.top + window.scrollY);
|
|
301
|
+
}, { passive: true });
|
|
302
|
+
info.el.addEventListener('pointerleave', hideTip, { passive: true });
|
|
303
|
+
|
|
304
|
+
// Tap (mobile) / click (fallback)
|
|
305
|
+
const openTipFromPoint = (pt) => {
|
|
306
|
+
setTipContent(html);
|
|
307
|
+
showTipAt((pt.clientX || 0) + window.scrollX, (pt.clientY || 0) + window.scrollY);
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
info.el.addEventListener('pointerdown', (e) => {
|
|
311
|
+
// On touch devices, FullCalendar can swallow click events during swipe;
|
|
312
|
+
// pointerdown is more reliable.
|
|
313
|
+
if (e && e.preventDefault) e.preventDefault();
|
|
314
|
+
if (e && e.stopPropagation) e.stopPropagation();
|
|
315
|
+
openTipFromPoint(e);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
info.el.addEventListener('touchstart', (e) => {
|
|
319
|
+
const t = e.touches && e.touches[0];
|
|
320
|
+
if (!t) return;
|
|
321
|
+
if (e && e.stopPropagation) e.stopPropagation();
|
|
322
|
+
openTipFromPoint(t);
|
|
323
|
+
}, { passive: true });
|
|
324
|
+
} catch (e) {}
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
calendar.render();
|
|
329
|
+
|
|
330
|
+
// Mobile swipe (left/right) to navigate weeks
|
|
331
|
+
try {
|
|
332
|
+
let touchStartX = null;
|
|
333
|
+
let touchStartY = null;
|
|
334
|
+
el.addEventListener('touchstart', (e) => {
|
|
335
|
+
const t = e.touches && e.touches[0];
|
|
336
|
+
if (!t) return;
|
|
337
|
+
touchStartX = t.clientX;
|
|
338
|
+
touchStartY = t.clientY;
|
|
339
|
+
}, { passive: true });
|
|
340
|
+
el.addEventListener('touchend', (e) => {
|
|
341
|
+
const t = e.changedTouches && e.changedTouches[0];
|
|
342
|
+
if (!t || touchStartX === null || touchStartY === null) return;
|
|
343
|
+
const dx = t.clientX - touchStartX;
|
|
344
|
+
const dy = t.clientY - touchStartY;
|
|
345
|
+
touchStartX = null;
|
|
346
|
+
touchStartY = null;
|
|
347
|
+
if (Math.abs(dx) < 55) return;
|
|
348
|
+
if (Math.abs(dx) < Math.abs(dy) * 1.2) return; // mostly vertical
|
|
349
|
+
if (dx < 0) {
|
|
350
|
+
calendar.next();
|
|
351
|
+
} else {
|
|
352
|
+
calendar.prev();
|
|
353
|
+
}
|
|
354
|
+
}, { passive: true });
|
|
355
|
+
} catch (e) {}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Widgets can be rendered after ajaxify; delay a tick.
|
|
359
|
+
setTimeout(() => init().catch(() => {}), 0);
|
|
360
|
+
})();
|
|
361
|
+
</script>
|
|
362
|
+
|
|
363
|
+
<style>
|
|
364
|
+
.onekite-twoweeks .fc .fc-toolbar-title { font-size: 1rem; }
|
|
365
|
+
.onekite-twoweeks .fc .fc-button { padding: .2rem .35rem; font-size: .75rem; }
|
|
366
|
+
.onekite-twoweeks .fc .fc-daygrid-day-number { font-size: .75rem; padding: 2px; }
|
|
367
|
+
.onekite-twoweeks .fc .fc-col-header-cell-cushion { font-size: .75rem; }
|
|
368
|
+
|
|
369
|
+
/* Single-day: show only a dot */
|
|
370
|
+
.onekite-twoweeks .fc .fc-event.onekite-singleday { background: transparent !important; border: none !important; }
|
|
371
|
+
.onekite-twoweeks .fc .fc-daygrid-event.onekite-singleday,
|
|
372
|
+
.onekite-twoweeks .fc .fc-daygrid-block-event.onekite-singleday {
|
|
373
|
+
background: transparent !important;
|
|
374
|
+
border: none !important;
|
|
375
|
+
box-shadow: none !important;
|
|
376
|
+
}
|
|
377
|
+
.onekite-twoweeks .fc .fc-daygrid-block-event.onekite-singleday .fc-event-main { padding: 0 !important; }
|
|
378
|
+
|
|
379
|
+
/* Multi-day: keep FullCalendar bar, but hide text and make it a pill */
|
|
380
|
+
.onekite-twoweeks .fc .fc-event.onekite-multiday {
|
|
381
|
+
border-radius: 999px !important;
|
|
382
|
+
overflow: hidden;
|
|
383
|
+
}
|
|
384
|
+
.onekite-twoweeks .fc .fc-daygrid-event.onekite-multiday,
|
|
385
|
+
.onekite-twoweeks .fc .fc-daygrid-block-event.onekite-multiday {
|
|
386
|
+
border-radius: 999px !important;
|
|
387
|
+
box-shadow: none !important;
|
|
388
|
+
}
|
|
389
|
+
.onekite-twoweeks .fc .fc-event.onekite-multiday .fc-event-main { padding: 0 !important; }
|
|
390
|
+
.onekite-twoweeks .fc .fc-event.onekite-multiday .fc-event-title,
|
|
391
|
+
.onekite-twoweeks .fc .fc-event.onekite-multiday .fc-event-time { display:none !important; }
|
|
392
|
+
|
|
393
|
+
.onekite-twoweeks .fc .fc-daygrid-event-harness { margin-top: 2px; }
|
|
394
|
+
/* Center single-day dots inside the day cell (match rentals) */
|
|
395
|
+
.onekite-twoweeks .fc .fc-daygrid-event-harness.onekite-harness-dot {
|
|
396
|
+
display: flex;
|
|
397
|
+
justify-content: center;
|
|
398
|
+
}
|
|
399
|
+
.onekite-twoweeks .fc .fc-daygrid-event { padding: 0 !important; }
|
|
400
|
+
.onekite-twoweeks .fc .fc-event-main { color: inherit; }
|
|
401
|
+
.onekite-twoweeks .fc .fc-event-title { display:none; }
|
|
402
|
+
.onekite-dot-wrap { display:flex; align-items:center; justify-content:center; width: 100%; }
|
|
403
|
+
.onekite-dot { width: 10px; height: 10px; border-radius: 999px; display:inline-block; }
|
|
404
|
+
.onekite-pill-spacer { display:block; height: 10px; line-height: 10px; }
|
|
405
|
+
.onekite-cal-tooltip {
|
|
406
|
+
position: absolute;
|
|
407
|
+
z-index: 99999;
|
|
408
|
+
max-width: 260px;
|
|
409
|
+
background: rgba(0,0,0,.92);
|
|
410
|
+
color: #fff;
|
|
411
|
+
padding: 8px 10px;
|
|
412
|
+
border-radius: 10px;
|
|
413
|
+
font-size: 0.9rem;
|
|
414
|
+
box-shadow: 0 8px 24px rgba(0,0,0,.25);
|
|
415
|
+
pointer-events: none;
|
|
416
|
+
}
|
|
417
|
+
</style>
|
|
418
|
+
`;
|
|
419
|
+
|
|
420
|
+
data = data || {};
|
|
421
|
+
data.html = html;
|
|
422
|
+
return data;
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
module.exports = widgets;
|
package/package.json
CHANGED
package/plugin.json
CHANGED