nodebb-plugin-recent-cards-2 1.0.0 → 1.0.15

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 CHANGED
@@ -7,6 +7,7 @@ const _ = require.main.require('lodash');
7
7
  const validator = require.main.require('validator');
8
8
  const db = require.main.require('./src/database');
9
9
  const topics = require.main.require('./src/topics');
10
+ const categories = require.main.require('./src/categories');
10
11
  const settings = require.main.require('./src/settings');
11
12
  const groups = require.main.require('./src/groups');
12
13
  const user = require.main.require('./src/user');
@@ -84,19 +85,7 @@ plugin.renderWidget = async function (widget) {
84
85
  }
85
86
  const topics = await getTopics(widget);
86
87
 
87
- const categoryMap = {};
88
- topics.forEach((t) => {
89
- if (t && t.category && !categoryMap[t.category.cid]) {
90
- categoryMap[t.category.cid] = {
91
- cid: t.category.cid,
92
- name: t.category.name,
93
- icon: t.category.icon,
94
- bgColor: t.category.bgColor,
95
- color: t.category.color,
96
- };
97
- }
98
- });
99
- const categories = Object.values(categoryMap);
88
+ const allCats = await getAllCategories();
100
89
 
101
90
  const widgetConfig = {
102
91
  sort: widget.data.sort || 'recent',
@@ -110,7 +99,7 @@ plugin.renderWidget = async function (widget) {
110
99
  config: widget.templateData.config,
111
100
  title: widget.data.title || '',
112
101
  carouselMode: plugin.settings.get('enableCarousel'),
113
- categories: JSON.stringify(categories).replace(/</g, '\\u003c'),
102
+ categories: JSON.stringify(allCats).replace(/</g, '\\u003c'),
114
103
  widgetConfig: JSON.stringify(widgetConfig).replace(/</g, '\\u003c'),
115
104
  });
116
105
  return widget;
@@ -121,6 +110,19 @@ function getIdsArray(data, field) {
121
110
  return ids.split(',').map(c => c.trim()).filter(Boolean);
122
111
  }
123
112
 
113
+ async function getAllCategories() {
114
+ const cids = await categories.getAllCidsFromSet('categories:cid');
115
+ let allCats = await categories.getCategoriesData(cids);
116
+ allCats = allCats.filter(c => c && !c.disabled && !c.link);
117
+ return allCats.map(c => ({
118
+ cid: c.cid,
119
+ name: c.name,
120
+ icon: c.icon,
121
+ bgColor: c.bgColor,
122
+ color: c.color,
123
+ }));
124
+ }
125
+
124
126
  function isVisibleInCategory(widget) {
125
127
  const cids = getIdsArray(widget.data, 'cid');
126
128
  return !(
@@ -256,25 +258,14 @@ async function renderExternal(req, res, next) {
256
258
  templateData: {},
257
259
  });
258
260
 
259
- const categoryMap = {};
260
- topicsData.forEach((t) => {
261
- if (t && t.category && !categoryMap[t.category.cid]) {
262
- categoryMap[t.category.cid] = {
263
- cid: t.category.cid,
264
- name: t.category.name,
265
- icon: t.category.icon,
266
- bgColor: t.category.bgColor,
267
- color: t.category.color,
268
- };
269
- }
270
- });
261
+ const allCats = await getAllCategories();
271
262
 
272
263
  res.render('partials/nodebb-plugin-recent-cards/header', {
273
264
  topics: topicsData,
274
265
  config: {
275
266
  relative_path: nconf.get('url'),
276
267
  },
277
- categories: JSON.stringify(Object.values(categoryMap)).replace(/</g, '\\u003c'),
268
+ categories: JSON.stringify(allCats).replace(/</g, '\\u003c'),
278
269
  widgetConfig: '{}',
279
270
  });
280
271
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-recent-cards-2",
3
- "version": "1.0.0",
3
+ "version": "1.0.15",
4
4
  "description": "Add lavender-style cards of recent topics to Persona's category homepage",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -99,12 +99,15 @@ $(document).ready(function () {
99
99
  const inner = pluginContainer.find('.rc-filter-dropdown-inner');
100
100
  inner.empty();
101
101
 
102
- // Header with reset link
102
+ // Sticky header with reset link
103
103
  const header = $('<div class="rc-filter-header d-flex align-items-center justify-content-between px-3 py-2"></div>');
104
104
  header.append($('<span class="text-muted text-xs fw-semibold text-uppercase"></span>').text('Kategoriler'));
105
105
  header.append($('<button type="button" class="btn btn-link btn-sm rc-clear-all text-decoration-none p-0 text-xs"></button>').text('Temizle'));
106
106
  inner.append(header);
107
107
 
108
+ // Scrollable category list
109
+ const list = $('<div class="rc-filter-dropdown-list"></div>');
110
+
108
111
  categories.forEach(function (cat) {
109
112
  const isChecked = selectedCids ? selectedCids.includes(cat.cid) : false;
110
113
  const item = $('<label class="rc-filter-option d-flex align-items-center gap-2 px-3 py-2"></label>');
@@ -121,8 +124,10 @@ $(document).ready(function () {
121
124
  item.append($('<i></i>').addClass('fa').addClass(cat.icon).css('color', cat.bgColor || '#6c757d'));
122
125
  }
123
126
  item.append(nameSpan);
124
- inner.append(item);
127
+ list.append(item);
125
128
  });
129
+
130
+ inner.append(list);
126
131
  }
127
132
 
128
133
  function updateFilterButton(pluginContainer, selectedCids, categories) {
package/static/style.scss CHANGED
@@ -62,17 +62,24 @@
62
62
  right: 0;
63
63
  left: auto;
64
64
  min-width: min(16rem, 90vw);
65
- max-height: clamp(10rem, 40vh, 20rem);
66
- overflow-y: auto;
67
65
  z-index: 1050;
68
66
  background: var(--bs-body-bg);
69
67
  border-color: var(--bs-border-color) !important;
70
68
  margin-top: 0.25rem;
69
+ overflow: hidden;
70
+ display: flex;
71
+ flex-direction: column;
71
72
 
72
73
  [data-dir="rtl"] & {
73
74
  right: auto;
74
75
  left: 0;
75
76
  }
77
+
78
+ .rc-filter-dropdown-list {
79
+ max-height: 16.5rem; // ~6 items (6 x 2.75rem)
80
+ overflow-y: auto;
81
+ -webkit-overflow-scrolling: touch;
82
+ }
76
83
  }
77
84
 
78
85
  .rc-filter-option {
@@ -118,13 +125,15 @@
118
125
  right: 0 !important;
119
126
  bottom: 0 !important;
120
127
  top: auto !important;
121
- max-height: 50vh;
122
- max-height: 50dvh; // dynamic viewport height for PWA standalone
123
128
  border-radius: var(--bs-border-radius-lg) var(--bs-border-radius-lg) 0 0;
124
129
  margin-top: 0;
125
130
  min-width: 100%;
126
- padding-bottom: env(safe-area-inset-bottom, 0); // iOS home indicator
127
- -webkit-overflow-scrolling: touch;
131
+ padding-bottom: env(safe-area-inset-bottom, 0);
132
+
133
+ .rc-filter-dropdown-list {
134
+ max-height: 50vh;
135
+ max-height: 50dvh;
136
+ }
128
137
  }
129
138
  }
130
139
  }