ydb-embedded-ui 4.16.2 → 4.17.0

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