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

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,24 @@ function getIdsArray(data, field) {
121
110
  return ids.split(',').map(c => c.trim()).filter(Boolean);
122
111
  }
123
112
 
113
+ const FILTER_CIDS = [1, 2, 64, 5, 10, 3, 49, 58, 9];
114
+
115
+ async function getAllCategories() {
116
+ let allCats = await categories.getCategoriesData(FILTER_CIDS);
117
+ allCats = allCats.filter(c => c && !c.disabled);
118
+ // Preserve the defined order
119
+ const orderMap = {};
120
+ FILTER_CIDS.forEach((cid, i) => { orderMap[cid] = i; });
121
+ allCats.sort((a, b) => orderMap[a.cid] - orderMap[b.cid]);
122
+ return allCats.map(c => ({
123
+ cid: c.cid,
124
+ name: c.name,
125
+ icon: c.icon,
126
+ bgColor: c.bgColor,
127
+ color: c.color,
128
+ }));
129
+ }
130
+
124
131
  function isVisibleInCategory(widget) {
125
132
  const cids = getIdsArray(widget.data, 'cid');
126
133
  return !(
@@ -256,25 +263,14 @@ async function renderExternal(req, res, next) {
256
263
  templateData: {},
257
264
  });
258
265
 
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
- });
266
+ const allCats = await getAllCategories();
271
267
 
272
268
  res.render('partials/nodebb-plugin-recent-cards/header', {
273
269
  topics: topicsData,
274
270
  config: {
275
271
  relative_path: nconf.get('url'),
276
272
  },
277
- categories: JSON.stringify(Object.values(categoryMap)).replace(/</g, '\\u003c'),
273
+ categories: JSON.stringify(allCats).replace(/</g, '\\u003c'),
278
274
  widgetConfig: '{}',
279
275
  });
280
276
  } 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.5",
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
  }