@gravity-ui/blog-constructor 3.4.0 → 3.5.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 (36) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/cjs/components/PostInfo/components/Save.js +6 -1
  3. package/build/cjs/components/Prompt/Prompt.css +61 -0
  4. package/build/cjs/components/Prompt/Prompt.d.ts +18 -0
  5. package/build/cjs/components/Prompt/Prompt.js +41 -0
  6. package/build/cjs/components/PromptSignIn/PromptSignIn.d.ts +10 -0
  7. package/build/cjs/components/PromptSignIn/PromptSignIn.js +34 -0
  8. package/build/cjs/components/PromptSignIn/hooks/usePromptSignInProps.d.ts +6 -0
  9. package/build/cjs/components/PromptSignIn/hooks/usePromptSignInProps.js +16 -0
  10. package/build/cjs/containers/BlogPage/BlogPage.d.ts +4 -1
  11. package/build/cjs/containers/BlogPage/BlogPage.js +56 -18
  12. package/build/cjs/contexts/LikesContext.d.ts +2 -0
  13. package/build/cjs/counters/metrika.d.ts +62 -0
  14. package/build/cjs/counters/metrika.js +173 -0
  15. package/build/cjs/hooks/useOpenCloseTimer.d.ts +9 -0
  16. package/build/cjs/hooks/useOpenCloseTimer.js +30 -0
  17. package/build/cjs/i18n/index.d.ts +3 -1
  18. package/build/cjs/i18n/index.js +6 -0
  19. package/build/esm/components/PostInfo/components/Save.js +6 -1
  20. package/build/esm/components/Prompt/Prompt.css +61 -0
  21. package/build/esm/components/Prompt/Prompt.d.ts +19 -0
  22. package/build/esm/components/Prompt/Prompt.js +35 -0
  23. package/build/esm/components/PromptSignIn/PromptSignIn.d.ts +10 -0
  24. package/build/esm/components/PromptSignIn/PromptSignIn.js +27 -0
  25. package/build/esm/components/PromptSignIn/hooks/usePromptSignInProps.d.ts +6 -0
  26. package/build/esm/components/PromptSignIn/hooks/usePromptSignInProps.js +12 -0
  27. package/build/esm/containers/BlogPage/BlogPage.d.ts +4 -1
  28. package/build/esm/containers/BlogPage/BlogPage.js +33 -18
  29. package/build/esm/contexts/LikesContext.d.ts +2 -0
  30. package/build/esm/counters/metrika.d.ts +62 -0
  31. package/build/esm/counters/metrika.js +169 -0
  32. package/build/esm/hooks/useOpenCloseTimer.d.ts +9 -0
  33. package/build/esm/hooks/useOpenCloseTimer.js +26 -0
  34. package/build/esm/i18n/index.d.ts +3 -1
  35. package/build/esm/i18n/index.js +6 -0
  36. package/package.json +4 -1
@@ -25,7 +25,7 @@ const b = block('post-info');
25
25
  * @returns jsx
26
26
  */
