@gravity-ui/blog-constructor 3.4.0 → 3.5.0-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }