ydb-embedded-ui 22.2.0 → 22.4.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 (405) hide show
  1. package/dist/components/DiskCapacityInfo/DiskCapacityInfo.d.ts +10 -1
  2. package/dist/components/DiskCapacityInfo/DiskCapacityInfo.js +75 -13
  3. package/dist/components/DiskCapacityInfo/DiskCapacityInfo.js.map +1 -1
  4. package/dist/components/DiskCapacityInfo/i18n/index.d.ts +1 -1
  5. package/dist/components/DiskPopup/DiskPopup.d.ts +25 -0
  6. package/dist/components/DiskPopup/DiskPopup.js +44 -0
  7. package/dist/components/DiskPopup/DiskPopup.js.map +1 -0
  8. package/dist/components/DiskPopup/DiskPopup.scss +203 -0
  9. package/dist/components/DiskPopup/i18n/en.json +3 -0
  10. package/dist/components/DiskPopup/i18n/index.d.ts +2 -0
  11. package/dist/components/DiskPopup/i18n/index.js +4 -0
  12. package/dist/components/DiskPopup/i18n/index.js.map +1 -0
  13. package/dist/components/DiskStatus/DiskStatus.d.ts +31 -0
  14. package/dist/components/DiskStatus/DiskStatus.js +61 -0
  15. package/dist/components/DiskStatus/DiskStatus.js.map +1 -0
  16. package/dist/components/DiskStatus/DiskStatus.scss +59 -0
  17. package/dist/components/DiskStatus/i18n/en.json +6 -0
  18. package/dist/components/DiskStatus/i18n/index.d.ts +2 -0
  19. package/dist/components/DiskStatus/i18n/index.js +4 -0
  20. package/dist/components/DiskStatus/i18n/index.js.map +1 -0
  21. package/dist/components/EntityStatus/EntityStatus.d.ts +1 -0
  22. package/dist/components/EntityStatus/EntityStatus.js +1 -1
  23. package/dist/components/EntityStatus/EntityStatus.js.map +1 -1
  24. package/dist/components/EvictVDiskButton/i18n/en.json +1 -1
  25. package/dist/components/FullNodeViewer/i18n/index.d.ts +1 -1
  26. package/dist/components/Graph/GravityGraph.js +9 -2
  27. package/dist/components/Graph/GravityGraph.js.map +1 -1
  28. package/dist/components/Graph/utils.d.ts +2 -1
  29. package/dist/components/Graph/utils.js +7 -0
  30. package/dist/components/Graph/utils.js.map +1 -1
  31. package/dist/components/HoverPopup/HoverPopup.d.ts +2 -1
  32. package/dist/components/HoverPopup/HoverPopup.js +49 -17
  33. package/dist/components/HoverPopup/HoverPopup.js.map +1 -1
  34. package/dist/components/HoverPopup/usePopupPriority.d.ts +4 -0
  35. package/dist/components/HoverPopup/usePopupPriority.js +30 -0
  36. package/dist/components/HoverPopup/usePopupPriority.js.map +1 -0
  37. package/dist/components/PDiskInfo/PDiskLogSize.d.ts +5 -0
  38. package/dist/components/PDiskInfo/PDiskLogSize.js +20 -0
  39. package/dist/components/PDiskInfo/PDiskLogSize.js.map +1 -0
  40. package/dist/components/PDiskInfo/PDiskLogSize.scss +12 -0
  41. package/dist/components/PDiskInfo/getPDiskDetails.d.ts +4 -0
  42. package/dist/components/PDiskInfo/getPDiskDetails.js +33 -0
  43. package/dist/components/PDiskInfo/getPDiskDetails.js.map +1 -0
  44. package/dist/components/PDiskInfo/i18n/en.json +64 -2
  45. package/dist/components/PDiskInfo/i18n/index.d.ts +1 -1
  46. package/dist/components/PDiskInfo/statuses.d.ts +7 -0
  47. package/dist/components/PDiskInfo/statuses.js +185 -0
  48. package/dist/components/PDiskInfo/statuses.js.map +1 -0
  49. package/dist/components/PDiskPopup/PDiskPopup.d.ts +4 -7
  50. package/dist/components/PDiskPopup/PDiskPopup.js +28 -99
  51. package/dist/components/PDiskPopup/PDiskPopup.js.map +1 -1
  52. package/dist/components/PDiskPopup/i18n/en.json +2 -12
  53. package/dist/components/PDiskPopup/i18n/index.d.ts +1 -1
  54. package/dist/components/PaginatedTable/rowLookup.js +30 -9
  55. package/dist/components/PaginatedTable/rowLookup.js.map +1 -1
  56. package/dist/components/StorageGroupInfo/StorageGroupInfo.d.ts +3 -3
  57. package/dist/components/StorageGroupInfo/StorageGroupInfo.js +78 -218
  58. package/dist/components/StorageGroupInfo/StorageGroupInfo.js.map +1 -1
  59. package/dist/components/StorageGroupInfo/StorageGroupInfo.scss +21 -0
  60. package/dist/components/StorageGroupInfo/i18n/en.json +1 -9
  61. package/dist/components/StorageGroupInfo/i18n/index.d.ts +1 -1
  62. package/dist/components/TableKeyboardNavigation/TableKeyboardNavigation.js +5 -1
  63. package/dist/components/TableKeyboardNavigation/TableKeyboardNavigation.js.map +1 -1
  64. package/dist/components/VDisk/VDisk.d.ts +2 -1
  65. package/dist/components/VDisk/VDisk.js +23 -32
  66. package/dist/components/VDisk/VDisk.js.map +1 -1
  67. package/dist/components/VDisk/VDiskWithDonorsStack.d.ts +1 -1
  68. package/dist/components/VDisk/VDiskWithDonorsStack.js +2 -1
  69. package/dist/components/VDisk/VDiskWithDonorsStack.js.map +1 -1
  70. package/dist/components/VDisk/getFlagStatusText.d.ts +2 -0
  71. package/dist/components/VDisk/getFlagStatusText.js +18 -0
  72. package/dist/components/VDisk/getFlagStatusText.js.map +1 -0
  73. package/dist/components/VDisk/i18n/en.json +1 -1
  74. package/dist/components/VDisk/i18n/index.d.ts +1 -1
  75. package/dist/components/VDiskInfo/getVDiskDetails.d.ts +5 -0
  76. package/dist/components/VDiskInfo/getVDiskDetails.js +29 -0
  77. package/dist/components/VDiskInfo/getVDiskDetails.js.map +1 -0
  78. package/dist/components/VDiskInfo/i18n/en.json +3 -1
  79. package/dist/components/VDiskInfo/i18n/index.d.ts +1 -1
  80. package/dist/components/VDiskPopup/VDiskPopup.d.ts +6 -8
  81. package/dist/components/VDiskPopup/VDiskPopup.js +106 -240
  82. package/dist/components/VDiskPopup/VDiskPopup.js.map +1 -1
  83. package/dist/components/VDiskPopup/VDiskPopup.scss +3 -10
  84. package/dist/components/VDiskPopup/i18n/en.json +6 -22
  85. package/dist/components/VDiskPopup/i18n/index.d.ts +1 -1
  86. package/dist/components/VDiskStatus/VDiskReplicationStatus.d.ts +8 -0
  87. package/dist/components/VDiskStatus/VDiskReplicationStatus.js +32 -0
  88. package/dist/components/VDiskStatus/VDiskReplicationStatus.js.map +1 -0
  89. package/dist/components/VDiskStatus/VDiskStatus.d.ts +16 -0
  90. package/dist/components/VDiskStatus/VDiskStatus.js +20 -0
  91. package/dist/components/VDiskStatus/VDiskStatus.js.map +1 -0
  92. package/dist/components/VDiskStatus/VDiskStatus.scss +32 -0
  93. package/dist/components/VDiskStatus/i18n/en.json +33 -0
  94. package/dist/components/VDiskStatus/i18n/index.d.ts +1 -0
  95. package/dist/components/VDiskStatus/i18n/index.js +5 -0
  96. package/dist/components/VDiskStatus/i18n/index.js.map +1 -0
  97. package/dist/components/VDiskStatus/index.d.ts +2 -0
  98. package/dist/components/VDiskStatus/index.js +3 -0
  99. package/dist/components/VDiskStatus/index.js.map +1 -0
  100. package/dist/components/VDiskStatus/statuses.d.ts +4 -0
  101. package/dist/components/VDiskStatus/statuses.js +120 -0
  102. package/dist/components/VDiskStatus/statuses.js.map +1 -0
  103. package/dist/components/capacityMetricsColumns/i18n/en.json +4 -4
  104. package/dist/containers/Authentication/Authentication.js +29 -30
  105. package/dist/containers/Authentication/Authentication.js.map +1 -1
  106. package/dist/containers/Authentication/utils.d.ts +2 -2
  107. package/dist/containers/Authentication/utils.js +1 -1
  108. package/dist/containers/Authentication/utils.js.map +1 -1
  109. package/dist/containers/Cluster/ClusterDrawerHealthcheck.js +6 -1
  110. package/dist/containers/Cluster/ClusterDrawerHealthcheck.js.map +1 -1
  111. package/dist/containers/Clusters/ClusterDrawerHealthcheck.js +1 -1
  112. package/dist/containers/Clusters/ClusterDrawerHealthcheck.js.map +1 -1
  113. package/dist/containers/Header/Header.js +8 -2
  114. package/dist/containers/Header/Header.js.map +1 -1
  115. package/dist/containers/Header/StorageGroupLeftControls.d.ts +1 -0
  116. package/dist/containers/Header/StorageGroupLeftControls.js +23 -0
  117. package/dist/containers/Header/StorageGroupLeftControls.js.map +1 -0
  118. package/dist/containers/Header/i18n/en.json +3 -1
  119. package/dist/containers/Header/i18n/index.d.ts +1 -1
  120. package/dist/containers/Operations/constants.d.ts +1 -1
  121. package/dist/containers/PDiskPage/PDiskSpaceDistribution/PDiskSpaceDistribution.js +4 -4
  122. package/dist/containers/PDiskPage/PDiskSpaceDistribution/PDiskSpaceDistribution.js.map +1 -1
  123. package/dist/containers/PDiskPage/i18n/index.d.ts +1 -1
  124. package/dist/containers/Storage/Disks/Disks.js +36 -9
  125. package/dist/containers/Storage/Disks/Disks.js.map +1 -1
  126. package/dist/containers/Storage/PDisk/PDisk.d.ts +2 -1
  127. package/dist/containers/Storage/PDisk/PDisk.js +2 -2
  128. package/dist/containers/Storage/PDisk/PDisk.js.map +1 -1
  129. package/dist/containers/Storage/PDisk/i18n/index.d.ts +1 -1
  130. package/dist/containers/Storage/PaginatedStorageGroupsTable/columns/columns.js +7 -2
  131. package/dist/containers/Storage/PaginatedStorageGroupsTable/columns/columns.js.map +1 -1
  132. package/dist/containers/Storage/PaginatedStorageGroupsTable/columns/i18n/index.d.ts +1 -1
  133. package/dist/containers/Storage/StorageExpertModePanel/components/SpaceLegend.scss +14 -82
  134. package/dist/containers/Storage/StorageExpertModePanel/i18n/index.d.ts +1 -1
  135. package/dist/containers/Storage/StorageGroupStateLabel.d.ts +4 -0
  136. package/dist/containers/Storage/StorageGroupStateLabel.js +9 -0
  137. package/dist/containers/Storage/StorageGroupStateLabel.js.map +1 -0
  138. package/dist/containers/Storage/utils/getStorageGroupStateLabel.d.ts +2 -0
  139. package/dist/containers/Storage/utils/getStorageGroupStateLabel.js +35 -0
  140. package/dist/containers/Storage/utils/getStorageGroupStateLabel.js.map +1 -0
  141. package/dist/containers/StorageGroupPage/StorageGroupPage.js +17 -12
  142. package/dist/containers/StorageGroupPage/StorageGroupPage.js.map +1 -1
  143. package/dist/containers/StorageGroupPage/StorageGroupPage.scss +9 -13
  144. package/dist/containers/StorageGroupPage/i18n/en.json +3 -1
  145. package/dist/containers/StorageGroupPage/i18n/index.d.ts +1 -1
  146. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.js +5 -1
  147. package/dist/containers/Tenant/Diagnostics/DiagnosticsPages.js.map +1 -1
  148. package/dist/containers/Tenant/Diagnostics/Overview/Overview.d.ts +2 -1
  149. package/dist/containers/Tenant/Diagnostics/Overview/Overview.js +11 -2
  150. package/dist/containers/Tenant/Diagnostics/Overview/Overview.js.map +1 -1
  151. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolInfo.scss +24 -0
  152. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.d.ts +8 -0
  153. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.js +34 -0
  154. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.js.map +1 -0
  155. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/en.json +4 -1
  156. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/index.d.ts +1 -1
  157. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.d.ts +1 -0
  158. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.js +1 -0
  159. package/dist/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.js.map +1 -1
  160. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.d.ts +2 -1
  161. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.js +12 -3
  162. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.js.map +1 -1
  163. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/prepareSchemaObjectInfo.d.ts +2 -1
  164. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/prepareSchemaObjectInfo.js +9 -8
  165. package/dist/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/prepareSchemaObjectInfo.js.map +1 -1
  166. package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.d.ts +16 -1
  167. package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.js +55 -33
  168. package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.js.map +1 -1
  169. package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/i18n/en.json +5 -1
  170. package/dist/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/i18n/index.d.ts +1 -1
  171. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +4 -0
  172. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/index.d.ts +1 -1
  173. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.js +4 -1
  174. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.js.map +1 -1
  175. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.js +4 -1
  176. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.js.map +1 -1
  177. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.js +41 -3
  178. package/dist/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.js.map +1 -1
  179. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.d.ts +7 -0
  180. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.js +38 -0
  181. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.js.map +1 -0
  182. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.scss +18 -0
  183. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/en.json +5 -0
  184. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.d.ts +2 -0
  185. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.js +5 -0
  186. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.js.map +1 -0
  187. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.d.ts +1 -0
  188. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.js +2 -0
  189. package/dist/containers/Tenant/Diagnostics/StreamingQueryGraph/index.js.map +1 -0
  190. package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantStorage/i18n/index.d.ts +1 -1
  191. package/dist/containers/Tenant/Diagnostics/i18n/en.json +1 -0
  192. package/dist/containers/Tenant/Diagnostics/i18n/index.d.ts +1 -1
  193. package/dist/containers/Tenant/Diagnostics/tabsContent.js +2 -0
  194. package/dist/containers/Tenant/Diagnostics/tabsContent.js.map +1 -1
  195. package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.d.ts +3 -1
  196. package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.js +3 -3
  197. package/dist/containers/Tenant/Healthcheck/components/HealthcheckDrawer.js.map +1 -1
  198. package/dist/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.js +8 -1
  199. package/dist/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.js.map +1 -1
  200. package/dist/containers/Tenant/TenantDrawerHealthcheck.js +8 -1
  201. package/dist/containers/Tenant/TenantDrawerHealthcheck.js.map +1 -1
  202. package/dist/containers/Tenants/DatabaseDrawerHealthcheck.js +8 -1
  203. package/dist/containers/Tenants/DatabaseDrawerHealthcheck.js.map +1 -1
  204. package/dist/containers/VDiskPage/i18n/index.d.ts +1 -1
  205. package/dist/lib.d.ts +1 -1
  206. package/dist/lib.js.map +1 -1
  207. package/dist/store/configureStore.d.ts +2 -2
  208. package/dist/store/defaultStore.d.ts +1 -1
  209. package/dist/store/reducers/executeTopQueries/executeTopQueries.d.ts +7 -0
  210. package/dist/store/reducers/executeTopQueries/executeTopQueries.js +38 -0
  211. package/dist/store/reducers/executeTopQueries/executeTopQueries.js.map +1 -1
  212. package/dist/store/reducers/header/types.d.ts +1 -1
  213. package/dist/store/reducers/index.d.ts +2 -2
  214. package/dist/store/reducers/pdisk/types.d.ts +1 -0
  215. package/dist/store/reducers/pdisk/utils.js +6 -1
  216. package/dist/store/reducers/pdisk/utils.js.map +1 -1
  217. package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.d.ts +8 -0
  218. package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.js +53 -0
  219. package/dist/store/reducers/query/parsers/prepareStreamingQueryPlan.js.map +1 -0
  220. package/dist/store/reducers/storage/prepareGroupsDisks.d.ts +1 -0
  221. package/dist/store/reducers/storage/prepareGroupsDisks.js +7 -18
  222. package/dist/store/reducers/storage/prepareGroupsDisks.js.map +1 -1
  223. package/dist/store/reducers/storage/utils.js +4 -0
  224. package/dist/store/reducers/storage/utils.js.map +1 -1
  225. package/dist/store/reducers/streamingQuery/streamingQuery.d.ts +5 -1
  226. package/dist/store/reducers/streamingQuery/streamingQuery.js +36 -13
  227. package/dist/store/reducers/streamingQuery/streamingQuery.js.map +1 -1
  228. package/dist/store/reducers/tenant/constants.d.ts +1 -0
  229. package/dist/store/reducers/tenant/constants.js +1 -0
  230. package/dist/store/reducers/tenant/constants.js.map +1 -1
  231. package/dist/styles/mixins.scss +22 -0
  232. package/dist/types/api/pdisk.d.ts +4 -0
  233. package/dist/types/api/pdisk.js.map +1 -1
  234. package/dist/types/api/schema/columnEntity.d.ts +2 -1
  235. package/dist/types/api/schema/sysView.d.ts +59 -2
  236. package/dist/types/api/schema/sysView.js +53 -1
  237. package/dist/types/api/schema/sysView.js.map +1 -1
  238. package/dist/types/api/schema/table.d.ts +8 -0
  239. package/dist/types/api/schema/table.js.map +1 -1
  240. package/dist/types/api/vdisk.d.ts +8 -0
  241. package/dist/types/api/vdisk.js +7 -0
  242. package/dist/types/api/vdisk.js.map +1 -1
  243. package/dist/types/store/nodesList.d.ts +4 -2
  244. package/dist/uiFactory/types.d.ts +5 -2
  245. package/dist/utils/bytesParsers/formatBytes.d.ts +3 -1
  246. package/dist/utils/bytesParsers/formatBytes.js +12 -3
  247. package/dist/utils/bytesParsers/formatBytes.js.map +1 -1
  248. package/dist/utils/disks/constants.d.ts +1 -0
  249. package/dist/utils/disks/constants.js +4 -0
  250. package/dist/utils/disks/constants.js.map +1 -1
  251. package/dist/utils/disks/diskInfo/getDiskLocationItems.d.ts +16 -0
  252. package/dist/utils/disks/diskInfo/getDiskLocationItems.js +30 -0
  253. package/dist/utils/disks/diskInfo/getDiskLocationItems.js.map +1 -0
  254. package/dist/utils/disks/diskInfo/i18n/en.json +9 -0
  255. package/dist/utils/disks/diskInfo/i18n/index.d.ts +2 -0
  256. package/dist/utils/disks/diskInfo/i18n/index.js +4 -0
  257. package/dist/utils/disks/diskInfo/i18n/index.js.map +1 -0
  258. package/dist/utils/disks/iconCalculators.d.ts +5 -0
  259. package/dist/utils/disks/iconCalculators.js +1 -1
  260. package/dist/utils/disks/iconCalculators.js.map +1 -1
  261. package/dist/utils/disks/prepareDisks.d.ts +6 -2
  262. package/dist/utils/disks/prepareDisks.js +22 -35
  263. package/dist/utils/disks/prepareDisks.js.map +1 -1
  264. package/dist/utils/disks/types.d.ts +9 -2
  265. package/dist/utils/hooks/useNodeMetadata.d.ts +2 -0
  266. package/dist/utils/hooks/useNodeMetadata.js +15 -0
  267. package/dist/utils/hooks/useNodeMetadata.js.map +1 -0
  268. package/dist/utils/nodes.js +6 -2
  269. package/dist/utils/nodes.js.map +1 -1
  270. package/dist/utils/query.d.ts +1 -0
  271. package/dist/utils/query.js +40 -0
  272. package/dist/utils/query.js.map +1 -1
  273. package/dist/utils/schema.d.ts +6 -2
  274. package/dist/utils/schema.js +14 -4
  275. package/dist/utils/schema.js.map +1 -1
  276. package/dist/utils/storageMetrics.d.ts +2 -2
  277. package/dist/utils/storageMetrics.js +22 -10
  278. package/dist/utils/storageMetrics.js.map +1 -1
  279. package/dist/utils/timeParsers/formatDuration.d.ts +4 -1
  280. package/dist/utils/timeParsers/formatDuration.js +16 -1
  281. package/dist/utils/timeParsers/formatDuration.js.map +1 -1
  282. package/dist/utils/timeParsers/i18n/en.json +5 -1
  283. package/dist/utils/timeParsers/i18n/index.d.ts +1 -1
  284. package/dist/utils/timeParsers/i18n/ru.json +5 -1
  285. package/package.json +2 -2
  286. package/src/components/DiskCapacityInfo/DiskCapacityInfo.tsx +106 -15
  287. package/src/components/DiskPopup/DiskPopup.scss +203 -0
  288. package/src/components/DiskPopup/DiskPopup.tsx +123 -0
  289. package/src/components/DiskPopup/i18n/en.json +3 -0
  290. package/src/components/DiskPopup/i18n/index.ts +5 -0
  291. package/src/components/DiskStatus/DiskStatus.scss +59 -0
  292. package/src/components/DiskStatus/DiskStatus.tsx +149 -0
  293. package/src/components/DiskStatus/i18n/en.json +6 -0
  294. package/src/components/DiskStatus/i18n/index.ts +5 -0
  295. package/src/components/EntityStatus/EntityStatus.tsx +1 -1
  296. package/src/components/EvictVDiskButton/i18n/en.json +1 -1
  297. package/src/components/Graph/GravityGraph.tsx +9 -2
  298. package/src/components/Graph/utils.ts +9 -1
  299. package/src/components/HoverPopup/HoverPopup.tsx +67 -20
  300. package/src/components/HoverPopup/usePopupPriority.ts +39 -0
  301. package/src/components/PDiskInfo/PDiskLogSize.scss +12 -0
  302. package/src/components/PDiskInfo/PDiskLogSize.tsx +37 -0
  303. package/src/components/PDiskInfo/getPDiskDetails.tsx +37 -0
  304. package/src/components/PDiskInfo/i18n/en.json +64 -8
  305. package/src/components/PDiskInfo/statuses.ts +209 -0
  306. package/src/components/PDiskPopup/PDiskPopup.tsx +62 -147
  307. package/src/components/PDiskPopup/i18n/en.json +2 -12
  308. package/src/components/PaginatedTable/rowLookup.ts +35 -10
  309. package/src/components/StorageGroupInfo/StorageGroupInfo.scss +21 -0
  310. package/src/components/StorageGroupInfo/StorageGroupInfo.tsx +121 -260
  311. package/src/components/StorageGroupInfo/i18n/en.json +1 -9
  312. package/src/components/TableKeyboardNavigation/TableKeyboardNavigation.tsx +5 -1
  313. package/src/components/VDisk/VDisk.tsx +31 -34
  314. package/src/components/VDisk/VDiskWithDonorsStack.tsx +2 -0
  315. package/src/components/VDisk/getFlagStatusText.ts +19 -0
  316. package/src/components/VDisk/i18n/en.json +1 -1
  317. package/src/components/VDiskInfo/getVDiskDetails.tsx +41 -0
  318. package/src/components/VDiskInfo/i18n/en.json +3 -10
  319. package/src/components/VDiskPopup/VDiskPopup.scss +3 -10
  320. package/src/components/VDiskPopup/VDiskPopup.tsx +197 -421
  321. package/src/components/VDiskPopup/i18n/en.json +6 -22
  322. package/src/components/VDiskStatus/VDiskReplicationStatus.tsx +77 -0
  323. package/src/components/VDiskStatus/VDiskStatus.scss +32 -0
  324. package/src/components/VDiskStatus/VDiskStatus.tsx +38 -0
  325. package/src/components/VDiskStatus/i18n/en.json +33 -0
  326. package/src/components/VDiskStatus/i18n/index.ts +7 -0
  327. package/src/components/VDiskStatus/index.ts +7 -0
  328. package/src/components/VDiskStatus/statuses.ts +139 -0
  329. package/src/components/capacityMetricsColumns/i18n/en.json +4 -4
  330. package/src/containers/Authentication/Authentication.tsx +29 -34
  331. package/src/containers/Authentication/utils.ts +3 -3
  332. package/src/containers/Cluster/ClusterDrawerHealthcheck.tsx +6 -0
  333. package/src/containers/Clusters/ClusterDrawerHealthcheck.tsx +1 -0
  334. package/src/containers/Header/Header.tsx +11 -3
  335. package/src/containers/Header/StorageGroupLeftControls.tsx +38 -0
  336. package/src/containers/Header/i18n/en.json +3 -1
  337. package/src/containers/PDiskPage/PDiskSpaceDistribution/PDiskSpaceDistribution.tsx +13 -2
  338. package/src/containers/Storage/Disks/Disks.tsx +66 -12
  339. package/src/containers/Storage/PDisk/PDisk.tsx +3 -0
  340. package/src/containers/Storage/PaginatedStorageGroupsTable/columns/columns.tsx +24 -3
  341. package/src/containers/Storage/StorageExpertModePanel/components/SpaceLegend.scss +14 -82
  342. package/src/containers/Storage/StorageGroupStateLabel.tsx +22 -0
  343. package/src/containers/Storage/utils/getStorageGroupStateLabel.ts +49 -0
  344. package/src/containers/StorageGroupPage/StorageGroupPage.scss +9 -13
  345. package/src/containers/StorageGroupPage/StorageGroupPage.tsx +53 -25
  346. package/src/containers/StorageGroupPage/i18n/en.json +3 -1
  347. package/src/containers/Tenant/Diagnostics/DiagnosticsPages.ts +6 -1
  348. package/src/containers/Tenant/Diagnostics/Overview/Overview.tsx +22 -2
  349. package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolInfo.scss +24 -0
  350. package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/ResourcePoolUsage.tsx +53 -0
  351. package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/i18n/en.json +4 -1
  352. package/src/containers/Tenant/Diagnostics/Overview/ResourcePoolInfo/index.ts +1 -0
  353. package/src/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/SchemaObjectInfo.tsx +19 -2
  354. package/src/containers/Tenant/Diagnostics/Overview/SchemaObjectInfo/prepareSchemaObjectInfo.tsx +11 -10
  355. package/src/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/StreamingQueryInfo.tsx +79 -34
  356. package/src/containers/Tenant/Diagnostics/Overview/StreamingQueryInfo/i18n/en.json +5 -1
  357. package/src/containers/Tenant/Diagnostics/Overview/TableInfo/i18n/en.json +4 -0
  358. package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareColumnTableInfo.tsx +11 -1
  359. package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareRowTableInfo.tsx +11 -1
  360. package/src/containers/Tenant/Diagnostics/Overview/TableInfo/prepareTableInfo/prepareTTL.ts +45 -3
  361. package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.scss +18 -0
  362. package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/StreamingQueryGraph.tsx +79 -0
  363. package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/en.json +5 -0
  364. package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/i18n/index.ts +7 -0
  365. package/src/containers/Tenant/Diagnostics/StreamingQueryGraph/index.ts +1 -0
  366. package/src/containers/Tenant/Diagnostics/i18n/en.json +1 -0
  367. package/src/containers/Tenant/Diagnostics/tabsContent.tsx +4 -0
  368. package/src/containers/Tenant/Healthcheck/components/HealthcheckDrawer.tsx +5 -2
  369. package/src/containers/Tenant/Query/QueryEditor/YqlEditor/YqlEditor.tsx +8 -1
  370. package/src/containers/Tenant/TenantDrawerHealthcheck.tsx +10 -0
  371. package/src/containers/Tenants/DatabaseDrawerHealthcheck.tsx +10 -0
  372. package/src/lib.ts +1 -0
  373. package/src/store/reducers/executeTopQueries/executeTopQueries.ts +46 -0
  374. package/src/store/reducers/header/types.ts +3 -1
  375. package/src/store/reducers/pdisk/types.ts +1 -0
  376. package/src/store/reducers/pdisk/utils.ts +6 -3
  377. package/src/store/reducers/query/parsers/prepareStreamingQueryPlan.ts +74 -0
  378. package/src/store/reducers/storage/prepareGroupsDisks.ts +7 -22
  379. package/src/store/reducers/storage/utils.ts +4 -0
  380. package/src/store/reducers/streamingQuery/streamingQuery.ts +44 -19
  381. package/src/store/reducers/tenant/constants.ts +1 -0
  382. package/src/styles/mixins.scss +22 -0
  383. package/src/types/api/pdisk.ts +4 -0
  384. package/src/types/api/schema/columnEntity.ts +2 -1
  385. package/src/types/api/schema/sysView.ts +60 -37
  386. package/src/types/api/schema/table.ts +7 -0
  387. package/src/types/api/vdisk.ts +9 -0
  388. package/src/types/store/nodesList.ts +7 -7
  389. package/src/uiFactory/types.ts +9 -2
  390. package/src/utils/bytesParsers/formatBytes.ts +23 -4
  391. package/src/utils/disks/constants.ts +5 -0
  392. package/src/utils/disks/diskInfo/getDiskLocationItems.ts +50 -0
  393. package/src/utils/disks/diskInfo/i18n/en.json +9 -0
  394. package/src/utils/disks/diskInfo/i18n/index.ts +5 -0
  395. package/src/utils/disks/iconCalculators.ts +1 -1
  396. package/src/utils/disks/prepareDisks.ts +21 -47
  397. package/src/utils/disks/types.ts +10 -2
  398. package/src/utils/hooks/useNodeMetadata.ts +21 -0
  399. package/src/utils/nodes.ts +6 -1
  400. package/src/utils/query.ts +55 -0
  401. package/src/utils/schema.ts +22 -5
  402. package/src/utils/storageMetrics.ts +27 -14
  403. package/src/utils/timeParsers/formatDuration.ts +22 -1
  404. package/src/utils/timeParsers/i18n/en.json +5 -1
  405. package/src/utils/timeParsers/i18n/ru.json +5 -1
