ydb-embedded-ui 4.16.2 → 4.17.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 (57) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/components/CircularProgressBar/CircularProgressBar.scss +42 -0
  3. package/dist/components/CircularProgressBar/CircularProgressBar.tsx +59 -0
  4. package/dist/components/DiagnosticCard/DiagnosticCard.scss +20 -3
  5. package/dist/components/DiagnosticCard/DiagnosticCard.tsx +5 -6
  6. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +1 -5
  7. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +40 -17
  8. package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/Details.tsx +3 -3
  9. package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.scss +27 -14
  10. package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Healthcheck.tsx +6 -6
  11. package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/Preview.tsx +15 -16
  12. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/Healthcheck.scss +108 -0
  13. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckDetails.tsx +45 -0
  14. package/dist/containers/Tenant/Diagnostics/TenantOverview/Healthcheck/HealthcheckPreview.tsx +83 -0
  15. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.scss +1 -3
  16. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTree.tsx +1 -1
  17. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.tsx +1 -1
  18. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/en.json +2 -1
  19. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/index.ts +1 -1
  20. package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/i18n/ru.json +2 -1
  21. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.scss +52 -0
  22. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricCard/MetricCard.tsx +48 -0
  23. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.scss +12 -0
  24. package/dist/containers/Tenant/Diagnostics/TenantOverview/MetricsCards/MetricsCards.tsx +134 -0
  25. package/dist/containers/Tenant/Diagnostics/TenantOverview/OldTenantOverview.tsx +155 -0
  26. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.scss +3 -5
  27. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +76 -86
  28. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +3 -1
  29. package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +3 -1
  30. package/dist/containers/Tenant/Diagnostics/TenantOverview/useHealthcheck.ts +53 -0
  31. package/dist/containers/Tenant/TenantPages.tsx +1 -0
  32. package/dist/containers/UserSettings/i18n/en.json +4 -1
  33. package/dist/containers/UserSettings/i18n/ru.json +4 -1
  34. package/dist/containers/UserSettings/settings.ts +7 -0
  35. package/dist/services/api.ts +6 -4
  36. package/dist/store/reducers/healthcheckInfo.ts +20 -12
  37. package/dist/store/reducers/settings/settings.ts +5 -0
  38. package/dist/store/reducers/tenant/constants.ts +7 -0
  39. package/dist/store/reducers/tenant/tenant.ts +15 -0
  40. package/dist/store/reducers/tenant/types.ts +5 -0
  41. package/dist/store/reducers/tenants/contants.ts +6 -0
  42. package/dist/store/reducers/tenants/types.ts +4 -0
  43. package/dist/store/reducers/tenants/utils.ts +114 -7
  44. package/dist/store/state-url-mapping.js +3 -0
  45. package/dist/styles/constants.scss +2 -0
  46. package/dist/types/api/tenant.ts +3 -0
  47. package/dist/utils/constants.ts +1 -0
  48. package/dist/utils/formatCPU/formatCPU.ts +20 -0
  49. package/dist/utils/formatCPU/i18n/en.json +3 -0
  50. package/dist/utils/formatCPU/i18n/index.ts +11 -0
  51. package/dist/utils/formatCPU/i18n/ru.json +3 -0
  52. package/package.json +1 -1
  53. /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Details/index.ts +0 -0
  54. /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/Preview/index.ts +0 -0
  55. /package/dist/containers/Tenant/Diagnostics/{Healthcheck → OldHealthcheck}/index.ts +0 -0
  56. /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/IssueTreeItem.scss +0 -0
  57. /package/dist/containers/Tenant/Diagnostics/{Healthcheck → TenantOverview/Healthcheck}/IssuesViewer/IssueTreeItem/index.ts +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.17.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.16.2...v4.17.0) (2023-09-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * add sorting of issues in issues tree ([#532](https://github.com/ydb-platform/ydb-embedded-ui/issues/532)) ([9f7837c](https://github.com/ydb-platform/ydb-embedded-ui/commit/9f7837c95bd1132dd287011e1aadc96c0819b40d))
9
+ * move healthcheck to tabs ([#531](https://github.com/ydb-platform/ydb-embedded-ui/issues/531)) ([1879d3d](https://github.com/ydb-platform/ydb-embedded-ui/commit/1879d3d8f717a0baaec0d506ad354d81a226fa62))
10
+ * update TenantOverview design ([#527](https://github.com/ydb-platform/ydb-embedded-ui/issues/527)) ([8a752e0](https://github.com/ydb-platform/ydb-embedded-ui/commit/8a752e0def3dc4317fd18519aed210bdc23fefa2))
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * fix Healthcheck blinking ([#528](https://github.com/ydb-platform/ydb-embedded-ui/issues/528)) ([0fc6c46](https://github.com/ydb-platform/ydb-embedded-ui/commit/0fc6c46eb15aeb73a984ba2c2cbe18ef7116382e))
16
+ * **Tenants:** use blob storage ([#530](https://github.com/ydb-platform/ydb-embedded-ui/issues/530)) ([8a546a1](https://github.com/ydb-platform/ydb-embedded-ui/commit/8a546a1ab2f812acc1523c1c35738f4c605c32a5))
17
+
3
18
  ## [4.16.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v4.16.1...v4.16.2) (2023-08-28)
4
19
 
5
20
 
@@ -0,0 +1,42 @@
1
+ .ydb-circular-progress-bar {
2
+ display: block;
3
+
4
+ max-width: 100%;
5
+
6
+ transform: rotate(90deg);
7
+
8
+ &__wrapper {
9
+ position: relative;
10
+ }
11
+ &__content {
12
+ position: absolute;
13
+ top: 50%;
14
+ left: 50%;
15
+
16
+ overflow: hidden;
17
+
18
+ max-width: 100%;
19
+
20
+ transform: translate(-50%, -50%);
21
+ }
22
+
23
+ &__circle-bg {
24
+ stroke: var(--yc-color-base-simple-hover);
25
+
26
+ fill: none;
27
+ }
28
+
29
+ &__circle {
30
+ fill: none;
31
+
32
+ &_status_good {
33
+ stroke: var(--yc-color-private-green-550);
34
+ }
35
+ &_status_warning {
36
+ stroke: var(--yc-color-private-yellow-550);
37
+ }
38
+ &_status_danger {
39
+ stroke: var(--yc-color-private-red-550);
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,59 @@
1
+ import cn from 'bem-cn-lite';
2
+ import type {ReactNode} from 'react';
3
+
4
+ import type {MetricStatus} from '../../store/reducers/tenants/types';
5
+ import {normalizeProgress} from '../../store/reducers/tenants/utils';
6
+
7
+ import './CircularProgressBar.scss';
8
+
9
+ const b = cn('ydb-circular-progress-bar');
10
+
11
+ interface CircularProgressBarProps {
12
+ size?: number;
13
+ progress?: number;
14
+ strokeWidth?: number;
15
+ content?: ReactNode;
16
+ status?: MetricStatus;
17
+ circleBgClassName?: string;
18
+ }
19
+
20
+ export function CircularProgressBar({
21
+ size = 100,
22
+ progress = 0,
23
+ strokeWidth = 10,
24
+ content,
25
+ status,
26
+ circleBgClassName,
27
+ }: CircularProgressBarProps) {
28
+ const center = size / 2;
29
+
30
+ const radius = size / 2 - strokeWidth / 2;
31
+ const circumference = 2 * Math.PI * radius;
32
+
33
+ const normalizedProgress = normalizeProgress(progress);
34
+
35
+ const offset = ((100 - normalizedProgress) / 100) * circumference;
36
+ return (
37
+ <div className={b('wrapper')}>
38
+ {content && <div className={b('content')}>{content}</div>}
39
+ <svg className={b()} width={size} height={size}>
40
+ <circle
41
+ className={b('circle-bg', circleBgClassName)}
42
+ cx={center}
43
+ cy={center}
44
+ r={radius}
45
+ strokeWidth={strokeWidth}
46
+ />
47
+ <circle
48
+ className={b('circle', {status: status?.toLocaleLowerCase()})}
49
+ cx={center}
50
+ cy={center}
51
+ r={radius}
52
+ strokeWidth={strokeWidth}
53
+ strokeDasharray={circumference}
54
+ strokeDashoffset={offset}
55
+ />
56
+ </svg>
57
+ </div>
58
+ );
59
+ }
@@ -1,5 +1,22 @@
1
- .diagnostic-card {
2
- min-width: 200px;
3
- max-width: 350px;
1
+ .ydb-diagnostic-card {
2
+ flex-shrink: 0;
3
+
4
+ width: 206px;
4
5
  padding: 16px;
6
+ padding-bottom: 28px;
7
+
8
+ border: 1px solid var(--yc-color-line-generic);
9
+ border-radius: 8px;
10
+ background-color: transparent;
11
+
12
+ &_active {
13
+ border-color: var(--yc-color-base-info-heavy);
14
+ background-color: var(--yc-color-base-selection);
15
+ }
16
+
17
+ &:hover {
18
+ cursor: pointer;
19
+
20
+ box-shadow: 0px 1px 5px var(--yc-color-sfx-shadow);
21
+ }
5
22
  }
@@ -1,17 +1,16 @@
1
- import {ReactNode} from 'react';
1
+ import type {ReactNode} from 'react';
2
2
  import cn from 'bem-cn-lite';
3
3
 
4
- import {Card} from '@gravity-ui/uikit';
5
-
6
4
  import './DiagnosticCard.scss';
7
5
 
8
- const b = cn('diagnostic-card');
6
+ const b = cn('ydb-diagnostic-card');
9
7
 
10
8
  interface DiagnosticCardProps {
11
9
  children?: ReactNode;
12
10
  className?: string;
11
+ active?: boolean;
13
12
  }
14
13
 
15
- export function DiagnosticCard({children, className}: DiagnosticCardProps) {
16
- return <Card className={b(null, className)}>{children}</Card>;
14
+ export function DiagnosticCard({children, className, active}: DiagnosticCardProps) {
15
+ return <div className={b({active}, className)}>{children}</div>;
17
16
  }
@@ -1,6 +1,3 @@
1
- $section-title-margin: 20px;
2
- $section-title-line-height: 24px;
3
-
4
1
  .kv-detailed-overview {
5
2
  display: flex;
6
3
 
@@ -10,8 +7,7 @@ $section-title-line-height: 24px;
10
7
 
11
8
  &__section {
12
9
  display: flex;
13
- overflow-x: hidden;
14
- flex: 0 0 calc(50% - 10px);
10
+ flex: 1 0 calc(50% - 10px);
15
11
  flex-direction: column;
16
12
 
17
13
  min-width: 300px;
@@ -7,9 +7,12 @@ import {Button, Modal} from '@gravity-ui/uikit';
7
7
  import type {EPathType} from '../../../../types/api/schema';
8
8
  import type {AdditionalTenantsProps} from '../../../../types/additionalProps';
9
9
  import {Icon} from '../../../../components/Icon';
10
+ import {useSetting} from '../../../../utils/hooks';
11
+ import {ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN} from '../../../../utils/constants';
10
12
  import Overview from '../Overview/Overview';
11
- import {Healthcheck} from '../Healthcheck';
13
+ import {Healthcheck} from '../OldHealthcheck';
12
14
  import {TenantOverview} from '../TenantOverview/TenantOverview';
15
+ import {OldTenantOverview} from '../TenantOverview/OldTenantOverview';
13
16
 
14
17
  import './DetailedOverview.scss';
15
18
 
@@ -23,10 +26,14 @@ interface DetailedOverviewProps {
23
26
  const b = cn('kv-detailed-overview');
24
27
 
25
28
  function DetailedOverview(props: DetailedOverviewProps) {
29
+ const {type, tenantName, additionalTenantProps} = props;
30
+
26
31
  const [isModalVisible, setIsModalVisible] = useState(false);
27
32
 
28
33
  const {currentSchemaPath} = useSelector((state: any) => state.schema);
29
34
 
35
+ const [newTenantDiagnostics] = useSetting(ENABLE_NEW_TENANT_DIAGNOSTICS_DESIGN);
36
+
30
37
  const openModalHandler = () => {
31
38
  setIsModalVisible(true);
32
39
  };
@@ -51,27 +58,43 @@ function DetailedOverview(props: DetailedOverviewProps) {
51
58
  );
52
59
  };
53
60
 
61
+ const renderTenantOverview = () => {
62
+ if (newTenantDiagnostics) {
63
+ return (
64
+ <div className={b('section')}>
65
+ <TenantOverview
66
+ tenantName={tenantName}
67
+ additionalTenantProps={additionalTenantProps}
68
+ />
69
+ </div>
70
+ );
71
+ }
72
+
73
+ return (
74
+ <>
75
+ <div className={b('section')}>
76
+ <OldTenantOverview
77
+ tenantName={tenantName}
78
+ additionalTenantProps={additionalTenantProps}
79
+ />
80
+ </div>
81
+ <div className={b('section')}>
82
+ <Healthcheck
83
+ tenant={tenantName}
84
+ preview={true}
85
+ showMoreHandler={openModalHandler}
86
+ />
87
+ </div>
88
+ </>
89
+ );
90
+ };
91
+
54
92
  const renderContent = () => {
55
- const {type, tenantName, additionalTenantProps} = props;
56
93
  const isTenant = tenantName === currentSchemaPath;
57
94
  return (
58
95
  <div className={b()}>
59
96
  {isTenant ? (
60
- <>
61
- <div className={b('section')}>
62
- <TenantOverview
63
- tenantName={tenantName}
64
- additionalTenantProps={additionalTenantProps}
65
- />
66
- </div>
67
- <div className={b('section')}>
68
- <Healthcheck
69
- tenant={tenantName}
70
- preview={true}
71
- showMoreHandler={openModalHandler}
72
- />
73
- </div>
74
- </>
97
+ renderTenantOverview()
75
98
  ) : (
76
99
  <Overview type={type} tenantName={tenantName} />
77
100
  )}
@@ -8,11 +8,11 @@ import type {IResponseError} from '../../../../../types/api/error';
8
8
  import type {IIssuesTree} from '../../../../../types/store/healthcheck';
9
9
  import {ResponseError} from '../../../../../components/Errors/ResponseError';
10
10
 
11
- import IssueTree from '../IssuesViewer/IssueTree';
11
+ import IssueTree from '../../TenantOverview/Healthcheck/IssuesViewer/IssueTree';
12
12
 
13
- import i18n from '../i18n';
13
+ import i18n from '../../TenantOverview/Healthcheck/i18n';
14
14
 
15
- const b = cn('healthcheck');
15
+ const b = cn('old-healthcheck');
16
16
 
17
17
  interface DetailsProps {
18
18
  issueTrees?: IIssuesTree[];
@@ -1,8 +1,7 @@
1
- @use '../DetailedOverview/DetailedOverview.scss' as detailedOverview;
2
1
  @import '../../../../styles/mixins.scss';
3
2
  @import '@gravity-ui/uikit/styles/mixins.scss';
4
3
 
5
- .healthcheck {
4
+ .old-healthcheck {
6
5
  display: flex;
7
6
 
8
7
  &_expanded {
@@ -12,6 +11,7 @@
12
11
  }
13
12
 
14
13
  &__details {
14
+ width: 860px;
15
15
  padding: 25px 20px 20px;
16
16
  }
17
17
 
@@ -27,11 +27,6 @@
27
27
  max-height: 70vh;
28
28
  }
29
29
 
30
- &__loader {
31
- display: flex;
32
- justify-content: center;
33
- }
34
-
35
30
  &__message-container {
36
31
  padding: 15px 0;
37
32
  }
@@ -53,34 +48,52 @@
53
48
  margin-left: 10px;
54
49
  }
55
50
 
56
- &__status-wrapper {
57
- display: flex;
51
+ &__preview {
52
+ width: 206px;
53
+ padding: 16px;
54
+ padding-bottom: 28px;
58
55
 
59
- margin-bottom: detailedOverview.$section-title-margin;
56
+ border: 1px solid var(--yc-color-line-generic);
57
+ border-radius: 8px;
58
+ background-color: transparent;
59
+ }
60
+
61
+ &__preview-header {
62
+ margin-bottom: var(--diagnostics-section-title-margin);
60
63
  gap: 8px;
61
64
  }
62
65
 
63
66
  &__preview-title {
64
67
  font-weight: 600;
65
- line-height: detailedOverview.$section-title-line-height;
68
+ @include lead-typography();
66
69
  }
67
70
 
68
71
  &__preview-content {
69
72
  line-height: 24px;
70
73
  }
71
74
 
75
+ &__preview-title-wrapper {
76
+ display: flex;
77
+ align-items: center;
78
+
79
+ margin-bottom: 4px;
80
+
81
+ gap: 8px;
82
+ }
83
+
72
84
  &__issues-statistics {
73
85
  display: flex;
74
86
  flex-wrap: wrap;
75
87
  align-items: center;
76
88
 
77
- margin: 10px 0;
89
+ margin: 8px 0;
78
90
 
79
- column-gap: 26px;
80
- row-gap: 16px;
91
+ gap: 10px;
81
92
  }
82
93
 
83
94
  &__self-check-status-indicator {
95
+ display: inline-block;
96
+
84
97
  padding: 0 8px;
85
98
 
86
99
  font-size: 13px;
@@ -12,7 +12,6 @@ import {
12
12
  selectIssuesTrees,
13
13
  setDataWasNotLoaded,
14
14
  } from '../../../../store/reducers/healthcheckInfo';
15
- import {DiagnosticCard} from '../../../../components/DiagnosticCard/DiagnosticCard';
16
15
 
17
16
  import {Details} from './Details';
18
17
  import {Preview} from './Preview';
@@ -26,7 +25,7 @@ interface HealthcheckProps {
26
25
  showMoreHandler?: VoidFunction;
27
26
  }
28
27
 
29
- const b = cn('healthcheck');
28
+ const b = cn('old-healthcheck');
30
29
 
31
30
  export const Healthcheck = (props: HealthcheckProps) => {
32
31
  const {tenant, preview, fetchData = true, showMoreHandler} = props;
@@ -34,12 +33,12 @@ export const Healthcheck = (props: HealthcheckProps) => {
34
33
  const dispatch = useDispatch();
35
34
 
36
35
  const {data, loading, wasLoaded, error} = useTypedSelector((state) => state.healthcheckInfo);
37
- const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
38
-
39
36
  const issuesStatistics = useTypedSelector(selectIssuesStatistics);
40
37
  const issueTrees = useTypedSelector(selectIssuesTrees);
41
38
  const {autorefresh} = useTypedSelector((state) => state.schema);
42
39
 
40
+ const selfCheckResult = data?.self_check_result || SelfCheckResult.UNSPECIFIED;
41
+
43
42
  const fetchHealthcheck = useCallback(
44
43
  (isBackground = true) => {
45
44
  if (!isBackground) {
@@ -64,11 +63,12 @@ export const Healthcheck = (props: HealthcheckProps) => {
64
63
  const renderContent = () => {
65
64
  if (loading && !wasLoaded) {
66
65
  return (
67
- <DiagnosticCard className={b('loader')}>
66
+ <div className={b('old-preview', {loader: true})}>
68
67
  <Loader size="m" />
69
- </DiagnosticCard>
68
+ </div>
70
69
  );
71
70
  }
71
+
72
72
  return preview ? (
73
73
  <Preview
74
74
  issuesStatistics={issuesStatistics}
@@ -6,13 +6,12 @@ import updateArrow from '../../../../../assets/icons/update-arrow.svg';
6
6
 
7
7
  import {SelfCheckResult, type StatusFlag} from '../../../../../types/api/healthcheck';
8
8
  import type {IResponseError} from '../../../../../types/api/error';
9
- import {DiagnosticCard} from '../../../../../components/DiagnosticCard/DiagnosticCard';
10
9
  import EntityStatus from '../../../../../components/EntityStatus/EntityStatus';
11
10
  import {ResponseError} from '../../../../../components/Errors/ResponseError';
12
11
 
13
- import i18n from '../i18n';
12
+ import i18n from '../../TenantOverview/Healthcheck/i18n';
14
13
 
15
- const b = cn('healthcheck');
14
+ const b = cn('old-healthcheck');
16
15
 
17
16
  interface PreviewProps {
18
17
  selfCheckResult: SelfCheckResult;
@@ -26,20 +25,20 @@ interface PreviewProps {
26
25
  export const Preview = (props: PreviewProps) => {
27
26
  const {selfCheckResult, issuesStatistics, loading, onShowMore, onUpdate, error} = props;
28
27
 
29
- const isStatusOK = selfCheckResult === SelfCheckResult.GOOD;
30
-
31
- const renderStatus = () => {
28
+ const renderHeader = () => {
32
29
  const modifier = selfCheckResult.toLowerCase();
33
30
 
34
31
  return (
35
- <div className={b('status-wrapper')}>
36
- <div className={b('preview-title')}>{i18n('title.healthcheck')}</div>
32
+ <div className={b('preview-header')}>
33
+ <div className={b('preview-title-wrapper')}>
34
+ <div className={b('preview-title')}>{i18n('title.healthcheck')}</div>
35
+ <Button size="s" onClick={onUpdate} loading={loading} view="flat-secondary">
36
+ <Icon data={updateArrow} width={20} height={20} />
37
+ </Button>
38
+ </div>
37
39
  <div className={b('self-check-status-indicator', {[modifier]: true})}>
38
40
  {selfCheckResult}
39
41
  </div>
40
- <Button size="s" onClick={onUpdate} loading={loading} view="flat-secondary">
41
- <Icon data={updateArrow} width={20} height={20} />
42
- </Button>
43
42
  </div>
44
43
  );
45
44
  };
@@ -51,11 +50,11 @@ export const Preview = (props: PreviewProps) => {
51
50
 
52
51
  return (
53
52
  <div className={b('preview-content')}>
54
- {isStatusOK || !issuesStatistics || !issuesStatistics.length ? (
53
+ {!issuesStatistics || !issuesStatistics.length ? (
55
54
  i18n('status_message.ok')
56
55
  ) : (
57
56
  <>
58
- <div>Issues:</div>
57
+ <div>{i18n('label.issues')}</div>
59
58
  <div className={b('issues-statistics')}>
60
59
  {issuesStatistics.map(([status, count]) => (
61
60
  <EntityStatus
@@ -75,9 +74,9 @@ export const Preview = (props: PreviewProps) => {
75
74
  };
76
75
 
77
76
  return (
78
- <DiagnosticCard className={b('preview')}>
79
- {renderStatus()}
77
+ <div className={b('preview')}>
78
+ {renderHeader()}
80
79
  {renderContent()}
81
- </DiagnosticCard>
80
+ </div>
82
81
  );
83
82
  };
@@ -0,0 +1,108 @@
1
+ @import '../../../../../styles/mixins.scss';
2
+
3
+ .healthcheck {
4
+ display: flex;
5
+
6
+ &_expanded {
7
+ // Since most of the inner containers have fixed width, we can set fixed width here as well
8
+ // Thus we will get rid of unneeded layout shift when scrollbar appear
9
+ min-width: 885px;
10
+ }
11
+
12
+ &__issue-preview {
13
+ margin-bottom: 15px;
14
+ }
15
+
16
+ &__message-container {
17
+ padding: 15px 0;
18
+ }
19
+
20
+ &__details {
21
+ width: 872px;
22
+ }
23
+
24
+ &__details-content-wrapper {
25
+ overflow-x: hidden;
26
+ }
27
+
28
+ &__preview {
29
+ height: 100%;
30
+ }
31
+
32
+ &__preview-header {
33
+ margin-bottom: var(--diagnostics-section-title-margin);
34
+ gap: 8px;
35
+ }
36
+
37
+ &__preview-title {
38
+ font-weight: 600;
39
+ @include lead-typography();
40
+ }
41
+
42
+ &__preview-content {
43
+ line-height: 24px;
44
+ }
45
+
46
+ &__preview-title-wrapper {
47
+ display: flex;
48
+ align-items: center;
49
+
50
+ margin-bottom: 4px;
51
+
52
+ gap: 8px;
53
+ }
54
+
55
+ &__issues-statistics {
56
+ display: flex;
57
+ flex-wrap: wrap;
58
+ align-items: center;
59
+
60
+ margin: 8px 0;
61
+
62
+ gap: 10px;
63
+ }
64
+
65
+ &__self-check-status-indicator {
66
+ display: inline-block;
67
+
68
+ padding: 0 8px;
69
+
70
+ font-size: 13px;
71
+ line-height: 24px;
72
+
73
+ border-radius: 4px;
74
+
75
+ &_good,
76
+ &_green {
77
+ color: var(--yc-color-text-positive);
78
+ background-color: var(--yc-color-base-positive);
79
+ }
80
+ &_degraded,
81
+ &_yellow {
82
+ color: var(--yc-color-text-warning);
83
+ background-color: var(--yc-color-base-warning);
84
+ }
85
+
86
+ &_blue {
87
+ color: var(--yc-color-text-info);
88
+ background-color: var(--yc-color-base-info);
89
+ }
90
+
91
+ &_emergency,
92
+ &_red {
93
+ color: var(--yc-color-text-danger);
94
+ background-color: var(--yc-color-base-danger);
95
+ }
96
+ &_unspecified,
97
+ &_gray,
98
+ &_grey {
99
+ color: var(--yc-color-text-misc);
100
+ background-color: var(--yc-color-base-misc);
101
+ }
102
+ &_maintenance_required,
103
+ &_orange {
104
+ color: var(--yc-color-text-warning-heavy);
105
+ background-color: var(--yc-color-infographics-warning-light);
106
+ }
107
+ }
108
+ }
@@ -0,0 +1,45 @@
1
+ import cn from 'bem-cn-lite';
2
+
3
+ import type {IResponseError} from '../../../../../types/api/error';
4
+ import type {IIssuesTree} from '../../../../../types/store/healthcheck';
5
+ import {ResponseError} from '../../../../../components/Errors/ResponseError';
6
+
7
+ import IssueTree from './IssuesViewer/IssueTree';
8
+
9
+ import i18n from './i18n';
10
+ import './Healthcheck.scss';
11
+
12
+ const b = cn('healthcheck');
13
+
14
+ interface HealthcheckDetailsProps {
15
+ issueTrees?: IIssuesTree[];
16
+ error?: IResponseError;
17
+ }
18
+
19
+ export function HealthcheckDetails(props: HealthcheckDetailsProps) {
20
+ const {issueTrees, error} = props;
21
+
22
+ const renderContent = () => {
23
+ if (error) {
24
+ return <ResponseError error={error} defaultMessage={i18n('no-data')} />;
25
+ }
26
+
27
+ if (!issueTrees || !issueTrees.length) {
28
+ return i18n('status_message.ok');
29
+ }
30
+
31
+ return (
32
+ <>
33
+ {issueTrees.map((issueTree) => (
34
+ <IssueTree key={issueTree.id} issueTree={issueTree} />
35
+ ))}
36
+ </>
37
+ );
38
+ };
39
+
40
+ return (
41
+ <div className={b('details')}>
42
+ <div className={b('details-content-wrapper')}>{renderContent()}</div>
43
+ </div>
44
+ );
45
+ }