ydb-embedded-ui 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2 -2
  4. package/dist/assets/icons/cluster.svg +1 -0
  5. package/dist/assets/icons/hide.svg +1 -0
  6. package/dist/assets/icons/show.svg +1 -0
  7. package/dist/assets/icons/user-check.svg +1 -1
  8. package/dist/assets/icons/user-secret.svg +1 -1
  9. package/dist/components/AsideNavigation/AsideHeader.scss +1 -2
  10. package/dist/components/AsideNavigation/AsideHeaderFooterItem/AsideHeaderFooterItem.scss +7 -7
  11. package/dist/components/AsideNavigation/AsideHeaderTooltip/AsideHeaderTooltip.scss +2 -2
  12. package/dist/components/AsideNavigation/CompositeBar/CompositeBar.scss +6 -6
  13. package/dist/components/AsideNavigation/Drawer/Drawer.scss +5 -5
  14. package/dist/components/AsideNavigation/Logo/Logo.scss +3 -4
  15. package/dist/components/AsideNavigation/Settings/Settings.scss +27 -12
  16. package/dist/components/AsideNavigation/Settings/SettingsMenu/SettingsMenu.scss +14 -6
  17. package/dist/components/Breadcrumbs/Breadcrumbs.scss +2 -1
  18. package/dist/components/ClusterInfo/ClusterInfo.scss +19 -12
  19. package/dist/components/ClusterInfo/ClusterInfo.tsx +110 -10
  20. package/dist/components/CopyToClipboard/CopyToClipboard.tsx +39 -0
  21. package/dist/components/CriticalActionDialog/CriticalActionDialog.scss +5 -4
  22. package/dist/components/Divider/Divider.scss +7 -0
  23. package/dist/components/Divider/Divider.tsx +11 -0
  24. package/dist/components/EmptyState/EmptyState.scss +14 -10
  25. package/dist/components/EnableFullscreenButton/EnableFullscreenButton.tsx +22 -0
  26. package/dist/components/EntityStatus/EntityStatus.js +5 -3
  27. package/dist/components/EntityStatus/EntityStatus.scss +35 -13
  28. package/dist/components/FullGroupViewer/FullGroupViewer.js +2 -4
  29. package/dist/components/FullGroupViewer/FullGroupViewer.scss +6 -3
  30. package/dist/components/FullNodeViewer/FullNodeViewer.scss +19 -11
  31. package/dist/components/Fullscreen/Fullscreen.scss +28 -0
  32. package/dist/components/Fullscreen/Fullscreen.tsx +81 -0
  33. package/dist/components/GroupTreeViewer/GroupTreeViewer.scss +1 -0
  34. package/dist/components/GroupViewer/GroupViewer.scss +8 -4
  35. package/dist/components/Icon/Icon.js +2 -0
  36. package/dist/components/InfoViewer/InfoViewer.scss +22 -16
  37. package/dist/components/NodesViewer/NodesViewer.js +25 -35
  38. package/dist/components/NodesViewer/NodesViewer.scss +15 -11
  39. package/dist/components/PDiskViewer/PDiskViewer.scss +10 -4
  40. package/dist/components/Pagination/Pagination.scss +6 -3
  41. package/dist/components/PoolBar/PoolBar.scss +14 -10
  42. package/dist/components/PoolUsage/PoolUsage.scss +17 -9
  43. package/dist/components/ProgressViewer/ProgressViewer.js +1 -1
  44. package/dist/components/ProgressViewer/ProgressViewer.scss +28 -18
  45. package/dist/components/QueryExecutionStatus/QueryExecutionStatus.scss +14 -0
  46. package/dist/components/QueryExecutionStatus/QueryExecutionStatus.tsx +29 -0
  47. package/dist/components/SplitPane/SplitPane.scss +33 -40
  48. package/dist/components/SplitPane/SplitPane.tsx +94 -0
  49. package/dist/components/Tablet/Tablet.scss +9 -6
  50. package/dist/components/TabletsOverall/TabletsOverall.scss +19 -0
  51. package/dist/components/TabletsOverall/TabletsOverall.tsx +105 -0
  52. package/dist/components/TabletsStatistic/TabletsStatistic.scss +24 -18
  53. package/dist/components/TabletsViewer/TabletsViewer.scss +12 -9
  54. package/dist/components/Tag/Tag.scss +6 -4
  55. package/dist/components/Tags/Tags.scss +1 -1
  56. package/dist/components/TreeView/TreeView.js +1 -1
  57. package/dist/components/TreeView/TreeView.scss +9 -0
  58. package/dist/components/TruncatedQuery/TruncatedQuery.scss +4 -3
  59. package/dist/containers/App/App.js +1 -0
  60. package/dist/containers/App/App.scss +50 -31
  61. package/dist/containers/App/Content.js +2 -2
  62. package/dist/containers/App/NodesTable.scss +25 -0
  63. package/dist/containers/App/TipPopup/TipPopup.scss +10 -6
  64. package/dist/containers/AppIcons/AppIcons.js +46 -22
  65. package/dist/containers/AsideNavigation/AsideNavigation.scss +1 -1
  66. package/dist/containers/AsideNavigation/AsideNavigation.tsx +12 -5
  67. package/dist/containers/Authentication/Authentication.scss +63 -14
  68. package/dist/containers/Authentication/Authentication.tsx +42 -9
  69. package/dist/containers/Cluster/Cluster.scss +5 -3
  70. package/dist/containers/Cluster/Cluster.tsx +49 -0
  71. package/dist/containers/Group/Group.scss +1 -1
  72. package/dist/containers/Header/Header.scss +15 -59
  73. package/dist/containers/Header/Header.tsx +75 -0
  74. package/dist/containers/Header/Host/Host.scss +10 -3
  75. package/dist/containers/Heatmap/Heatmap.js +1 -1
  76. package/dist/containers/Heatmap/Heatmap.scss +16 -7
  77. package/dist/containers/Heatmap/HeatmapCanvas/HeatmapCanvas.js +3 -3
  78. package/dist/containers/Heatmap/Histogram/Histogram.scss +21 -9
  79. package/dist/containers/Node/Node.js +1 -1
  80. package/dist/containers/Node/Node.scss +6 -4
  81. package/dist/containers/Nodes/Nodes.js +28 -27
  82. package/dist/containers/Nodes/Nodes.scss +5 -17
  83. package/dist/containers/Pdisk/Pdisk.scss +6 -4
  84. package/dist/containers/Pool/Pool.scss +7 -4
  85. package/dist/containers/ReduxTooltip/ReduxTooltip.scss +5 -1
  86. package/dist/containers/Storage/DiskStateProgressBar/DiskStateProgressBar.scss +77 -0
  87. package/dist/containers/{StorageV2 → Storage}/DiskStateProgressBar/DiskStateProgressBar.tsx +1 -1
  88. package/dist/containers/{StorageV2 → Storage}/Pdisk/Pdisk.scss +6 -4
  89. package/dist/containers/{StorageV2 → Storage}/Pdisk/Pdisk.tsx +1 -2
  90. package/dist/containers/{StorageV2 → Storage}/Storage.js +72 -34
  91. package/dist/containers/{StorageV2 → Storage}/Storage.scss +12 -14
  92. package/dist/containers/{StorageV2 → Storage}/StorageFilter/StorageFilter.js +1 -9
  93. package/dist/containers/{StorageV2 → Storage}/StorageGroups/StorageGroups.scss +2 -0
  94. package/dist/containers/{StorageV2 → Storage}/StorageGroups/StorageGroups.tsx +1 -1
  95. package/dist/containers/{StorageV2 → Storage}/StorageNodes/StorageNodes.scss +2 -0
  96. package/dist/containers/{StorageV2 → Storage}/StorageNodes/StorageNodes.tsx +1 -1
  97. package/dist/containers/{StorageV2 → Storage}/Vdisk/Vdisk.js +0 -0
  98. package/dist/containers/{StorageV2 → Storage}/Vdisk/Vdisk.scss +6 -4
  99. package/dist/containers/Tablet/Tablet.scss +13 -9
  100. package/dist/containers/Tablets/Tablets.js +21 -90
  101. package/dist/containers/Tablets/Tablets.scss +9 -35
  102. package/dist/containers/TabletsFilters/TabletsFilters.js +2 -75
  103. package/dist/containers/TabletsFilters/TabletsFilters.scss +15 -35
  104. package/dist/containers/Tenant/Acl/Acl.js +54 -47
  105. package/dist/containers/Tenant/Acl/Acl.scss +15 -4
  106. package/dist/containers/Tenant/{Compute → Diagnostics/Compute}/Compute.js +35 -12
  107. package/dist/containers/Tenant/Diagnostics/Compute/Compute.scss +14 -0
  108. package/dist/containers/Tenant/{Describe → Diagnostics/Describe}/Describe.js +50 -1
  109. package/dist/containers/Tenant/{Describe → Diagnostics/Describe}/Describe.scss +5 -3
  110. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.scss +27 -0
  111. package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +88 -0
  112. package/dist/containers/Tenant/Diagnostics/Diagnostics.scss +50 -0
  113. package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +208 -0
  114. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.ts +75 -0
  115. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.js +191 -0
  116. package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +79 -0
  117. package/dist/containers/Tenant/{Healthcheck → Diagnostics/Healthcheck}/IssuesViewer/IssueViewer.scss +25 -13
  118. package/dist/containers/Tenant/{Healthcheck → Diagnostics/Healthcheck}/IssuesViewer/IssuesViewer.js +2 -2
  119. package/dist/containers/Tenant/{Schema → Diagnostics}/HotKeys/HotKeys.js +14 -8
  120. package/dist/containers/Tenant/{Schema → Diagnostics}/HotKeys/HotKeys.scss +7 -5
  121. package/dist/containers/Tenant/{Network → Diagnostics/Network}/Network.js +39 -9
  122. package/dist/containers/Tenant/{Network → Diagnostics/Network}/Network.scss +35 -36
  123. package/dist/containers/Tenant/{Network → Diagnostics/Network}/NodeNetwork/NodeNetwork.js +0 -0
  124. package/dist/containers/Tenant/{Network → Diagnostics/Network}/NodeNetwork/NodeNetwork.scss +11 -9
  125. package/dist/containers/Tenant/Diagnostics/Overview/Overview.scss +13 -0
  126. package/dist/containers/Tenant/Diagnostics/Overview/Overview.tsx +123 -0
  127. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +200 -0
  128. package/dist/{components → containers/Tenant/Diagnostics}/TenantOverview/TenantOverview.scss +24 -17
  129. package/dist/containers/Tenant/{TopQueries → Diagnostics/TopQueries}/TopQueries.js +32 -30
  130. package/dist/containers/Tenant/{TopQueries → Diagnostics/TopQueries}/TopQueries.scss +10 -9
  131. package/dist/containers/Tenant/{TopShards → Diagnostics/TopShards}/TopShards.js +25 -29
  132. package/dist/containers/Tenant/{TopShards → Diagnostics/TopShards}/TopShards.scss +1 -13
  133. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.scss +38 -0
  134. package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +104 -0
  135. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.scss +165 -0
  136. package/dist/containers/Tenant/ObjectSummary/ObjectSummary.tsx +310 -0
  137. package/dist/containers/Tenant/Preview/Preview.js +50 -12
  138. package/dist/containers/Tenant/Preview/Preview.scss +45 -3
  139. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.scss +85 -0
  140. package/dist/containers/Tenant/QueryEditor/QueriesHistory/QueriesHistory.tsx +94 -0
  141. package/dist/containers/Tenant/QueryEditor/QueryEditor.js +291 -264
  142. package/dist/containers/Tenant/QueryEditor/QueryEditor.scss +47 -18
  143. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.js +132 -32
  144. package/dist/containers/Tenant/QueryEditor/QueryExplain/QueryExplain.scss +47 -11
  145. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.js +89 -20
  146. package/dist/containers/Tenant/QueryEditor/QueryResult/QueryResult.scss +60 -6
  147. package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.js +10 -23
  148. package/dist/containers/Tenant/QueryEditor/SaveQuery/SaveQuery.scss +15 -7
  149. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.js +7 -3
  150. package/dist/containers/Tenant/QueryEditor/SavedQueries/SavedQueries.scss +28 -17
  151. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.js +7 -7
  152. package/dist/containers/Tenant/Schema/SchemaInfoViewer/SchemaInfoViewer.scss +1 -11
  153. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.js +37 -17
  154. package/dist/containers/Tenant/Schema/SchemaNode/SchemaNode.scss +33 -12
  155. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.scss +17 -0
  156. package/dist/containers/Tenant/Schema/SchemaNodeActions/SchemaNodeActions.tsx +125 -0
  157. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.js +5 -4
  158. package/dist/containers/Tenant/Schema/SchemaTree/SchemaTree.scss +6 -2
  159. package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.js +53 -34
  160. package/dist/containers/Tenant/Schema/SchemaViewer/SchemaViewer.scss +1 -22
  161. package/dist/containers/Tenant/Tenant.scss +3 -32
  162. package/dist/containers/Tenant/Tenant.tsx +161 -0
  163. package/dist/containers/Tenant/TenantPages.tsx +48 -0
  164. package/dist/containers/Tenant/utils/ToggleButton.scss +26 -0
  165. package/dist/containers/Tenant/utils/paneVisibilityToggleHelpers.tsx +126 -0
  166. package/dist/containers/Tenants/Tenants.js +41 -55
  167. package/dist/containers/Tenants/Tenants.scss +4 -17
  168. package/dist/containers/UserSettings/UserSettings.tsx +0 -2
  169. package/dist/containers/Vdisk/Vdisk.scss +6 -4
  170. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.js +1 -1
  171. package/dist/containers/VdiskPdiskNode/VdiskPdiskNode.scss +5 -5
  172. package/dist/{routes.js → routes.ts} +14 -4
  173. package/dist/store/reducers/clusterNodes.js +1 -1
  174. package/dist/store/reducers/fullscreen.ts +31 -0
  175. package/dist/store/reducers/header.ts +23 -0
  176. package/dist/store/reducers/hotKeys.js +1 -1
  177. package/dist/store/reducers/index.js +6 -0
  178. package/dist/store/reducers/saveQuery.ts +33 -0
  179. package/dist/store/reducers/schema.js +14 -0
  180. package/dist/store/reducers/shardsWorkload.js +1 -1
  181. package/dist/store/state-url-mapping.js +1 -1
  182. package/dist/store/utils.js +2 -6
  183. package/dist/styles/mixins.scss +49 -34
  184. package/dist/utils/autofetcher.ts +51 -0
  185. package/dist/utils/constants.js +25 -7
  186. package/dist/utils/createToast.tsx +23 -0
  187. package/dist/utils/getNodesColumns.js +25 -28
  188. package/dist/utils/index.js +6 -2
  189. package/package.json +8 -4
  190. package/dist/components/SplitPane/SplitPane.js +0 -368
  191. package/dist/components/TenantOverview/TenantOverview.js +0 -148
  192. package/dist/containers/Cluster/Cluster.js +0 -168
  193. package/dist/containers/Header/Header.js +0 -88
  194. package/dist/containers/StorageV2/DiskStateProgressBar/DiskStateProgressBar.scss +0 -81
  195. package/dist/containers/Tenant/Compute/Compute.scss +0 -6
  196. package/dist/containers/Tenant/Healthcheck/Healthcheck.js +0 -116
  197. package/dist/containers/Tenant/Healthcheck/Healthcheck.scss +0 -64
  198. package/dist/containers/Tenant/Schema/Info/Info.js +0 -84
  199. package/dist/containers/Tenant/Schema/Info/Info.scss +0 -3
  200. package/dist/containers/Tenant/Schema/SchemaMain/SchemaMain.js +0 -439
  201. package/dist/containers/Tenant/Schema/SchemaMain/SchemaMain.scss +0 -90
  202. package/dist/containers/Tenant/Schema/SchemaPages.js +0 -56
  203. package/dist/containers/Tenant/Tenant.js +0 -199
  204. package/dist/containers/Tenant/TenantPages.js +0 -35
