ydb-embedded-ui 4.28.0 → 4.29.0

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.29.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.28.0...v4.29.0) (2024-01-12)
4
+
5
+
6
+ ### Features
7
+
8
+ * add ErrorBoundary ([#549](https://github.com/ydb-platform/ydb-embedded-ui/issues/549)) ([f5ad224](https://github.com/ydb-platform/ydb-embedded-ui/commit/f5ad224b342e0fa25b1bafa3f5e2202ce165ef80))
9
+
3
10
  ## [4.28.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.27.1...v4.28.0) (2024-01-10)
4
11
 
5
12
 
@@ -0,0 +1,32 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="230" height="230" fill="none">
2
+ <path fill="#BECFE0" fill-opacity=".8" fill-rule="evenodd" d="M169.001 51.666c5.523 0 10 4.477 10 10v21.017l18.197-10.506c4.783-2.762 10.899-1.123 13.66 3.66 2.761 4.783 1.123 10.899-3.66 13.66l-18.197 10.507 18.198 10.506c4.783 2.762 6.421 8.878 3.66 13.661-2.762 4.782-8.877 6.421-13.66 3.66l-18.198-10.506v21.008c0 5.523-4.477 10-10 10-5.522 0-10-4.477-10-10v-21.009l-18.199 10.507c-4.782 2.761-10.898 1.122-13.66-3.66-2.761-4.783-1.122-10.899 3.66-13.661l18.199-10.506-18.198-10.507c-4.783-2.761-6.421-8.877-3.66-13.66 2.762-4.783 8.877-6.422 13.66-3.66l18.198 10.507V61.666c0-5.523 4.478-10 10-10Z" clip-rule="evenodd"/>
3
+ <path fill="#E7E7E7" fill-rule="evenodd" d="M171.523 95.922a11.003 11.003 0 0 1 1.099 8.347l-13.208 49.291c-1.572 5.868-7.604 9.351-13.472 7.778l-25.356-6.794a44.998 44.998 0 0 1-.53 1.929l25.368 6.797c6.935 1.858 14.064-2.257 15.922-9.192l13.207-49.291c.893-3.33.426-6.879-1.298-9.865L155.598 64.34a12.999 12.999 0 0 0-7.894-6.057l-29.972-8.031c-6.935-1.858-14.063 2.257-15.922 9.192l-11.328 42.277c.64.192 1.276.398 1.905.618l11.355-42.377c1.573-5.868 7.604-9.35 13.472-7.778l29.973 8.03a11 11 0 0 1 6.679 5.126l17.657 30.582Z" clip-rule="evenodd"/>
4
+ <path fill="#FF5958" fill-opacity=".8" d="M35.388 155.273c-6.29-23.472 7.64-47.599 31.113-53.889 23.472-6.289 47.599 7.641 53.889 31.113 6.289 23.473-7.641 47.599-31.113 53.889-23.473 6.289-47.6-7.64-53.889-31.113Z"/>
5
+ <path stroke="#E7E7E7" stroke-width="2" d="M60.636 117.734c53.586-33.459-26.868-81.505-36.557-61.318-11.802 24.59 99.395 51.098 128.865-26.3"/>
6
+ <mask id="b" width="89" height="89" x="33" y="99" maskUnits="userSpaceOnUse" style="mask-type:alpha">
7
+ <path fill="#FF5958" fill-opacity=".9" d="M35.388 155.273c-6.29-23.472 7.64-47.599 31.113-53.889 23.472-6.289 47.599 7.641 53.889 31.113 6.289 23.473-7.641 47.599-31.113 53.889-23.473 6.289-47.6-7.64-53.889-31.113Z"/>
8
+ </mask>
9
+ <g filter="url(#a)" mask="url(#b)">
10
+ <path stroke="#E7E7E7" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".6" stroke-width="2" d="M172.389 95.422a12.004 12.004 0 0 1 1.199 9.106l-13.208 49.291c-1.715 6.401-8.295 10.2-14.697 8.485L91.591 147.81c-6.401-1.715-10.2-8.295-8.485-14.697l19.67-73.41c1.716-6.402 8.296-10.2 14.697-8.485l29.972 8.03a11.998 11.998 0 0 1 7.287 5.592l17.657 30.582Z"/>
11
+ </g>
12
+ <g filter="url(#c)">
13
+ <path fill="#fff" fill-opacity=".72" fill-rule="evenodd" d="M80.866 130.432a6.359 6.359 0 1 1-12.284 3.29 6.359 6.359 0 0 1 12.284-3.29Zm4.817-1.291c1.621 6.052-1.97 12.273-8.022 13.894-6.052 1.622-12.273-1.97-13.895-8.022-1.621-6.052 1.97-12.272 8.022-13.894 6.052-1.622 12.273 1.97 13.895 8.022Zm-21.346 32.565c-.154-.577-.009-2.61 2.877-5.555 2.665-2.721 6.917-5.33 12.158-6.734 5.24-1.404 10.227-1.271 13.896-.247 3.971 1.108 5.114 2.796 5.268 3.372a3.116 3.116 0 0 1-2.204 3.817l-28.178 7.55a3.116 3.116 0 0 1-3.817-2.203ZM78.081 144.6c-12.054 3.23-20.238 12.134-18.56 18.396a8.103 8.103 0 0 0 9.924 5.73l28.178-7.55a8.104 8.104 0 0 0 5.73-9.925c-1.678-6.261-13.218-9.881-25.272-6.651Z" clip-rule="evenodd"/>
14
+ </g>
15
+ <defs>
16
+ <filter id="a" width="113.303" height="133.91" x="71.693" y="39.806" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
17
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
18
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
19
+ <feGaussianBlur result="effect1_foregroundBlur_1301_35376" stdDeviation="5"/>
20
+ </filter>
21
+ <filter id="c" width="73.289" height="73.288" x="41.018" y="106.391" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
22
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
23
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
24
+ <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
25
+ <feOffset/>
26
+ <feGaussianBlur stdDeviation="1.917"/>
27
+ <feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
28
+ <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.8 0"/>
29
+ <feBlend in2="shape" result="effect1_innerShadow_1301_35376"/>
30
+ </filter>
31
+ </defs>
32
+ </svg>
@@ -0,0 +1,32 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="230" height="230" fill="none">
2
+ <path fill="#BECFE0" fill-opacity=".9" fill-rule="evenodd" d="M169.001 51.666c5.523 0 10 4.477 10 10v21.017l18.197-10.506c4.783-2.762 10.899-1.123 13.66 3.66 2.761 4.783 1.123 10.899-3.66 13.66l-18.197 10.507 18.198 10.506c4.783 2.762 6.421 8.878 3.66 13.661-2.762 4.782-8.877 6.421-13.66 3.66l-18.198-10.506v21.008c0 5.523-4.477 10-10 10-5.522 0-10-4.477-10-10v-21.009l-18.199 10.507c-4.782 2.761-10.898 1.122-13.66-3.66-2.761-4.783-1.122-10.899 3.66-13.661l18.199-10.506-18.198-10.507c-4.783-2.761-6.421-8.877-3.66-13.66 2.762-4.783 8.877-6.422 13.66-3.66l18.198 10.507V61.666c0-5.523 4.478-10 10-10Z" clip-rule="evenodd"/>
3
+ <path fill="#262626" fill-rule="evenodd" d="M171.523 95.922a11.003 11.003 0 0 1 1.099 8.347l-13.208 49.291c-1.572 5.868-7.604 9.351-13.472 7.778l-25.356-6.794a44.998 44.998 0 0 1-.53 1.929l25.368 6.797c6.935 1.858 14.064-2.257 15.922-9.192l13.207-49.291c.893-3.33.426-6.879-1.298-9.865L155.598 64.34a12.999 12.999 0 0 0-7.894-6.057l-29.972-8.031c-6.935-1.858-14.063 2.257-15.922 9.192l-11.328 42.277c.64.192 1.276.398 1.905.618l11.355-42.377c1.573-5.868 7.604-9.35 13.472-7.778l29.973 8.03a11 11 0 0 1 6.679 5.126l17.657 30.582Z" clip-rule="evenodd"/>
4
+ <path fill="#FF5958" fill-opacity=".9" d="M35.388 155.273c-6.29-23.472 7.64-47.599 31.113-53.889 23.472-6.289 47.599 7.641 53.889 31.113 6.289 23.473-7.641 47.599-31.113 53.889-23.473 6.289-47.6-7.64-53.889-31.113Z"/>
5
+ <path stroke="#262626" stroke-width="2" d="M60.636 117.734c53.586-33.459-26.868-81.505-36.557-61.318-11.802 24.59 99.395 51.098 128.865-26.3"/>
6
+ <mask id="b" width="89" height="89" x="33" y="99" maskUnits="userSpaceOnUse" style="mask-type:alpha">
7
+ <path fill="#FF5958" fill-opacity=".9" d="M35.388 155.273c-6.29-23.472 7.64-47.599 31.113-53.889 23.472-6.289 47.599 7.641 53.889 31.113 6.289 23.473-7.641 47.599-31.113 53.889-23.473 6.289-47.6-7.64-53.889-31.113Z"/>
8
+ </mask>
9
+ <g filter="url(#a)" mask="url(#b)">
10
+ <path stroke="#262626" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".6" stroke-width="2" d="M172.389 95.422a12.004 12.004 0 0 1 1.199 9.106l-13.208 49.291c-1.715 6.401-8.295 10.2-14.697 8.485L91.591 147.81c-6.401-1.715-10.2-8.295-8.485-14.697l19.67-73.41c1.716-6.402 8.296-10.2 14.697-8.485l29.972 8.03a11.998 11.998 0 0 1 7.287 5.592l17.657 30.582Z"/>
11
+ </g>
12
+ <g filter="url(#c)">
13
+ <path fill="#fff" fill-opacity=".72" fill-rule="evenodd" d="M80.866 130.432a6.359 6.359 0 1 1-12.284 3.29 6.359 6.359 0 0 1 12.284-3.29Zm4.817-1.291c1.621 6.052-1.97 12.273-8.022 13.894-6.052 1.622-12.273-1.97-13.895-8.022-1.621-6.052 1.97-12.272 8.022-13.894 6.052-1.622 12.273 1.97 13.895 8.022Zm-21.346 32.565c-.154-.577-.009-2.61 2.877-5.555 2.665-2.721 6.917-5.33 12.158-6.734 5.24-1.404 10.227-1.271 13.896-.247 3.971 1.108 5.114 2.796 5.268 3.372a3.116 3.116 0 0 1-2.204 3.817l-28.178 7.55a3.116 3.116 0 0 1-3.817-2.203ZM78.081 144.6c-12.054 3.23-20.238 12.134-18.56 18.396a8.103 8.103 0 0 0 9.924 5.73l28.178-7.55a8.104 8.104 0 0 0 5.73-9.925c-1.678-6.261-13.218-9.881-25.272-6.651Z" clip-rule="evenodd"/>
14
+ </g>
15
+ <defs>
16
+ <filter id="a" width="113.303" height="133.91" x="71.693" y="39.806" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
17
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
18
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
19
+ <feGaussianBlur result="effect1_foregroundBlur_1301_31085" stdDeviation="5"/>
20
+ </filter>
21
+ <filter id="c" width="73.289" height="73.288" x="41.018" y="106.391" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">
22
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
23
+ <feBlend in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
24
+ <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
25
+ <feOffset/>
26
+ <feGaussianBlur stdDeviation="1.917"/>
27
+ <feComposite in2="hardAlpha" k2="-1" k3="1" operator="arithmetic"/>
28
+ <feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.8 0"/>
29
+ <feBlend in2="shape" result="effect1_innerShadow_1301_31085"/>
30
+ </filter>
31
+ </defs>
32
+ </svg>
@@ -0,0 +1,40 @@
1
+ @import '../../styles/mixins.scss';
2
+
3
+ .ydb-error-boundary {
4
+ display: flex;
5
+ flex-direction: row;
6
+ align-items: flex-start;
7
+
8
+ padding: 20px;
9
+
10
+ @include body-2-typography();
11
+
12
+ &__illustration {
13
+ width: 230px;
14
+ height: 230px;
15
+ margin-right: 20px;
16
+ }
17
+ &__error-title {
18
+ margin-top: 44px;
19
+ @include lead-typography();
20
+ }
21
+ &__error-description {
22
+ margin-top: 12px;
23
+ }
24
+ &__show-details {
25
+ margin-top: 8px;
26
+ }
27
+ &__error-details {
28
+ padding: 13px 18px;
29
+
30
+ border: 1px solid var(--g-color-line-generic);
31
+ background-color: var(--g-color-base-generic-ultralight);
32
+ }
33
+ &__actions {
34
+ display: flex;
35
+ flex-direction: row;
36
+ gap: 10px;
37
+
38
+ margin-top: 20px;
39
+ }
40
+ }
@@ -0,0 +1,62 @@
1
+ import type {ReactNode} from 'react';
2
+ import {ErrorBoundary as ErrorBoundaryBase} from 'react-error-boundary';
3
+ import cn from 'bem-cn-lite';
4
+
5
+ import {Button, Disclosure} from '@gravity-ui/uikit';
6
+
7
+ import {registerError} from '../../utils/registerError';
8
+ import {Illustration} from '../Illustration';
9
+ import i18n from './i18n';
10
+ import './ErrorBoundary.scss';
11
+
12
+ const b = cn('ydb-error-boundary');
13
+
14
+ interface ErrorBoundaryProps {
15
+ children?: ReactNode;
16
+ useRetry?: boolean;
17
+ onReportProblem?: (error?: Error) => void;
18
+ }
19
+
20
+ export const ErrorBoundary = ({children, useRetry = true, onReportProblem}: ErrorBoundaryProps) => {
21
+ return (
22
+ <ErrorBoundaryBase
23
+ onError={(error, info) => {
24
+ registerError(error, info.componentStack, 'error-boundary');
25
+ }}
26
+ fallbackRender={({error, resetErrorBoundary}) => {
27
+ return (
28
+ <div className={b(null)}>
29
+ <Illustration name="error" className={b('illustration')} />
30
+ <div className={b('content')}>
31
+ <h2 className={b('error-title')}>{i18n('error-title')}</h2>
32
+ <div className={b('error-description')}>
33
+ {i18n('error-description')}
34
+ </div>
35
+ <Disclosure
36
+ summary={i18n('show-details')}
37
+ className={b('show-details')}
38
+ size="m"
39
+ >
40
+ <pre className={b('error-details')}>{error.stack}</pre>
41
+ </Disclosure>
42
+ <div className={b('actions')}>
43
+ {useRetry && (
44
+ <Button view="outlined" onClick={resetErrorBoundary}>
45
+ {i18n('button-reset')}
46
+ </Button>
47
+ )}
48
+ {onReportProblem && (
49
+ <Button view="outlined" onClick={() => onReportProblem(error)}>
50
+ {i18n('report-problem')}
51
+ </Button>
52
+ )}
53
+ </div>
54
+ </div>
55
+ </div>
56
+ );
57
+ }}
58
+ >
59
+ {children}
60
+ </ErrorBoundaryBase>
61
+ );
62
+ };
@@ -0,0 +1,7 @@
1
+ {
2
+ "error-title": "Something went wrong",
3
+ "error-description": "We have something broken, but don't worry, it won't last long",
4
+ "show-details": "Show details",
5
+ "report-problem": "Report a problem",
6
+ "button-reset": "Try again"
7
+ }
@@ -0,0 +1,11 @@
1
+ import {i18n, Lang} from '../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+ import ru from './ru.json';
5
+
6
+ const COMPONENT = 'ydb-error-boundary';
7
+
8
+ i18n.registerKeyset(Lang.En, COMPONENT, en);
9
+ i18n.registerKeyset(Lang.Ru, COMPONENT, ru);
10
+
11
+ export default i18n.keyset(COMPONENT);
@@ -0,0 +1,7 @@
1
+ {
2
+ "error-title": "Что-то пошло не так",
3
+ "error-description": "У нас что-то сломалось, но не переживайте, это ненадолго",
4
+ "show-details": "Показать детали",
5
+ "report-problem": "Сообщить о проблеме",
6
+ "button-reset": "Попробовать снова"
7
+ }
@@ -13,10 +13,12 @@ const store: IllustrationStore = {
13
13
  light: {
14
14
  403: () => import('../../assets/illustrations/light/403.svg'),
15
15
  thumbsUp: () => import('../../assets/illustrations/light/thumbsUp.svg'),
16
+ error: () => import('../../assets/illustrations/light/error.svg'),
16
17
  },
17
18
  dark: {
18
19
  403: () => import('../../assets/illustrations/dark/403.svg'),
19
- thumbsUp: () => import('../../assets/illustrations/light/thumbsUp.svg'),
20
+ thumbsUp: () => import('../../assets/illustrations/dark/thumbsUp.svg'),
21
+ error: () => import('../../assets/illustrations/dark/error.svg'),
20
22
  },
21
23
  };
22
24
 
@@ -7,6 +7,7 @@ import AsideNavigation from '../AsideNavigation/AsideNavigation';
7
7
 
8
8
  import {getUser} from '../../store/reducers/authentication/authentication';
9
9
  import {registerLanguages} from '../../utils/monaco';
10
+ import {ErrorBoundary} from '../../components/ErrorBoundary/ErrorBoundary';
10
11
 
11
12
  import './App.scss';
12
13
 
@@ -38,8 +39,10 @@ class App extends React.Component {
38
39
  const {singleClusterMode, clusterName} = this.props;
39
40
  return (
40
41
  <AsideNavigation>
41
- <Content singleClusterMode={singleClusterMode} clusterName={clusterName} />
42
- <div id="fullscreen-root"></div>
42
+ <ErrorBoundary>
43
+ <Content singleClusterMode={singleClusterMode} clusterName={clusterName} />
44
+ <div id="fullscreen-root"></div>
45
+ </ErrorBoundary>
43
46
  </AsideNavigation>
44
47
  );
45
48
  }
package/dist/index.tsx CHANGED
@@ -8,6 +8,7 @@ import App from './containers/App/App';
8
8
  import configureStore from './store';
9
9
  import reportWebVitals from './reportWebVitals';
10
10
  import HistoryContext from './contexts/HistoryContext';
11
+ import {ErrorBoundary} from './components/ErrorBoundary/ErrorBoundary';
11
12
 
12
13
  import './styles/themes.scss';
13
14
  import './styles/constants.scss';
@@ -18,11 +19,13 @@ window.store = store;
18
19
 
19
20
  ReactDOM.render(
20
21
  <React.StrictMode>
21
- <Provider store={store}>
22
- <HistoryContext.Provider value={history}>
23
- <App />
24
- </HistoryContext.Provider>
25
- </Provider>
22
+ <ErrorBoundary>
23
+ <Provider store={store}>
24
+ <HistoryContext.Provider value={history}>
25
+ <App />
26
+ </HistoryContext.Provider>
27
+ </Provider>
28
+ </ErrorBoundary>
26
29
  </React.StrictMode>,
27
30
  document.getElementById('root'),
28
31
  );
@@ -0,0 +1,18 @@
1
+ export function registerError(error: Error, message?: string, type = 'error') {
2
+ if (typeof window !== 'undefined' && window.Ya?.Rum) {
3
+ window.Ya.Rum.logError(
4
+ {
5
+ additional: {
6
+ url: window.location.href,
7
+ },
8
+ type,
9
+ message,
10
+ level: window.Ya.Rum.ERROR_LEVEL.ERROR,
11
+ },
12
+ error,
13
+ );
14
+ } else {
15
+ // eslint-disable-next-line no-console
16
+ console.error(error);
17
+ }
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.28.0",
3
+ "version": "4.29.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -30,6 +30,7 @@
30
30
  "numeral": "2.0.6",
31
31
  "path-to-regexp": "3.0.0",
32
32
  "qs": "^6.11.0",
33
+ "react-error-boundary": "^4.0.12",
33
34
  "react-json-inspector": "7.1.1",
34
35
  "react-list": "0.8.11",
35
36
  "react-monaco-editor": "0.30.1",