@gravity-ui/blog-constructor 3.4.0 → 4.0.0-alpha.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +0 -7
  2. package/build/cjs/blocks/Feed/Feed.js +37 -47
  3. package/build/cjs/blocks/Feed/reducer.d.ts +5 -0
  4. package/build/cjs/blocks/Feed/reducer.js +4 -1
  5. package/build/cjs/blocks/YFM/YFM.js +1 -1
  6. package/build/cjs/blocks/YFM/__tests__/YFM.test.d.ts +1 -0
  7. package/build/cjs/blocks/YFM/__tests__/YFM.test.js +16 -0
  8. package/build/cjs/components/FeedHeader/FeedHeader.js +2 -2
  9. package/build/cjs/components/FeedHeader/components/Controls/Controls.d.ts +3 -2
  10. package/build/cjs/components/FeedHeader/components/Controls/Controls.js +16 -24
  11. package/build/cjs/components/Paginator/Paginator.d.ts +1 -1
  12. package/build/cjs/components/Paginator/Paginator.js +2 -2
  13. package/build/cjs/components/Paginator/types.d.ts +1 -0
  14. package/build/cjs/components/Posts/Posts.css +0 -25
  15. package/build/cjs/components/Posts/Posts.d.ts +1 -0
  16. package/build/cjs/components/Posts/Posts.js +4 -5
  17. package/build/cjs/components/Search/Search.js +1 -1
  18. package/build/cjs/containers/BlogPostPage/BlogPostPage.css +0 -12
  19. package/build/cjs/counters/metrika.d.ts +62 -0
  20. package/build/cjs/counters/metrika.js +173 -0
  21. package/build/cjs/models/common.d.ts +1 -5
  22. package/build/cjs/utils/common.d.ts +1 -1
  23. package/build/cjs/utils/common.js +1 -1
  24. package/build/esm/blocks/Feed/Feed.js +37 -47
  25. package/build/esm/blocks/Feed/reducer.d.ts +5 -0
  26. package/build/esm/blocks/Feed/reducer.js +4 -1
  27. package/build/esm/blocks/YFM/YFM.js +1 -1
  28. package/build/esm/blocks/YFM/__tests__/YFM.test.d.ts +1 -0
  29. package/build/esm/blocks/YFM/__tests__/YFM.test.js +11 -0
  30. package/build/esm/components/FeedHeader/FeedHeader.js +2 -2
  31. package/build/esm/components/FeedHeader/components/Controls/Controls.d.ts +3 -2
  32. package/build/esm/components/FeedHeader/components/Controls/Controls.js +17 -25
  33. package/build/esm/components/Paginator/Paginator.d.ts +1 -1
  34. package/build/esm/components/Paginator/Paginator.js +2 -2
  35. package/build/esm/components/Paginator/types.d.ts +1 -0
  36. package/build/esm/components/Posts/Posts.css +0 -25
  37. package/build/esm/components/Posts/Posts.d.ts +1 -0
  38. package/build/esm/components/Posts/Posts.js +4 -5
  39. package/build/esm/components/Search/Search.js +1 -1
  40. package/build/esm/containers/BlogPostPage/BlogPostPage.css +0 -12
  41. package/build/esm/counters/metrika.d.ts +62 -0
  42. package/build/esm/counters/metrika.js +169 -0
  43. package/build/esm/models/common.d.ts +1 -5
  44. package/build/esm/utils/common.d.ts +1 -1
  45. package/build/esm/utils/common.js +1 -1
  46. package/package.json +5 -2
  47. package/server/data/sanitizeMeta.d.ts +0 -2
  48. package/server/data/sanitizeMeta.js +0 -2
  49. package/server/data/transformPageContent.js +16 -3
  50. package/server/models/common.d.ts +1 -5
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.initCounters = void 0;
4
+ /**
5
+ * @deprecated Metrika will be deleted after launch of analyticsEvents
6
+ */
7
+ const Goal = {
8
+ SUPPORT_OPEN_FORM: 'SUPPORTOPENFORM',
9
+ SUPPORT_STEP_1_SUBMIT: 'SUPPORTSTEP1SUBMIT',
10
+ SUPPORT_STEP_2_SUBMIT: 'SUPPORTSTEP2SUBMIT',
11
+ SUPPORT_STEP_3_SUBMIT: 'SUPPORTSTEP3SUBMIT',
12
+ SUPPORT_THANKYOU_SUBMIT: 'SUPPORTTHANKYOUSUBMIT',
13
+ MP_OPEN_FORM: 'MPOPENFORM',
14
+ EDIT_ON_GITHUB: 'EDITONGITHUB',
15
+ MAIN_GO_TO_VAR: 'MAINGOTOVAR',
16
+ MAIN_GO_TO_ISV: 'MAINGOTOISV',
17
+ MAIN_ALL_PARTNERS: 'MAINALLPARTNERS',
18
+ FIND_GO_TO_VAR: 'FINDGOTOVAR',
19
+ ISV_GO_TO_MP: 'ISVGOTOMP',
20
+ FOOTER_SUBSCRIBE: 'FOOTERSUBSCRIBE',
21
+ FOOTER_MNG_SUBSCRIPTIONS: 'FOOTERMNGSUBSCRIPTIONS',
22
+ MOBILE_STORE_IOS: '154_Mobile_App_Store_Badge',
23
+ MOBILE_STORE_ANDROID: '155_Mobile_Google_Play_Badge',
24
+ REGION_POPUP_SHOW: 'REGIONPOPUP',
25
+ REGION_POPUP_YES: 'REGIONPOPUPYES',
26
+ REGION_POPUP_NO: 'REGIONPOPUPNO',
27
+ REGION_POPUP_CLOSE: 'REGIONPOPUPCLOSE',
28
+ SCALE_REGISTRATION: 'Scale_registration',
29
+ DLGOTOPRODUCT_MPSITE: 'DLGOTOPRODUCT_MPSITE',
30
+ MPK8S_CLCK: 'MPK8S_CLCK',
31
+ 'SITE_CALCULATOR_SHARE-RESULT_CLICK': 'SITE_CALCULATOR_SHARE-RESULT_CLICK',
32
+ };
33
+ const HIT_COUNTERS = ['main', 'cross-site', 'scale'];
34
+ const counterIds = {};
35
+ function getCounter(name) {
36
+ const counterId = counterIds[name];
37
+ return window['yaCounter' + counterId];
38
+ }
39
+ function initCounters(configs) {
40
+ configs.forEach((config) => {
41
+ counterIds[config.name] = config.id;
42
+ });
43
+ }
44
+ exports.initCounters = initCounters;
45
+ function hit(...args) {
46
+ HIT_COUNTERS.forEach((counterName) => {
47
+ const counter = getCounter(counterName);
48
+ if (!counter) {
49
+ return;
50
+ }
51
+ counter.hit(...args);
52
+ });
53
+ }
54
+ function params(...args) {
55
+ const counter = getCounter('main');
56
+ if (!counter) {
57
+ return;
58
+ }
59
+ counter.params(...args);
60
+ }
61
+ function reachGoal(counterName, ...args) {
62
+ const counter = getCounter(counterName);
63
+ if (!counter) {
64
+ return;
65
+ }
66
+ counter.reachGoal(...args);
67
+ }
68
+ function reachGoals(goals, counterName = 'main') {
69
+ if (!goals) {
70
+ return;
71
+ }
72
+ const goalsArray = Array.isArray(goals) ? goals : [goals];
73
+ goalsArray.forEach((goal) => {
74
+ if (typeof goal === 'object') {
75
+ reachGoal(counterName, goal.name, goal.params);
76
+ }
77
+ else {
78
+ reachGoal(counterName, goal);
79
+ }
80
+ });
81
+ }
82
+ // eslint-disable-next-line complexity
83
+ function getServicePrefix(id) {
84
+ switch (id) {
85
+ case 'compute':
86
+ return 'CMPT';
87
+ case 'iam':
88
+ return 'IAM';
89
+ case 'vpc':
90
+ return 'VPC';
91
+ case 'storage':
92
+ return 'STRG';
93
+ case 'speechkit':
94
+ return 'SK';
95
+ case 'managed-clickhouse':
96
+ return 'CH';
97
+ case 'managed-mongodb':
98
+ return 'MONGO';
99
+ case 'managed-postgresql':
100
+ return 'POSTGR';
101
+ case 'managed-redis':
102
+ return 'MR';
103
+ case 'managed-mysql':
104
+ return 'MMSQL';
105
+ case 'managed-kubernetes':
106
+ return 'MK';
107
+ case 'translate':
108
+ return 'TRSL';
109
+ case 'instance-groups':
110
+ return 'INSTGR';
111
+ case 'load-balancer':
112
+ return 'LB';
113
+ case 'message-queue':
114
+ return 'MQ';
115
+ case 'datalens':
116
+ return 'DL';
117
+ case 'monitoring':
118
+ return 'MNTRG';
119
+ case 'data-proc':
120
+ return 'DP';
121
+ case 'kms':
122
+ return 'KMS';
123
+ case 'ydb':
124
+ return 'YDB';
125
+ case 'interconnect':
126
+ return 'INTRCNCT';
127
+ }
128
+ return undefined;
129
+ }
130
+ function getMarketPlacePrefix(id) {
131
+ return `product_${id}_`;
132
+ }
133
+ function goalGoToConsole(prefix) {
134
+ return prefix && `${prefix}GOTOCONSOLE`;
135
+ }
136
+ function goalGoToForm(prefix) {
137
+ return prefix && `${prefix}GOTOFORM`;
138
+ }
139
+ function goalGoToDocs(prefix) {
140
+ return prefix && `${prefix}GOTODOCS`;
141
+ }
142
+ function goalFormSubmit(prefix) {
143
+ return prefix && `${prefix}FORMSUBMIT`;
144
+ }
145
+ function goalEventFormSubmit(id) {
146
+ return `event${id || 's'}_form_submit`;
147
+ }
148
+ function goalEventVideoAction(id, action) {
149
+ return `event${id}_video_${action}`;
150
+ }
151
+ function goalCaseFormSubmit(id) {
152
+ return `case${id ? `_${id}` : 's'}_form_submit`;
153
+ }
154
+ function goalSwitchLang(place) {
155
+ return `SWITCH_LANG_${place}`;
156
+ }
157
+ exports.default = {
158
+ hit,
159
+ params,
160
+ reachGoal,
161
+ reachGoals,
162
+ Goal,
163
+ getServicePrefix,
164
+ getMarketPlacePrefix,
165
+ goalGoToConsole,
166
+ goalGoToForm,
167
+ goalGoToDocs,
168
+ goalFormSubmit,
169
+ goalEventFormSubmit,
170
+ goalEventVideoAction,
171
+ goalCaseFormSubmit,
172
+ goalSwitchLang,
173
+ };
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
- import { HeaderBlockProps as PageConstructorHeaderBlockProps } from '@gravity-ui/page-constructor';
3
2
  import { IBrowser, IDevice } from 'ua-parser-js';
3
+ import { HeaderBlockProps as PageConstructorHeaderBlockProps } from '@gravity-ui/page-constructor';
4
4
  import { Locale } from '../models/locale';
5
5
  export declare enum Theme {
6
6
  Light = "light",
@@ -161,7 +161,3 @@ 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
- };
@@ -23,7 +23,7 @@ export declare const updateContentSizes: ({ size, colSizes, theme, ...contentDat
23
23
  md: number;
24
24
  } | Partial<Record<import("@gravity-ui/page-constructor").GridColumnSize, number>>;
25
25
  theme: import("@gravity-ui/page-constructor").ContentTheme;
26
- title?: string | import("@gravity-ui/page-constructor").TitleBaseProps | undefined;
26
+ title?: string | import("@gravity-ui/page-constructor").TitleItemBaseProps | undefined;
27
27
  text?: string | undefined;
28
28
  additionalInfo?: string | undefined;
29
29
  links?: import("@gravity-ui/page-constructor").LinkProps[] | undefined;
@@ -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 page_constructor_1 = require("@gravity-ui/page-constructor");
17
16
  const lodash_1 = require("lodash");
17
+ const page_constructor_1 = require("@gravity-ui/page-constructor");
18
18
  const constants_1 = require("../blocks/constants");
19
19
  const i18n_1 = require("../i18n");
20
20
  function getAbsolutePath(router, url) {
@@ -27,10 +27,11 @@ 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, isShowMoreVisible, lastLoadedCount, postCountOnPage, postsOnPage, pinnedPostOnPage, currentPage, queryParams, }, dispatch,] = useReducer(reducer, {
30
+ const [{ errorLoad, errorShowMore, isFetching, isShowMoreFetching, 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,
34
35
  isShowMoreVisible: true,
35
36
  lastLoadedCount: (posts === null || posts === void 0 ? void 0 : posts.length) || 0,
36
37
  postCountOnPage: totalCount || 0,
@@ -45,36 +46,36 @@ export const Feed = ({ image }) => {
45
46
  const pageChange = (value) => {
46
47
  dispatch({ type: ActionTypes.PageChange, payload: value });
47
48
  };
48
- const setIsFetching = (value) => {
49
- dispatch({ type: ActionTypes.SetIsFetching, payload: value });
50
- };
51
- const setErrorLoad = (value) => {
52
- dispatch({ type: ActionTypes.SetErrorLoad, payload: value });
53
- };
54
- const handleChangeQueryParams = useCallback((value) => {
49
+ const handleChangeQueryParams = (value) => {
55
50
  dispatch({ type: ActionTypes.QueryParamsChange, payload: value });
56
51
  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);
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);
57
+ };
58
+ const handlePageChange = async (value) => {
59
+ pageChange(value);
60
+ handleChangeQueryParams({ page: value });
61
+ };
62
+ const fetchData = useCallback(async (pageNumber) => {
63
+ if (queryParams && getPosts) {
64
+ const query = getFeedQueryParams(queryParams, pageNumber);
65
+ const data = await getPosts(query);
65
66
  return data;
66
67
  }
67
68
  else {
68
69
  throw new Error('cant get request');
69
70
  }
70
71
  }, [getPosts, queryParams]);
71
- const handleLoad = useCallback(async ({ page, query }) => {
72
- const pageNumber = Number(page || queryParams.page || DEFAULT_PAGE);
73
- handleChangeQueryParams(query);
72
+ const setIsFetching = (value) => {
73
+ dispatch({ type: ActionTypes.SetIsFetching, payload: value });
74
+ };
75
+ const fetchAndReplaceData = useCallback(async (pageNumber) => {
74
76
  try {
75
- setErrorLoad(false);
76
- setIsFetching(true);
77
- const fetchedData = await fetchData({ page: pageNumber, query });
77
+ dispatch({ type: ActionTypes.SetErrorLoad, payload: false });
78
+ const fetchedData = await fetchData(pageNumber);
78
79
  if (fetchedData) {
79
80
  dispatch({
80
81
  type: ActionTypes.SetPosts,
@@ -88,35 +89,22 @@ export const Feed = ({ image }) => {
88
89
  }
89
90
  }
90
91
  catch (err) {
91
- setErrorLoad(true);
92
+ dispatch({ type: ActionTypes.SetErrorLoad, payload: true });
92
93
  }
93
94
  scrollOnPageChange(CONTAINER_ID);
94
95
  setIsFetching(false);
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
- };
96
+ }, [fetchData]);
103
97
  const handleShowMore = async () => {
98
+ dispatch({ type: ActionTypes.SetIsShowMoreFetching, payload: true });
104
99
  /**
105
100
  * @deprecated Metrika will be deleted after launch of analyticsEvents
106
101
  */
107
102
  metrika.reachGoal(MetrikaCounter.CrossSite, BlogMetrikaGoalIds.showMore);
108
103
  handleAnalytics();
109
- const nextPage = currentPage + 1;
110
104
  try {
111
- setIsFetching(true);
112
- const fetchedData = await fetchData({
113
- page: nextPage,
114
- query: {
115
- page: nextPage,
116
- },
117
- });
105
+ const fetchedData = await fetchData(currentPage + 1);
118
106
  handleChangeQueryParams({
119
- page: nextPage,
107
+ page: currentPage + 1,
120
108
  });
121
109
  if (fetchedData) {
122
110
  dispatch({
@@ -124,7 +112,7 @@ export const Feed = ({ image }) => {
124
112
  payload: {
125
113
  posts: (postsOnPage !== null && postsOnPage !== void 0 ? postsOnPage : []).concat(fetchedData.posts),
126
114
  count: fetchedData.count,
127
- currentPage: nextPage,
115
+ currentPage: currentPage + 1,
128
116
  lastLoadedCount: fetchedData.posts.length,
129
117
  },
130
118
  });
@@ -133,11 +121,13 @@ export const Feed = ({ image }) => {
133
121
  catch (err) {
134
122
  dispatch({ type: ActionTypes.SetErrorShowMore, payload: true });
135
123
  }
136
- setIsFetching(false);
124
+ dispatch({ type: ActionTypes.SetIsShowMoreFetching, payload: false });
137
125
  };
138
- const handleOnErrorReload = useCallback(() => {
139
- handleLoad({ page: currentPage, query: queryParams });
140
- }, [currentPage, handleLoad, queryParams]);
126
+ useEffect(() => {
127
+ if (isFetching) {
128
+ fetchAndReplaceData(Number(queryParams.page || DEFAULT_PAGE));
129
+ }
130
+ }, [fetchAndReplaceData, isFetching, queryParams.page]);
141
131
  useEffect(() => {
142
132
  const loadedPostsCount = currentPage * perPageInQuery;
143
133
  dispatch({
@@ -155,10 +145,10 @@ export const Feed = ({ image }) => {
155
145
  icon: tag.icon && React.createElement(Icon, { data: tag.icon }),
156
146
  })), [tags]);
157
147
  return (React.createElement("div", null,
158
- React.createElement(FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems, handleLoadData: handleLoad, queryParams: queryParams, background: {
148
+ React.createElement(FeedHeader, { verticalOffset: "s", tags: tagItems, services: serviceItems, setIsFetching: setIsFetching, handleChangeQuery: handleChangeQueryParams, queryParams: queryParams, background: {
159
149
  fullWidth: true,
160
150
  url: image,
161
151
  disableCompress: true,
162
152
  } }),
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 }))));
153
+ errorLoad ? (React.createElement(PostsError, { onButtonClick: () => fetchAndReplaceData(Number(queryParams.page || DEFAULT_PAGE)) })) : (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, isShowMoreFetching: isShowMoreFetching, pageCountForShowSupportButtons: pageCountForShowSupportButtons }))));
164
154
  };
@@ -6,6 +6,7 @@ export declare enum ActionTypes {
6
6
  SetPosts = "setPosts",
7
7
  SetShowMore = "setShowMore",
8
8
  SetIsFetching = "setIsFetching",
9
+ SetIsShowMoreFetching = "setIsShowMoreFetching",
9
10
  PageChange = "pageChange",
10
11
  QueryParamsChange = "queryParamsChange"
11
12
  }
@@ -14,6 +15,7 @@ export type State = {
14
15
  errorLoad: boolean;
15
16
  errorShowMore: boolean;
16
17
  isFetching: boolean;
18
+ isShowMoreFetching: boolean;
17
19
  isShowMoreVisible: boolean;
18
20
  lastLoadedCount: number;
19
21
  pinnedPostOnPage?: PostData;
@@ -27,6 +29,9 @@ type Action = {
27
29
  } | {
28
30
  type: ActionTypes.SetIsFetching;
29
31
  payload: boolean;
32
+ } | {
33
+ type: ActionTypes.SetIsShowMoreFetching;
34
+ payload: boolean;
30
35
  } | {
31
36
  type: ActionTypes.SetPosts;
32
37
  payload: {
@@ -6,6 +6,7 @@ export var ActionTypes;
6
6
  ActionTypes["SetPosts"] = "setPosts";
7
7
  ActionTypes["SetShowMore"] = "setShowMore";
8
8
  ActionTypes["SetIsFetching"] = "setIsFetching";
9
+ ActionTypes["SetIsShowMoreFetching"] = "setIsShowMoreFetching";
9
10
  ActionTypes["PageChange"] = "pageChange";
10
11
  ActionTypes["QueryParamsChange"] = "queryParamsChange";
11
12
  })(ActionTypes || (ActionTypes = {}));
@@ -16,9 +17,11 @@ export const reducer = (state, { type, payload }) => {
16
17
  case ActionTypes.SetPosts:
17
18
  return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.count, postCountOnPage: payload.count, pinnedPostOnPage: payload.pinnedPost, postsOnPage: payload.posts, currentPage: payload.page });
18
19
  case ActionTypes.SetShowMore:
19
- return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.lastLoadedCount, postCountOnPage: payload.count, currentPage: payload.currentPage, postsOnPage: payload.posts, errorShowMore: false });
20
+ return Object.assign(Object.assign({}, state), { lastLoadedCount: payload.lastLoadedCount, postCountOnPage: payload.count, currentPage: payload.currentPage, postsOnPage: payload.posts, errorShowMore: false, isShowMoreFetching: true });
20
21
  case ActionTypes.SetIsFetching:
21
22
  return Object.assign(Object.assign({}, state), { isFetching: payload });
23
+ case ActionTypes.SetIsShowMoreFetching:
24
+ return Object.assign(Object.assign({}, state), { isShowMoreFetching: payload });
22
25
  case ActionTypes.PageChange:
23
26
  return Object.assign(Object.assign({}, state), { currentPage: payload, isFetching: true });
24
27
  case ActionTypes.SetErrorLoad:
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
- import { YFMWrapper } from '@gravity-ui/page-constructor';
3
2
  import block from 'bem-cn-lite';
3
+ import { YFMWrapper } from '@gravity-ui/page-constructor';
4
4
  import { Wrapper } from '../../components/Wrapper/Wrapper';
5
5
  import { PaddingsDirections } from '../../models/paddings';
6
6
  const b = block('yfm');
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { YFM } from '../YFM';
4
+ const text = 'YFM block';
5
+ describe('YFM', () => {
6
+ test('Has id', async () => {
7
+ render(React.createElement(YFM, { text: text }));
8
+ const yfm = screen.getByText(text);
9
+ expect(yfm).toHaveClass('yfm');
10
+ });
11
+ });
@@ -4,7 +4,7 @@ import { block } from '../../utils/cn';
4
4
  import { Controls } from './components/Controls/Controls';
5
5
  import './FeedHeader.css';
6
6
  const b = block('feed-header');
7
- export const FeedHeader = ({ tags, services, handleLoadData, offset = 'default', background, theme = 'default', verticalOffset = 'l', className, queryParams, }) => {
7
+ export const FeedHeader = ({ tags, services, setIsFetching, offset = 'default', background, theme = 'default', verticalOffset = 'l', className, handleChangeQuery, queryParams, }) => {
8
8
  const backgroundThemed = background && getThemedValue(background, theme);
9
9
  return (React.createElement("header", { className: b('header', { ['has-background']: Boolean(background) }, className) },
10
10
  (backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color) ? (React.createElement(FullWidthBackground, { style: { backgroundColor: backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color }, theme: "rounded" })) : null,
@@ -14,5 +14,5 @@ export const FeedHeader = ({ tags, services, handleLoadData, offset = 'default',
14
14
  ? ''
15
15
  : backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.color,
16
16
  }, disableCompress: backgroundThemed === null || backgroundThemed === void 0 ? void 0 : backgroundThemed.disableCompress })) : null,
17
- React.createElement(Controls, { tags: tags, services: services, handleLoadData: handleLoadData, queryParams: queryParams }))));
17
+ React.createElement(Controls, { tags: tags, services: services, setIsFetching: setIsFetching, handleChangeQuery: handleChangeQuery, queryParams: queryParams }))));
18
18
  };
@@ -1,5 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
- import { FetchArgs, Query, SetQueryType } from '../../../../models/common';
2
+ import { HandleChangeQueryParams, Query, SetQueryType } from '../../../../models/common';
3
3
  import './Controls.css';
4
4
  export type SelectItem = {
5
5
  content: string;
@@ -7,9 +7,10 @@ export type SelectItem = {
7
7
  icon?: ReactNode;
8
8
  };
9
9
  export type ControlsProps = {
10
- handleLoadData: (props: FetchArgs) => void;
10
+ setIsFetching: (value: boolean) => void;
11
11
  tags?: SelectItem[];
12
12
  services?: SelectItem[];
13
+ handleChangeQuery: HandleChangeQueryParams;
13
14
  queryParams: Query;
14
15
  setQuery?: SetQueryType;
15
16
  };
@@ -10,7 +10,7 @@ import metrika from '../../../../counters/metrika.js';
10
10
  import { MetrikaCounter } from '../../../../counters/utils';
11
11
  import { Keyset, i18 } from '../../../../i18n';
12
12
  import { Save } from '../../../../icons/Save';
13
- import { DefaultEventNames } from '../../../../models/common';
13
+ import { DefaultEventNames, } from '../../../../models/common';
14
14
  import { block } from '../../../../utils/cn';
15
15
  import { Search } from '../../../Search/Search';
16
16
  import { renderFilter, renderOption, renderSwitcher } from './customRenders';
@@ -19,7 +19,7 @@ const b = block('feed-controls');
19
19
  const ICON_SIZE = 16;
20
20
  const DEFAULT_PAGE = 1;
21
21
  const VIRTUALIZATION_THRESHOLD = 1000;
22
- export const Controls = ({ handleLoadData, tags = [], services = [], queryParams, }) => {
22
+ export const Controls = ({ setIsFetching, tags = [], services = [], handleChangeQuery, queryParams, }) => {
23
23
  const { hasLikes } = useContext(LikesContext);
24
24
  const handleAnalyticsTag = useAnalytics(DefaultEventNames.Tag);
25
25
  const handleAnalyticsService = useAnalytics(DefaultEventNames.Service);
@@ -28,25 +28,21 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
28
28
  const [savedOnly, setSavedOnly] = useState(savedOnlyInitial === 'true');
29
29
  const [search, setSearch] = useState(searchInitial);
30
30
  const handleSavedOnly = () => {
31
- handleAnalyticsSaveOnly();
32
- setSavedOnly(!savedOnly);
33
- handleLoadData({
31
+ handleChangeQuery({
32
+ savedOnly: savedOnly ? '' : 'true',
33
+ search: '',
34
+ tags: '',
34
35
  page: DEFAULT_PAGE,
35
- query: {
36
- savedOnly: savedOnly ? '' : 'true',
37
- search: '',
38
- tags: '',
39
- page: DEFAULT_PAGE,
40
- services: '',
41
- },
36
+ services: '',
42
37
  });
38
+ handleAnalyticsSaveOnly();
39
+ setSavedOnly(!savedOnly);
40
+ setIsFetching(true);
43
41
  };
44
42
  const handleSearch = (searchValue) => {
43
+ handleChangeQuery({ search: searchValue, page: DEFAULT_PAGE });
45
44
  setSearch(searchValue);
46
- handleLoadData({
47
- page: DEFAULT_PAGE,
48
- query: { search: searchValue, page: DEFAULT_PAGE },
49
- });
45
+ setIsFetching(true);
50
46
  };
51
47
  const handleTagSelect = (selectedTags) => {
52
48
  /**
@@ -59,13 +55,11 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
59
55
  theme: selectedTags[0],
60
56
  });
61
57
  const isEmptyTag = selectedTags.some((tag) => tag === 'empty');
62
- handleLoadData({
58
+ handleChangeQuery({
59
+ tags: isEmptyTag ? '' : selectedTags[0],
63
60
  page: DEFAULT_PAGE,
64
- query: {
65
- tags: isEmptyTag ? '' : selectedTags[0],
66
- page: DEFAULT_PAGE,
67
- },
68
61
  });
62
+ setIsFetching(true);
69
63
  };
70
64
  const handleServicesSelect = (selectedServices) => {
71
65
  const forMetrikaServices = services.filter((service) => {
@@ -82,10 +76,8 @@ export const Controls = ({ handleLoadData, tags = [], services = [], queryParams
82
76
  service: metrikaAsString,
83
77
  });
84
78
  const servicesAsString = selectedServices.join(',');
85
- handleLoadData({
86
- page: DEFAULT_PAGE,
87
- query: { services: servicesAsString, page: DEFAULT_PAGE },
88
- });
79
+ handleChangeQuery({ services: servicesAsString, page: DEFAULT_PAGE });
80
+ setIsFetching(true);
89
81
  };
90
82
  const tagsItems = useMemo(() => [{ value: 'empty', content: i18(Keyset.AllTags) }, ...tags], [tags]);
91
83
  const servicesItems = useMemo(() => (servicesInitial ? [...servicesInitial.split(',')] : []), [servicesInitial]);
@@ -1,3 +1,3 @@
1
1
  import { PaginatorProps } from './types';
2
2
  import './Paginator.css';
3
- export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons, }: PaginatorProps) => JSX.Element | null;
3
+ export declare const Paginator: ({ itemsPerPage, totalItems, maxPages, page, className, loading, onPageChange, pageCountForShowSupportButtons, }: PaginatorProps) => JSX.Element | null;
@@ -26,7 +26,7 @@ import { getPageConfigs, getPagesCount } from './utils';
26
26
  import './Paginator.css';
27
27
  const b = block('paginator');
28
28
  const DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS = 6;
29
- export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, onPageChange, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
29
+ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className, loading, onPageChange, pageCountForShowSupportButtons = DEFAULT_PAGE_COUNT_FOR_SHOW_SUPPORT_BUTTONS, }) => {
30
30
  const [pagesCount, setPagesCount] = useState(getPagesCount({ itemsPerPage, totalItems, maxPages }));
31
31
  useEffect(() => {
32
32
  const count = getPagesCount({ itemsPerPage, totalItems, maxPages });
@@ -95,7 +95,7 @@ export const Paginator = ({ itemsPerPage, totalItems, maxPages, page, className,
95
95
  }
96
96
  const renderPaginatorItem = (item) => {
97
97
  const { key } = item, rest = __rest(item, ["key"]);
98
- return React.createElement(PaginatorItem, Object.assign({ key: `page_${key}` }, rest));
98
+ return React.createElement(PaginatorItem, Object.assign({ key: `page_${key}` }, rest, { loading: loading }));
99
99
  };
100
100
  return (React.createElement("div", { className: b('pagination') },
101
101
  page > 1 && (React.createElement("div", { className: b('pagination-block') },
@@ -15,6 +15,7 @@ export type PaginatorProps = {
15
15
  totalItems: number;
16
16
  itemsPerPage: number;
17
17
  maxPages: number;
18
+ loading: boolean;
18
19
  onPageChange: (page: number) => void;
19
20
  pageCountForShowSupportButtons?: number;
20
21
  } & ClassNameProps;
@@ -1,15 +1,9 @@
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
- }
6
3
  .bc-posts__cards-container, .bc-posts__pinned-container {
7
4
  padding-top: 24px;
8
5
  scroll-margin: 48px;
9
6
  }
10
- .bc-posts__cards-container_isLoading {
11
- opacity: 0.7;
12
- }
13
7
  .bc-posts__pagination {
14
8
  display: flex;
15
9
  flex-direction: column;
@@ -31,23 +25,4 @@ unpredictable css rules order in build */
31
25
  }
32
26
  .bc-posts__paginator {
33
27
  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
- }
53
28
  }
@@ -9,6 +9,7 @@ type PostCardProps = {
9
9
  postCountOnPage: number;
10
10
  perPageInQuery: number;
11
11
  isFetching: boolean;
12
+ isShowMoreFetching: boolean;
12
13
  handleShowMore: (value?: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => Promise<void> | void;
13
14
  handlePageChange: (value: number) => Promise<void> | void;
14
15
  postsOnPage?: PostData[];