27
27
  export const Save = ({ title, postId, hasUserLike, handleUserLike, metrikaGoal, size, theme, dataQa, }) => {
28
- const { toggleLike } = useContext(LikesContext);
28
+ const { toggleLike, isSignedInUser, requireSignIn } = useContext(LikesContext);
29
29
  const handleAnalytics = useAnalytics(DefaultEventNames.SaveButton);
30
30
  const isLikeable = Boolean(toggleLike);
31
31
  return (React.createElement("div", { className: b('item', { size }), onClick: (event) => {
@@ -36,6 +36,11 @@ export const Save = ({ title, postId, hasUserLike, handleUserLike, metrikaGoal,
36
36
  if (!isLikeable) {
37
37
  return;
38
38
  }
39
+ // Open Popup to ask the User to sign in first
40
+ if (!isSignedInUser && requireSignIn) {
41
+ requireSignIn(event);
42
+ return;
43
+ }
39
44
  postLikeStatus(postId, Boolean(hasUserLike));
40
45
  handleUserLike();
41
46
  metrika.reachGoal(MetrikaCounter.CrossSite, metrikaGoal);
@@ -0,0 +1,61 @@
1
+ .bc-prompt__content {
2
+ box-shadow: 0px 4px 24px var(--pc-color-sfx-shadow), 0px 2px 8px var(--pc-color-sfx-shadow);
3
+ }
4
+
5
+ /* use this for style redefinitions to awoid problems with
6
+ unpredictable css rules order in build */
7
+ @keyframes bc-prompt_open {
8
+ 0% {
9
+ opacity: 0;
10
+ transform: translateY(100%);
11
+ }
12
+ 100% {
13
+ opacity: 1;
14
+ transform: translateY(0%);
15
+ }
16
+ }
17
+ @keyframes bc-prompt_close {
18
+ 0% {
19
+ opacity: 1;
20
+ transform: translateY(0%);
21
+ }
22
+ 100% {
23
+ opacity: 0;
24
+ transform: translateY(100%);
25
+ }
26
+ }
27
+ .bc-prompt {
28
+ display: flex;
29
+ width: 100%;
30
+ justify-content: center;
31
+ overflow: hidden;
32
+ position: fixed;
33
+ bottom: 0;
34
+ }
35
+ .bc-prompt:not(.bc-prompt_mounted) {
36
+ display: none;
37
+ }
38
+ .bc-prompt__content {
39
+ display: flex;
40
+ flex-flow: row wrap;
41
+ gap: 16px;
42
+ align-items: center;
43
+ margin: 24px;
44
+ padding: 16px 20px;
45
+ border-radius: var(--pc-border-radius);
46
+ background-color: var(--yc-color-base-float);
47
+ font-size: 1rem;
48
+ }
49
+ .bc-prompt_close {
50
+ pointer-events: none;
51
+ }
52
+ .bc-prompt_open > .bc-prompt__content {
53
+ opacity: 0;
54
+ transform: translateY(100%);
55
+ animation: bc-prompt_open 600ms forwards;
56
+ }
57
+ .bc-prompt_close > .bc-prompt__content {
58
+ opacity: 1;
59
+ transform: translateY(0%);
60
+ animation: bc-prompt_close 600ms forwards;
61
+ }
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { ButtonProps } from '@gravity-ui/uikit';
3
+ import './Prompt.css';
4
+ export interface PromptProps {
5
+ text: string;
6
+ actions: ButtonProps[];
7
+ openTimestamp?: number;
8
+ openDuration?: number;
9
+ className?: string;
10
+ theme?: 'grey' | 'beige' | 'white';
11
+ }
12
+ /**
13
+ * Popup that appears with text message and button(s) for given `actions`.
14
+ * Features:
15
+ * - Automatically disappears after `openDuration` in milliseconds
16
+ * - `openTimestamp` (`Date.now()`) resets the visible duration
17
+ * @returns {JSX|null}
18
+ */
19
+ export declare const Prompt: React.FC<PromptProps>;
@@ -0,0 +1,35 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from 'react';
13
+ import { Button } from '@gravity-ui/uikit';
14
+ import { useOpenCloseTimer } from '../../hooks/useOpenCloseTimer';
15
+ import { block } from '../../utils/cn';
16
+ import './Prompt.css';
17
+ const b = block('prompt');
18
+ /**
19
+ * Popup that appears with text message and button(s) for given `actions`.
20
+ * Features:
21
+ * - Automatically disappears after `openDuration` in milliseconds
22
+ * - `openTimestamp` (`Date.now()`) resets the visible duration
23
+ * @returns {JSX|null}
24
+ */
25
+ export const Prompt = ({ text, actions, className, openTimestamp = 0, openDuration, theme, }) => {
26
+ const { open } = useOpenCloseTimer(openTimestamp, openDuration);
27
+ const mounted = openTimestamp > 0;
28
+ return (React.createElement("div", { className: b({ theme, open, close: !open, mounted }, className) },
29
+ React.createElement("div", { className: b('content') },
30
+ React.createElement("span", { className: b('text') }, text),
31
+ React.createElement("div", { className: b('actions') }, actions.map((_a, i) => {
32
+ var { view = 'action', className: btnClass } = _a, btnProps = __rest(_a, ["view", "className"]);
33
+ return (React.createElement(Button, Object.assign({ key: i, className: b('action', btnClass), view: view }, btnProps)));
34
+ })))));
35
+ };
@@ -0,0 +1,10 @@
1
+ import React, { SyntheticEvent } from 'react';
2
+ import { PromptProps } from '../Prompt/Prompt';
3
+ export interface PromptSignInProps extends Partial<PromptProps> {
4
+ onClickSignIn?: React.EventHandler<SyntheticEvent>;
5
+ }
6
+ /**
7
+ * Authentication Popup that appears when user action requires login
8
+ * @returns {JSX|null}
9
+ */
10
+ export declare const PromptSignIn: React.FC<PromptSignInProps>;
@@ -0,0 +1,27 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from 'react';
13
+ import { Keyset, i18 } from '../../i18n';
14
+ import { Prompt } from '../Prompt/Prompt';
15
+ /**
16
+ * Authentication Popup that appears when user action requires login
17
+ * @returns {JSX|null}
18
+ */
19
+ export const PromptSignIn = (_a) => {
20
+ var { text = i18(Keyset.PromptSignInOnLike), onClickSignIn = () => alert(i18(Keyset.SignIn)), actions = [
21
+ {
22
+ children: i18(Keyset.SignIn),
23
+ onClick: onClickSignIn,
24
+ },
25
+ ] } = _a, props = __rest(_a, ["text", "onClickSignIn", "actions"]);
26
+ return React.createElement(Prompt, Object.assign({}, { text, actions }, props));
27
+ };
@@ -0,0 +1,6 @@
1
+ import React, { SyntheticEvent } from 'react';
2
+ export declare function usePromptSignInProps(onClickSignIn?: React.EventHandler<SyntheticEvent>): {
3
+ onClickSignIn: ((event: React.SyntheticEvent<Element, Event>) => void) | undefined;
4
+ openTimestamp: number;
5
+ requireSignIn: (() => void) | undefined;
6
+ };
@@ -0,0 +1,12 @@
1
+ import { useMemo, useState } from 'react';
2
+ export function usePromptSignInProps(onClickSignIn) {
3
+ const [openTimestamp, setTime] = useState(0);
4
+ const requireSignIn = useMemo(() => {
5
+ return onClickSignIn
6
+ ? () => {
7
+ setTime(Date.now());
8
+ }
9
+ : undefined;
10
+ }, [onClickSignIn, setTime]);
11
+ return { onClickSignIn, openTimestamp, requireSignIn };
12
+ }
@@ -1,3 +1,4 @@
1
+ import React, { SyntheticEvent } from 'react';
1
2
  import { NavigationData, PageConstructorProviderProps, PageContent } from '@gravity-ui/page-constructor';
2
3
  import { GetPostsType, MetaProps, PostsProps, Service, SetQueryType, Tag, ToggleLikeCallbackType } from '../../models/common';
3
4
  import './BlogPage.css';
@@ -14,5 +15,7 @@ export type BlogPageProps = {
14
15
  setQuery?: SetQueryType;
15
16
  settings?: PageConstructorProviderProps;
16
17
  pageCountForShowSupportButtons?: number;
18
+ isSignedInUser?: boolean;
19
+ onClickSignIn?: React.EventHandler<SyntheticEvent>;
17
20
  };
18
- export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, }: BlogPageProps) => JSX.Element;
21
+ export declare const BlogPage: ({ content, posts, tags, services, getPosts, metaData, hasLikes, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser, onClickSignIn, }: BlogPageProps) => JSX.Element;
@@ -1,24 +1,39 @@
1
- import React from 'react';
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React, { useMemo } from 'react';
2
13
  import { PageConstructor, PageConstructorProvider, } from '@gravity-ui/page-constructor';
3
14
  import { MetaWrapper } from '../../components/MetaWrapper/MetaWrapper';
15
+ import { PromptSignIn } from '../../components/PromptSignIn/PromptSignIn';
16
+ import { usePromptSignInProps } from '../../components/PromptSignIn/hooks/usePromptSignInProps';
4
17
  import componentMap from '../../constructor/blocksMap';
5
18
  import { FeedContext } from '../../contexts/FeedContext';
6
19
  import { LikesContext } from '../../contexts/LikesContext';
7
20
  import './BlogPage.css';
8
- export const BlogPage = ({ content, posts, tags, services, getPosts, metaData, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, }) => (React.createElement("main", null,
9
- React.createElement(LikesContext.Provider, { value: {
10
- toggleLike: toggleLike,
11
- hasLikes,
12
- } },
13
- React.createElement(FeedContext.Provider, { value: {
14
- posts: posts.posts,
15
- pinnedPost: posts.pinnedPost,
16
- totalCount: posts.count,
17
- tags,
18
- services: services !== null && services !== void 0 ? services : [],
19
- getPosts,
20
- pageCountForShowSupportButtons,
21
- } },
22
- React.createElement(PageConstructorProvider, Object.assign({}, settings),
23
- metaData ? React.createElement(MetaWrapper, Object.assign({}, metaData)) : null,
24
- React.createElement(PageConstructor, { content: content, custom: componentMap, navigation: navigation }))))));
21
+ export const BlogPage = ({ content, posts, tags, services, getPosts, metaData, hasLikes = false, toggleLike, navigation, settings, pageCountForShowSupportButtons, isSignedInUser = false, onClickSignIn, }) => {
22
+ const _a = usePromptSignInProps(onClickSignIn), { requireSignIn } = _a, promptSignInProps = __rest(_a, ["requireSignIn"]);
23
+ const likes = useMemo(() => ({ toggleLike, hasLikes, isSignedInUser, requireSignIn }), [toggleLike, hasLikes, isSignedInUser, requireSignIn]);
24
+ return (React.createElement("main", null,
25
+ React.createElement(LikesContext.Provider, { value: likes },
26
+ React.createElement(FeedContext.Provider, { value: {
27
+ posts: posts.posts,
28
+ pinnedPost: posts.pinnedPost,
29
+ totalCount: posts.count,
30
+ tags,
31
+ services: services !== null && services !== void 0 ? services : [],
32
+ getPosts,
33
+ pageCountForShowSupportButtons,
34
+ } },
35
+ React.createElement(PageConstructorProvider, Object.assign({}, settings),
36
+ metaData ? React.createElement(MetaWrapper, Object.assign({}, metaData)) : null,
37
+ React.createElement(PageConstructor, { content: content, custom: componentMap, navigation: navigation })))),
38
+ React.createElement(PromptSignIn, Object.assign({}, promptSignInProps))));
39
+ };
@@ -3,5 +3,7 @@ import { ToggleLikeCallbackType } from '../models/common';
3
3
  export interface LikesContextProps {
4
4
  toggleLike?: ToggleLikeCallbackType;
5
5
  hasLikes?: boolean;
6
+ isSignedInUser?: boolean;
7
+ requireSignIn?: React.MouseEventHandler;
6
8
  }
7
9
  export declare const LikesContext: React.Context<LikesContextProps>;
@@ -0,0 +1,62 @@
1
+ export function initCounters(configs: any): void;
2
+ declare namespace _default {
3
+ export { hit };
4
+ export { params };
5
+ export { reachGoal };
6
+ export { reachGoals };
7
+ export { Goal };
8
+ export { getServicePrefix };
9
+ export { getMarketPlacePrefix };
10
+ export { goalGoToConsole };
11
+ export { goalGoToForm };
12
+ export { goalGoToDocs };
13
+ export { goalFormSubmit };
14
+ export { goalEventFormSubmit };
15
+ export { goalEventVideoAction };
16
+ export { goalCaseFormSubmit };
17
+ export { goalSwitchLang };
18
+ }
19
+ export default _default;
20
+ declare function hit(...args: any[]): void;
21
+ declare function params(...args: any[]): void;
22
+ declare function reachGoal(counterName: any, ...args: any[]): void;
23
+ declare function reachGoals(goals: any, counterName?: string): void;
24
+ /**
25
+ * @deprecated Metrika will be deleted after launch of analyticsEvents
26
+ */
27
+ declare const Goal: {
28
+ SUPPORT_OPEN_FORM: string;
29
+ SUPPORT_STEP_1_SUBMIT: string;
30
+ SUPPORT_STEP_2_SUBMIT: string;
31
+ SUPPORT_STEP_3_SUBMIT: string;
32
+ SUPPORT_THANKYOU_SUBMIT: string;
33
+ MP_OPEN_FORM: string;
34
+ EDIT_ON_GITHUB: string;
35
+ MAIN_GO_TO_VAR: string;
36
+ MAIN_GO_TO_ISV: string;
37
+ MAIN_ALL_PARTNERS: string;
38
+ FIND_GO_TO_VAR: string;
39
+ ISV_GO_TO_MP: string;
40
+ FOOTER_SUBSCRIBE: string;
41
+ FOOTER_MNG_SUBSCRIPTIONS: string;
42
+ MOBILE_STORE_IOS: string;
43
+ MOBILE_STORE_ANDROID: string;
44
+ REGION_POPUP_SHOW: string;
45
+ REGION_POPUP_YES: string;
46
+ REGION_POPUP_NO: string;
47
+ REGION_POPUP_CLOSE: string;
48
+ SCALE_REGISTRATION: string;
49
+ DLGOTOPRODUCT_MPSITE: string;
50
+ MPK8S_CLCK: string;
51
+ 'SITE_CALCULATOR_SHARE-RESULT_CLICK': string;
52
+ };
53
+ declare function getServicePrefix(id: any): "CMPT" | "IAM" | "VPC" | "STRG" | "SK" | "CH" | "MONGO" | "POSTGR" | "MR" | "MMSQL" | "MK" | "TRSL" | "INSTGR" | "LB" | "MQ" | "DL" | "MNTRG" | "DP" | "KMS" | "YDB" | "INTRCNCT" | undefined;
54
+ declare function getMarketPlacePrefix(id: any): string;
55
+ declare function goalGoToConsole(prefix: any): any;
56
+ declare function goalGoToForm(prefix: any): any;
57
+ declare function goalGoToDocs(prefix: any): any;
58
+ declare function goalFormSubmit(prefix: any): any;
59
+ declare function goalEventFormSubmit(id: any): string;
60
+ declare function goalEventVideoAction(id: any, action: any): string;
61
+ declare function goalCaseFormSubmit(id: any): string;
62
+ declare function goalSwitchLang(place: any): string;
@@ -0,0 +1,169 @@
1
+ /**
2
+ * @deprecated Metrika will be deleted after launch of analyticsEvents
3
+ */
4
+ const Goal = {
5
+ SUPPORT_OPEN_FORM: 'SUPPORTOPENFORM',
6
+ SUPPORT_STEP_1_SUBMIT: 'SUPPORTSTEP1SUBMIT',
7
+ SUPPORT_STEP_2_SUBMIT: 'SUPPORTSTEP2SUBMIT',
8
+ SUPPORT_STEP_3_SUBMIT: 'SUPPORTSTEP3SUBMIT',
9
+ SUPPORT_THANKYOU_SUBMIT: 'SUPPORTTHANKYOUSUBMIT',
10
+ MP_OPEN_FORM: 'MPOPENFORM',
11
+ EDIT_ON_GITHUB: 'EDITONGITHUB',
12
+ MAIN_GO_TO_VAR: 'MAINGOTOVAR',
13
+ MAIN_GO_TO_ISV: 'MAINGOTOISV',
14
+ MAIN_ALL_PARTNERS: 'MAINALLPARTNERS',
15
+ FIND_GO_TO_VAR: 'FINDGOTOVAR',
16
+ ISV_GO_TO_MP: 'ISVGOTOMP',
17
+ FOOTER_SUBSCRIBE: 'FOOTERSUBSCRIBE',
18
+ FOOTER_MNG_SUBSCRIPTIONS: 'FOOTERMNGSUBSCRIPTIONS',
19
+ MOBILE_STORE_IOS: '154_Mobile_App_Store_Badge',
20
+ MOBILE_STORE_ANDROID: '155_Mobile_Google_Play_Badge',
21
+ REGION_POPUP_SHOW: 'REGIONPOPUP',
22
+ REGION_POPUP_YES: 'REGIONPOPUPYES',
23
+ REGION_POPUP_NO: 'REGIONPOPUPNO',
24
+ REGION_POPUP_CLOSE: 'REGIONPOPUPCLOSE',
25
+ SCALE_REGISTRATION: 'Scale_registration',
26
+ DLGOTOPRODUCT_MPSITE: 'DLGOTOPRODUCT_MPSITE',
27
+ MPK8S_CLCK: 'MPK8S_CLCK',
28
+ 'SITE_CALCULATOR_SHARE-RESULT_CLICK': 'SITE_CALCULATOR_SHARE-RESULT_CLICK',
29
+ };
30
+ const HIT_COUNTERS = ['main', 'cross-site', 'scale'];
31
+ const counterIds = {};
32
+ function getCounter(name) {
33
+ const counterId = counterIds[name];
34
+ return window['yaCounter' + counterId];
35
+ }
36
+ export function initCounters(configs) {
37
+ configs.forEach((config) => {
38
+ counterIds[config.name] = config.id;
39
+ });
40
+ }
41
+ function hit(...args) {
42
+ HIT_COUNTERS.forEach((counterName) => {
43
+ const counter = getCounter(counterName);
44
+ if (!counter) {
45
+ return;
46
+ }
47
+ counter.hit(...args);
48
+ });
49
+ }
50
+ function params(...args) {
51
+ const counter = getCounter('main');
52
+ if (!counter) {
53
+ return;
54
+ }
55
+ counter.params(...args);
56
+ }
57
+ function reachGoal(counterName, ...args) {
58
+ const counter = getCounter(counterName);
59
+ if (!counter) {
60
+ return;
61
+ }
62
+ counter.reachGoal(...args);
63
+ }
64
+ function reachGoals(goals, counterName = 'main') {
65
+ if (!goals) {
66
+ return;
67
+ }
68
+ const goalsArray = Array.isArray(goals) ? goals : [goals];
69
+ goalsArray.forEach((goal) => {
70
+ if (typeof goal === 'object') {
71
+ reachGoal(counterName, goal.name, goal.params);
72
+ }
73
+ else {
74
+ reachGoal(counterName, goal);
75
+ }
76
+ });
77
+ }
78
+ // eslint-disable-next-line complexity
79
+ function getServicePrefix(id) {
80
+ switch (id) {
81
+ case 'compute':
82
+ return 'CMPT';
83
+ case 'iam':
84
+ return 'IAM';
85
+ case 'vpc':
86
+ return 'VPC';
87
+ case 'storage':
88
+ return 'STRG';
89
+ case 'speechkit':
90
+ return 'SK';
91
+ case 'managed-clickhouse':
92
+ return 'CH';
93
+ case 'managed-mongodb':
94
+ return 'MONGO';
95
+ case 'managed-postgresql':
96
+ return 'POSTGR';
97
+ case 'managed-redis':
98
+ return 'MR';
99
+ case 'managed-mysql':
100
+ return 'MMSQL';
101
+ case 'managed-kubernetes':
102
+ return 'MK';
103
+ case 'translate':
104
+ return 'TRSL';
105
+ case 'instance-groups':
106
+ return 'INSTGR';
107
+ case 'load-balancer':
108
+ return 'LB';
109
+ case 'message-queue':
110
+ return 'MQ';
111
+ case 'datalens':
112
+ return 'DL';
113
+ case 'monitoring':
114
+ return 'MNTRG';
115
+ case 'data-proc':
116
+ return 'DP';
117
+ case 'kms':
118
+ return 'KMS';
119
+ case 'ydb':
120
+ return 'YDB';
121
+ case 'interconnect':
122
+ return 'INTRCNCT';
123
+ }
124
+ return undefined;
125
+ }
126
+ function getMarketPlacePrefix(id) {
127
+ return `product_${id}_`;
128
+ }
129
+ function goalGoToConsole(prefix) {
130
+ return prefix && `${prefix}GOTOCONSOLE`;
131
+ }
132
+ function goalGoToForm(prefix) {
133
+ return prefix && `${prefix}GOTOFORM`;
134
+ }
135
+ function goalGoToDocs(prefix) {
136
+ return prefix && `${prefix}GOTODOCS`;
137
+ }
138
+ function goalFormSubmit(prefix) {
139
+ return prefix && `${prefix}FORMSUBMIT`;
140
+ }
141
+ function goalEventFormSubmit(id) {
142
+ return `event${id || 's'}_form_submit`;
143
+ }
144
+ function goalEventVideoAction(id, action) {
145
+ return `event${id}_video_${action}`;
146
+ }
147
+ function goalCaseFormSubmit(id) {
148
+ return `case${id ? `_${id}` : 's'}_form_submit`;
149
+ }
150
+ function goalSwitchLang(place) {
151
+ return `SWITCH_LANG_${place}`;
152
+ }
153
+ export default {
154
+ hit,
155
+ params,
156
+ reachGoal,
157
+ reachGoals,
158
+ Goal,
159
+ getServicePrefix,
160
+ getMarketPlacePrefix,
161
+ goalGoToConsole,
162
+ goalGoToForm,
163
+ goalGoToDocs,
164
+ goalFormSubmit,
165
+ goalEventFormSubmit,
166
+ goalEventVideoAction,
167
+ goalCaseFormSubmit,
168
+ goalSwitchLang,
169
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Timer to automatically update `open` state after a given duration
3
+ * @param {number} openTimestamp - UNIX timestamp in milliseconds
4
+ * @param {number} openDuration - in milliseconds
5
+ * @returns {{open: boolean}} {open} - whether the state is open
6
+ */
7
+ export declare function useOpenCloseTimer(openTimestamp?: number, openDuration?: number): {
8
+ open: boolean;
9
+ };
@@ -0,0 +1,26 @@
1
+ import { useEffect, useState } from 'react';
2
+ /**
3
+ * Timer to automatically update `open` state after a given duration
4
+ * @param {number} openTimestamp - UNIX timestamp in milliseconds
5
+ * @param {number} openDuration - in milliseconds
6
+ * @returns {{open: boolean}} {open} - whether the state is open
7
+ */
8
+ export function useOpenCloseTimer(openTimestamp = Date.now(), openDuration = 4000) {
9
+ const open = Date.now() - openTimestamp < openDuration;
10
+ const [, reset] = useState(0); // time to reset `open` state
11
+ useEffect(() => {
12
+ const closeTime = openTimestamp + openDuration;
13
+ const delay = closeTime - Date.now();
14
+ if (delay <= 0) {
15
+ return;
16
+ }
17
+ const timer = setTimeout(() => {
18
+ reset(Date.now);
19
+ }, delay);
20
+ // eslint-disable-next-line consistent-return
21
+ return () => {
22
+ clearTimeout(timer);
23
+ };
24
+ }, [openTimestamp, openDuration]);
25
+ return { open };
26
+ }
@@ -17,6 +17,8 @@ export declare enum Keyset {
17
17
  Search = "search_placeholder",
18
18
  AllTags = "label_all_tags",
19
19
  ActionSavedOnly = "action_saved_only",
20
- AllServices = "label_all_services"
20
+ AllServices = "label_all_services",
21
+ PromptSignInOnLike = "prompt_sign_in_on_like",
22
+ SignIn = "Sign In"
21
23
  }
22
24
  export declare const i18: (key: string, params?: import("@gravity-ui/i18n").Params | undefined) => string;
@@ -21,6 +21,8 @@ export var Keyset;
21
21
  Keyset["AllTags"] = "label_all_tags";
22
22
  Keyset["ActionSavedOnly"] = "action_saved_only";
23
23
  Keyset["AllServices"] = "label_all_services";
24
+ Keyset["PromptSignInOnLike"] = "prompt_sign_in_on_like";
25
+ Keyset["SignIn"] = "Sign In";
24
26
  })(Keyset || (Keyset = {}));
25
27
  i18n.registerKeyset(Lang.En, KEYSET_NAME, {
26
28
  [Keyset.Title]: 'Blog',
@@ -39,11 +41,13 @@ i18n.registerKeyset(Lang.En, KEYSET_NAME, {
39
41
  [Keyset.AllTags]: 'All topics',
40
42
  [Keyset.ActionSavedOnly]: 'Saved',
41
43
  [Keyset.AllServices]: 'All Services',
44
+ [Keyset.PromptSignInOnLike]: 'Please sign in to save your bookmarks',
42
45
  [Keyset.ContextReadingTime]: [
43
46
  '{{count}} min to read',
44
47
  '{{count}} mins to read',
45
48
  '{{count}} mins to read',
46
49
  ],
50
+ [Keyset.SignIn]: 'Sign In',
47
51
  });
48
52
  i18n.registerKeyset(Lang.Ru, KEYSET_NAME, {
49
53
  [Keyset.Title]: 'Блог',
@@ -62,10 +66,12 @@ i18n.registerKeyset(Lang.Ru, KEYSET_NAME, {
62
66
  [Keyset.AllTags]: 'Все темы',
63
67
  [Keyset.ActionSavedOnly]: 'Сохранённые',
64
68
  [Keyset.AllServices]: 'Все сервисы',
69
+ [Keyset.PromptSignInOnLike]: 'Войдите, чтобы добавить доклад в своё расписание',
65
70
  [Keyset.ContextReadingTime]: [
66
71
  '{{count}} минута чтения',
67
72
  '{{count}} минуты чтения',
68
73
  '{{count}} минут чтения',
69
74
  ],
75
+ [Keyset.SignIn]: 'Войти',
70
76
  });
71
77
  export const i18 = i18n.keyset(KEYSET_NAME);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/blog-constructor",
3
- "version": "3.4.0",
3
+ "version": "3.5.0-alpha.0",
4
4
  "description": "Gravity UI Blog Constructor",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -141,5 +141,8 @@
141
141
  "*.{json,yaml,yml,md}": [
142
142
  "prettier --write"
143
143
  ]
144
+ },
145
+ "publishConfig": {
146
+ "tag": "alpha"
144
147
  }
145
148
  }