@gravity-ui/blog-constructor 3.3.0 → 3.4.0
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/CHANGELOG.md +7 -0
- package/build/cjs/blocks/Feed/Feed.js +47 -37
- package/build/cjs/blocks/Feed/reducer.d.ts +0 -5
- package/build/cjs/blocks/Feed/reducer.js +1 -4
- package/build/cjs/blocks/YFM/YFM.js +1 -1
- package/build/cjs/components/FeedHeader/FeedHeader.js +2 -2
- package/build/cjs/components/FeedHeader/components/Controls/Controls.d.ts +2 -3
- package/build/cjs/components/FeedHeader/components/Controls/Controls.js +24 -16
- package/build/cjs/components/Paginator/Paginator.d.ts +1 -1
- package/build/cjs/components/Paginator/Paginator.js +2 -2
- package/build/cjs/components/Paginator/types.d.ts +0 -1
- package/build/cjs/components/Posts/Posts.css +25 -0
- package/build/cjs/components/Posts/Posts.d.ts +0 -1
- package/build/cjs/components/Posts/Posts.js +5 -4
- package/build/cjs/components/Search/Search.js +1 -1
- package/build/cjs/models/common.d.ts +5 -1
- package/build/cjs/utils/common.js +1 -1
- package/build/esm/blocks/Feed/Feed.js +47 -37
- package/build/esm/blocks/Feed/reducer.d.ts +0 -5
- package/build/esm/blocks/Feed/reducer.js +1 -4
- package/build/esm/blocks/YFM/YFM.js +1 -1
- package/build/esm/components/FeedHeader/FeedHeader.js +2 -2
- package/build/esm/components/FeedHeader/components/Controls/Controls.d.ts +2 -3
- package/build/esm/components/FeedHeader/components/Controls/Controls.js +25 -17
- package/build/esm/components/Paginator/Paginator.d.ts +1 -1
- package/build/esm/components/Paginator/Paginator.js +2 -2
- package/build/esm/components/Paginator/types.d.ts +0 -1
- package/build/esm/components/Posts/Posts.css +25 -0
- package/build/esm/components/Posts/Posts.d.ts +0 -1
- package/build/esm/components/Posts/Posts.js +5 -4
- package/build/esm/components/Search/Search.js +1 -1
- package/build/esm/models/common.d.ts +5 -1
- package/build/esm/utils/common.js +1 -1
- package/package.json +1 -1
- package/server/data/sanitizeMeta.d.ts +2 -0
- package/server/data/sanitizeMeta.js +2 -0
- package/server/data/transformPageContent.js +1 -1
- package/server/models/common.d.ts +5 -1
- package/build/cjs/blocks/YFM/__tests__/YFM.test.d.ts +0 -1
- package/build/cjs/blocks/YFM/__tests__/YFM.test.js +0 -16
- package/build/cjs/counters/metrika.d.ts +0 -62
- package/build/cjs/counters/metrika.js +0 -173
- package/build/esm/blocks/YFM/__tests__/YFM.test.d.ts +0 -1
- package/build/esm/blocks/YFM/__tests__/YFM.test.js +0 -11
- package/build/esm/counters/metrika.d.ts +0 -62
- package/build/esm/counters/metrika.js +0 -169
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.4.0](https://github.com/gravity-ui/blog-constructor/compare/v3.3.0...v3.4.0) (2023-05-24)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* new loading UI (shimmer) ([#50](https://github.com/gravity-ui/blog-constructor/issues/50)) ([ccdf08c](https://github.com/gravity-ui/blog-constructor/commit/ccdf08ccc62dd9930ab8c994601c787b03897f05))
|
|
9
|
+
|
|
3
10
|
## [3.3.0](https://github.com/gravity-ui/blog-constructor/compare/v3.2.1...v3.3.0) (2023-05-16)
|
|
4
11
|
|
|
5
12
|
|
|
@@ -56,11 +56,10 @@ const Feed = ({ image }) => {
|
|
|
56
56
|
const { posts, totalCount, tags, services, pinnedPost, getPosts, pageCountForShowSupportButtons, } = (0, react_1.useContext)(FeedContext_1.FeedContext);
|
|
57
57
|
const router = (0, react_1.useContext)(RouterContext_1.RouterContext);
|
|
58
58
|
const handleAnalytics = (0, page_constructor_1.useAnalytics)(common_1.DefaultEventNames.ShowMore);
|
|
59
|
-
const [{ errorLoad, errorShowMore, isFetching,
|
|
59
|
+
const [{ errorLoad, errorShowMore, isFetching, isShowMoreVisible, lastLoadedCount, postCountOnPage, postsOnPage, pinnedPostOnPage, currentPage, queryParams, }, dispatch,] = (0, react_1.useReducer)(reducer_1.reducer, {
|
|
60
60
|
errorLoad: false,
|
|
61
61
|
errorShowMore: false,
|
|
62
62
|
isFetching: false,
|
|
63
|
-
isShowMoreFetching: false,
|
|
64
63
|
isShowMoreVisible: true,
|
|
65
64
|
lastLoadedCount: (posts === null || posts === void 0 ? void 0 : posts.length) || 0,
|
|
66
65
|
postCountOnPage: totalCount || 0,
|
|
@@ -75,36 +74,36 @@ const Feed = ({ image }) => {
|
|
|
75
74
|
const pageChange = (value) => {
|
|
76
75
|
dispatch({ type: reducer_1.ActionTypes.PageChange, payload: value });
|
|
77
76
|
};
|
|
78
|
-
const
|
|
79
|
-
dispatch({ type: reducer_1.ActionTypes.
|
|
80
|
-
const hasFirstPageQuery = Object.keys(value).some((queryKey) => queryKey === PAGE_QUERY && value[queryKey] === FIRST_PAGE);
|
|
81
|
-
if (hasFirstPageQuery) {
|
|
82
|
-
// eslint-disable-next-line no-not-accumulator-reassign/no-not-accumulator-reassign
|
|
83
|
-
value[PAGE_QUERY] = null;
|
|
84
|
-
}
|
|
85
|
-
router.updateQueryCallback(value);
|
|
77
|
+
const setIsFetching = (value) => {
|
|
78
|
+
dispatch({ type: reducer_1.ActionTypes.SetIsFetching, payload: value });
|
|
86
79
|
};
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
handleChangeQueryParams({ page: value });
|
|
80
|
+
const setErrorLoad = (value) => {
|
|
81
|
+
dispatch({ type: reducer_1.ActionTypes.SetErrorLoad, payload: value });
|
|
90
82
|
};
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
83
|
+
const handleChangeQueryParams = (0, react_1.useCallback)((value) => {
|
|
84
|
+
dispatch({ type: reducer_1.ActionTypes.QueryParamsChange, payload: value });
|
|
85
|
+
const hasFirstPageQuery = Object.keys(value).some((queryKey) => queryKey === PAGE_QUERY && value[queryKey] === FIRST_PAGE);
|
|
86
|
+
const result = hasFirstPageQuery
|
|
87
|
+
? Object.assign(Object.assign({}, value), { [PAGE_QUERY]: null }) : Object.assign({}, value);
|
|
88
|
+
router.updateQueryCallback(result);
|
|
89
|
+
}, [router]);
|
|
90
|
+
const fetchData = (0, react_1.useCallback)(async ({ page, query }) => {
|
|
91
|
+
if (query && getPosts) {
|
|
92
|
+
const queryParamsForRequest = (0, common_2.getFeedQueryParams)(Object.assign(Object.assign({}, queryParams), query), page);
|
|
93
|
+
const data = await getPosts(queryParamsForRequest);
|
|
95
94
|
return data;
|
|
96
95
|
}
|
|
97
96
|
else {
|
|
98
97
|
throw new Error('cant get request');
|
|
99
98
|
}
|
|
100
99
|
}, [getPosts, queryParams]);
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const fetchAndReplaceData = (0, react_1.useCallback)(async (pageNumber) => {
|
|
100
|
+
const handleLoad = (0, react_1.useCallback)(async ({ page, query }) => {
|
|
101
|
+
const pageNumber = Number(page || queryParams.page || constants_2.DEFAULT_PAGE);
|
|
102
|
+
handleChangeQueryParams(query);
|
|
105
103
|
try {
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
setErrorLoad(false);
|
|
105
|
+
setIsFetching(true);
|
|
106
|
+
const fetchedData = await fetchData({ page: pageNumber, query });
|
|
108
107
|
if (fetchedData) {
|
|
109
108
|
dispatch({
|
|
110
109
|
type: reducer_1.ActionTypes.SetPosts,
|
|
@@ -118,22 +117,35 @@ const Feed = ({ image }) => {
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
catch (err) {
|
|
121
|
-
|
|
120
|
+
setErrorLoad(true);
|
|
122
121
|
}
|
|
123
122
|
(0, common_2.scrollOnPageChange)(CONTAINER_ID);
|
|
124
123
|
setIsFetching(false);
|
|
125
|
-
}, [fetchData]);
|
|
124
|
+
}, [fetchData, handleChangeQueryParams, queryParams]);
|
|
125
|
+
const handlePageChange = async (value) => {
|
|
126
|
+
pageChange(value);
|
|
127
|
+
handleLoad({
|
|
128
|
+
page: value,
|
|
129
|
+
query: Object.assign(Object.assign({}, queryParams), { page: value }),
|
|
130
|
+
});
|
|
131
|
+
};
|
|
126
132
|
const handleShowMore = async () => {
|
|
127
|
-
dispatch({ type: reducer_1.ActionTypes.SetIsShowMoreFetching, payload: true });
|
|
128
133
|
/**
|
|
129
134
|
* @deprecated Metrika will be deleted after launch of analyticsEvents
|
|
130
135
|
*/
|
|
131
136
|
metrika_js_1.default.reachGoal(utils_1.MetrikaCounter.CrossSite, constants_1.BlogMetrikaGoalIds.showMore);
|
|
132
137
|
handleAnalytics();
|
|
138
|
+
const nextPage = currentPage + 1;
|
|
133
139
|
try {
|
|
134
|
-
|
|
140
|
+
setIsFetching(true);
|
|
141
|
+
const fetchedData = await fetchData({
|
|
142
|
+
page: nextPage,
|
|
143
|
+
query: {
|
|
144
|
+
page: nextPage,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
135
147
|
handleChangeQueryParams({
|
|
136
|
-
page:
|
|
148
|
+
page: nextPage,
|
|
137
149
|
});
|
|
138
150
|
if (fetchedData) {
|
|
139
151
|
dispatch({
|
|
@@ -141,7 +153,7 @@ const Feed = ({ image }) => {
|
|
|
141
153
|
payload: {
|
|
142
154
|
posts: (postsOnPage !== null && postsOnPage !== void 0 ? postsOnPage : []).concat(fetchedData.posts),
|
|
143
155
|
count: fetchedData.count,
|
|
144
|
-
currentPage:
|
|
156
|
+
currentPage: nextPage,
|
|
145
157
|
lastLoadedCount: fetchedData.posts.length,
|
|
146
158
|
},
|
|
147
159
|
});
|
|
@@ -150,13 +162,11 @@ const Feed = ({ image }) => {
|
|
|
150
162
|
catch (err) {
|
|
151
163
|
dispatch({ type: reducer_1.ActionTypes.SetErrorShowMore, payload: true });
|
|
152
164
|
}
|
|
153
|
-
|
|
165
|
+
setIsFetching(false);
|
|
154
166
|
};
|
|
155
|
-
(0, react_1.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
}, [fetchAndReplaceData, isFetching, queryParams.page]);
|
|
167
|
+
const handleOnErrorReload = (0, react_1.useCallback)(() => {
|
|
168
|
+
handleLoad({ page: currentPage, query: queryParams });
|
|
169
|
+
}, [currentPage, handleLoad, queryParams]);
|
|
160
170
|
(0, react_1.useEffect)(() => {
|
|
161
171
|
const loadedPostsCount = currentPage * perPageInQuery;
|
|
162
172
|
dispatch({
|
|
@@ -174,11 +184,11 @@ const Feed = ({ image }) => {
|
|
|
174
184
|
icon: tag.icon && react_1.default.createElement(uikit_1.Icon, { data: tag.icon }),
|
|
175
185
|
})), [tags]);
|
|
176
186
|
return (react_1.default.createElement("div", null,
|
|
177
|
-
react_1.default.createElement(FeedHeader_1.FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems,
|
|
187
|
+
react_1.default.createElement(FeedHeader_1.FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems, handleLoadData: handleLoad, queryParams: queryParams, background: {
|
|
178
188
|
fullWidth: true,
|
|
179
189
|
url: image,
|
|
180
190
|
disableCompress: true,
|
|
181
191
|
} }),
|
|
182
|
-
errorLoad ? (react_1.default.createElement(PostsError_1.PostsError, { onButtonClick:
|
|
192
|
+
errorLoad ? (react_1.default.createElement(PostsError_1.PostsError, { onButtonClick: handleOnErrorReload })) : (react_1.default.createElement(Posts_1.Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
|
|
183
193
|
};
|
|
184
194
|
exports.Feed = Feed;
|
|
@@ -6,7 +6,6 @@ export declare enum ActionTypes {
|
|
|
6
6
|
SetPosts = "setPosts",
|
|
7
7
|
SetShowMore = "setShowMore",
|
|
8
8
|
SetIsFetching = "setIsFetching",
|
|
9
|
-
SetIsShowMoreFetching = "setIsShowMoreFetching",
|
|
10
9
|
PageChange = "pageChange",
|
|
11
10
|
QueryParamsChange = "queryParamsChange"
|
|
12
11
|
}
|
|
@@ -15,7 +14,6 @@ export type State = {
|
|
|
15
14
|
errorLoad: boolean;
|
|
16
15
|
errorShowMore: boolean;
|
|
17
16
|
isFetching: boolean;
|
|
18
|
-
isShowMoreFetching: boolean;
|
|
19
17
|
isShowMoreVisible: boolean;
|
|
20
18
|
lastLoadedCount: number;
|
|
21
19
|
pinnedPostOnPage?: PostData;
|
|
@@ -29,9 +27,6 @@ type Action = {
|
|
|
29
27
|
} | {
|
|
30
28
|
type: ActionTypes.SetIsFetching;
|
|
31
29
|
payload: boolean;
|
|
32
|
-
} | {
|
|
33
|
-
type: ActionTypes.SetIsShowMoreFetching;
|
|
34
|
-
payload: boolean;
|
|
35
30
|
} | {
|
|
36
31
|
type: ActionTypes.SetPosts;
|
|
37
32
|
payload: {
|
|
@@ -9,7 +9,6 @@ var ActionTypes;
|
|
|
9
9
|
ActionTypes["SetPosts"] = "setPosts";
|
|
10
10
|
ActionTypes["SetShowMore"] = "setShowMore";
|
|
11
11
|
ActionTypes["SetIsFetching"] = "setIsFetching";
|
|
12
|
-
ActionTypes["SetIsShowMoreFetching"] = "setIsShowMoreFetching";
|
|
13
12
|
ActionTypes["PageChange"] = "pageChange";
|
|
14
13
|
ActionTypes["QueryParamsChange"] = "queryParamsChange";
|
|
15
14
|
})(ActionTypes = exports.ActionTypes || (exports.ActionTypes = {}));
|
|
@@ -20,11 +19,9 @@ const reducer = (state, { type, payload }) => {
|
|
|
20
19
|
case ActionTypes.SetPosts:
|
|
21
20
|
return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.count, postCountOnPage: payload.count, pinnedPostOnPage: payload.pinnedPost, postsOnPage: payload.posts, currentPage: payload.page });
|
|
22
21
|
case ActionTypes.SetShowMore:
|
|
23
|
-
return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.lastLoadedCount, postCountOnPage: payload.count, currentPage: payload.currentPage, postsOnPage: payload.posts, errorShowMore: false
|
|
22
|
+
return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.lastLoadedCount, postCountOnPage: payload.count, currentPage: payload.currentPage, postsOnPage: payload.posts, errorShowMore: false });
|
|
24
23
|
case ActionTypes.SetIsFetching:
|
|
25
24
|
return Object.assign(Object.assign({}, state), { isFetching: payload });
|
|
26
|
-
case ActionTypes.SetIsShowMoreFetching:
|
|
27
|
-
return Object.assign(Object.assign({}, state), { isShowMoreFetching: payload });
|
|
28
25
|
case ActionTypes.PageChange:
|
|
29
26
|
return Object.assign(Object.assign({}, state), { currentPage: payload, isFetching: true });
|
|
30
27
|
case ActionTypes.SetErrorLoad:
|
|
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.YFM = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const bem_cn_lite_1 = __importDefault(require("bem-cn-lite"));
|
|
9
8
|
const page_constructor_1 = require("@gravity-ui/page-constructor");
|
|
9
|
+
const bem_cn_lite_1 = __importDefault(require("bem-cn-lite"));
|
|
10
10
|
const Wrapper_1 = require("../../components/Wrapper/Wrapper");
|
|
11
11
|
const paddings_1 = require("../../models/paddings");
|
|
12
12
|
const b = (0, bem_cn_lite_1.default)('yfm');
|
|
@@ -9,7 +9,7 @@ const page_constructor_1 = require("@gravity-ui/page-constructor");
|
|
|
9
9
|
const cn_1 = require("../../utils/cn");
|
|
10
10
|
const Controls_1 = require("./components/Controls/Controls");
|
|
11
11
|
const b = (0, cn_1.block)('feed-header');
|
|
12
|
-
const FeedHeader = ({ tags, services,
|
|
12
|
+
const FeedHeader = ({ tags, services, handleLoadData, offset = 'default', background, theme = 'default', verticalOffset = 'l', className, queryParams, }) => {
|
|
13
13
|
const backgroundThemed = background && (0, page_constructor_1.getThemedValue)(background, theme);
|
|
14
14
|
return (react_1.default.createElement("header", { className: b('header', { ['has-background']: Boolean(background) }, className) },
|
|
15
15
|
(backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color) ? (react_1.default.createElement(page_constructor_1.FullWidthBackground, { style: { backgroundColor: backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color }, theme: "rounded" })) : null,
|
|
@@ -19,6 +19,6 @@ const FeedHeader = ({ tags, services, setIsFetching, offset = 'default', backgro
|
|
|
19
19
|
? ''
|
|
20
20
|
: backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color,
|
|
21
21
|
}, disableCompress: backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.disableCompress })) : null,
|
|
22
|
-
react_1.default.createElement(Controls_1.Controls, { tags: tags, services: services,
|
|
22
|
+
react_1.default.createElement(Controls_1.Controls, { tags: tags, services: services, handleLoadData: handleLoadData, queryParams: queryParams }))));
|
|
23
23
|
};
|
|
24
24
|
exports.FeedHeader = FeedHeader;
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { FetchArgs, Query, SetQueryType } from '../../../../models/common';
|
|
3
3
|
export type SelectItem = {
|
|
4
4
|
content: string;
|
|
5
5
|
value: string;
|
|
6
6
|
icon?: ReactNode;
|
|
7
7
|
};
|
|
8
8
|
export type ControlsProps = {
|
|
9
|
-
|
|
9
|
+
handleLoadData: (props: FetchArgs) => void;
|
|
10
10
|
tags?: SelectItem[];
|
|
11
11
|
services?: SelectItem[];
|
|
12
|
-
handleChangeQuery: HandleChangeQueryParams;
|
|
13
12
|
queryParams: Query;
|
|
14
13
|
setQuery?: SetQueryType;
|
|
15
14
|
};
|
|
@@ -47,7 +47,7 @@ const b = (0, cn_1.block)('feed-controls');
|
|
|
47
47
|
const ICON_SIZE = 16;
|
|
48
48
|
const DEFAULT_PAGE = 1;
|
|
49
49
|
const VIRTUALIZATION_THRESHOLD = 1000;
|
|
50
|
-
const Controls = ({
|
|
50
|
+
const Controls = ({ handleLoadData, tags = [], services = [], queryParams, }) => {
|
|
51
51
|
const { hasLikes } = (0, react_1.useContext)(LikesContext_1.LikesContext);
|
|
52
52
|
const handleAnalyticsTag = (0, page_constructor_1.useAnalytics)(common_1.DefaultEventNames.Tag);
|
|
53
53
|
const handleAnalyticsService = (0, page_constructor_1.useAnalytics)(common_1.DefaultEventNames.Service);
|
|
@@ -56,21 +56,25 @@ const Controls = ({ setIsFetching, tags = [], services = [], handleChangeQuery,
|
|
|
56
56
|
const [savedOnly, setSavedOnly] = (0, react_1.useState)(savedOnlyInitial === 'true');
|
|
57
57
|
const [search, setSearch] = (0, react_1.useState)(searchInitial);
|
|
58
58
|
const handleSavedOnly = () => {
|
|
59
|
-
handleChangeQuery({
|
|
60
|
-
savedOnly: savedOnly ? '' : 'true',
|
|
61
|
-
search: '',
|
|
62
|
-
tags: '',
|
|
63
|
-
page: DEFAULT_PAGE,
|
|
64
|
-
services: '',
|
|
65
|
-
});
|
|
66
59
|
handleAnalyticsSaveOnly();
|
|
67
60
|
setSavedOnly(!savedOnly);
|
|
68
|
-
|
|
61
|
+
handleLoadData({
|
|
62
|
+
page: DEFAULT_PAGE,
|
|
63
|
+
query: {
|
|
64
|
+
savedOnly: savedOnly ? '' : 'true',
|
|
65
|
+
search: '',
|
|
66
|
+
tags: '',
|
|
67
|
+
page: DEFAULT_PAGE,
|
|
68
|
+
services: '',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
69
71
|
};
|
|
70
72
|
const handleSearch = (searchValue) => {
|
|
71
|
-
handleChangeQuery({ search: searchValue, page: DEFAULT_PAGE });
|
|
72
73
|
setSearch(searchValue);
|
|
73
|
-
|
|
74
|
+
handleLoadData({
|
|
75
|
+
page: DEFAULT_PAGE,
|
|
76
|
+
query: { search: searchValue, page: DEFAULT_PAGE },
|
|
77
|
+
});
|
|
74
78
|
};
|
|
75
79
|
const handleTagSelect = (selectedTags) => {
|
|
76
80
|
/**
|
|
@@ -83,11 +87,13 @@ const Controls = ({ setIsFetching, tags = [], services = [], handleChangeQuery,
|
|
|
83
87
|
theme: selectedTags[0],
|
|
84
88
|
});
|
|
85
89
|
const isEmptyTag = selectedTags.some((tag) => tag === 'empty');
|
|
86
|
-
|
|
87
|
-
tags: isEmptyTag ? '' : selectedTags[0],
|
|
90
|
+
handleLoadData({
|
|
88
91
|
page: DEFAULT_PAGE,
|
|
92
|
+
query: {
|
|
93
|
+
tags: isEmptyTag ? '' : selectedTags[0],
|
|
94
|
+
page: DEFAULT_PAGE,
|
|
95
|
+
},
|
|
89
96
|
});
|
|
90
|
-
setIsFetching(true);
|
|
91
97
|
};
|
|
92
98
|
const handleServicesSelect = (selectedServices) => {
|
|
93
99
|
const forMetrikaServices = services.filter((service) => {
|
|
@@ -104,8 +110,10 @@ const Controls = ({ setIsFetching, tags = [], services = [], handleChangeQuery,
|
|
|
104
110
|
service: metrikaAsString,
|
|
105
111
|
});
|
|
106
112
|
const servicesAsString = selectedServices.join(',');
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
handleLoadData({
|
|
114
|
+
page: DEFAULT_PAGE,
|
|
115
|
+
query: { services: servicesAsString, page: DEFAULT_PAGE },
|
|
116
|
+
});
|
|
109
117
|
};
|
|
110
118
|
const tagsItems = (0, react_1.useMemo)(() => [{ value: 'empty', content: (0, i18n_1.i18)(i18n_1.Keyset.AllTags) }, ...tags], [tags]);
|
|
111
119
|
const servicesItems = (0, react_1.useMemo)(() => (servicesInitial ? [...servicesInitial.split(',')] : []), [servicesInitial]);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { PaginatorProps } from './types';
|
|
2
|
-
export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className,
|
|
2
|
+
export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons, }: PaginatorProps) => JSX.Element | null;
|
|
@@ -54,7 +54,7 @@ const types_1 = require("./types");
|
|
|
54
54
|
const utils_2 = require("./utils");
|
|
55
55
|
const b = (0, cn_1.block)('paginator');
|
|
56
56
|
const DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS = 6;
|
|
57
|
-
const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
|
|
57
|
+
const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
|
|
58
58
|
const [pagesCount, setPagesCount] = (0, react_1.useState)((0, utils_2.getPagesCount)({ itemsPerPage, totalItems, maxPages }));
|
|
59
59
|
(0, react_1.useEffect)(() => {
|
|
60
60
|
const count = (0, utils_2.getPagesCount)({ itemsPerPage, totalItems, maxPages });
|
|
@@ -123,7 +123,7 @@ const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, loadin
|
|
|
123
123
|
}
|
|
124
124
|
const renderPaginatorItem = (item) => {
|
|
125
125
|
const { key } = item, rest = __rest(item, ["key"]);
|
|
126
|
-
return react_1.default.createElement(PaginatorItem_1.PaginatorItem, Object.assign({ key: `page_${key}` }, rest
|
|
126
|
+
return react_1.default.createElement(PaginatorItem_1.PaginatorItem, Object.assign({ key: `page_${key}` }, rest));
|
|
127
127
|
};
|
|
128
128
|
return (react_1.default.createElement("div", { className: b('pagination') },
|
|
129
129
|
page > 1 && (react_1.default.createElement("div", { className: b('pagination-block') },
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
/* use this for style redefinitions to awoid problems with
|
|
2
2
|
unpredictable css rules order in build */
|
|
3
|
+
.bc-posts {
|
|
4
|
+
position: relative;
|
|
5
|
+
}
|
|
3
6
|
.bc-posts__cards-container, .bc-posts__pinned-container {
|
|
4
7
|
padding-top: 24px;
|
|
5
8
|
scroll-margin: 48px;
|
|
6
9
|
}
|
|
10
|
+
.bc-posts__cards-container_isLoading {
|
|
11
|
+
opacity: 0.7;
|
|
12
|
+
}
|
|
7
13
|
.bc-posts__pagination {
|
|
8
14
|
display: flex;
|
|
9
15
|
flex-direction: column;
|
|
@@ -25,4 +31,23 @@ unpredictable css rules order in build */
|
|
|
25
31
|
}
|
|
26
32
|
.bc-posts__paginator {
|
|
27
33
|
padding-top: 12px;
|
|
34
|
+
}
|
|
35
|
+
.bc-posts__loaderContainer {
|
|
36
|
+
z-index: 6;
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
width: 70%;
|
|
41
|
+
height: 100%;
|
|
42
|
+
background: linear-gradient(90deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
|
43
|
+
animation: shimmer 2s infinite linear;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@keyframes shimmer {
|
|
47
|
+
from {
|
|
48
|
+
transform: translateX(-200%);
|
|
49
|
+
}
|
|
50
|
+
to {
|
|
51
|
+
transform: translateX(300%);
|
|
52
|
+
}
|
|
28
53
|
}
|
|
@@ -8,7 +8,6 @@ type PostCardProps = {
|
|
|
8
8
|
postCountOnPage: number;
|
|
9
9
|
perPageInQuery: number;
|
|
10
10
|
isFetching: boolean;
|
|
11
|
-
isShowMoreFetching: boolean;
|
|
12
11
|
handleShowMore: (value?: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => Promise<void> | void;
|
|
13
12
|
handlePageChange: (value: number) => Promise<void> | void;
|
|
14
13
|
postsOnPage?: PostData[];
|
|
@@ -13,8 +13,9 @@ const Paginator_1 = require("../Paginator/Paginator");
|
|
|
13
13
|
const PostCard_1 = require("../PostCard/PostCard");
|
|
14
14
|
const PostsEmpty_1 = require("../PostsEmpty/PostsEmpty");
|
|
15
15
|
const b = (0, cn_1.block)('posts');
|
|
16
|
-
const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching,
|
|
17
|
-
react_1.default.createElement("div", {
|
|
16
|
+
const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShowMoreVisible, errorShowMore, postCountOnPage, perPageInQuery, isFetching, handleShowMore, handlePageChange, pageCountForShowSupportButtons, }) => (react_1.default.createElement("div", { className: b() },
|
|
17
|
+
isFetching && react_1.default.createElement("div", { className: b('loaderContainer') }),
|
|
18
|
+
react_1.default.createElement("div", { id: containerId, className: b('cards-container', { isLoading: isFetching }) },
|
|
18
19
|
pinnedPostOnPage && currentPage === 1 && (react_1.default.createElement("div", { className: b('pinned-container') },
|
|
19
20
|
react_1.default.createElement(PostCard_1.PostCard, { post: pinnedPostOnPage, size: "m", fullWidth: true, showTag: true }))),
|
|
20
21
|
(postsOnPage === null || postsOnPage === void 0 ? void 0 : postsOnPage.length) ? (react_1.default.createElement(page_constructor_1.CardLayoutBlock, { title: '', colSizes: {
|
|
@@ -23,10 +24,10 @@ const Posts = ({ containerId, pinnedPostOnPage, currentPage, postsOnPage, isShow
|
|
|
23
24
|
md: 6,
|
|
24
25
|
} }, postsOnPage === null || postsOnPage === void 0 ? void 0 : postsOnPage.map((post) => (react_1.default.createElement(PostCard_1.PostCard, { key: post.id, post: post, showTag: true }))))) : (react_1.default.createElement(PostsEmpty_1.PostsEmpty, null))),
|
|
25
26
|
react_1.default.createElement("div", { className: b('pagination') },
|
|
26
|
-
Boolean(isShowMoreVisible && (postsOnPage === null || postsOnPage === void 0 ? void 0 : postsOnPage.length)) && (react_1.default.createElement(uikit_1.Button, { view: "outlined", size: "xl", className: b('more-button'), onClick: handleShowMore
|
|
27
|
+
Boolean(isShowMoreVisible && (postsOnPage === null || postsOnPage === void 0 ? void 0 : postsOnPage.length)) && (react_1.default.createElement(uikit_1.Button, { view: "outlined", size: "xl", className: b('more-button'), onClick: handleShowMore }, (0, i18n_1.i18)(i18n_1.Keyset.ActionLoadMore))),
|
|
27
28
|
errorShowMore && (react_1.default.createElement("div", { className: b('error-show-more') },
|
|
28
29
|
react_1.default.createElement("div", null, (0, i18n_1.i18)(i18n_1.Keyset.ErrorTitle)),
|
|
29
30
|
react_1.default.createElement("div", null, (0, i18n_1.i18)(i18n_1.Keyset.PostLoadError)))),
|
|
30
31
|
Boolean(currentPage && postCountOnPage) && (react_1.default.createElement("div", { className: b('paginator') },
|
|
31
|
-
react_1.default.createElement(Paginator_1.Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery,
|
|
32
|
+
react_1.default.createElement(Paginator_1.Paginator, { onPageChange: handlePageChange, page: currentPage, totalItems: postCountOnPage, itemsPerPage: perPageInQuery, maxPages: Infinity, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))))));
|
|
32
33
|
exports.Posts = Posts;
|
|
@@ -25,8 +25,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.Search = void 0;
|
|
27
27
|
const react_1 = __importStar(require("react"));
|
|
28
|
-
const lodash_1 = require("lodash");
|
|
29
28
|
const uikit_1 = require("@gravity-ui/uikit");
|
|
29
|
+
const lodash_1 = require("lodash");
|
|
30
30
|
const useIsIPhone_1 = require("../../hooks/useIsIPhone");
|
|
31
31
|
const i18n_1 = require("../../i18n");
|
|
32
32
|
const Close_1 = require("../../icons/Close");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { IBrowser, IDevice } from 'ua-parser-js';
|
|
3
2
|
import { HeaderBlockProps as PageConstructorHeaderBlockProps } from '@gravity-ui/page-constructor';
|
|
3
|
+
import { IBrowser, IDevice } from 'ua-parser-js';
|
|
4
4
|
import { Locale } from '../models/locale';
|
|
5
5
|
export declare enum Theme {
|
|
6
6
|
Light = "light",
|
|
@@ -161,3 +161,7 @@ export declare enum DefaultEventNames {
|
|
|
161
161
|
Service = "selector-service-click",
|
|
162
162
|
SaveOnly = "save-only-button-click"
|
|
163
163
|
}
|
|
164
|
+
export type FetchArgs = {
|
|
165
|
+
page?: number;
|
|
166
|
+
query: Query;
|
|
167
|
+
};
|
|
@@ -13,8 +13,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.scrollOnPageChange = exports.getFeedQueryParams = exports.getBlogElementMetrika = exports.isMetrikaExist = exports.getBreadcrumbs = exports.getBlogPath = exports.updateContentSizes = exports.getTagFilterUrl = exports.postLikeStatus = exports.getTags = exports.scrollToHash = exports.getPageSearchParams = exports.getAbsolutePath = void 0;
|
|
15
15
|
const url_1 = require("url");
|
|
16
|
-
const lodash_1 = require("lodash");
|
|
17
16
|
const page_constructor_1 = require("@gravity-ui/page-constructor");
|
|
17
|
+
const lodash_1 = require("lodash");
|
|
18
18
|
const constants_1 = require("../blocks/constants");
|
|
19
19
|
const i18n_1 = require("../i18n");
|
|
20
20
|
function getAbsolutePath(router, url) {
|
|
@@ -27,11 +27,10 @@ export const Feed = ({ image }) => {
|
|
|
27
27
|
const { posts, totalCount, tags, services, pinnedPost, getPosts, pageCountForShowSupportButtons, } = useContext(FeedContext);
|
|
28
28
|
const router = useContext(RouterContext);
|
|
29
29
|
const handleAnalytics = useAnalytics(DefaultEventNames.ShowMore);
|
|
30
|
-
const [{ errorLoad, errorShowMore, isFetching,
|
|
30
|
+
const [{ errorLoad, errorShowMore, isFetching, isShowMoreVisible, lastLoadedCount, postCountOnPage, postsOnPage, pinnedPostOnPage, currentPage, queryParams, }, dispatch,] = useReducer(reducer, {
|
|
31
31
|
errorLoad: false,
|
|
32
32
|
errorShowMore: false,
|
|
33
33
|
isFetching: false,
|
|
34
|
-
isShowMoreFetching: false,
|
|
35
34
|
isShowMoreVisible: true,
|
|
36
35
|
lastLoadedCount: (posts === null || posts === void 0 ? void 0 : posts.length) || 0,
|
|
37
36
|
postCountOnPage: totalCount || 0,
|
|
@@ -46,36 +45,36 @@ export const Feed = ({ image }) => {
|
|
|
46
45
|
const pageChange = (value) => {
|
|
47
46
|
dispatch({ type: ActionTypes.PageChange, payload: value });
|
|
48
47
|
};
|
|
49
|
-
const
|
|
50
|
-
dispatch({ type: ActionTypes.
|
|
51
|
-
const hasFirstPageQuery = Object.keys(value).some((queryKey) => queryKey === PAGE_QUERY && value[queryKey] === FIRST_PAGE);
|
|
52
|
-
if (hasFirstPageQuery) {
|
|
53
|
-
// eslint-disable-next-line no-not-accumulator-reassign/no-not-accumulator-reassign
|
|
54
|
-
value[PAGE_QUERY] = null;
|
|
55
|
-
}
|
|
56
|
-
router.updateQueryCallback(value);
|
|
48
|
+
const setIsFetching = (value) => {
|
|
49
|
+
dispatch({ type: ActionTypes.SetIsFetching, payload: value });
|
|
57
50
|
};
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
handleChangeQueryParams({ page: value });
|
|
51
|
+
const setErrorLoad = (value) => {
|
|
52
|
+
dispatch({ type: ActionTypes.SetErrorLoad, payload: value });
|
|
61
53
|
};
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
54
|
+
const handleChangeQueryParams = useCallback((value) => {
|
|
55
|
+
dispatch({ type: ActionTypes.QueryParamsChange, payload: value });
|
|
56
|
+
const hasFirstPageQuery = Object.keys(value).some((queryKey) => queryKey === PAGE_QUERY && value[queryKey] === FIRST_PAGE);
|
|
57
|
+
const result = hasFirstPageQuery
|
|
58
|
+
? Object.assign(Object.assign({}, value), { [PAGE_QUERY]: null }) : Object.assign({}, value);
|
|
59
|
+
router.updateQueryCallback(result);
|
|
60
|
+
}, [router]);
|
|
61
|
+
const fetchData = useCallback(async ({ page, query }) => {
|
|
62
|
+
if (query && getPosts) {
|
|
63
|
+
const queryParamsForRequest = getFeedQueryParams(Object.assign(Object.assign({}, queryParams), query), page);
|
|
64
|
+
const data = await getPosts(queryParamsForRequest);
|
|
66
65
|
return data;
|
|
67
66
|
}
|
|
68
67
|
else {
|
|
69
68
|
throw new Error('cant get request');
|
|
70
69
|
}
|
|
71
70
|
}, [getPosts, queryParams]);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const fetchAndReplaceData = useCallback(async (pageNumber) => {
|
|
71
|
+
const handleLoad = useCallback(async ({ page, query }) => {
|
|
72
|
+
const pageNumber = Number(page || queryParams.page || DEFAULT_PAGE);
|
|
73
|
+
handleChangeQueryParams(query);
|
|
76
74
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
setErrorLoad(false);
|
|
76
|
+
setIsFetching(true);
|
|
77
|
+
const fetchedData = await fetchData({ page: pageNumber, query });
|
|
79
78
|
if (fetchedData) {
|
|
80
79
|
dispatch({
|
|
81
80
|
type: ActionTypes.SetPosts,
|
|
@@ -89,22 +88,35 @@ export const Feed = ({ image }) => {
|
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
catch (err) {
|
|
92
|
-
|
|
91
|
+
setErrorLoad(true);
|
|
93
92
|
}
|
|
94
93
|
scrollOnPageChange(CONTAINER_ID);
|
|
95
94
|
setIsFetching(false);
|
|
96
|
-
}, [fetchData]);
|
|
95
|
+
}, [fetchData, handleChangeQueryParams, queryParams]);
|
|
96
|
+
const handlePageChange = async (value) => {
|
|
97
|
+
pageChange(value);
|
|
98
|
+
handleLoad({
|
|
99
|
+
page: value,
|
|
100
|
+
query: Object.assign(Object.assign({}, queryParams), { page: value }),
|
|
101
|
+
});
|
|
102
|
+
};
|
|
97
103
|
const handleShowMore = async () => {
|
|
98
|
-
dispatch({ type: ActionTypes.SetIsShowMoreFetching, payload: true });
|
|
99
104
|
/**
|
|
100
105
|
* @deprecated Metrika will be deleted after launch of analyticsEvents
|
|
101
106
|
*/
|
|
102
107
|
metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.showMore);
|
|
103
108
|
handleAnalytics();
|
|
109
|
+
const nextPage = currentPage + 1;
|
|
104
110
|
try {
|
|
105
|
-
|
|
111
|
+
setIsFetching(true);
|
|
112
|
+
const fetchedData = await fetchData({
|
|
113
|
+
page: nextPage,
|
|
114
|
+
query: {
|
|
115
|
+
page: nextPage,
|
|
116
|
+
},
|
|
117
|
+
});
|
|
106
118
|
handleChangeQueryParams({
|
|
107
|
-
page:
|
|
119
|
+
page: nextPage,
|
|
108
120
|
});
|
|
109
121
|
if (fetchedData) {
|
|
110
122
|
dispatch({
|
|
@@ -112,7 +124,7 @@ export const Feed = ({ image }) => {
|
|
|
112
124
|
payload: {
|
|
113
125
|
posts: (postsOnPage !== null && postsOnPage !== void 0 ? postsOnPage : []).concat(fetchedData.posts),
|
|
114
126
|
count: fetchedData.count,
|
|
115
|
-
currentPage:
|
|
127
|
+
currentPage: nextPage,
|
|
116
128
|
lastLoadedCount: fetchedData.posts.length,
|
|
117
129
|
},
|
|
118
130
|
});
|
|
@@ -121,13 +133,11 @@ export const Feed = ({ image }) => {
|
|
|
121
133
|
catch (err) {
|
|
122
134
|
dispatch({ type: ActionTypes.SetErrorShowMore, payload: true });
|
|
123
135
|
}
|
|
124
|
-
|
|
136
|
+
setIsFetching(false);
|
|
125
137
|
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
}, [fetchAndReplaceData, isFetching, queryParams.page]);
|
|
138
|
+
const handleOnErrorReload = useCallback(() => {
|
|
139
|
+
handleLoad({ page: currentPage, query: queryParams });
|
|
140
|
+
}, [currentPage, handleLoad, queryParams]);
|
|
131
141
|
useEffect(() => {
|
|
132
142
|
const loadedPostsCount = currentPage * perPageInQuery;
|
|
133
143
|
dispatch({
|
|
@@ -145,10 +155,10 @@ export const Feed = ({ image }) => {
|
|
|
145
155
|
icon: tag.icon && React.createElement(Icon, { data: tag.icon }),
|
|
146
156
|
})), [tags]);
|
|
147
157
|
return (React.createElement("div", null,
|
|
148
|
-
React.createElement(FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems,
|
|
158
|
+
React.createElement(FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems, handleLoadData: handleLoad, queryParams: queryParams, background: {
|
|
149
159
|
fullWidth: true,
|
|
150
160
|
url: image,
|
|
151
161
|
disableCompress: true,
|
|
152
162
|
} }),
|
|
153
|
-
errorLoad ? (React.createElement(PostsError, { onButtonClick:
|
|
163
|
+
errorLoad ? (React.createElement(PostsError, { onButtonClick: handleOnErrorReload })) : (React.createElement(Posts, { containerId: CONTAINER_ID, currentPage: currentPage, isShowMoreVisible: isShowMoreVisible, errorShowMore: errorShowMore, postCountOnPage: postCountOnPage, perPageInQuery: perPageInQuery, handleShowMore: handleShowMore, handlePageChange: handlePageChange, postsOnPage: postsOnPage, pinnedPostOnPage: pinnedPostOnPage, isFetching: isFetching, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
|
|
154
164
|
};
|