@@ -0,0 +1,104 @@
1
+ import {Link} from 'react-router-dom';
2
+ import cn from 'bem-cn-lite';
3
+ import {useLocation} from 'react-router';
4
+ import qs from 'qs';
5
+ import _ from 'lodash';
6
+
7
+ import {Tabs, useThemeValue} from '@yandex-cloud/uikit';
8
+ //@ts-ignore
9
+ import QueryEditor from '../QueryEditor/QueryEditor';
10
+ import Diagnostics from '../Diagnostics/Diagnostics';
11
+
12
+ import {TenantGeneralTabsIds, TenantTabsGroups, TENANT_GENERAL_TABS} from '../TenantPages';
13
+ import routes, {createHref} from '../../../routes';
14
+
15
+ import './ObjectGeneral.scss';
16
+
17
+ const b = cn('object-general');
18
+
19
+ interface ObjectGeneralProps {
20
+ type: string;
21
+ additionalTenantInfo?: any;
22
+ additionalNodesInfo?: any;
23
+ }
24
+
25
+ function ObjectGeneral(props: ObjectGeneralProps) {
26
+ const location = useLocation();
27
+
28
+ const theme = useThemeValue();
29
+
30
+ const queryParams = qs.parse(location.search, {
31
+ ignoreQueryPrefix: true,
32
+ });
33
+
34
+ const {name: tenantName, general: generalTab} = queryParams;
35
+
36
+ const renderTabs = () => {
37
+ const pages = TENANT_GENERAL_TABS.map((page) => {
38
+ return {
39
+ ...page,
40
+ title: (
41
+ <div className={b('tab-label')}>
42
+ {page.icon}
43
+ {page.title}
44
+ </div>
45
+ ),
46
+ };
47
+ });
48
+ return (
49
+ <div className={b('tabs')}>
50
+ <Tabs
51
+ items={pages}
52
+ activeTab={generalTab as string}
53
+ wrapTo={({id}, node) => {
54
+ const path = createHref(routes.tenant, undefined, {
55
+ ...queryParams,
56
+ name: tenantName as string,
57
+ [TenantTabsGroups.general]: id,
58
+ });
59
+ return (
60
+ <Link to={path} key={id} className={b('tab')}>
61
+ {node}
62
+ </Link>
63
+ );
64
+ }}
65
+ allowNotSelected
66
+ />
67
+ </div>
68
+ );
69
+ };
70
+
71
+ const renderTabContent = () => {
72
+ const {type, additionalTenantInfo, additionalNodesInfo} = props;
73
+ switch (generalTab) {
74
+ case TenantGeneralTabsIds.query: {
75
+ return <QueryEditor path={tenantName as string} theme={theme} type={type} />;
76
+ }
77
+ default: {
78
+ return (
79
+ <Diagnostics
80
+ type={type}
81
+ additionalTenantInfo={additionalTenantInfo}
82
+ additionalNodesInfo={additionalNodesInfo}
83
+ />
84
+ );
85
+ }
86
+ }
87
+ };
88
+
89
+ const renderContent = () => {
90
+ if (!tenantName) {
91
+ return null;
92
+ }
93
+ return (
94
+ <div className={b()}>
95
+ {renderTabs()}
96
+ {renderTabContent()}
97
+ </div>
98
+ );
99
+ };
100
+
101
+ return renderContent();
102
+ }
103
+
104
+ export default ObjectGeneral;
@@ -0,0 +1,165 @@
1
+ @import '../../../styles/mixins.scss';
2
+
3
+ .object-summary {
4
+ position: relative;
5
+
6
+ display: flex;
7
+ overflow: hidden;
8
+ flex-grow: 1;
9
+ flex-direction: column;
10
+
11
+ width: 100%;
12
+ height: 100%;
13
+ max-height: 100%;
14
+
15
+ &__overview-wrapper {
16
+ overflow: auto;
17
+
18
+ padding: 0 12px 16px;
19
+ }
20
+
21
+ &_hidden {
22
+ visibility: hidden;
23
+ }
24
+
25
+ &__action-button {
26
+ position: absolute;
27
+ top: 12px;
28
+ right: 4px;
29
+
30
+ background-color: var(--yc-color-base-background);
31
+ &_hidden {
32
+ visibility: hidden;
33
+ }
34
+ }
35
+
36
+ &__loader {
37
+ display: flex;
38
+ justify-content: center;
39
+ align-items: center;
40
+ }
41
+
42
+ &__tree {
43
+ display: flex;
44
+ overflow: scroll;
45
+ flex: 0 0 auto;
46
+ flex-direction: column;
47
+
48
+ height: 100%;
49
+ padding: 0 12px 12px;
50
+
51
+ .tree-view_item {
52
+ margin: 0;
53
+ padding: 2px 0;
54
+ }
55
+
56
+ & > div > .tree-view {
57
+ padding-bottom: 15px;
58
+ }
59
+ }
60
+
61
+ &__tree-header {
62
+ display: flex;
63
+ justify-content: space-between;
64
+ align-items: center;
65
+
66
+ padding: 12px 12px 8px;
67
+ @include sticky-top();
68
+ }
69
+
70
+ &__tree-title {
71
+ font-weight: 600;
72
+ }
73
+
74
+ &__sticky-top {
75
+ z-index: 5;
76
+ @include sticky-top();
77
+ }
78
+
79
+ &__tabs {
80
+ padding: 8px 12px 16px;
81
+ }
82
+
83
+ &__tab {
84
+ margin-right: 40px;
85
+
86
+ text-decoration: none;
87
+
88
+ &:first-letter {
89
+ text-transform: uppercase;
90
+ }
91
+ }
92
+
93
+ &__info {
94
+ overflow: hidden;
95
+ }
96
+
97
+ &__info-controls {
98
+ display: flex;
99
+ gap: 4px;
100
+ }
101
+
102
+ &__info-action-button {
103
+ background-color: var(--yc-color-base-background);
104
+ &_hidden {
105
+ display: none;
106
+ }
107
+ }
108
+
109
+ &__rotated90 {
110
+ transform: rotate(-90deg);
111
+ }
112
+ &__rotated180 {
113
+ transform: rotate(180deg);
114
+ }
115
+ &__rotated270 {
116
+ transform: rotate(90deg);
117
+ }
118
+
119
+ &__info-header {
120
+ display: flex;
121
+ justify-content: space-between;
122
+ align-items: center;
123
+
124
+ padding: 12px 12px 10px;
125
+
126
+ border-bottom: 1px solid var(--yc-color-line-generic);
127
+ }
128
+
129
+ &__info-title {
130
+ display: flex;
131
+ overflow: hidden;
132
+ align-items: center;
133
+
134
+ font-weight: 600;
135
+ }
136
+
137
+ &__path-name {
138
+ overflow: hidden;
139
+
140
+ text-overflow: ellipsis;
141
+ }
142
+
143
+ &__entity-type {
144
+ display: inline-block;
145
+
146
+ margin-right: 5px;
147
+ padding: 3px 8px;
148
+
149
+ font-weight: 400;
150
+ text-transform: lowercase;
151
+
152
+ border-radius: 3px;
153
+ background-color: var(--yc-color-base-generic);
154
+
155
+ &_error {
156
+ padding: 3px 0;
157
+
158
+ background-color: transparent;
159
+ }
160
+ }
161
+
162
+ .yc-button__text {
163
+ margin: 0 6px;
164
+ }
165
+ }
@@ -0,0 +1,310 @@
1
+ import React, {useEffect, useReducer} from 'react';
2
+ import {useDispatch, useSelector} from 'react-redux';
3
+ import {Link} from 'react-router-dom';
4
+ import cn from 'bem-cn-lite';
5
+ import {useHistory, useLocation} from 'react-router';
6
+ import qs from 'qs';
7
+ import _ from 'lodash';
8
+
9
+ import {Button, HelpTooltip, Loader, Tabs} from '@yandex-cloud/uikit';
10
+ //@ts-ignore
11
+ import SplitPane from '../../../components/SplitPane';
12
+ //@ts-ignore
13
+ import SchemaNode from '../Schema/SchemaNode/SchemaNode';
14
+ //@ts-ignore
15
+ import Acl from '../Acl/Acl';
16
+ //@ts-ignore
17
+ import SchemaViewer from '../Schema/SchemaViewer/SchemaViewer';
18
+ import CopyToClipboard from '../../../components/CopyToClipboard/CopyToClipboard';
19
+ //@ts-ignore
20
+ import InfoViewer from '../../../components/InfoViewer/InfoViewer';
21
+ //@ts-ignore
22
+ import Icon from '../../../components/Icon/Icon';
23
+
24
+ import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
25
+
26
+ import {
27
+ DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED,
28
+ DEFAULT_SIZE_TENANT_SUMMARY_KEY,
29
+ //@ts-ignore
30
+ } from '../../../utils/constants';
31
+ import {
32
+ TenantGeneralTabsIds,
33
+ TenantInfoTabsIds,
34
+ TenantTabsGroups,
35
+ TENANT_INFO_TABS,
36
+ TENANT_SCHEMA_TAB,
37
+ } from '../TenantPages';
38
+ import routes, {createHref} from '../../../routes';
39
+ import {
40
+ PaneVisibilityActionTypes,
41
+ paneVisibilityToggleReducerCreator,
42
+ PaneVisibilityToggleButtons,
43
+ } from '../utils/paneVisibilityToggleHelpers';
44
+ //@ts-ignore
45
+ import {setShowPreview} from '../../../store/reducers/schema';
46
+
47
+ import './ObjectSummary.scss';
48
+ const b = cn('object-summary');
49
+
50
+ const getInitialIsSummaryCollapsed = () => {
51
+ return Boolean(localStorage.getItem(DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED));
52
+ };
53
+
54
+ const initialTenantCommonInfoState = {
55
+ triggerExpand: false,
56
+ triggerCollapse: false,
57
+ collapsed: getInitialIsSummaryCollapsed(),
58
+ };
59
+
60
+ function prepareOlapTableSchema(tableSchema: any) {
61
+ const {Name, Schema = {}} = tableSchema;
62
+ const {Columns, KeyColumnNames} = Schema;
63
+ const KeyColumnIds = KeyColumnNames?.map((name: string) => {
64
+ const column = Columns?.find((el: any) => el.Name === name);
65
+ return column.Id;
66
+ });
67
+
68
+ return {
69
+ Columns,
70
+ KeyColumnNames,
71
+ Name,
72
+ KeyColumnIds,
73
+ };
74
+ }
75
+
76
+ interface ObjectSummaryProps {
77
+ type: string;
78
+ onCollapseSummary: VoidFunction;
79
+ onExpandSummary: VoidFunction;
80
+ isCollapsed: boolean;
81
+ additionalTenantInfo?: any
82
+ }
83
+
84
+ function ObjectSummary(props: ObjectSummaryProps) {
85
+ const dispatch = useDispatch();
86
+ const [commonInfoVisibilityState, dispatchCommonInfoVisibilityState] = useReducer(
87
+ paneVisibilityToggleReducerCreator(DEFAULT_IS_TENANT_COMMON_INFO_COLLAPSED),
88
+ initialTenantCommonInfoState,
89
+ );
90
+ const {
91
+ data,
92
+ currentSchemaPath,
93
+ currentSchema: currentItem = {},
94
+ loading: loadingSchema,
95
+ } = useSelector((state: any) => state.schema);
96
+
97
+ const location = useLocation();
98
+
99
+ const history = useHistory();
100
+
101
+ const queryParams = qs.parse(location.search, {
102
+ ignoreQueryPrefix: true,
103
+ });
104
+
105
+ const {name: tenantName, info: infoTab} = queryParams;
106
+ const tenantData = _.get(data[tenantName as string], 'PathDescription.Self');
107
+
108
+ const tableSchema =
109
+ currentItem?.PathDescription?.Table || currentItem?.PathDescription?.OlapTableDescription;
110
+
111
+ const schema =
112
+ props.type === OLAP_TABLE_TYPE ? prepareOlapTableSchema(tableSchema) : tableSchema;
113
+
114
+ useEffect(() => {
115
+ const {type} = props;
116
+ const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
117
+
118
+ if (type && !isTable && !TENANT_INFO_TABS.find((el) => el.id === infoTab)) {
119
+ history.push({
120
+ pathname: location.pathname,
121
+ search: qs.stringify({...queryParams, info: TenantInfoTabsIds.overview}),
122
+ });
123
+ }
124
+ }, [props.type]);
125
+
126
+ const renderTabs = () => {
127
+ const {type} = props;
128
+ const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
129
+ const tabsItems = isTable ? [...TENANT_INFO_TABS, ...TENANT_SCHEMA_TAB] : TENANT_INFO_TABS;
130
+
131
+ return (
132
+ <div className={b('tabs')}>
133
+ <Tabs
134
+ items={tabsItems}
135
+ activeTab={infoTab as string}
136
+ wrapTo={({id}, node) => {
137
+ const path = createHref(routes.tenant, undefined, {
138
+ ...queryParams,
139
+ name: tenantName as string,
140
+ [TenantTabsGroups.info]: id,
141
+ });
142
+ return (
143
+ <Link to={path} key={id} className={b('tab')}>
144
+ {node}
145
+ </Link>
146
+ );
147
+ }}
148
+ allowNotSelected
149
+ />
150
+ </div>
151
+ );
152
+ };
153
+
154
+ const renderObjectOverview = () => {
155
+ const startTimeInMilliseconds = tenantData?.CreateStep / 1000;
156
+ let createTime = 'Unknown';
157
+ if (startTimeInMilliseconds) {
158
+ createTime = new Date(startTimeInMilliseconds).toUTCString();
159
+ }
160
+ return (
161
+ <div className={b('overview-wrapper')}>
162
+ <InfoViewer info={[{label: 'Create time', value: createTime}]} />
163
+ </div>
164
+ );
165
+ };
166
+
167
+ const renderTabContent = () => {
168
+ switch (infoTab) {
169
+ case TenantInfoTabsIds.acl: {
170
+ return <Acl additionalTenantInfo={props.additionalTenantInfo}/>;
171
+ }
172
+ case TenantInfoTabsIds.schema: {
173
+ return loadingSchema ? renderLoader() : <SchemaViewer data={schema} />;
174
+ }
175
+ default: {
176
+ return renderObjectOverview();
177
+ }
178
+ }
179
+ };
180
+
181
+ const renderLoader = () => {
182
+ return (
183
+ <div className={b('loader')}>
184
+ <Loader size="m" />
185
+ </div>
186
+ );
187
+ };
188
+
189
+ const renderTree = () => {
190
+ return (
191
+ <div>
192
+ <div className={b('tree-header')}>
193
+ <div className={b('tree-title')}>Navigation</div>
194
+ </div>
195
+ <div className={b('tree')}>
196
+ {tenantData && <SchemaNode fullPath={tenantName as string} data={tenantData} isRoot />}
197
+ </div>
198
+ </div>
199
+ );
200
+ };
201
+
202
+ const onCollapseInfoHandler = () => {
203
+ dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.triggerCollapse);
204
+ };
205
+ const onExpandInfoHandler = () => {
206
+ dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.triggerExpand);
207
+ };
208
+
209
+ const onSplitStartDrugAdditional = () => {
210
+ dispatchCommonInfoVisibilityState(PaneVisibilityActionTypes.clear);
211
+ };
212
+
213
+ const onOpenPreview = () => {
214
+ dispatch(setShowPreview(true));
215
+ history.push(
216
+ createHref(routes.tenant, undefined, {
217
+ ...queryParams,
218
+ [TenantTabsGroups.general]: TenantGeneralTabsIds.query,
219
+ }),
220
+ );
221
+ };
222
+
223
+ const renderCommonInfoControls = () => {
224
+ const {type} = props;
225
+ const isTable = type === TABLE_TYPE || type === OLAP_TABLE_TYPE;
226
+ return (
227
+ <React.Fragment>
228
+ {isTable && (
229
+ <Button view="flat-secondary" onClick={onOpenPreview} title="Show preview">
230
+ <Icon name="tablePreview" viewBox={'0 0 16 16'} height={16} width={16} />
231
+ </Button>
232
+ )}
233
+ <CopyToClipboard text={currentSchemaPath} title="Copy schema path" />
234
+ <PaneVisibilityToggleButtons
235
+ onCollapse={onCollapseInfoHandler}
236
+ onExpand={onExpandInfoHandler}
237
+ isCollapsed={commonInfoVisibilityState.collapsed}
238
+ initialDirection="bottom"
239
+ />
240
+ </React.Fragment>
241
+ );
242
+ };
243
+
244
+ const renderEntityTypeBadge = () => {
245
+ const {type} = props;
246
+ const {Status, Reason} = currentItem;
247
+
248
+ let message;
249
+ if (!type && Status && Reason) {
250
+ message = `${Status}: ${Reason}`;
251
+ }
252
+
253
+ return props.type ? (
254
+ <div className={b('entity-type')}>{type}</div>
255
+ ) : (
256
+ <div className={b('entity-type', {error: true})}>
257
+ <HelpTooltip content={message} offset={{left: 0}} />
258
+ </div>
259
+ );
260
+ };
261
+
262
+ const renderContent = () => {
263
+ if (!tenantName) {
264
+ return null;
265
+ }
266
+ return (
267
+ <div className={b()}>
268
+ <div className={b({hidden: props.isCollapsed})}>
269
+ <SplitPane
270
+ direction="vertical"
271
+ defaultSizePaneKey={DEFAULT_SIZE_TENANT_SUMMARY_KEY}
272
+ onSplitStartDrugAdditional={onSplitStartDrugAdditional}
273
+ triggerCollapse={commonInfoVisibilityState.triggerCollapse}
274
+ triggerExpand={commonInfoVisibilityState.triggerExpand}
275
+ minSize={[200, 52]}
276
+ collapsedSizes={[100, 0]}
277
+ >
278
+ {currentSchemaPath ? renderTree() : renderLoader()}
279
+ <div className={b('info')}>
280
+ <div className={b('sticky-top')}>
281
+ <div className={b('info-header')}>
282
+ <div className={b('info-title')}>
283
+ {renderEntityTypeBadge()}
284
+ <div className={b('path-name')}>{currentSchemaPath}</div>
285
+ </div>
286
+ <div className={b('info-controls')}>
287
+ {renderCommonInfoControls()}
288
+ </div>
289
+ </div>
290
+ {renderTabs()}
291
+ </div>
292
+ {renderTabContent()}
293
+ </div>
294
+ </SplitPane>
295
+ </div>
296
+ <PaneVisibilityToggleButtons
297
+ onCollapse={props.onCollapseSummary}
298
+ onExpand={props.onExpandSummary}
299
+ isCollapsed={props.isCollapsed}
300
+ initialDirection="left"
301
+ className={b('action-button')}
302
+ />
303
+ </div>
304
+ );
305
+ };
306
+
307
+ return renderContent();
308
+ }
309
+
310
+ export default ObjectSummary;
@@ -4,21 +4,26 @@ import {connect} from 'react-redux';
4
4
  import cn from 'bem-cn-lite';
5
5
 
6
6
  import DataTable from '@yandex-cloud/react-data-table';
7
- import {Loader} from '@yandex-cloud/uikit';
7
+ import {Loader, Button} from '@yandex-cloud/uikit';
8
+
9
+ import Icon from '../../../components/Icon/Icon';
10
+ import Fullscreen from '../../../components/Fullscreen/Fullscreen';
8
11
 
9
12
  import {sendQuery, setQueryOptions} from '../../../store/reducers/preview';
10
13
  import {showTooltip, hideTooltip} from '../../../store/reducers/tooltip';
11
14
  import {prepareQueryResponse} from '../../../utils/index';
12
15
 
13
- import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Schema/SchemaMain/SchemaMain';
14
- import {AutoFetcher} from '../../Cluster/Cluster';
16
+ import {OLAP_TABLE_TYPE, TABLE_TYPE} from '../Tenant';
17
+ import {AutoFetcher} from '../../../utils/autofetcher';
18
+ import EnableFullscreenButton from '../../../components/EnableFullscreenButton/EnableFullscreenButton';
19
+ import {DEFAULT_TABLE_SETTINGS} from '../../../utils/constants';
20
+ import {setShowPreview} from '../../../store/reducers/schema';
15
21
 
16
22
  import './Preview.scss';