@@ -0,0 +1,123 @@
1
+ import React from 'react';
2
+
3
+ import {ClipboardButton, Flex, Text, Tooltip} from '@gravity-ui/uikit';
4
+ import {isNil} from 'lodash';
5
+
6
+ import {cn} from '../../utils/cn';
7
+ import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants';
8
+ import type {DiskDetailItem} from '../../utils/disks/diskInfo/getDiskLocationItems';
9
+ import {DiskTypeLabel} from '../DiskStatus/DiskStatus';
10
+ import {YDBDefinitionList} from '../YDBDefinitionList/YDBDefinitionList';
11
+
12
+ import i18n from './i18n';
13
+
14
+ import './DiskPopup.scss';
15
+
16
+ const b = cn('ydb-disk-popup');
17
+
18
+ export function DiskPopup({
19
+ children,
20
+ combined = false,
21
+ className,
22
+ }: {
23
+ children: React.ReactNode;
24
+ combined?: boolean;
25
+ className?: string;
26
+ }) {
27
+ return <div className={b({combined}, className)}>{children}</div>;
28
+ }
29
+
30
+ export function DiskPopupPanel({
31
+ children,
32
+ footer,
33
+ }: {
34
+ children: React.ReactNode;
35
+ footer?: React.ReactNode;
36
+ }) {
37
+ return (
38
+ <div className={b('panel')}>
39
+ <div className={b('body')}>{children}</div>
40
+ {footer && <div className={b('footer')}>{footer}</div>}
41
+ </div>
42
+ );
43
+ }
44
+
45
+ export function DiskPopupHeader({
46
+ title,
47
+ id,
48
+ type,
49
+ statuses,
50
+ }: {
51
+ title: string;
52
+ id?: string;
53
+ type?: string;
54
+ statuses: React.ReactNode;
55
+ }) {
56
+ return (
57
+ <React.Fragment>
58
+ <Flex gap={1} alignItems="center" wrap="wrap">
59
+ <Text variant="subheader-2">{title}</Text>
60
+ <Text color="secondary">•</Text>
61
+ <Text variant="body-2" color="secondary" className={b('id')}>
62
+ {id || EMPTY_DATA_PLACEHOLDER}
63
+ </Text>
64
+ {id && (
65
+ <ClipboardButton
66
+ text={id}
67
+ size="s"
68
+ view="flat-secondary"
69
+ aria-label={i18n('action_copy-field', {field: title})}
70
+ />
71
+ )}
72
+ <DiskTypeLabel type={type} size="xs" />
73
+ </Flex>
74
+ <Flex gap={1} wrap="wrap" alignItems="center">
75
+ {statuses}
76
+ </Flex>
77
+ </React.Fragment>
78
+ );
79
+ }
80
+
81
+ export function DiskPopupText({
82
+ value,
83
+ withLeftTrim = false,
84
+ }: {
85
+ value?: string | number;
86
+ withLeftTrim?: boolean;
87
+ }) {
88
+ const hasValue = !isNil(value) && value !== '';
89
+ const text = hasValue ? value : EMPTY_DATA_PLACEHOLDER;
90
+ return (
91
+ <Tooltip content={text} disabled={!hasValue} className={b('text-tooltip')}>
92
+ <span
93
+ className={b('text', {'with-left-trim': withLeftTrim})}
94
+ tabIndex={hasValue ? 0 : undefined}
95
+ >
96
+ {withLeftTrim ? <span>{text}</span> : text}
97
+ </span>
98
+ </Tooltip>
99
+ );
100
+ }
101
+
102
+ export function DiskPopupLocation({items}: {items: DiskDetailItem[]}) {
103
+ if (!items.length) {
104
+ return null;
105
+ }
106
+ const locationItems = items.map((item) => {
107
+ if (['fqdn', 'rack', 'datacenter'].includes(item.id)) {
108
+ return {...item, content: <DiskPopupText value={item.copyText} />};
109
+ }
110
+ if (item.id === 'pdisk-path' && typeof item.copyText === 'string') {
111
+ return {
112
+ ...item,
113
+ content: <DiskPopupText value={item.copyText} withLeftTrim />,
114
+ };
115
+ }
116
+ return item;
117
+ });
118
+ return (
119
+ <div className={b('location')}>
120
+ <YDBDefinitionList items={locationItems} nameMaxWidth={100} />
121
+ </div>
122
+ );
123
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "action_copy-field": "Copy {{field}}"
3
+ }
@@ -0,0 +1,5 @@
1
+ import {registerKeysets} from '../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+
5
+ export default registerKeysets('ydb-disk-popup', {en});
@@ -0,0 +1,59 @@
1
+ @use '../../styles/mixins';
2
+
3
+ .ydb-disk-status {
4
+ &__type_hdd {
5
+ color: var(--g-color-text-utility);
6
+ background-color: var(--g-color-base-utility-light);
7
+ }
8
+
9
+ &__type_ssd {
10
+ color: var(--g-color-text-misc);
11
+ background-color: var(--g-color-base-misc-medium);
12
+ }
13
+
14
+ &__type_nvme {
15
+ color: var(--g-color-text-info);
16
+ background-color: var(--g-color-base-info-light);
17
+ }
18
+
19
+ &__capacity-alert {
20
+ $space-colors: (
21
+ 'green': 'green',
22
+ 'yellow': 'yellow',
23
+ 'red': 'red',
24
+ 'spacecyan': 'cyan',
25
+ 'spacelightyellow': 'light-yellow',
26
+ 'spacelightorange': 'light-orange',
27
+ 'spacepreorange': 'pre-orange',
28
+ 'spaceorange': 'orange',
29
+ 'spaceblack': 'black',
30
+ );
31
+
32
+ @each $color, $token in $space-colors {
33
+ &_color_#{$color} {
34
+ @include mixins.capacity-alert-label-colors($token);
35
+ }
36
+ }
37
+ }
38
+
39
+ &__label,
40
+ &__tooltip {
41
+ cursor: default;
42
+ }
43
+
44
+ &__label_danger-heavy {
45
+ color: var(--g-color-text-light-primary);
46
+ background-color: var(--g-color-base-danger-heavy);
47
+ }
48
+
49
+ &__tooltip {
50
+ display: inline-flex;
51
+
52
+ border-radius: var(--g-border-radius-s);
53
+
54
+ &:focus-visible {
55
+ outline: 2px solid var(--g-color-line-focus);
56
+ outline-offset: 2px;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,149 @@
1
+ import type {IconData, LabelProps} from '@gravity-ui/uikit';
2
+ import {Icon, Label, Tooltip} from '@gravity-ui/uikit';
3
+ import {capitalize} from 'lodash';
4
+
5
+ import {EFlag, isCapacityAlert} from '../../types/api/enums';
6
+ import {normalizeCapacityAlert} from '../../utils/capacityAlerts';
7
+ import {cn} from '../../utils/cn';
8
+ import {formatPDiskType} from '../../utils/disks/getPDiskType';
9
+ import {getDisplaySeverityColor} from '../../utils/disks/helpers';
10
+ import {getFlagIconWithColor} from '../../utils/disks/iconCalculators';
11
+ import {normalizeMediaType} from '../../utils/disks/normalizeMediaType';
12
+ import {calculateSpaceSeverity} from '../../utils/disks/severityCalculators';
13
+ import {EFlagToLabelTheme} from '../EntityStatus/EntityStatus';
14
+ import {getFlagStatusText} from '../VDisk/getFlagStatusText';
15
+
16
+ import i18n from './i18n';
17
+
18
+ import './DiskStatus.scss';
19
+
20
+ const b = cn('ydb-disk-status');
21
+
22
+ export interface DiskStatusLabelData {
23
+ value: string;
24
+ title?: string;
25
+ theme?: LabelProps['theme'];
26
+ icon?: IconData;
27
+ tooltip?: string;
28
+ dangerHeavy?: boolean;
29
+ }
30
+
31
+ export type TitledDiskStatusLabelData = Omit<DiskStatusLabelData, 'title' | 'value'> & {
32
+ title: string;
33
+ value?: string;
34
+ };
35
+
36
+ export function DiskStatusLabel({
37
+ value,
38
+ theme = 'normal',
39
+ icon,
40
+ title,
41
+ tooltip,
42
+ dangerHeavy,
43
+ size = 's',
44
+ iconSize = 12,
45
+ className,
46
+ }: (DiskStatusLabelData | TitledDiskStatusLabelData) &
47
+ Pick<LabelProps, 'size' | 'className'> & {iconSize?: number}) {
48
+ const label = (
49
+ <Label
50
+ size={size}
51
+ theme={theme}
52
+ className={b('label', {'danger-heavy': dangerHeavy}, className)}
53
+ icon={icon ? <Icon data={icon} size={iconSize} /> : undefined}
54
+ value={title ? value : undefined}
55
+ >
56
+ {title ?? value}
57
+ </Label>
58
+ );
59
+ return tooltip ? (
60
+ <Tooltip content={tooltip} placement="top">
61
+ <span tabIndex={0} className={b('tooltip')}>
62
+ {label}
63
+ </span>
64
+ </Tooltip>
65
+ ) : (
66
+ label
67
+ );
68
+ }
69
+
70
+ export function DiskTypeLabel({type, size}: {type?: string} & Pick<LabelProps, 'size'>) {
71
+ if (!type?.trim()) {
72
+ return null;
73
+ }
74
+ const mediaType = normalizeMediaType(type);
75
+ const value = formatPDiskType(mediaType) ?? mediaType;
76
+ let tooltip: string | undefined;
77
+ switch (mediaType) {
78
+ case 'HDD':
79
+ tooltip = i18n('context_hdd');
80
+ break;
81
+ case 'SSD':
82
+ tooltip = i18n('context_ssd');
83
+ break;
84
+ case 'NVME':
85
+ tooltip = i18n('context_nvme');
86
+ break;
87
+ }
88
+ return (
89
+ <DiskStatusLabel
90
+ value={value}
91
+ tooltip={tooltip}
92
+ size={size}
93
+ className={b('type', {
94
+ hdd: mediaType === 'HDD',
95
+ ssd: mediaType === 'SSD',
96
+ nvme: mediaType === 'NVME',
97
+ })}
98
+ />
99
+ );
100
+ }
101
+
102
+ export function DiskCapacityAlertLabel({
103
+ value,
104
+ emptyText = i18n('value_no-data'),
105
+ }: {
106
+ value?: string;
107
+ emptyText?: string;
108
+ }) {
109
+ const capacityAlert = normalizeCapacityAlert(value);
110
+ if (!capacityAlert) {
111
+ return <DiskStatusLabel size="xs" value={emptyText} theme="unknown" />;
112
+ }
113
+ const color = isCapacityAlert(capacityAlert)
114
+ ? getDisplaySeverityColor(
115
+ calculateSpaceSeverity({CapacityAlert: capacityAlert}),
116
+ ).toLowerCase()
117
+ : undefined;
118
+ return (
119
+ <DiskStatusLabel
120
+ size="xs"
121
+ value={capitalize(capacityAlert.replaceAll('_', ' '))}
122
+ className={b('capacity-alert', {color})}
123
+ />
124
+ );
125
+ }
126
+
127
+ export function DiskFlagLabel({
128
+ flag,
129
+ title,
130
+ icon,
131
+ emptyText = i18n('value_no-data'),
132
+ }: {
133
+ flag?: EFlag;
134
+ title?: string;
135
+ icon?: IconData;
136
+ emptyText?: string;
137
+ }) {
138
+ const resolvedFlag = flag || EFlag.Grey;
139
+ return (
140
+ <DiskStatusLabel
141
+ value={resolvedFlag === EFlag.Grey ? emptyText : getFlagStatusText(resolvedFlag)}
142
+ title={title}
143
+ theme={EFlagToLabelTheme[resolvedFlag] ?? 'normal'}
144
+ icon={icon ?? getFlagIconWithColor(resolvedFlag)?.icon}
145
+ dangerHeavy={resolvedFlag === EFlag.Red}
146
+ size="xs"
147
+ />
148
+ );
149
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "value_no-data": "Not available",
3
+ "context_hdd": "Hard disk drive",
4
+ "context_ssd": "Solid-state drive connected over SATA or SAS interface",
5
+ "context_nvme": "Solid-state drive connected over NVMe interface"
6
+ }
@@ -0,0 +1,5 @@
1
+ import {registerKeysets} from '../../../utils/i18n';
2
+
3
+ import en from './en.json';
4
+
5
+ export default registerKeysets('ydb-disk-status', {en});
@@ -14,7 +14,7 @@ import './EntityStatus.scss';
14
14
 
15
15
  const b = cn('ydb-entity-status');
16
16
 
17
- const EFlagToLabelTheme: Record<EFlag, LabelProps['theme']> = {
17
+ export const EFlagToLabelTheme: Record<EFlag, LabelProps['theme']> = {
18
18
  [EFlag.Red]: 'danger',
19
19
  [EFlag.Blue]: 'success',
20
20
  [EFlag.Green]: 'success',
@@ -3,7 +3,7 @@
3
3
  "action_evict-short": "Evict",
4
4
  "action_force-evict": "Evict anyway",
5
5
  "title_evict-dialog": "Evict VDisk?",
6
- "confirm_evict": "The VDisk will be evicted from the PDisk. All data will be moved to another PDisk.",
6
+ "confirm_evict": "The VDisk will be evicted from the PDisk. This VDisk will be replaced by a new one in the group. Data will be replicated to the new disk. The old VDisk will serve as a donor until replication is complete, and then it will be removed.",
7
7
  "alert_evict": "This operation cannot be cancelled.",
8
8
  "alert_not-allowed": "You don't have enough rights to evict VDisk",
9
9
  "alert_donor-mode-impossible": "Evicting a donor VDisk is not possible"
@@ -21,7 +21,7 @@ import {NonSelectableConnection} from './NonSelectableConnection';
21
21
  import {graphColorsConfig} from './colorsConfig';
22
22
  import {runTreeLayout} from './runTreeLayout';
23
23
  import type {Data} from './types';
24
- import {parseCustomPropertyValue} from './utils';
24
+ import {getLayoutSignature, parseCustomPropertyValue} from './utils';
25
25
 
26
26
  import './GravityGraph.scss';
27
27
 
@@ -81,6 +81,7 @@ export function GravityGraph<T>({data, onError, theme}: Props<T>) {
81
81
  const {graph, start} = useGraph(config);
82
82
  const cameraSizeRef = React.useRef({width: 0, height: 0});
83
83
  const graphBlockIdsRef = React.useRef<TBlockId[]>([]);
84
+ const layoutSignatureRef = React.useRef<string>();
84
85
  const fitFrameRef = React.useRef<number>();
85
86
  const fitGraphToViewport = React.useCallback(() => {
86
87
  const {width, height} = graph.cameraService.getCameraState();
@@ -125,11 +126,17 @@ export function GravityGraph<T>({data, onError, theme}: Props<T>) {
125
126
  createWorker: createGraphLayoutWorker,
126
127
  onResult: ({layout, edges}) => {
127
128
  graphBlockIdsRef.current = layout.map(({id}) => id);
129
+ // Statistics-only updates keep the layout, so the camera stays where the user put it.
130
+ const signature = getLayoutSignature(layout, edges);
131
+ const sameLayout = layoutSignatureRef.current === signature;
132
+ layoutSignatureRef.current = signature;
128
133
  graph.setEntities({
129
134
  blocks: layout,
130
135
  connections: edges,
131
136
  });
132
- scheduleGraphFit();
137
+ if (!sameLayout) {
138
+ scheduleGraphFit();
139
+ }
133
140
  },
134
141
  onError,
135
142
  });
@@ -3,7 +3,7 @@ import type {TBlock} from '@gravity-ui/graph';
3
3
  import type {ExplainPlanNodeData} from '../../store/reducers/query/types';
4
4
 
5
5
  import type {AbstractGraphColorsConfig} from './colorsConfig';
6
- import type {Data, TreeConnection} from './types';
6
+ import type {Data, EdgeResult, TreeConnection} from './types';
7
7
 
8
8
  const BLOCK_TOP_PADDING = 8;
9
9
  const BLOCK_LINE_HEIGHT = 16;
@@ -110,3 +110,11 @@ export function parseCustomPropertyValue<T extends AbstractGraphColorsConfig>(
110
110
 
111
111
  return parsed as T;
112
112
  }
113
+
114
+ // Identifies the geometry the camera is aimed at: block placement and the edges between them.
115
+ export function getLayoutSignature(blocks: TBlock[], edges: EdgeResult[]) {
116
+ return JSON.stringify([
117
+ blocks.map(({id, x, y, width, height}) => [id, x, y, width, height]),
118
+ edges.map(({sourceBlockId, targetBlockId}) => [sourceBlockId, targetBlockId]),
119
+ ]);
120
+ }
@@ -8,26 +8,38 @@ import {YDB_POPOVER_CLASS_NAME} from '../../utils/constants';
8
8
  import {useEventHandler} from '../../utils/hooks/useEventHandler';
9
9
 
10
10
  import {getPopupScrollContainer} from './getPopupScrollContainer';
11
+ import {usePopupPriority} from './usePopupPriority';
11
12
 
12
13
  const DEBOUNCE_TIMEOUT = 100;
13
14
 
14
- function useVisibleAnchor(anchorElement: HTMLElement | null, open: boolean) {
15
+ function useVisibleAnchor(
16
+ anchorElement: HTMLElement | null,
17
+ open: boolean,
18
+ onHidden: VoidFunction,
19
+ ) {
15
20
  const [visibleAnchor, setVisibleAnchor] = React.useState<HTMLElement | null>(null);
21
+ // Mouse events can arrive before React renders the observer's next visibility state.
22
+ const visibleAnchorRef = React.useRef<HTMLElement | null>(null);
16
23
 
17
24
  React.useLayoutEffect(() => {
18
25
  setVisibleAnchor(null);
26
+ visibleAnchorRef.current = null;
19
27
  if (!open || !anchorElement) {
20
28
  return undefined;
21
29
  }
22
30
 
23
31
  const observer = new IntersectionObserver(([entry]) => {
24
- setVisibleAnchor(entry.isIntersecting ? anchorElement : null);
32
+ visibleAnchorRef.current = entry.isIntersecting ? anchorElement : null;
33
+ setVisibleAnchor(visibleAnchorRef.current);
34
+ if (!entry.isIntersecting) {
35
+ onHidden();
36
+ }
25
37
  });
26
38
  observer.observe(anchorElement);
27
39
  return () => observer.disconnect();
28
- }, [anchorElement, open]);
40
+ }, [anchorElement, open, onHidden]);
29
41
 
30
- return anchorElement !== null && visibleAnchor === anchorElement;
42
+ return [anchorElement !== null && visibleAnchor === anchorElement, visibleAnchorRef] as const;
31
43
  }
32
44
 
33
45
  type HoverPopupProps = {
@@ -37,6 +49,7 @@ type HoverPopupProps = {
37
49
  anchorRef?: React.RefObject<HTMLElement>;
38
50
  onShowPopup?: VoidFunction;
39
51
  onHidePopup?: VoidFunction;
52
+ onClosePopup?: VoidFunction;
40
53
  delayOpen?: number;
41
54
  delayClose?: number;
42
55
  contentClassName?: string;
@@ -50,6 +63,7 @@ export const HoverPopup = ({
50
63
  anchorRef,
51
64
  onShowPopup,
52
65
  onHidePopup,
66
+ onClosePopup,
53
67
  placement = ['top', 'bottom', 'left', 'right'],
54
68
  contentClassName,
55
69
  delayClose = DEBOUNCE_TIMEOUT,
@@ -60,6 +74,8 @@ export const HoverPopup = ({
60
74
  const [isFocused, setIsFocused] = React.useState(false);
61
75
 
62
76
  const anchor = React.useRef<HTMLSpanElement>(null);
77
+ const {activate, zIndex} = usePopupPriority();
78
+ const bringToFront = useEventHandler(() => activate(anchorRef?.current || anchor.current));
63
79
 
64
80
  const reportedOpenRef = React.useRef(false);
65
81
 
@@ -113,9 +129,33 @@ export const HoverPopup = ({
113
129
  setIsPopupContentHovered(false);
114
130
  setIsFocused(false);
115
131
  reportOpen(false, true);
116
- }, [debouncedHandleHidePopup, debouncedHandleShowPopup, reportOpen]);
132
+ onClosePopup?.();
133
+ }, [debouncedHandleHidePopup, debouncedHandleShowPopup, onClosePopup, reportOpen]);
117
134
 
118
- const onMouseEnter = () => {
135
+ const hideClippedPopup = useEventHandler(() => {
136
+ debouncedHandleShowPopup.cancel();
137
+ setIsPopupContentHovered(false);
138
+ setIsFocused(false);
139
+ debouncedHandleHidePopup();
140
+ });
141
+
142
+ const internalOpen = isPopupVisible || isPopupContentHovered || isFocused;
143
+ const open = Boolean(internalOpen || showPopup);
144
+
145
+ const anchorElement = anchorRef?.current || anchor.current;
146
+ // Release only this popup's hover source; a hovered peer can keep the pair open.
147
+ const [isAnchorVisible, visibleAnchorRef] = useVisibleAnchor(
148
+ anchorElement,
149
+ open,
150
+ hideClippedPopup,
151
+ );
152
+ const container = getPopupScrollContainer(anchorElement);
153
+
154
+ const onMouseEnter = (event: React.MouseEvent<HTMLSpanElement>) => {
155
+ if (event.buttons !== 0) {
156
+ return;
157
+ }
158
+ bringToFront();
119
159
  debouncedHandleHidePopup.cancel();
120
160
  debouncedHandleShowPopup();
121
161
  };
@@ -125,11 +165,21 @@ export const HoverPopup = ({
125
165
  debouncedHandleHidePopup();
126
166
  };
127
167
 
128
- const onPopupMouseEnter = React.useCallback(() => {
129
- debouncedHandleHidePopup.cancel();
130
- setIsPopupContentHovered(true);
131
- reportOpen(true);
132
- }, [reportOpen, debouncedHandleHidePopup]);
168
+ const onPopupMouseEnter = React.useCallback(
169
+ (event: React.MouseEvent<HTMLDivElement>) => {
170
+ // An exiting popup can still receive events during its close animation.
171
+ if (!open || visibleAnchorRef.current !== anchorElement) {
172
+ return;
173
+ }
174
+ if (event.buttons === 0) {
175
+ bringToFront();
176
+ }
177
+ debouncedHandleHidePopup.cancel();
178
+ setIsPopupContentHovered(true);
179
+ reportOpen(true);
180
+ },
181
+ [bringToFront, reportOpen, debouncedHandleHidePopup, open, visibleAnchorRef, anchorElement],
182
+ );
133
183
 
134
184
  const onPopupMouseLeave = React.useCallback(() => {
135
185
  setIsPopupContentHovered(false);
@@ -137,9 +187,13 @@ export const HoverPopup = ({
137
187
  }, [debouncedHandleHidePopup]);
138
188
 
139
189
  const onPopupContextMenu = React.useCallback(() => {
190
+ if (!open || visibleAnchorRef.current !== anchorElement) {
191
+ return;
192
+ }
193
+ bringToFront();
140
194
  setIsFocused(true);
141
195
  reportOpen(true);
142
- }, [reportOpen]);
196
+ }, [bringToFront, reportOpen, open, visibleAnchorRef, anchorElement]);
143
197
 
144
198
  const onPopupBlur = React.useCallback(() => {
145
199
  setIsFocused(false);
@@ -149,14 +203,6 @@ export const HoverPopup = ({
149
203
  closePopup();
150
204
  }, [closePopup]);
151
205
 
152
- const internalOpen = isPopupVisible || isPopupContentHovered || isFocused;
153
- const open = Boolean(internalOpen || showPopup);
154
-
155
- const anchorElement = anchorRef?.current || anchor.current;
156
- // Clipping a paired disk must not clear the shared hover state via onHidePopup.
157
- const isAnchorVisible = useVisibleAnchor(anchorElement, open);
158
- const container = getPopupScrollContainer(anchorElement);
159
-
160
206
  return (
161
207
  <React.Fragment>
162
208
  <span ref={anchor} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
@@ -165,6 +211,7 @@ export const HoverPopup = ({
165
211
  {anchorElement ? (
166
212
  <Popup
167
213
  container={container}
214
+ zIndex={zIndex}
168
215
  // Keep portal typography when the page uses a different font.
169
216
  floatingStyles={{fontFamily: 'var(--g-text-body-font-family)'}}
170
217
  anchorElement={anchorElement}
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+
3
+ // Only the previously active popup needs updating when another one is entered.
4
+ const activePopups = new WeakMap<Document, VoidFunction>();
5
+
6
+ export function usePopupPriority() {
7
+ const [active, setActive] = React.useState(false);
8
+ const documentRef = React.useRef<Document>();
9
+ const deactivate = React.useCallback(() => setActive(false), []);
10
+ const activate = React.useCallback(
11
+ (element: HTMLElement | null) => {
12
+ if (!element) {
13
+ return;
14
+ }
15
+ const doc = element.ownerDocument;
16
+ const previous = activePopups.get(doc);
17
+ if (previous !== deactivate) {
18
+ previous?.();
19
+ activePopups.set(doc, deactivate);
20
+ }
21
+ documentRef.current = doc;
22
+ setActive(true);
23
+ },
24
+ [deactivate],
25
+ );
26
+
27
+ React.useEffect(
28
+ () => () => {
29
+ const doc = documentRef.current;
30
+ if (doc && activePopups.get(doc) === deactivate) {
31
+ activePopups.delete(doc);
32
+ }
33
+ },
34
+ [deactivate],
35
+ );
36
+
37
+ // Keep tooltips, menus and modal dialogs (Gravity UI's default 1000) above cards.
38
+ return {activate, zIndex: active ? 999 : 998};
39
+ }
@@ -0,0 +1,12 @@
1
+ .ydb-pdisk-log-size {
2
+ width: 100%;
3
+
4
+ white-space: nowrap;
5
+
6
+ &__progress {
7
+ flex: 0 0 auto;
8
+
9
+ width: var(--ydb-pdisk-log-size-progress-width, 100px);
10
+ margin: 0;
11
+ }
12
+ }