nodebb-plugin-recent-cards-2 3.3.19 → 3.3.21
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 +49 -0
- package/package.json +1 -1
- package/static/lib/main.js +113 -111
- package/static/style.scss +23 -31
- package/static/templates/partials/nodebb-plugin-recent-cards/header.tpl +10 -8
package/library.js
CHANGED
|
@@ -29,6 +29,7 @@ plugin.init = async function (params) {
|
|
|
29
29
|
|
|
30
30
|
router.get('/plugins/nodebb-plugin-recent-cards/render', renderExternal);
|
|
31
31
|
router.get('/plugins/nodebb-plugin-recent-cards/render/style.css', renderExternalStyle);
|
|
32
|
+
router.get('/plugins/nodebb-plugin-recent-cards/filter', renderFiltered);
|
|
32
33
|
router.get('/admin/plugins/nodebb-plugin-recent-cards/tests/external', testRenderExternal);
|
|
33
34
|
|
|
34
35
|
plugin.settings = new settings('recentcards', '1.0.0', defaultSettings);
|
|
@@ -97,12 +98,20 @@ plugin.renderWidget = async function (widget) {
|
|
|
97
98
|
});
|
|
98
99
|
const categories = Object.values(categoryMap);
|
|
99
100
|
|
|
101
|
+
const widgetConfig = {
|
|
102
|
+
sort: widget.data.sort || 'recent',
|
|
103
|
+
teaserPost: widget.data.teaserPost || 'first',
|
|
104
|
+
teaserParseType: widget.data.teaserParseType || 'default',
|
|
105
|
+
thumbnailStyle: widget.data.thumbnailStyle || 'background',
|
|
106
|
+
};
|
|
107
|
+
|
|
100
108
|
widget.html = await app.renderAsync('partials/nodebb-plugin-recent-cards/header', {
|
|
101
109
|
topics: topics,
|
|
102
110
|
config: widget.templateData.config,
|
|
103
111
|
title: widget.data.title || '',
|
|
104
112
|
carouselMode: plugin.settings.get('enableCarousel'),
|
|
105
113
|
categories: JSON.stringify(categories).replace(/</g, '\\u003c'),
|
|
114
|
+
widgetConfig: JSON.stringify(widgetConfig).replace(/</g, '\\u003c'),
|
|
106
115
|
});
|
|
107
116
|
return widget;
|
|
108
117
|
};
|
|
@@ -266,7 +275,47 @@ async function renderExternal(req, res, next) {
|
|
|
266
275
|
relative_path: nconf.get('url'),
|
|
267
276
|
},
|
|
268
277
|
categories: JSON.stringify(Object.values(categoryMap)).replace(/</g, '\\u003c'),
|
|
278
|
+
widgetConfig: '{}',
|
|
279
|
+
});
|
|
280
|
+
} catch (err) {
|
|
281
|
+
next(err);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async function renderFiltered(req, res, next) {
|
|
286
|
+
try {
|
|
287
|
+
const cids = String(req.query.cids || '');
|
|
288
|
+
const sort = String(req.query.sort || 'recent');
|
|
289
|
+
const teaserPost = String(req.query.teaserPost || 'first');
|
|
290
|
+
const teaserParseType = String(req.query.teaserParseType || 'default');
|
|
291
|
+
const thumbnailStyle = String(req.query.thumbnailStyle || 'background');
|
|
292
|
+
|
|
293
|
+
const allowedSorts = ['recent', 'create', 'votes', 'posts'];
|
|
294
|
+
const allowedTeasers = ['first', 'last-post'];
|
|
295
|
+
const allowedParseTypes = ['default', 'plaintext'];
|
|
296
|
+
const allowedThumbs = ['background', 'inline'];
|
|
297
|
+
|
|
298
|
+
const filteredTopics = await getTopics({
|
|
299
|
+
uid: req.uid,
|
|
300
|
+
data: {
|
|
301
|
+
topicsFromCid: cids,
|
|
302
|
+
sort: allowedSorts.includes(sort) ? sort : 'recent',
|
|
303
|
+
teaserPost: allowedTeasers.includes(teaserPost) ? teaserPost : 'first',
|
|
304
|
+
teaserParseType: allowedParseTypes.includes(teaserParseType) ? teaserParseType : 'default',
|
|
305
|
+
thumbnailStyle: allowedThumbs.includes(thumbnailStyle) ? thumbnailStyle : 'background',
|
|
306
|
+
},
|
|
307
|
+
templateData: {},
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
const html = await app.renderAsync('partials/nodebb-plugin-recent-cards/header', {
|
|
311
|
+
topics: filteredTopics,
|
|
312
|
+
config: { relative_path: nconf.get('relative_path') },
|
|
313
|
+
carouselMode: plugin.settings.get('enableCarousel'),
|
|
314
|
+
categories: '[]',
|
|
315
|
+
widgetConfig: '{}',
|
|
269
316
|
});
|
|
317
|
+
|
|
318
|
+
res.json({ html: html });
|
|
270
319
|
} catch (err) {
|
|
271
320
|
next(err);
|
|
272
321
|
}
|
package/package.json
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -93,18 +93,6 @@ $(document).ready(function () {
|
|
|
93
93
|
document.body.style.overflow = '';
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
function isLightColor(hex) {
|
|
97
|
-
if (!hex) return true;
|
|
98
|
-
hex = hex.replace('#', '');
|
|
99
|
-
if (hex.length === 3) {
|
|
100
|
-
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
101
|
-
}
|
|
102
|
-
const r = parseInt(hex.substr(0, 2), 16);
|
|
103
|
-
const g = parseInt(hex.substr(2, 2), 16);
|
|
104
|
-
const b = parseInt(hex.substr(4, 2), 16);
|
|
105
|
-
return (r * 299 + g * 587 + b * 114) / 1000 > 128;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
96
|
function getStorageKey(categories) {
|
|
109
97
|
const sortedCids = categories.map(c => c.cid).sort((a, b) => a - b);
|
|
110
98
|
return 'rc-filter-' + sortedCids.join('-');
|
|
@@ -133,6 +121,12 @@ $(document).ready(function () {
|
|
|
133
121
|
const inner = pluginContainer.find('.rc-filter-dropdown-inner');
|
|
134
122
|
inner.empty();
|
|
135
123
|
|
|
124
|
+
// Header with reset link
|
|
125
|
+
const header = $('<div class="rc-filter-header d-flex align-items-center justify-content-between px-3 py-2"></div>');
|
|
126
|
+
header.append($('<span class="text-muted text-xs fw-semibold text-uppercase"></span>').text('Kategoriler'));
|
|
127
|
+
header.append($('<button type="button" class="btn btn-link btn-sm rc-clear-all text-decoration-none p-0 text-xs"></button>').text('Temizle'));
|
|
128
|
+
inner.append(header);
|
|
129
|
+
|
|
136
130
|
categories.forEach(function (cat) {
|
|
137
131
|
const isChecked = !selectedCids || selectedCids.includes(cat.cid);
|
|
138
132
|
const item = $('<label class="rc-filter-option d-flex align-items-center gap-2 px-3 py-2"></label>');
|
|
@@ -153,104 +147,120 @@ $(document).ready(function () {
|
|
|
153
147
|
});
|
|
154
148
|
}
|
|
155
149
|
|
|
156
|
-
function updateChips(pluginContainer, selectedCids, categories) {
|
|
157
|
-
const chipsContainer = pluginContainer.find('.rc-filter-chips');
|
|
158
|
-
chipsContainer.empty();
|
|
159
|
-
|
|
160
|
-
if (!selectedCids || selectedCids.length === 0 || selectedCids.length === categories.length) {
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
selectedCids.forEach(function (cid) {
|
|
165
|
-
const cat = categories.find(c => c.cid === cid);
|
|
166
|
-
if (!cat) return;
|
|
167
|
-
const chip = $('<span class="rc-filter-chip badge d-flex align-items-center gap-1"></span>')
|
|
168
|
-
.attr('data-cid', cid)
|
|
169
|
-
.css({ backgroundColor: cat.bgColor || '#6c757d', color: cat.color || '#fff' });
|
|
170
|
-
chip.append($('<span></span>').text(cat.name));
|
|
171
|
-
const closeBtn = $('<button type="button" class="btn-close rc-chip-remove" aria-label="Remove"></button>');
|
|
172
|
-
if (!isLightColor(cat.bgColor)) {
|
|
173
|
-
closeBtn.addClass('btn-close-white');
|
|
174
|
-
}
|
|
175
|
-
chip.append(closeBtn);
|
|
176
|
-
chipsContainer.append(chip);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
chipsContainer.append(
|
|
180
|
-
$('<button type="button" class="btn btn-link btn-sm rc-clear-all text-decoration-none p-0 ms-1"></button>')
|
|
181
|
-
.text('Temizle')
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
150
|
function updateFilterButton(pluginContainer, selectedCids, categories) {
|
|
186
151
|
const btn = pluginContainer.find('.rc-filter-btn');
|
|
187
152
|
const isFiltered = selectedCids && selectedCids.length > 0 && selectedCids.length < categories.length;
|
|
188
|
-
btn.toggleClass('
|
|
189
|
-
btn.toggleClass('btn-primary', isFiltered);
|
|
153
|
+
btn.toggleClass('rc-filter-active', isFiltered);
|
|
190
154
|
const label = btn.find('.rc-filter-label');
|
|
191
155
|
label.text(isFiltered ? 'Filtrele (' + selectedCids.length + ')' : 'Filtrele');
|
|
192
156
|
}
|
|
193
157
|
|
|
158
|
+
function parseWidgetConfig(pluginContainer) {
|
|
159
|
+
const scriptTag = pluginContainer.find('script.rc-widget-config');
|
|
160
|
+
if (!scriptTag.length) return {};
|
|
161
|
+
try {
|
|
162
|
+
return JSON.parse(scriptTag.text()) || {};
|
|
163
|
+
} catch (e) {
|
|
164
|
+
return {};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
194
168
|
function applyFilter(pluginContainer, selectedCids, categories) {
|
|
195
169
|
const carouselContainer = pluginContainer.find('.recent-cards');
|
|
196
|
-
const isSlickInitialized = carouselContainer.hasClass('slick-initialized');
|
|
197
170
|
const isCarouselMode = config.recentCards && config.recentCards.enableCarousel;
|
|
198
171
|
const showAll = !selectedCids || selectedCids.length === 0 || selectedCids.length === categories.length;
|
|
172
|
+
const emptyState = pluginContainer.find('.rc-empty-state');
|
|
173
|
+
const widgetCfg = parseWidgetConfig(pluginContainer);
|
|
199
174
|
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
try {
|
|
203
|
-
carouselContainer.slick('unslick');
|
|
204
|
-
} catch (e) {
|
|
205
|
-
// Slick was not properly initialized
|
|
206
|
-
}
|
|
207
|
-
}
|
|
175
|
+
// Update button immediately
|
|
176
|
+
updateFilterButton(pluginContainer, selectedCids, categories);
|
|
208
177
|
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
pluginContainer.removeData('rc-stashed-cards');
|
|
178
|
+
// If showing all, and we have the original cards stashed, restore them
|
|
179
|
+
if (showAll && pluginContainer.data('rc-original-cards')) {
|
|
180
|
+
swapCards(carouselContainer, emptyState, pluginContainer.data('rc-original-cards'), isCarouselMode);
|
|
181
|
+
return;
|
|
214
182
|
}
|
|
215
183
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
carouselContainer.find('.recent-card-container').each(function () {
|
|
220
|
-
const cardCid = parseInt($(this).attr('data-cid'), 10);
|
|
221
|
-
if (showAll || selectedCids.includes(cardCid)) {
|
|
222
|
-
visibleCount++;
|
|
223
|
-
} else {
|
|
224
|
-
toStashElements.push(this);
|
|
225
|
-
}
|
|
226
|
-
});
|
|
184
|
+
if (showAll) {
|
|
185
|
+
return; // nothing to filter, initial load handles it
|
|
186
|
+
}
|
|
227
187
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
pluginContainer.data('rc-
|
|
188
|
+
// Stash original cards on first filter
|
|
189
|
+
if (!pluginContainer.data('rc-original-cards')) {
|
|
190
|
+
pluginContainer.data('rc-original-cards', carouselContainer.html());
|
|
231
191
|
}
|
|
232
192
|
|
|
233
|
-
//
|
|
234
|
-
const
|
|
235
|
-
if (
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
} else {
|
|
239
|
-
emptyState.addClass('d-none');
|
|
240
|
-
carouselContainer.removeClass('d-none');
|
|
193
|
+
// Abort any in-flight request (safe to call on completed/null)
|
|
194
|
+
const prevXhr = pluginContainer.data('rc-xhr');
|
|
195
|
+
if (prevXhr) {
|
|
196
|
+
prevXhr.abort();
|
|
197
|
+
pluginContainer.removeData('rc-xhr');
|
|
241
198
|
}
|
|
242
199
|
|
|
243
|
-
//
|
|
244
|
-
|
|
200
|
+
// Keep old cards visible while loading — no blank flash
|
|
201
|
+
const params = $.param({
|
|
202
|
+
cids: selectedCids.join(','),
|
|
203
|
+
sort: widgetCfg.sort || 'recent',
|
|
204
|
+
teaserPost: widgetCfg.teaserPost || 'first',
|
|
205
|
+
teaserParseType: widgetCfg.teaserParseType || 'default',
|
|
206
|
+
thumbnailStyle: widgetCfg.thumbnailStyle || 'background',
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const xhr = $.getJSON(config.relative_path + '/plugins/nodebb-plugin-recent-cards/filter?' + params)
|
|
210
|
+
.done(function (data) {
|
|
211
|
+
const parsed = $('<div>').html(data.html);
|
|
212
|
+
const newCards = parsed.find('.recent-cards').html();
|
|
213
|
+
|
|
214
|
+
if (!newCards || !newCards.trim()) {
|
|
215
|
+
destroySlick(carouselContainer);
|
|
216
|
+
emptyState.removeClass('d-none');
|
|
217
|
+
carouselContainer.addClass('d-none');
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Translate, then do instant swap (destroy → replace → reinit in one tick)
|
|
222
|
+
require(['translator'], function (translator) {
|
|
223
|
+
translator.Translator.create().translate(newCards).then(function (translated) {
|
|
224
|
+
swapCards(carouselContainer, emptyState, translated, isCarouselMode);
|
|
225
|
+
}).catch(function () {
|
|
226
|
+
swapCards(carouselContainer, emptyState, newCards, isCarouselMode);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
})
|
|
230
|
+
.fail(function (jqXHR, textStatus) {
|
|
231
|
+
if (textStatus === 'abort') return;
|
|
232
|
+
// On error, keep current cards as-is
|
|
233
|
+
})
|
|
234
|
+
.always(function () {
|
|
235
|
+
pluginContainer.removeData('rc-xhr');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
pluginContainer.data('rc-xhr', xhr);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function swapCards(carouselContainer, emptyState, html, isCarouselMode) {
|
|
242
|
+
// Instant swap: destroy → replace → reinit in one synchronous block (no blank flash)
|
|
243
|
+
destroySlick(carouselContainer);
|
|
244
|
+
emptyState.addClass('d-none');
|
|
245
|
+
carouselContainer.removeClass('d-none').html(html);
|
|
246
|
+
carouselContainer.find('.timeago').timeago();
|
|
247
|
+
|
|
248
|
+
if (isCarouselMode) {
|
|
245
249
|
carouselContainer.addClass('overflow-hidden invisible');
|
|
246
250
|
initSlick(carouselContainer);
|
|
247
|
-
} else
|
|
248
|
-
carouselContainer.removeClass('carousel-mode invisible');
|
|
251
|
+
} else {
|
|
252
|
+
carouselContainer.removeClass('carousel-mode invisible overflow-hidden');
|
|
249
253
|
}
|
|
254
|
+
}
|
|
250
255
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
256
|
+
function destroySlick(container) {
|
|
257
|
+
if (container.hasClass('slick-initialized')) {
|
|
258
|
+
try {
|
|
259
|
+
container.slick('unslick');
|
|
260
|
+
} catch (e) {
|
|
261
|
+
// Slick was not properly initialized
|
|
262
|
+
}
|
|
263
|
+
}
|
|
254
264
|
}
|
|
255
265
|
|
|
256
266
|
function parseCategories(pluginContainer) {
|
|
@@ -293,26 +303,21 @@ $(document).ready(function () {
|
|
|
293
303
|
}
|
|
294
304
|
});
|
|
295
305
|
|
|
296
|
-
// Checkbox change
|
|
306
|
+
// Checkbox change (debounced — user may click multiple checkboxes rapidly)
|
|
307
|
+
let filterTimeout;
|
|
297
308
|
pluginContainer.on('change.rcFilter', '.rc-filter-option input[type="checkbox"]', function () {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
selected
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
pluginContainer.on('click.rcFilter', '.rc-chip-remove', function (e) {
|
|
308
|
-
e.stopPropagation();
|
|
309
|
-
const chip = $(this).closest('.rc-filter-chip');
|
|
310
|
-
const cidToRemove = parseInt(chip.attr('data-cid'), 10);
|
|
311
|
-
pluginContainer.find('.rc-filter-option input[data-cid="' + cidToRemove + '"]')
|
|
312
|
-
.prop('checked', false).trigger('change');
|
|
309
|
+
clearTimeout(filterTimeout);
|
|
310
|
+
filterTimeout = setTimeout(function () {
|
|
311
|
+
const selected = [];
|
|
312
|
+
pluginContainer.find('.rc-filter-option input:checked').each(function () {
|
|
313
|
+
selected.push(parseInt($(this).attr('data-cid'), 10));
|
|
314
|
+
});
|
|
315
|
+
saveFilter(storageKey, selected, allCids);
|
|
316
|
+
applyFilter(pluginContainer, selected, categories);
|
|
317
|
+
}, 300);
|
|
313
318
|
});
|
|
314
319
|
|
|
315
|
-
// Clear all
|
|
320
|
+
// Clear all (from dropdown header)
|
|
316
321
|
pluginContainer.on('click.rcFilter', '.rc-clear-all', function (e) {
|
|
317
322
|
e.stopPropagation();
|
|
318
323
|
pluginContainer.find('.rc-filter-option input').prop('checked', true);
|
|
@@ -320,20 +325,17 @@ $(document).ready(function () {
|
|
|
320
325
|
applyFilter(pluginContainer, null, categories);
|
|
321
326
|
});
|
|
322
327
|
|
|
323
|
-
//
|
|
328
|
+
// Always init slick first with whatever cards are on the page
|
|
329
|
+
initSlick(pluginContainer.find('.recent-cards'));
|
|
330
|
+
|
|
331
|
+
// Then apply saved filter if exists (triggers AJAX fetch)
|
|
324
332
|
if (savedFilter) {
|
|
325
333
|
applyFilter(pluginContainer, savedFilter, categories);
|
|
326
|
-
return true; // filter was applied (slick handled inside applyFilter)
|
|
327
334
|
}
|
|
328
|
-
|
|
329
|
-
return false; // no filter applied, caller should init slick
|
|
330
335
|
}
|
|
331
336
|
|
|
332
337
|
function setupWidget(pluginContainer) {
|
|
333
|
-
|
|
334
|
-
if (!filterApplied) {
|
|
335
|
-
initSlick(pluginContainer.find('.recent-cards'));
|
|
336
|
-
}
|
|
338
|
+
initFilter(pluginContainer);
|
|
337
339
|
}
|
|
338
340
|
|
|
339
341
|
// Close dropdown on outside click & Escape
|
package/static/style.scss
CHANGED
|
@@ -33,9 +33,24 @@
|
|
|
33
33
|
.rc-filter-btn {
|
|
34
34
|
white-space: nowrap;
|
|
35
35
|
font-size: 0.85rem;
|
|
36
|
-
border-radius: var(--bs-border-radius);
|
|
36
|
+
border-radius: var(--bs-border-radius-pill);
|
|
37
|
+
color: var(--bs-body-color);
|
|
38
|
+
background-color: var(--bs-tertiary-bg);
|
|
39
|
+
border: 1px solid var(--bs-border-color);
|
|
40
|
+
padding: 0.35rem 0.85rem;
|
|
41
|
+
transition: all 0.15s ease;
|
|
42
|
+
&:hover {
|
|
43
|
+
background-color: var(--bs-secondary-bg);
|
|
44
|
+
border-color: var(--bs-secondary-bg);
|
|
45
|
+
}
|
|
46
|
+
&.rc-filter-active {
|
|
47
|
+
background-color: var(--bs-secondary-bg);
|
|
48
|
+
border-color: var(--bs-secondary-bg);
|
|
49
|
+
font-weight: 600;
|
|
50
|
+
}
|
|
37
51
|
.rc-caret {
|
|
38
52
|
transition: transform 0.2s;
|
|
53
|
+
opacity: 0.6;
|
|
39
54
|
}
|
|
40
55
|
&[aria-expanded="true"] .rc-caret {
|
|
41
56
|
transform: rotate(180deg);
|
|
@@ -44,8 +59,9 @@
|
|
|
44
59
|
|
|
45
60
|
.rc-filter-dropdown {
|
|
46
61
|
top: 100%;
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
right: 0;
|
|
63
|
+
left: auto;
|
|
64
|
+
min-width: min(16rem, 90vw);
|
|
49
65
|
max-height: clamp(10rem, 40vh, 20rem);
|
|
50
66
|
overflow-y: auto;
|
|
51
67
|
z-index: 1050;
|
|
@@ -54,8 +70,8 @@
|
|
|
54
70
|
margin-top: 0.25rem;
|
|
55
71
|
|
|
56
72
|
[data-dir="rtl"] & {
|
|
57
|
-
|
|
58
|
-
|
|
73
|
+
right: auto;
|
|
74
|
+
left: 0;
|
|
59
75
|
}
|
|
60
76
|
}
|
|
61
77
|
|
|
@@ -83,32 +99,8 @@
|
|
|
83
99
|
-webkit-tap-highlight-color: transparent;
|
|
84
100
|
}
|
|
85
101
|
|
|
86
|
-
.rc-filter-
|
|
87
|
-
|
|
88
|
-
scrollbar-width: thin;
|
|
89
|
-
&::-webkit-scrollbar {
|
|
90
|
-
height: 3px;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.rc-filter-chip {
|
|
95
|
-
font-size: 0.75rem;
|
|
96
|
-
line-height: 1.5;
|
|
97
|
-
padding: 0.25rem 0.5rem;
|
|
98
|
-
border-radius: var(--bs-border-radius-pill);
|
|
99
|
-
white-space: nowrap;
|
|
100
|
-
.rc-chip-remove {
|
|
101
|
-
width: 1rem;
|
|
102
|
-
height: 1rem;
|
|
103
|
-
padding: 0.25rem;
|
|
104
|
-
margin-left: 0.125rem;
|
|
105
|
-
opacity: 0.7;
|
|
106
|
-
background-size: 0.5rem;
|
|
107
|
-
box-sizing: content-box;
|
|
108
|
-
&:hover {
|
|
109
|
-
opacity: 1;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
102
|
+
.rc-filter-header {
|
|
103
|
+
border-bottom: 1px solid var(--bs-border-color);
|
|
112
104
|
}
|
|
113
105
|
|
|
114
106
|
.rc-empty-state {
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
{{{ if topics.length }}}
|
|
2
2
|
<div class="recent-cards-plugin preventSlideout">
|
|
3
3
|
<script type="application/json" class="rc-categories-data">{categories}</script>
|
|
4
|
-
|
|
5
|
-
<h5>{title}</h5>
|
|
6
|
-
{{{ end }}}
|
|
4
|
+
<script type="application/json" class="rc-widget-config">{widgetConfig}</script>
|
|
7
5
|
|
|
8
|
-
<div class="rc-filter-bar d-flex align-items-center
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
<div class="rc-filter-bar d-flex align-items-center justify-content-between mb-2">
|
|
7
|
+
{{{ if title }}}
|
|
8
|
+
<h5 class="mb-0 flex-grow-1">{title}</h5>
|
|
9
|
+
{{{ else }}}
|
|
10
|
+
<div class="flex-grow-1"></div>
|
|
11
|
+
{{{ end }}}
|
|
12
|
+
<div class="rc-filter-wrapper position-relative flex-shrink-0">
|
|
13
|
+
<button class="rc-filter-btn btn btn-sm d-flex align-items-center gap-1"
|
|
11
14
|
type="button"
|
|
12
15
|
aria-haspopup="listbox"
|
|
13
16
|
aria-expanded="false">
|
|
14
|
-
<i class="fa fa-
|
|
17
|
+
<i class="fa fa-sliders fa-xs"></i>
|
|
15
18
|
<span class="rc-filter-label">Filtrele</span>
|
|
16
19
|
<i class="fa fa-caret-down fa-xs rc-caret"></i>
|
|
17
20
|
</button>
|
|
@@ -19,7 +22,6 @@
|
|
|
19
22
|
<div class="rc-filter-dropdown-inner"></div>
|
|
20
23
|
</div>
|
|
21
24
|
</div>
|
|
22
|
-
<div class="rc-filter-chips d-flex align-items-center flex-wrap gap-1"></div>
|
|
23
25
|
</div>
|
|
24
26
|
|
|
25
27
|
<div class="{{{ if !carouselMode }}}row{{{ else }}}d-flex gap-3{{{ end }}} recent-cards carousel-mode overflow-hidden invisible" itemscope itemtype="http://www.schema.org/ItemList" {{{ if carouselMode }}}style=""{{{ end }}}>
|