@blocklet/list 0.8.62 → 0.8.65
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/base.js +2 -2
- package/lib/components/list/index.js +8 -8
- package/lib/contexts/filter.js +67 -116
- package/lib/libs/constant.js +17 -0
- package/lib/libs/utils.js +15 -28
- package/package.json +3 -3
- package/src/base.js +2 -2
- package/src/components/list/index.js +7 -7
- package/src/contexts/filter.js +57 -104
- package/src/libs/constant.js +11 -0
- package/src/libs/utils.js +12 -18
package/lib/base.js
CHANGED
|
@@ -40,7 +40,7 @@ function ListBase() {
|
|
|
40
40
|
|
|
41
41
|
const {
|
|
42
42
|
handleDeveloper,
|
|
43
|
-
|
|
43
|
+
blockletList,
|
|
44
44
|
filters,
|
|
45
45
|
developerName,
|
|
46
46
|
handleSort,
|
|
@@ -117,7 +117,7 @@ function ListBase() {
|
|
|
117
117
|
overflow: 'auto'
|
|
118
118
|
},
|
|
119
119
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_list.default, {
|
|
120
|
-
blocklets:
|
|
120
|
+
blocklets: blockletList
|
|
121
121
|
})
|
|
122
122
|
})
|
|
123
123
|
})]
|
|
@@ -54,7 +54,6 @@ function BlockletList(_ref) {
|
|
|
54
54
|
errors,
|
|
55
55
|
loadings,
|
|
56
56
|
selectedCategory,
|
|
57
|
-
finalBlockletList,
|
|
58
57
|
getCategoryLocale,
|
|
59
58
|
filters,
|
|
60
59
|
t,
|
|
@@ -62,9 +61,10 @@ function BlockletList(_ref) {
|
|
|
62
61
|
loadMore,
|
|
63
62
|
endpoint
|
|
64
63
|
} = (0, _filter.useFilterContext)();
|
|
65
|
-
const showFilterTip = !!selectedCategory || !!filters.price;
|
|
64
|
+
const showFilterTip = !!selectedCategory || !!filters.price; // eslint-disable-next-line no-unused-vars
|
|
65
|
+
|
|
66
66
|
const [sentryRef] = (0, _reactInfiniteScrollHook.default)({
|
|
67
|
-
loading: loadings.fetchBlockletsLoading,
|
|
67
|
+
loading: loadings.fetchBlockletsLoading || loadings.loadingMore,
|
|
68
68
|
hasNextPage,
|
|
69
69
|
onLoadMore: loadMore
|
|
70
70
|
});
|
|
@@ -85,7 +85,7 @@ function BlockletList(_ref) {
|
|
|
85
85
|
});
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
if (filters.keyword && showFilterTip &&
|
|
88
|
+
if (filters.keyword && showFilterTip && blocklets.length === 0) {
|
|
89
89
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(CustomEmpty, {
|
|
90
90
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_empty.EmptyTitle, {
|
|
91
91
|
primaryStart: t('blocklet.noBlockletPart1'),
|
|
@@ -98,7 +98,7 @@ function BlockletList(_ref) {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
if (filters.keyword &&
|
|
101
|
+
if (filters.keyword && blocklets.length === 0) {
|
|
102
102
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(CustomEmpty, {
|
|
103
103
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_empty.EmptyTitle, {
|
|
104
104
|
primaryStart: t('blocklet.noBlockletPart1'),
|
|
@@ -110,7 +110,7 @@ function BlockletList(_ref) {
|
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
if (showFilterTip &&
|
|
113
|
+
if (showFilterTip && blocklets.length === 0) {
|
|
114
114
|
const categoryLocale = getCategoryLocale(selectedCategory);
|
|
115
115
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(CustomEmpty, {
|
|
116
116
|
children: [categoryLocale ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_empty.EmptyTitle, {
|
|
@@ -123,7 +123,7 @@ function BlockletList(_ref) {
|
|
|
123
123
|
});
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
if (
|
|
126
|
+
if (blocklets.length === 0) {
|
|
127
127
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(CustomEmpty, {
|
|
128
128
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_empty.NoResults, {})
|
|
129
129
|
});
|
|
@@ -141,7 +141,7 @@ function BlockletList(_ref) {
|
|
|
141
141
|
"data-blocklet-did": blocklet.did,
|
|
142
142
|
children: blockletRender({
|
|
143
143
|
blocklet,
|
|
144
|
-
blocklets
|
|
144
|
+
blocklets
|
|
145
145
|
})
|
|
146
146
|
}, blocklet.did)), hasNextPage && /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledGridItem, {
|
|
147
147
|
item: true,
|
package/lib/contexts/filter.js
CHANGED
|
@@ -17,14 +17,14 @@ var _orderBy = _interopRequireDefault(require("lodash/orderBy"));
|
|
|
17
17
|
|
|
18
18
|
var _axios = _interopRequireDefault(require("axios"));
|
|
19
19
|
|
|
20
|
-
var _isArray = _interopRequireDefault(require("lodash/isArray"));
|
|
21
|
-
|
|
22
20
|
var _utils = require("../libs/utils");
|
|
23
21
|
|
|
24
22
|
var _locale = _interopRequireDefault(require("../assets/locale"));
|
|
25
23
|
|
|
26
24
|
var _propTypes2 = require("../libs/prop-types");
|
|
27
25
|
|
|
26
|
+
var _constant = _interopRequireDefault(require("../libs/constant"));
|
|
27
|
+
|
|
28
28
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
29
29
|
|
|
30
30
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -57,118 +57,72 @@ function FilterProvider(_ref) {
|
|
|
57
57
|
baseURL: endpoint
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
const finalFilters = (0, _react.useMemo)(() => {
|
|
61
|
+
return _objectSpread({
|
|
62
|
+
sortBy: 'popularity',
|
|
63
|
+
sortDirection: 'desc'
|
|
64
|
+
}, filters);
|
|
65
|
+
}, [filters]);
|
|
66
|
+
const selectedCategory = finalFilters.category;
|
|
67
|
+
const paginateState = (0, _ahooks.useReactive)({
|
|
68
|
+
currentPage: _constant.default.currentPage,
|
|
69
|
+
pageSize: (0, _utils.isMobileScreen)() ? _constant.default.mobilePageSize : _constant.default.pageSize,
|
|
70
|
+
defaultCurrentPage: _constant.default.defaultCurrentPage
|
|
71
|
+
});
|
|
60
72
|
const {
|
|
61
|
-
data:
|
|
73
|
+
data: blockletsState,
|
|
62
74
|
error: fetchBlockletsError,
|
|
63
75
|
loading: fetchBlockletsLoading,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
} = await storeApi.get('/api/blocklets.json');
|
|
76
|
+
loadMore: _loadMore,
|
|
77
|
+
loadingMore
|
|
78
|
+
} = (0, _ahooks.useRequest)(async d => {
|
|
79
|
+
var _d$list;
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
const params = _objectSpread(_objectSpread({}, finalFilters), {}, {
|
|
82
|
+
sortBy: _constant.default[finalFilters.sortBy],
|
|
83
|
+
page: (0, _utils.getCurrentPage)((d === null || d === void 0 ? void 0 : (_d$list = d.list) === null || _d$list === void 0 ? void 0 : _d$list.length) || 0, paginateState.pageSize),
|
|
84
|
+
pageSize: paginateState.pageSize
|
|
85
|
+
});
|
|
73
86
|
|
|
87
|
+
const {
|
|
88
|
+
data = {}
|
|
89
|
+
} = await storeApi.get('/api/v2/blocklets.json', {
|
|
90
|
+
params
|
|
91
|
+
});
|
|
74
92
|
return data;
|
|
75
93
|
}, {
|
|
76
|
-
initialData:
|
|
77
|
-
|
|
94
|
+
initialData: {
|
|
95
|
+
list: [],
|
|
96
|
+
total: 0
|
|
97
|
+
},
|
|
98
|
+
loadMore: true,
|
|
99
|
+
isNoMore: d => d ? d.list.length >= d.total : false,
|
|
100
|
+
// eslint-disable-next-line no-console
|
|
101
|
+
formatResult: response => {
|
|
102
|
+
return {
|
|
103
|
+
list: response === null || response === void 0 ? void 0 : response.dataList,
|
|
104
|
+
total: response.total
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
refreshDeps: [endpoint, filters]
|
|
78
108
|
});
|
|
79
109
|
const {
|
|
80
110
|
data: allCategories,
|
|
81
111
|
error: fetchCategoriesError,
|
|
82
|
-
loading: fetchCategoriesLoading
|
|
83
|
-
run: fetchCategories
|
|
112
|
+
loading: fetchCategoriesLoading
|
|
84
113
|
} = (0, _ahooks.useRequest)(async () => {
|
|
85
114
|
const {
|
|
86
115
|
data
|
|
87
116
|
} = await storeApi.get('/api/blocklets/categories');
|
|
88
|
-
|
|
89
|
-
if (!(0, _isArray.default)(data)) {
|
|
90
|
-
throw new Error('/api/blocklets/categories response is not array');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
117
|
return data;
|
|
94
118
|
}, {
|
|
95
|
-
initialData: []
|
|
96
|
-
manual: true
|
|
119
|
+
initialData: []
|
|
97
120
|
});
|
|
98
|
-
const paginateState = (0, _ahooks.useReactive)({
|
|
99
|
-
currentPage: 1,
|
|
100
|
-
pageSize: (0, _utils.isMobileScreen)() ? 10 : 18,
|
|
101
|
-
defaultCurrentPage: 1
|
|
102
|
-
}); // TODO: 这里如果用 useMemo 包裹,滚动分页会异常
|
|
103
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
104
|
-
|
|
105
|
-
const finalFilters = _objectSpread({
|
|
106
|
-
sortBy: 'popularity',
|
|
107
|
-
sortDirection: 'desc'
|
|
108
|
-
}, filters);
|
|
109
|
-
|
|
110
|
-
const selectedCategory = finalFilters.category;
|
|
111
|
-
const hasDeveloperFilter = !!finalFilters.developer;
|
|
112
|
-
const categoryState = (0, _react.useMemo)(() => {
|
|
113
|
-
// 当按作者过滤时,需要从所有blocklets中找出属于作者的分类
|
|
114
|
-
return !hasDeveloperFilter ? {
|
|
115
|
-
data: allCategories
|
|
116
|
-
} : (0, _utils.getCategoriesByAuthor)(allBlocklets, finalFilters.developer);
|
|
117
|
-
}, [hasDeveloperFilter, allCategories, allBlocklets, finalFilters.developer]);
|
|
118
|
-
const blockletList = (0, _react.useMemo)(() => {
|
|
119
|
-
var _finalFilters$keyword;
|
|
120
|
-
|
|
121
|
-
const sortByName = x => {
|
|
122
|
-
var _x$title, _x$name;
|
|
123
|
-
|
|
124
|
-
return (x === null || x === void 0 ? void 0 : (_x$title = x.title) === null || _x$title === void 0 ? void 0 : _x$title.toLocaleLowerCase()) || (x === null || x === void 0 ? void 0 : (_x$name = x.name) === null || _x$name === void 0 ? void 0 : _x$name.toLocaleLowerCase());
|
|
125
|
-
}; // 按名称排序
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const sortByPopularity = x => x.stats.downloads; // 按下载量排序
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const sortByPublish = x => x.lastPublishedAt; // 按发布时间
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const sortMap = {
|
|
135
|
-
nameAsc: sortByName,
|
|
136
|
-
nameDesc: sortByName,
|
|
137
|
-
popularity: sortByPopularity,
|
|
138
|
-
publishAt: sortByPublish
|
|
139
|
-
};
|
|
140
|
-
let blocklets = allBlocklets || []; // 按照付费/免费筛选
|
|
141
|
-
|
|
142
|
-
blocklets = (0, _utils.filterBlockletByPrice)(blocklets, finalFilters.price); // 按照分类筛选
|
|
143
|
-
|
|
144
|
-
blocklets = blocklets.filter(item => {
|
|
145
|
-
var _item$category;
|
|
146
|
-
|
|
147
|
-
return selectedCategory ? (item === null || item === void 0 ? void 0 : (_item$category = item.category) === null || _item$category === void 0 ? void 0 : _item$category.name) === selectedCategory : true;
|
|
148
|
-
}); // 按照作者筛选
|
|
149
|
-
|
|
150
|
-
blocklets = blocklets.filter(item => finalFilters !== null && finalFilters !== void 0 && finalFilters.developer ? item.owner.did === finalFilters.developer : true);
|
|
151
|
-
const lowerSearch = (finalFilters === null || finalFilters === void 0 ? void 0 : (_finalFilters$keyword = finalFilters.keyword) === null || _finalFilters$keyword === void 0 ? void 0 : _finalFilters$keyword.toLocaleLowerCase()) || ''; // 按照搜索筛选
|
|
152
|
-
|
|
153
|
-
blocklets = blocklets.filter(item => {
|
|
154
|
-
var _ref2, _item$description, _item$version;
|
|
155
|
-
|
|
156
|
-
return ((_ref2 = (item === null || item === void 0 ? void 0 : item.title) || (item === null || item === void 0 ? void 0 : item.name)) === null || _ref2 === void 0 ? void 0 : _ref2.toLocaleLowerCase().includes(lowerSearch)) || ((_item$description = item.description) === null || _item$description === void 0 ? void 0 : _item$description.toLocaleLowerCase().includes(lowerSearch)) || (item === null || item === void 0 ? void 0 : (_item$version = item.version) === null || _item$version === void 0 ? void 0 : _item$version.toLocaleLowerCase().includes(lowerSearch));
|
|
157
|
-
}); // 用户传入的过滤函数
|
|
158
|
-
|
|
159
|
-
blocklets = extraFilter(blocklets); // 排序
|
|
160
|
-
|
|
161
|
-
return (0, _orderBy.default)(blocklets, [sortMap[finalFilters.sortBy]], [finalFilters.sortDirection]);
|
|
162
|
-
}, [allBlocklets, finalFilters, selectedCategory, extraFilter]);
|
|
163
|
-
const finalBlockletList = (0, _react.useMemo)(() => {
|
|
164
|
-
// 前端分页 currentPage 当前页数 pageSize 每页条数
|
|
165
|
-
return blockletList.slice((paginateState.defaultCurrentPage - 1) * paginateState.pageSize, paginateState.currentPage * paginateState.pageSize);
|
|
166
|
-
}, [blockletList, paginateState]);
|
|
167
121
|
const categoryList = (0, _react.useMemo)(() => {
|
|
168
|
-
const list =
|
|
122
|
+
const list = allCategories || []; // 分类按照名称排序
|
|
169
123
|
|
|
170
124
|
return (0, _orderBy.default)(list, [i => i.name], ['asc']);
|
|
171
|
-
}, [
|
|
125
|
+
}, [allCategories]);
|
|
172
126
|
|
|
173
127
|
const translate = (key, data) => {
|
|
174
128
|
if (!_locale.default[locale] || !_locale.default[locale][key]) {
|
|
@@ -179,6 +133,12 @@ function FilterProvider(_ref) {
|
|
|
179
133
|
return (0, _utils.replaceTranslate)(_locale.default[locale][key], data);
|
|
180
134
|
};
|
|
181
135
|
|
|
136
|
+
const blockletList = (0, _react.useMemo)(() => {
|
|
137
|
+
let blocklets = blockletsState.list || []; // 用户传入的过滤函数
|
|
138
|
+
|
|
139
|
+
blocklets = extraFilter(blocklets);
|
|
140
|
+
return blocklets; // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
141
|
+
}, [blockletsState, extraFilter]);
|
|
182
142
|
const categoryOptions = (0, _react.useMemo)(() => (0, _utils.getCategoryOptions)(categoryList, locale), [categoryList, locale]);
|
|
183
143
|
const priceOptions = (0, _utils.getPrices)(translate);
|
|
184
144
|
const filterStore = {
|
|
@@ -188,10 +148,11 @@ function FilterProvider(_ref) {
|
|
|
188
148
|
},
|
|
189
149
|
loadings: {
|
|
190
150
|
fetchBlockletsLoading,
|
|
191
|
-
fetchCategoriesLoading
|
|
151
|
+
fetchCategoriesLoading,
|
|
152
|
+
loadingMore
|
|
192
153
|
},
|
|
193
154
|
endpoint,
|
|
194
|
-
|
|
155
|
+
blockletList,
|
|
195
156
|
t: translate,
|
|
196
157
|
filters: finalFilters,
|
|
197
158
|
selectedCategory,
|
|
@@ -200,7 +161,7 @@ function FilterProvider(_ref) {
|
|
|
200
161
|
locale,
|
|
201
162
|
categoryOptions,
|
|
202
163
|
priceOptions,
|
|
203
|
-
hasNextPage:
|
|
164
|
+
hasNextPage: blockletsState.list.length < blockletsState.total,
|
|
204
165
|
handleSort: sort => {
|
|
205
166
|
const changeData = _objectSpread(_objectSpread({}, finalFilters), {}, {
|
|
206
167
|
sortBy: sort,
|
|
@@ -236,9 +197,9 @@ function FilterProvider(_ref) {
|
|
|
236
197
|
|
|
237
198
|
onFilterChange(changeData);
|
|
238
199
|
},
|
|
239
|
-
handleDeveloper:
|
|
200
|
+
handleDeveloper: owner => {
|
|
240
201
|
const changeData = _objectSpread(_objectSpread({}, finalFilters), {}, {
|
|
241
|
-
|
|
202
|
+
owner: owner || undefined
|
|
242
203
|
});
|
|
243
204
|
|
|
244
205
|
onFilterChange(changeData);
|
|
@@ -252,13 +213,13 @@ function FilterProvider(_ref) {
|
|
|
252
213
|
},
|
|
253
214
|
loadMore: () => {
|
|
254
215
|
setTimeout(() => {
|
|
255
|
-
|
|
216
|
+
_loadMore();
|
|
256
217
|
}, 1000);
|
|
257
218
|
},
|
|
258
219
|
getCategoryLocale: category => {
|
|
259
220
|
if (!category) return null;
|
|
260
221
|
let result = null;
|
|
261
|
-
const find =
|
|
222
|
+
const find = allCategories.find(item => item._id === category);
|
|
262
223
|
|
|
263
224
|
if (find) {
|
|
264
225
|
result = find.locales[locale];
|
|
@@ -267,28 +228,18 @@ function FilterProvider(_ref) {
|
|
|
267
228
|
return result;
|
|
268
229
|
},
|
|
269
230
|
|
|
270
|
-
get allBlocklets() {
|
|
271
|
-
return allBlocklets || [];
|
|
272
|
-
},
|
|
273
|
-
|
|
274
231
|
get developerName() {
|
|
275
232
|
var _blocklets$find, _blocklets$find$owner;
|
|
276
233
|
|
|
277
|
-
const blocklets =
|
|
278
|
-
return ((_blocklets$find = blocklets.find(blocklet =>
|
|
234
|
+
const blocklets = blockletList;
|
|
235
|
+
return ((_blocklets$find = blocklets.find(blocklet => {
|
|
236
|
+
var _blocklet$owner;
|
|
237
|
+
|
|
238
|
+
return (blocklet === null || blocklet === void 0 ? void 0 : (_blocklet$owner = blocklet.owner) === null || _blocklet$owner === void 0 ? void 0 : _blocklet$owner.did) === finalFilters.owner;
|
|
239
|
+
})) === null || _blocklets$find === void 0 ? void 0 : (_blocklets$find$owner = _blocklets$find.owner) === null || _blocklets$find$owner === void 0 ? void 0 : _blocklets$find$owner.name) || '';
|
|
279
240
|
}
|
|
280
241
|
|
|
281
242
|
};
|
|
282
|
-
(0, _react.useEffect)(() => {
|
|
283
|
-
if (!hasDeveloperFilter) {
|
|
284
|
-
fetchCategories();
|
|
285
|
-
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
286
|
-
|
|
287
|
-
}, [hasDeveloperFilter]);
|
|
288
|
-
(0, _react.useEffect)(() => {
|
|
289
|
-
fetchBlocklets();
|
|
290
|
-
fetchCategories(); // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
291
|
-
}, [endpoint]);
|
|
292
243
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(Provider, {
|
|
293
244
|
value: filterStore,
|
|
294
245
|
children: children
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
const constant = {
|
|
8
|
+
nameAsc: 'title',
|
|
9
|
+
nameDesc: 'title',
|
|
10
|
+
popularity: 'stats.downloads',
|
|
11
|
+
publishAt: 'lastPublishedAt',
|
|
12
|
+
mobilePageSize: 10,
|
|
13
|
+
pageSize: 18,
|
|
14
|
+
defaultCurrentPage: 1
|
|
15
|
+
};
|
|
16
|
+
var _default = constant;
|
|
17
|
+
exports.default = _default;
|
package/lib/libs/utils.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.urlStringify = exports.replaceTranslate = exports.removeUndefined = exports.isMobileScreen = exports.getStoreDetail = exports.getSortOptions = exports.getPrices = exports.
|
|
6
|
+
exports.urlStringify = exports.replaceTranslate = exports.removeUndefined = exports.isMobileScreen = exports.getStoreDetail = exports.getSortOptions = exports.getPrices = exports.getCurrentPage = exports.getCategoryOptions = exports.formatLogoPath = exports.formatError = exports.filterBlockletByPrice = void 0;
|
|
7
7
|
|
|
8
8
|
var _urlJoin = _interopRequireDefault(require("url-join"));
|
|
9
9
|
|
|
@@ -11,12 +11,12 @@ var _cloneDeep = _interopRequireDefault(require("lodash/cloneDeep"));
|
|
|
11
11
|
|
|
12
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
13
|
|
|
14
|
-
const isFreeBlocklet =
|
|
15
|
-
if (!
|
|
14
|
+
const isFreeBlocklet = blocklet => {
|
|
15
|
+
if (!blocklet.payment) {
|
|
16
16
|
return true;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const priceList = (
|
|
19
|
+
const priceList = (blocklet.payment.price || []).map(x => x.value || 0);
|
|
20
20
|
return priceList.every(x => x === 0);
|
|
21
21
|
};
|
|
22
22
|
|
|
@@ -55,30 +55,9 @@ const getCategoryOptions = function getCategoryOptions() {
|
|
|
55
55
|
let locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'en';
|
|
56
56
|
return list.map(item => ({
|
|
57
57
|
name: item.locales[locale],
|
|
58
|
-
value: item.
|
|
58
|
+
value: item._id
|
|
59
59
|
}));
|
|
60
60
|
};
|
|
61
|
-
/**
|
|
62
|
-
* 从 blocklets 中的得到属于作者的 Categories
|
|
63
|
-
* @param {*} list
|
|
64
|
-
* @param {*} developerDid
|
|
65
|
-
* @returns
|
|
66
|
-
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
exports.getCategoryOptions = getCategoryOptions;
|
|
70
|
-
|
|
71
|
-
const getCategoriesByAuthor = function getCategoriesByAuthor() {
|
|
72
|
-
let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
73
|
-
let developerDid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
74
|
-
const filterList = list.filter(item => developerDid ? item.owner.did === developerDid : true);
|
|
75
|
-
const Categories = filterList.map(item => item.category);
|
|
76
|
-
const res = new Map();
|
|
77
|
-
const result = Categories.filter(i => !!i).filter(a => !res.has(a._id) && res.set(a._id, 1));
|
|
78
|
-
return {
|
|
79
|
-
data: result
|
|
80
|
-
};
|
|
81
|
-
};
|
|
82
61
|
/**
|
|
83
62
|
* 根据 是否付费 过滤 blocklet list
|
|
84
63
|
* @param {*} list
|
|
@@ -87,7 +66,7 @@ const getCategoriesByAuthor = function getCategoriesByAuthor() {
|
|
|
87
66
|
*/
|
|
88
67
|
|
|
89
68
|
|
|
90
|
-
exports.
|
|
69
|
+
exports.getCategoryOptions = getCategoryOptions;
|
|
91
70
|
|
|
92
71
|
const filterBlockletByPrice = function filterBlockletByPrice() {
|
|
93
72
|
let list = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
|
@@ -165,4 +144,12 @@ const isMobileScreen = () => {
|
|
|
165
144
|
return window.innerWidth <= 600;
|
|
166
145
|
};
|
|
167
146
|
|
|
168
|
-
exports.isMobileScreen = isMobileScreen;
|
|
147
|
+
exports.isMobileScreen = isMobileScreen;
|
|
148
|
+
|
|
149
|
+
const getCurrentPage = (length, pageSize) => {
|
|
150
|
+
const page = (length + pageSize) / pageSize;
|
|
151
|
+
if (page > 1) return page.toFixed();
|
|
152
|
+
return 1;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
exports.getCurrentPage = getCurrentPage;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/list",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.65",
|
|
4
4
|
"description": "Common ux components of blocklet",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"react": ">=18.1.0"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@arcblock/ux": "^2.1.
|
|
41
|
+
"@arcblock/ux": "^2.1.71",
|
|
42
42
|
"@emotion/react": "^11.9.0",
|
|
43
43
|
"@emotion/styled": "^11.8.1",
|
|
44
44
|
"@mui/icons-material": "^5.6.2",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"eslint": "^8.16.0",
|
|
65
65
|
"prettier": "^2.6.2"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "3ddb0217a07753400bdcfefd10c76f76e69a3b05"
|
|
68
68
|
}
|
package/src/base.js
CHANGED
|
@@ -16,7 +16,7 @@ import Search from './components/search';
|
|
|
16
16
|
function ListBase() {
|
|
17
17
|
const {
|
|
18
18
|
handleDeveloper,
|
|
19
|
-
|
|
19
|
+
blockletList,
|
|
20
20
|
filters,
|
|
21
21
|
developerName,
|
|
22
22
|
handleSort,
|
|
@@ -79,7 +79,7 @@ function ListBase() {
|
|
|
79
79
|
</Box>
|
|
80
80
|
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
|
81
81
|
<div style={{ position: 'relative', flex: 1, overflow: 'auto' }}>
|
|
82
|
-
<BlockletList blocklets={
|
|
82
|
+
<BlockletList blocklets={blockletList} />
|
|
83
83
|
</div>
|
|
84
84
|
</ErrorBoundary>
|
|
85
85
|
</StyledMin>
|
|
@@ -17,7 +17,6 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
17
17
|
errors,
|
|
18
18
|
loadings,
|
|
19
19
|
selectedCategory,
|
|
20
|
-
finalBlockletList,
|
|
21
20
|
getCategoryLocale,
|
|
22
21
|
filters,
|
|
23
22
|
t,
|
|
@@ -28,8 +27,9 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
28
27
|
|
|
29
28
|
const showFilterTip = !!selectedCategory || !!filters.price;
|
|
30
29
|
|
|
30
|
+
// eslint-disable-next-line no-unused-vars
|
|
31
31
|
const [sentryRef] = useInfiniteScroll({
|
|
32
|
-
loading: loadings.fetchBlockletsLoading,
|
|
32
|
+
loading: loadings.fetchBlockletsLoading || loadings.loadingMore,
|
|
33
33
|
hasNextPage,
|
|
34
34
|
onLoadMore: loadMore,
|
|
35
35
|
});
|
|
@@ -48,7 +48,7 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
48
48
|
</Box>
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
|
-
if (filters.keyword && showFilterTip &&
|
|
51
|
+
if (filters.keyword && showFilterTip && blocklets.length === 0) {
|
|
52
52
|
return (
|
|
53
53
|
<CustomEmpty>
|
|
54
54
|
<EmptyTitle
|
|
@@ -60,7 +60,7 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
60
60
|
</CustomEmpty>
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
|
-
if (filters.keyword &&
|
|
63
|
+
if (filters.keyword && blocklets.length === 0) {
|
|
64
64
|
return (
|
|
65
65
|
<CustomEmpty>
|
|
66
66
|
<EmptyTitle
|
|
@@ -72,7 +72,7 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
72
72
|
</CustomEmpty>
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
|
-
if (showFilterTip &&
|
|
75
|
+
if (showFilterTip && blocklets.length === 0) {
|
|
76
76
|
const categoryLocale = getCategoryLocale(selectedCategory);
|
|
77
77
|
return (
|
|
78
78
|
<CustomEmpty>
|
|
@@ -89,7 +89,7 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
89
89
|
</CustomEmpty>
|
|
90
90
|
);
|
|
91
91
|
}
|
|
92
|
-
if (
|
|
92
|
+
if (blocklets.length === 0) {
|
|
93
93
|
return (
|
|
94
94
|
<CustomEmpty>
|
|
95
95
|
<NoResults />
|
|
@@ -101,7 +101,7 @@ export default function BlockletList({ blocklets, ...rest }) {
|
|
|
101
101
|
<StyledGrid container {...rest}>
|
|
102
102
|
{blocklets.map((blocklet) => (
|
|
103
103
|
<StyledGridItem item lg={4} md={6} sm={6} xs={12} key={blocklet.did} data-blocklet-did={blocklet.did}>
|
|
104
|
-
{blockletRender({ blocklet, blocklets
|
|
104
|
+
{blockletRender({ blocklet, blocklets })}
|
|
105
105
|
</StyledGridItem>
|
|
106
106
|
))}
|
|
107
107
|
{hasNextPage && (
|
package/src/contexts/filter.js
CHANGED
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
import { useContext, createContext, useMemo
|
|
1
|
+
import { useContext, createContext, useMemo } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { useRequest, useReactive } from 'ahooks';
|
|
4
4
|
import orderBy from 'lodash/orderBy';
|
|
5
5
|
import axios from 'axios';
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
getCategoriesByAuthor,
|
|
9
|
-
filterBlockletByPrice,
|
|
10
|
-
replaceTranslate,
|
|
11
|
-
getPrices,
|
|
12
|
-
getCategoryOptions,
|
|
13
|
-
isMobileScreen,
|
|
14
|
-
} from '../libs/utils';
|
|
6
|
+
import { replaceTranslate, getPrices, getCategoryOptions, isMobileScreen, getCurrentPage } from '../libs/utils';
|
|
15
7
|
import translations from '../assets/locale';
|
|
16
8
|
import { propTypes, defaultProps } from '../libs/prop-types';
|
|
9
|
+
import constant from '../libs/constant';
|
|
17
10
|
|
|
18
11
|
const Filter = createContext({});
|
|
19
12
|
const { Provider, Consumer } = Filter;
|
|
@@ -22,97 +15,65 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
22
15
|
const storeApi = axios.create({
|
|
23
16
|
baseURL: endpoint,
|
|
24
17
|
});
|
|
18
|
+
|
|
19
|
+
const finalFilters = useMemo(() => {
|
|
20
|
+
return { sortBy: 'popularity', sortDirection: 'desc', ...filters };
|
|
21
|
+
}, [filters]);
|
|
22
|
+
|
|
23
|
+
const selectedCategory = finalFilters.category;
|
|
24
|
+
|
|
25
|
+
const paginateState = useReactive({
|
|
26
|
+
currentPage: constant.currentPage,
|
|
27
|
+
pageSize: isMobileScreen() ? constant.mobilePageSize : constant.pageSize,
|
|
28
|
+
defaultCurrentPage: constant.defaultCurrentPage,
|
|
29
|
+
});
|
|
30
|
+
|
|
25
31
|
const {
|
|
26
|
-
data:
|
|
32
|
+
data: blockletsState,
|
|
27
33
|
error: fetchBlockletsError,
|
|
28
34
|
loading: fetchBlockletsLoading,
|
|
29
|
-
|
|
35
|
+
loadMore,
|
|
36
|
+
loadingMore,
|
|
30
37
|
} = useRequest(
|
|
31
|
-
async () => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
async (d) => {
|
|
39
|
+
const params = {
|
|
40
|
+
...finalFilters,
|
|
41
|
+
sortBy: constant[finalFilters.sortBy],
|
|
42
|
+
page: getCurrentPage(d?.list?.length || 0, paginateState.pageSize),
|
|
43
|
+
pageSize: paginateState.pageSize,
|
|
44
|
+
};
|
|
45
|
+
const { data = {} } = await storeApi.get('/api/v2/blocklets.json', { params });
|
|
36
46
|
return data;
|
|
37
47
|
},
|
|
38
|
-
{
|
|
48
|
+
{
|
|
49
|
+
initialData: { list: [], total: 0 },
|
|
50
|
+
loadMore: true,
|
|
51
|
+
isNoMore: (d) => (d ? d.list.length >= d.total : false),
|
|
52
|
+
// eslint-disable-next-line no-console
|
|
53
|
+
formatResult: (response) => {
|
|
54
|
+
return { list: response?.dataList, total: response.total };
|
|
55
|
+
},
|
|
56
|
+
refreshDeps: [endpoint, filters],
|
|
57
|
+
}
|
|
39
58
|
);
|
|
40
59
|
|
|
41
60
|
const {
|
|
42
61
|
data: allCategories,
|
|
43
62
|
error: fetchCategoriesError,
|
|
44
63
|
loading: fetchCategoriesLoading,
|
|
45
|
-
run: fetchCategories,
|
|
46
64
|
} = useRequest(
|
|
47
65
|
async () => {
|
|
48
66
|
const { data } = await storeApi.get('/api/blocklets/categories');
|
|
49
|
-
if (!isArray(data)) {
|
|
50
|
-
throw new Error('/api/blocklets/categories response is not array');
|
|
51
|
-
}
|
|
52
67
|
return data;
|
|
53
68
|
},
|
|
54
|
-
{ initialData: []
|
|
69
|
+
{ initialData: [] }
|
|
55
70
|
);
|
|
56
71
|
|
|
57
|
-
const paginateState = useReactive({ currentPage: 1, pageSize: isMobileScreen() ? 10 : 18, defaultCurrentPage: 1 });
|
|
58
|
-
// TODO: 这里如果用 useMemo 包裹,滚动分页会异常
|
|
59
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60
|
-
const finalFilters = { sortBy: 'popularity', sortDirection: 'desc', ...filters };
|
|
61
|
-
|
|
62
|
-
const selectedCategory = finalFilters.category;
|
|
63
|
-
const hasDeveloperFilter = !!finalFilters.developer;
|
|
64
|
-
const categoryState = useMemo(() => {
|
|
65
|
-
// 当按作者过滤时,需要从所有blocklets中找出属于作者的分类
|
|
66
|
-
return !hasDeveloperFilter ? { data: allCategories } : getCategoriesByAuthor(allBlocklets, finalFilters.developer);
|
|
67
|
-
}, [hasDeveloperFilter, allCategories, allBlocklets, finalFilters.developer]);
|
|
68
|
-
|
|
69
|
-
const blockletList = useMemo(() => {
|
|
70
|
-
const sortByName = (x) => x?.title?.toLocaleLowerCase() || x?.name?.toLocaleLowerCase(); // 按名称排序
|
|
71
|
-
const sortByPopularity = (x) => x.stats.downloads; // 按下载量排序
|
|
72
|
-
const sortByPublish = (x) => x.lastPublishedAt; // 按发布时间
|
|
73
|
-
const sortMap = {
|
|
74
|
-
nameAsc: sortByName,
|
|
75
|
-
nameDesc: sortByName,
|
|
76
|
-
popularity: sortByPopularity,
|
|
77
|
-
publishAt: sortByPublish,
|
|
78
|
-
};
|
|
79
|
-
let blocklets = allBlocklets || [];
|
|
80
|
-
// 按照付费/免费筛选
|
|
81
|
-
blocklets = filterBlockletByPrice(blocklets, finalFilters.price);
|
|
82
|
-
// 按照分类筛选
|
|
83
|
-
blocklets = blocklets.filter((item) => (selectedCategory ? item?.category?.name === selectedCategory : true));
|
|
84
|
-
// 按照作者筛选
|
|
85
|
-
blocklets = blocklets.filter((item) =>
|
|
86
|
-
finalFilters?.developer ? item.owner.did === finalFilters.developer : true
|
|
87
|
-
);
|
|
88
|
-
const lowerSearch = finalFilters?.keyword?.toLocaleLowerCase() || '';
|
|
89
|
-
// 按照搜索筛选
|
|
90
|
-
blocklets = blocklets.filter((item) => {
|
|
91
|
-
return (
|
|
92
|
-
(item?.title || item?.name)?.toLocaleLowerCase().includes(lowerSearch) ||
|
|
93
|
-
item.description?.toLocaleLowerCase().includes(lowerSearch) ||
|
|
94
|
-
item?.version?.toLocaleLowerCase().includes(lowerSearch)
|
|
95
|
-
);
|
|
96
|
-
});
|
|
97
|
-
// 用户传入的过滤函数
|
|
98
|
-
blocklets = extraFilter(blocklets);
|
|
99
|
-
// 排序
|
|
100
|
-
return orderBy(blocklets, [sortMap[finalFilters.sortBy]], [finalFilters.sortDirection]);
|
|
101
|
-
}, [allBlocklets, finalFilters, selectedCategory, extraFilter]);
|
|
102
|
-
|
|
103
|
-
const finalBlockletList = useMemo(() => {
|
|
104
|
-
// 前端分页 currentPage 当前页数 pageSize 每页条数
|
|
105
|
-
return blockletList.slice(
|
|
106
|
-
(paginateState.defaultCurrentPage - 1) * paginateState.pageSize,
|
|
107
|
-
paginateState.currentPage * paginateState.pageSize
|
|
108
|
-
);
|
|
109
|
-
}, [blockletList, paginateState]);
|
|
110
|
-
|
|
111
72
|
const categoryList = useMemo(() => {
|
|
112
|
-
const list =
|
|
73
|
+
const list = allCategories || [];
|
|
113
74
|
// 分类按照名称排序
|
|
114
75
|
return orderBy(list, [(i) => i.name], ['asc']);
|
|
115
|
-
}, [
|
|
76
|
+
}, [allCategories]);
|
|
116
77
|
|
|
117
78
|
const translate = (key, data) => {
|
|
118
79
|
if (!translations[locale] || !translations[locale][key]) {
|
|
@@ -122,13 +83,21 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
122
83
|
|
|
123
84
|
return replaceTranslate(translations[locale][key], data);
|
|
124
85
|
};
|
|
86
|
+
const blockletList = useMemo(() => {
|
|
87
|
+
let blocklets = blockletsState.list || [];
|
|
88
|
+
// 用户传入的过滤函数
|
|
89
|
+
blocklets = extraFilter(blocklets);
|
|
90
|
+
return blocklets;
|
|
91
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
|
+
}, [blockletsState, extraFilter]);
|
|
93
|
+
|
|
125
94
|
const categoryOptions = useMemo(() => getCategoryOptions(categoryList, locale), [categoryList, locale]);
|
|
126
95
|
const priceOptions = getPrices(translate);
|
|
127
96
|
const filterStore = {
|
|
128
97
|
errors: { fetchBlockletsError, fetchCategoriesError },
|
|
129
|
-
loadings: { fetchBlockletsLoading, fetchCategoriesLoading },
|
|
98
|
+
loadings: { fetchBlockletsLoading, fetchCategoriesLoading, loadingMore },
|
|
130
99
|
endpoint,
|
|
131
|
-
|
|
100
|
+
blockletList,
|
|
132
101
|
t: translate,
|
|
133
102
|
filters: finalFilters,
|
|
134
103
|
selectedCategory,
|
|
@@ -137,7 +106,7 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
137
106
|
locale,
|
|
138
107
|
categoryOptions,
|
|
139
108
|
priceOptions,
|
|
140
|
-
hasNextPage:
|
|
109
|
+
hasNextPage: blockletsState.list.length < blockletsState.total,
|
|
141
110
|
handleSort: (sort) => {
|
|
142
111
|
const changeData = {
|
|
143
112
|
...finalFilters,
|
|
@@ -165,8 +134,8 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
165
134
|
const changeData = { ...finalFilters, category: finalCategory };
|
|
166
135
|
onFilterChange(changeData);
|
|
167
136
|
},
|
|
168
|
-
handleDeveloper: (
|
|
169
|
-
const changeData = { ...finalFilters,
|
|
137
|
+
handleDeveloper: (owner) => {
|
|
138
|
+
const changeData = { ...finalFilters, owner: owner || undefined };
|
|
170
139
|
onFilterChange(changeData);
|
|
171
140
|
},
|
|
172
141
|
handlePage: (page) => {
|
|
@@ -175,40 +144,24 @@ function FilterProvider({ filters, children, endpoint, locale, blockletRender, o
|
|
|
175
144
|
},
|
|
176
145
|
loadMore: () => {
|
|
177
146
|
setTimeout(() => {
|
|
178
|
-
|
|
147
|
+
loadMore();
|
|
179
148
|
}, 1000);
|
|
180
149
|
},
|
|
181
150
|
getCategoryLocale: (category) => {
|
|
182
151
|
if (!category) return null;
|
|
183
152
|
let result = null;
|
|
184
|
-
const find =
|
|
153
|
+
const find = allCategories.find((item) => item._id === category);
|
|
185
154
|
if (find) {
|
|
186
155
|
result = find.locales[locale];
|
|
187
156
|
}
|
|
188
157
|
return result;
|
|
189
158
|
},
|
|
190
|
-
get allBlocklets() {
|
|
191
|
-
return allBlocklets || [];
|
|
192
|
-
},
|
|
193
159
|
get developerName() {
|
|
194
|
-
const blocklets =
|
|
195
|
-
return blocklets.find((blocklet) => blocklet
|
|
160
|
+
const blocklets = blockletList;
|
|
161
|
+
return blocklets.find((blocklet) => blocklet?.owner?.did === finalFilters.owner)?.owner?.name || '';
|
|
196
162
|
},
|
|
197
163
|
};
|
|
198
164
|
|
|
199
|
-
useEffect(() => {
|
|
200
|
-
if (!hasDeveloperFilter) {
|
|
201
|
-
fetchCategories();
|
|
202
|
-
}
|
|
203
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
204
|
-
}, [hasDeveloperFilter]);
|
|
205
|
-
|
|
206
|
-
useEffect(() => {
|
|
207
|
-
fetchBlocklets();
|
|
208
|
-
fetchCategories();
|
|
209
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
210
|
-
}, [endpoint]);
|
|
211
|
-
|
|
212
165
|
return <Provider value={filterStore}>{children}</Provider>;
|
|
213
166
|
}
|
|
214
167
|
|
package/src/libs/utils.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import joinURL from 'url-join';
|
|
2
2
|
import cloneDeep from 'lodash/cloneDeep';
|
|
3
3
|
|
|
4
|
-
const isFreeBlocklet = (
|
|
5
|
-
if (!
|
|
4
|
+
const isFreeBlocklet = (blocklet) => {
|
|
5
|
+
if (!blocklet.payment) {
|
|
6
6
|
return true;
|
|
7
7
|
}
|
|
8
|
-
const priceList = (
|
|
8
|
+
const priceList = (blocklet.payment.price || []).map((x) => x.value || 0);
|
|
9
9
|
return priceList.every((x) => x === 0);
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -36,21 +36,9 @@ const getPrices = (t) => {
|
|
|
36
36
|
];
|
|
37
37
|
};
|
|
38
38
|
const getCategoryOptions = (list = [], locale = 'en') => {
|
|
39
|
-
return list.map((item) => ({ name: item.locales[locale], value: item.
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* 从 blocklets 中的得到属于作者的 Categories
|
|
43
|
-
* @param {*} list
|
|
44
|
-
* @param {*} developerDid
|
|
45
|
-
* @returns
|
|
46
|
-
*/
|
|
47
|
-
const getCategoriesByAuthor = (list = [], developerDid = null) => {
|
|
48
|
-
const filterList = list.filter((item) => (developerDid ? item.owner.did === developerDid : true));
|
|
49
|
-
const Categories = filterList.map((item) => item.category);
|
|
50
|
-
const res = new Map();
|
|
51
|
-
const result = Categories.filter((i) => !!i).filter((a) => !res.has(a._id) && res.set(a._id, 1));
|
|
52
|
-
return { data: result };
|
|
39
|
+
return list.map((item) => ({ name: item.locales[locale], value: item._id }));
|
|
53
40
|
};
|
|
41
|
+
|
|
54
42
|
/**
|
|
55
43
|
* 根据 是否付费 过滤 blocklet list
|
|
56
44
|
* @param {*} list
|
|
@@ -110,10 +98,15 @@ const isMobileScreen = () => {
|
|
|
110
98
|
return window.innerWidth <= 600;
|
|
111
99
|
};
|
|
112
100
|
|
|
101
|
+
const getCurrentPage = (length, pageSize) => {
|
|
102
|
+
const page = (length + pageSize) / pageSize;
|
|
103
|
+
if (page > 1) return page.toFixed();
|
|
104
|
+
return 1;
|
|
105
|
+
};
|
|
106
|
+
|
|
113
107
|
export {
|
|
114
108
|
getSortOptions,
|
|
115
109
|
getPrices,
|
|
116
|
-
getCategoriesByAuthor,
|
|
117
110
|
filterBlockletByPrice,
|
|
118
111
|
getStoreDetail,
|
|
119
112
|
formatLogoPath,
|
|
@@ -123,4 +116,5 @@ export {
|
|
|
123
116
|
urlStringify,
|
|
124
117
|
getCategoryOptions,
|
|
125
118
|
isMobileScreen,
|
|
119
|
+
getCurrentPage,
|
|
126
120
|
};
|