17
23
 
18
24
  const TABLE_SETTINGS = {
19
- displayIndices: false,
20
- syncHeadOnResize: true,
21
- stickyHead: DataTable.MOVING,
25
+ ...DEFAULT_TABLE_SETTINGS,
26
+ stripedRows: true,
22
27
  };
23
28
 
24
29
  const b = cn('kv-preview');
@@ -90,6 +95,31 @@ class Preview extends React.Component {
90
95
  });
91
96
  };
92
97
 
98
+ onClosePreview = () => {
99
+ this.props.setShowPreview(false);
100
+ };
101
+
102
+ renderHeader = () => {
103
+ const {currentSchemaPath, error} = this.props;
104
+ return (
105
+ <div className={b('header')}>
106
+ <div className={b('title')}>
107
+ Preview <div className={b('table-name')}>{currentSchemaPath}</div>
108
+ </div>
109
+ <div className={b('controls-left')}>
110
+ <EnableFullscreenButton disabled={Boolean(error)} />
111
+ <Button
112
+ view="flat-secondary"
113
+ onClick={this.onClosePreview}
114
+ title="Close preview"
115
+ >
116
+ <Icon name="close" viewBox={'0 0 16 16'} width={16} height={16} />
117
+ </Button>
118
+ </div>
119
+ </div>
120
+ );
121
+ };
122
+
93
123
  renderTable = () => {
94
124
  const {data, showTooltip} = this.props;
95
125
 
@@ -116,10 +146,12 @@ class Preview extends React.Component {
116
146
  };
117
147
 
118
148
  render() {
119
- const {error, loading, data = [], type, wasLoaded} = this.props;
149
+ const {error, loading, data = [], type, wasLoaded, isFullscreen} = this.props;
150
+
151
+ let message;
120
152
 
121
153
  if (type !== TABLE_TYPE && type !== OLAP_TABLE_TYPE) {
122
- return <div className={b('message-container')}>Not available</div>;
154
+ message = <div className={b('message-container')}>Not available</div>;
123
155
  }
124
156
 
125
157
  if (loading && !wasLoaded) {
@@ -131,16 +163,19 @@ class Preview extends React.Component {
131
163
  }
132
164
 
133
165
  if (error) {
134
- return <div className={b('message-container')}>{error.data || error}</div>;
166
+ message = <div className={b('message-container')}>{error.data || error}</div>;
135
167
  }
136
168
 
137
169
  if (!loading && data.length === 0) {
138
- return <div className={b('message-container')}>Table is empty</div>;
170
+ message = <div className={b('message-container')}>Table is empty</div>;
139
171
  }
140
172
 
173
+ const content = message ?? <div className={b('result')}>{this.renderTable()}</div>;
174
+
141
175
  return (
142
176
  <div className={b()}>
143
- <div className={b('result')}>{this.renderTable()}</div>
177
+ {this.renderHeader()}
178
+ {isFullscreen ? <Fullscreen>{content}</Fullscreen> : content}
144
179
  </div>
145
180
  );
146
181
  }
@@ -148,7 +183,7 @@ class Preview extends React.Component {
148
183
 
149
184
  const mapStateToProps = (state) => {
150
185
  const {data = [], loading, error, wasLoaded} = state.preview;
151
- const {autorefresh} = state.schema;
186
+ const {autorefresh, currentSchemaPath} = state.schema;
152
187
 
153
188
  return {
154
189
  data,
@@ -156,6 +191,8 @@ const mapStateToProps = (state) => {
156
191
  error,
157
192
  autorefresh,
158
193
  wasLoaded,
194
+ currentSchemaPath,
195
+ isFullscreen: state.fullscreen,
159
196
  };
160
197
  };
161
198
 
@@ -164,6 +201,7 @@ const mapDispatchToProps = {
164
201
  showTooltip,
165
202
  hideTooltip,
166
203
  setQueryOptions,
204
+ setShowPreview,
167
205
  };
168
206
 
169
207
  export default connect(mapStateToProps, mapDispatchToProps)(Preview);