@postgres.ai/shared 3.5.1-pr-1027.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 (202) hide show
  1. package/.gitlab-ci.yml +60 -0
  2. package/components/AlertSnackbar/index.tsx +23 -0
  3. package/components/AlertSnackbar/useAlertSnackbar.tsx +65 -0
  4. package/components/Button/index.tsx +79 -0
  5. package/components/Button2/index.tsx +43 -0
  6. package/components/Button2/styles.module.scss +82 -0
  7. package/components/DestroyCloneModal/index.tsx +56 -0
  8. package/components/DestroyCloneRestrictionModal/index.tsx +50 -0
  9. package/components/ErrorStub/index.tsx +83 -0
  10. package/components/FormattedText/index.tsx +44 -0
  11. package/components/FormattedText/styles.module.scss +34 -0
  12. package/components/GatewayLink/index.tsx +33 -0
  13. package/components/HorizontalScrollContainer/index.tsx +131 -0
  14. package/components/HorizontalScrollContainer/types.ts +12 -0
  15. package/components/HorizontalScrollContainer/utils.ts +16 -0
  16. package/components/ImportantText/index.tsx +29 -0
  17. package/components/Link2/index.tsx +31 -0
  18. package/components/Link2/styles.module.scss +12 -0
  19. package/components/MenuButton/index.tsx +80 -0
  20. package/components/MenuButton/styles.module.scss +42 -0
  21. package/components/Modal/index.tsx +93 -0
  22. package/components/PageSpinner/index.tsx +18 -0
  23. package/components/PageSpinner/styles.module.scss +13 -0
  24. package/components/ResetCloneModal/index.tsx +154 -0
  25. package/components/SectionTitle/index.tsx +74 -0
  26. package/components/Select/index.tsx +42 -0
  27. package/components/SimpleModalControls/index.tsx +56 -0
  28. package/components/Spinner/icon.tsx +29 -0
  29. package/components/Spinner/index.tsx +16 -0
  30. package/components/Spinner/styles.module.scss +33 -0
  31. package/components/Status/index.tsx +61 -0
  32. package/components/Status/styles.module.scss +45 -0
  33. package/components/StubContainer/index.tsx +41 -0
  34. package/components/StubSpinner/index.tsx +49 -0
  35. package/components/StubSpinnerFlex/index.tsx +20 -0
  36. package/components/StubSpinnerFlex/styles.module.scss +20 -0
  37. package/components/SyntaxHighlight/index.tsx +107 -0
  38. package/components/Table/RowMenu/index.tsx +111 -0
  39. package/components/Table/index.tsx +140 -0
  40. package/components/Text/index.tsx +28 -0
  41. package/components/TextField/index.tsx +117 -0
  42. package/components/Tooltip/index.tsx +52 -0
  43. package/config/index.ts +32 -0
  44. package/config/links.ts +6 -0
  45. package/craco.config.js +80 -0
  46. package/helpers/getEntropy.ts +232 -0
  47. package/helpers/localStorage.ts +15 -0
  48. package/helpers/request.ts +47 -0
  49. package/hooks/useWindowDimensions.ts +16 -0
  50. package/icons/ArrowDropDown/index.tsx +29 -0
  51. package/icons/Circle/index.tsx +27 -0
  52. package/icons/External/index.tsx +14 -0
  53. package/icons/Info/index.tsx +12 -0
  54. package/icons/Renewable/index.tsx +65 -0
  55. package/icons/Shield/index.tsx +33 -0
  56. package/icons/Warning/index.tsx +29 -0
  57. package/meta.json +1 -0
  58. package/package.json +55 -0
  59. package/pages/Clone/Status/index.tsx +73 -0
  60. package/pages/Clone/context.ts +22 -0
  61. package/pages/Clone/index.tsx +634 -0
  62. package/pages/Clone/stores/Main.ts +206 -0
  63. package/pages/Clone/useCreatedStores.ts +11 -0
  64. package/pages/Configuration/Header/index.tsx +84 -0
  65. package/pages/Configuration/InputWithTooltip/index.tsx +240 -0
  66. package/pages/Configuration/ResponseMessage/index.tsx +71 -0
  67. package/pages/Configuration/configOptions.ts +60 -0
  68. package/pages/Configuration/index.tsx +1184 -0
  69. package/pages/Configuration/styles.module.scss +122 -0
  70. package/pages/Configuration/tooltipText.tsx +157 -0
  71. package/pages/Configuration/useForm.ts +108 -0
  72. package/pages/Configuration/utils/index.ts +153 -0
  73. package/pages/CreateClone/index.tsx +311 -0
  74. package/pages/CreateClone/stores/Main.ts +107 -0
  75. package/pages/CreateClone/styles.module.scss +71 -0
  76. package/pages/CreateClone/useCreatedStores.ts +11 -0
  77. package/pages/CreateClone/useForm.ts +36 -0
  78. package/pages/Instance/Clones/Header/Item/index.tsx +15 -0
  79. package/pages/Instance/Clones/Header/Item/styles.module.scss +17 -0
  80. package/pages/Instance/Clones/Header/index.tsx +74 -0
  81. package/pages/Instance/Clones/Header/styles.module.scss +11 -0
  82. package/pages/Instance/Clones/index.tsx +135 -0
  83. package/pages/Instance/ClonesModal/index.tsx +71 -0
  84. package/pages/Instance/ClonesModal/utils.ts +21 -0
  85. package/pages/Instance/InactiveInstance/index.tsx +165 -0
  86. package/pages/Instance/InactiveInstance/utils.ts +9 -0
  87. package/pages/Instance/Info/Connection/ConnectModal/Content/index.tsx +176 -0
  88. package/pages/Instance/Info/Connection/ConnectModal/Content/utils.ts +24 -0
  89. package/pages/Instance/Info/Connection/ConnectModal/index.tsx +36 -0
  90. package/pages/Instance/Info/Connection/index.tsx +81 -0
  91. package/pages/Instance/Info/Details/index.tsx +20 -0
  92. package/pages/Instance/Info/Disks/Disk/ActionsMenu/index.tsx +100 -0
  93. package/pages/Instance/Info/Disks/Disk/Marker/index.tsx +26 -0
  94. package/pages/Instance/Info/Disks/Disk/ProgressBar/PointerIcon.tsx +20 -0
  95. package/pages/Instance/Info/Disks/Disk/ProgressBar/index.tsx +73 -0
  96. package/pages/Instance/Info/Disks/Disk/Status/index.tsx +75 -0
  97. package/pages/Instance/Info/Disks/Disk/index.tsx +168 -0
  98. package/pages/Instance/Info/Disks/index.tsx +65 -0
  99. package/pages/Instance/Info/Icons/index.tsx +39 -0
  100. package/pages/Instance/Info/Retrieval/RefreshFailedAlert/index.tsx +32 -0
  101. package/pages/Instance/Info/Retrieval/RefreshFailedAlert/styles.module.scss +33 -0
  102. package/pages/Instance/Info/Retrieval/RetrievalModal/index.tsx +49 -0
  103. package/pages/Instance/Info/Retrieval/RetrievalModal/styles.module.scss +6 -0
  104. package/pages/Instance/Info/Retrieval/RetrievalTable/index.tsx +53 -0
  105. package/pages/Instance/Info/Retrieval/RetrievalTable/styles.module.scss +29 -0
  106. package/pages/Instance/Info/Retrieval/index.tsx +95 -0
  107. package/pages/Instance/Info/Retrieval/utils.ts +10 -0
  108. package/pages/Instance/Info/Snapshots/Calendar/Day/index.tsx +125 -0
  109. package/pages/Instance/Info/Snapshots/Calendar/index.tsx +133 -0
  110. package/pages/Instance/Info/Snapshots/Calendar/utils.ts +74 -0
  111. package/pages/Instance/Info/Snapshots/TimeLine/Day/index.tsx +79 -0
  112. package/pages/Instance/Info/Snapshots/TimeLine/index.tsx +57 -0
  113. package/pages/Instance/Info/Snapshots/index.tsx +97 -0
  114. package/pages/Instance/Info/Snapshots/utils.ts +18 -0
  115. package/pages/Instance/Info/Status/InstanceResponseModal/index.tsx +32 -0
  116. package/pages/Instance/Info/Status/InstanceResponseModal/styles.module.scss +3 -0
  117. package/pages/Instance/Info/Status/index.tsx +85 -0
  118. package/pages/Instance/Info/Status/styles.module.scss +12 -0
  119. package/pages/Instance/Info/Status/utils.ts +24 -0
  120. package/pages/Instance/Info/components/Property/index.tsx +32 -0
  121. package/pages/Instance/Info/components/Property/styles.module.scss +21 -0
  122. package/pages/Instance/Info/components/Section/index.tsx +50 -0
  123. package/pages/Instance/Info/components/ValueStatus/index.tsx +51 -0
  124. package/pages/Instance/Info/index.tsx +129 -0
  125. package/pages/Instance/SnapshotsModal/index.tsx +169 -0
  126. package/pages/Instance/SnapshotsModal/utils.ts +17 -0
  127. package/pages/Instance/Tabs/index.tsx +98 -0
  128. package/pages/Instance/components/ClonesList/ConnectionModal/index.tsx +196 -0
  129. package/pages/Instance/components/ClonesList/MenuCell/index.tsx +98 -0
  130. package/pages/Instance/components/ClonesList/MenuCell/utils.ts +21 -0
  131. package/pages/Instance/components/ClonesList/index.tsx +189 -0
  132. package/pages/Instance/components/ClonesList/styles.module.scss +32 -0
  133. package/pages/Instance/components/ErrorStub/index.tsx +77 -0
  134. package/pages/Instance/components/ModalReloadButton/index.tsx +43 -0
  135. package/pages/Instance/components/Tags/Tag/index.tsx +60 -0
  136. package/pages/Instance/components/Tags/index.tsx +42 -0
  137. package/pages/Instance/context.ts +39 -0
  138. package/pages/Instance/index.tsx +235 -0
  139. package/pages/Instance/stores/ClonesModal.ts +35 -0
  140. package/pages/Instance/stores/Main.ts +335 -0
  141. package/pages/Instance/stores/SnapshotsModal.ts +35 -0
  142. package/pages/Instance/styles.scss +40 -0
  143. package/pages/Instance/useCreatedStores.ts +14 -0
  144. package/pages/Logs/Icons/PlusIcon.tsx +8 -0
  145. package/pages/Logs/constants/index.ts +7 -0
  146. package/pages/Logs/hooks/useWsScroll.tsx +44 -0
  147. package/pages/Logs/index.tsx +267 -0
  148. package/pages/Logs/utils/index.ts +20 -0
  149. package/pages/Logs/wsLogs.ts +110 -0
  150. package/pages/Logs/wsSnackbar.ts +27 -0
  151. package/postgres.ai-shared-3.5.0.tgz +0 -0
  152. package/react-app-env.d.ts +71 -0
  153. package/scripts/copy-assets.js +30 -0
  154. package/scripts/pack.js +70 -0
  155. package/stores/Snapshots.ts +54 -0
  156. package/styles/colors.ts +67 -0
  157. package/styles/global.scss +29 -0
  158. package/styles/icons.tsx +1917 -0
  159. package/styles/mixins.scss +30 -0
  160. package/styles/styles.ts +87 -0
  161. package/styles/theme.ts +53 -0
  162. package/styles/vars.scss +43 -0
  163. package/styles/vars.ts +40 -0
  164. package/tsconfig.build.json +37 -0
  165. package/tsconfig.json +30 -0
  166. package/types/api/endpoints/createClone.ts +10 -0
  167. package/types/api/endpoints/destroyClone.ts +7 -0
  168. package/types/api/endpoints/getClone.ts +6 -0
  169. package/types/api/endpoints/getConfig.ts +6 -0
  170. package/types/api/endpoints/getEngine.ts +13 -0
  171. package/types/api/endpoints/getFullConfig.ts +4 -0
  172. package/types/api/endpoints/getInstance.ts +6 -0
  173. package/types/api/endpoints/getInstanceRetrieval.ts +6 -0
  174. package/types/api/endpoints/getSeImages.ts +22 -0
  175. package/types/api/endpoints/getSnapshots.ts +6 -0
  176. package/types/api/endpoints/getWSToken.ts +6 -0
  177. package/types/api/endpoints/initWS.ts +1 -0
  178. package/types/api/endpoints/refreshInstance.ts +4 -0
  179. package/types/api/endpoints/resetClone.ts +8 -0
  180. package/types/api/endpoints/testDbSource.ts +48 -0
  181. package/types/api/endpoints/updateClone.ts +10 -0
  182. package/types/api/endpoints/updateConfig.ts +6 -0
  183. package/types/api/entities/clone.ts +42 -0
  184. package/types/api/entities/config.ts +114 -0
  185. package/types/api/entities/dbSource.ts +13 -0
  186. package/types/api/entities/instance.ts +67 -0
  187. package/types/api/entities/instanceRetrieval.ts +46 -0
  188. package/types/api/entities/instanceState.ts +102 -0
  189. package/types/api/entities/pool.ts +27 -0
  190. package/types/api/entities/snapshot.ts +18 -0
  191. package/types/api/entities/wsToken.ts +7 -0
  192. package/types/byte-size/index.d.ts +22 -0
  193. package/utils/api.ts +30 -0
  194. package/utils/clone.ts +31 -0
  195. package/utils/connection.ts +38 -0
  196. package/utils/date.ts +87 -0
  197. package/utils/instance.ts +10 -0
  198. package/utils/numbers.ts +11 -0
  199. package/utils/react.ts +10 -0
  200. package/utils/snapshot.ts +4 -0
  201. package/utils/strings.ts +11 -0
  202. package/utils/units.ts +23 -0
@@ -0,0 +1,81 @@
1
+ /*--------------------------------------------------------------------------
2
+ * Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
3
+ * All Rights Reserved. Proprietary and confidential.
4
+ * Unauthorized copying of this file, via any medium is strictly prohibited
5
+ *--------------------------------------------------------------------------
6
+ */
7
+
8
+ import { makeStyles } from '@material-ui/styles'
9
+ import { observer } from 'mobx-react-lite'
10
+
11
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
12
+ import { ShieldIcon } from '@postgres.ai/shared/icons/Shield'
13
+ import { WarningIcon } from '@postgres.ai/shared/icons/Warning'
14
+
15
+ import { Section } from '../components/Section'
16
+ import { Property } from '../components/Property'
17
+ import { ValueStatus } from '../components/ValueStatus'
18
+
19
+ import { ConnectModal } from './ConnectModal'
20
+
21
+ const useStyles = makeStyles(
22
+ {
23
+ connectButton: {
24
+ marginTop: '10px',
25
+ },
26
+ url: {
27
+ overflowWrap: 'break-word',
28
+ },
29
+ icon: {
30
+ top: 0,
31
+ left: 0,
32
+ position: 'absolute',
33
+ height: '100%',
34
+ width: '100%',
35
+ },
36
+ },
37
+ { index: 1 },
38
+ )
39
+
40
+ const checkIsSecureUrl = (urlStr: string) => {
41
+ const url = new URL(urlStr)
42
+ return url.protocol === 'https:'
43
+ }
44
+
45
+ export const Connection = observer(() => {
46
+ const stores = useStores()
47
+ const classes = useStyles()
48
+
49
+ const { instance } = stores.main
50
+ if (!instance?.url) return null
51
+
52
+ const isSecureUrl = checkIsSecureUrl(instance.url) || instance.useTunnel
53
+
54
+ return (
55
+ <Section title="Connection">
56
+ <Property name="URL">
57
+ <span className={classes.url}>{instance.url}</span>
58
+ <br />
59
+ <ValueStatus
60
+ type={isSecureUrl ? 'ok' : 'warning'}
61
+ icon={
62
+ isSecureUrl ? (
63
+ <ShieldIcon className={classes.icon} />
64
+ ) : (
65
+ <WarningIcon className={classes.icon} />
66
+ )
67
+ }
68
+ >
69
+ The connection to Database Lab API is{' '}
70
+ {isSecureUrl ? 'secure' : 'not secure'}
71
+ </ValueStatus>
72
+ </Property>
73
+
74
+ <Property name="WS tunnels">
75
+ {instance.useTunnel ? 'used' : 'not used'}
76
+ </Property>
77
+
78
+ <ConnectModal className={classes.connectButton} />
79
+ </Section>
80
+ )
81
+ })
@@ -0,0 +1,20 @@
1
+ /*--------------------------------------------------------------------------
2
+ * Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
3
+ * All Rights Reserved. Proprietary and confidential.
4
+ * Unauthorized copying of this file, via any medium is strictly prohibited
5
+ *--------------------------------------------------------------------------
6
+ */
7
+
8
+ import React from 'react';
9
+
10
+ import { Section } from '../components/Section';
11
+ import { Property } from '../components/Property';
12
+
13
+ export const Details = () => {
14
+ return (
15
+ <Section title='Details'>
16
+ <Property name='Database docker image'>postgres:12</Property>
17
+ <Property name='Version'>0.4.4</Property>
18
+ </Section>
19
+ );
20
+ };
@@ -0,0 +1,100 @@
1
+ /*--------------------------------------------------------------------------
2
+ * Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
3
+ * All Rights Reserved. Proprietary and confidential.
4
+ * Unauthorized copying of this file, via any medium is strictly prohibited
5
+ *--------------------------------------------------------------------------
6
+ */
7
+
8
+ import React, { useState } from 'react'
9
+ import { IconButton, makeStyles, Menu, MenuItem } from '@material-ui/core'
10
+ import { MoreVert } from '@material-ui/icons'
11
+ import copy from 'copy-to-clipboard'
12
+
13
+ import { colors } from '@postgres.ai/shared/styles/colors'
14
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
15
+
16
+ type Props = {
17
+ poolId: string | null
18
+ poolName: string
19
+ isActive: boolean
20
+ }
21
+
22
+ const useStyles = makeStyles(
23
+ {
24
+ root: {
25
+ padding: '3px 1px',
26
+ border: `1px solid ${colors.consoleStroke}`,
27
+ borderRadius: '4px',
28
+ },
29
+ },
30
+ { index: 1 },
31
+ )
32
+
33
+ export const ActionsMenu = (props: Props) => {
34
+ const classes = useStyles()
35
+ const stores = useStores()
36
+
37
+ const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null)
38
+
39
+ const isOpen = Boolean(anchorEl)
40
+
41
+ const openMenu = (e: React.MouseEvent<HTMLButtonElement>) => {
42
+ e.stopPropagation()
43
+ setAnchorEl(e.currentTarget)
44
+ }
45
+
46
+ const closeMenu = () => setAnchorEl(null)
47
+
48
+ return (
49
+ <>
50
+ <IconButton className={classes.root} onClick={openMenu}>
51
+ <MoreVert />
52
+ </IconButton>
53
+
54
+ <Menu
55
+ anchorOrigin={{
56
+ vertical: 'top',
57
+ horizontal: 'left',
58
+ }}
59
+ transformOrigin={{
60
+ vertical: 'top',
61
+ horizontal: 'left',
62
+ }}
63
+ anchorEl={anchorEl}
64
+ keepMounted
65
+ open={isOpen}
66
+ onClose={closeMenu}
67
+ onClick={(e) => e.stopPropagation()}
68
+ >
69
+ <MenuItem
70
+ onClick={() => {
71
+ closeMenu()
72
+ copy(props.poolName)
73
+ }}
74
+ >
75
+ Copy name
76
+ </MenuItem>
77
+ {props.isActive && (
78
+ <div>
79
+ <MenuItem
80
+ onClick={() => {
81
+ closeMenu()
82
+ stores.clonesModal.openModal({ pool: props.poolId })
83
+ }}
84
+ >
85
+ List clones
86
+ </MenuItem>
87
+ <MenuItem
88
+ onClick={() => {
89
+ closeMenu()
90
+ stores.snapshotsModal.openModal({ pool: props.poolId })
91
+ }}
92
+ >
93
+ List snapshots
94
+ </MenuItem>
95
+ </div>
96
+ )}
97
+ </Menu>
98
+ </>
99
+ )
100
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react'
2
+ import { makeStyles } from '@material-ui/core'
3
+ import clsx from 'clsx'
4
+
5
+ import { CircleIcon } from '@postgres.ai/shared/icons/Circle'
6
+
7
+ type Props = {
8
+ className: string
9
+ }
10
+
11
+ const useStyles = makeStyles(
12
+ {
13
+ root: {
14
+ display: 'inline',
15
+ verticalAlign: 'middle',
16
+ width: '10px',
17
+ },
18
+ },
19
+ { index: 1 },
20
+ )
21
+
22
+ export const Marker = (props: Props) => {
23
+ const classes = useStyles()
24
+
25
+ return <CircleIcon className={clsx(classes.root, props.className)} />
26
+ }
@@ -0,0 +1,20 @@
1
+ export const PoinerIcon = ({
2
+ className,
3
+ style,
4
+ }: {
5
+ className?: string
6
+
7
+ style?: React.CSSProperties
8
+ }) => (
9
+ <svg
10
+ width="5"
11
+ height="14"
12
+ viewBox="0 0 5 14"
13
+ fill="none"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ style={style}
16
+ className={className}
17
+ >
18
+ <path d="M2.5 14L-2.06593e-07 -4.37114e-07L5 0L2.5 14Z" fill="#EE0202" />
19
+ </svg>
20
+ )
@@ -0,0 +1,73 @@
1
+ import { makeStyles } from '@material-ui/core'
2
+
3
+ import { colors } from '@postgres.ai/shared/styles/colors'
4
+ import { Tooltip } from '@postgres.ai/shared/components/Tooltip'
5
+
6
+ import { PoinerIcon } from './PointerIcon'
7
+
8
+ type Props = {
9
+ value: number
10
+ total: number
11
+ thresholdPercent: number
12
+ }
13
+
14
+ const useStyles = makeStyles(
15
+ (theme) => ({
16
+ '@keyframes grow': {
17
+ '0%': {
18
+ transform: 'scaleX(0)',
19
+ },
20
+ '100%': {
21
+ transform: 'scaleX(1)',
22
+ },
23
+ },
24
+ root: {
25
+ height: '12px',
26
+ position: 'relative',
27
+ borderRadius: '4px',
28
+ background: colors.gray,
29
+ overflow: 'hidden',
30
+ marginTop: '8px',
31
+ },
32
+ indicator: {
33
+ position: 'absolute',
34
+ top: 0,
35
+ left: 0,
36
+ height: '100%',
37
+ width: '30%',
38
+ background: colors.primary.light,
39
+ animation: `$grow 500ms ${theme.transitions.easing.easeOut}`,
40
+ transformOrigin: 0,
41
+ },
42
+ pointer: {
43
+ position: 'absolute',
44
+ height: '100%',
45
+ top: 0,
46
+ transform: 'translateX(-50%)',
47
+ },
48
+ }),
49
+ { index: 1 },
50
+ )
51
+
52
+ export const ProgressBar = (props: Props) => {
53
+ const classes = useStyles()
54
+
55
+ return (
56
+ <div className={classes.root}>
57
+ <div
58
+ className={classes.indicator}
59
+ style={{ width: `${(props.value / props.total) * 100}%` }}
60
+ />
61
+ <Tooltip
62
+ content={`+${props.thresholdPercent}% disk usage may result in performance degradation`}
63
+ >
64
+ <PoinerIcon
65
+ className={classes.pointer}
66
+ style={{
67
+ left: `${props.thresholdPercent}%`,
68
+ }}
69
+ />
70
+ </Tooltip>
71
+ </div>
72
+ )
73
+ }
@@ -0,0 +1,75 @@
1
+ import { makeStyles } from '@material-ui/core'
2
+
3
+ import { WarningIcon } from '@postgres.ai/shared/icons/Warning'
4
+ import { Tooltip } from '@postgres.ai/shared/components/Tooltip'
5
+ import { colors } from '@postgres.ai/shared/styles/colors'
6
+
7
+ export type Props = {
8
+ value: 'refreshing' | 'active' | 'empty'
9
+ hasWarning: boolean
10
+ }
11
+
12
+ const VALUE_TO_NAME: Record<Props['value'], string> = {
13
+ refreshing: 'Data refreshing',
14
+ active: 'Active',
15
+ empty: 'Empty',
16
+ }
17
+
18
+ const VALUE_TO_DESC: Record<Props['value'], string> = {
19
+ refreshing: 'Data retrieval is in progress',
20
+ active: 'Disk is ready to provision clones',
21
+ empty: 'Disk is emptied and ready for a data retrieval',
22
+ }
23
+
24
+ const useStyles = makeStyles(
25
+ {
26
+ root: {
27
+ display: 'flex',
28
+ color: colors.white,
29
+ },
30
+ warning: {
31
+ display: 'flex',
32
+ flex: '0 0 16px',
33
+ alignItems: 'center',
34
+ justifyContent: 'center',
35
+ marginRight: '4px',
36
+ height: '16px',
37
+ background: colors.state.warning,
38
+ borderRadius: '3px',
39
+ },
40
+ icon: {
41
+ height: '10px',
42
+ },
43
+ label: {
44
+ fontSize: '12px',
45
+ padding: '1px 6px',
46
+ borderRadius: '3px',
47
+ flex: '0 0 auto',
48
+ background: (props: Props) => {
49
+ if (props.value === 'refreshing') return colors.state.notice
50
+ if (props.value === 'active') return colors.state.ok
51
+ return colors.state.unknown
52
+ },
53
+ },
54
+ },
55
+ { index: 1 },
56
+ )
57
+
58
+ export const Status = (props: Props) => {
59
+ const { value, hasWarning } = props
60
+
61
+ const classes = useStyles(props)
62
+
63
+ return (
64
+ <div className={classes.root}>
65
+ {hasWarning && (
66
+ <div className={classes.warning}>
67
+ <WarningIcon className={classes.icon} />
68
+ </div>
69
+ )}
70
+ <Tooltip content={VALUE_TO_DESC[value]}>
71
+ <div className={classes.label}>{VALUE_TO_NAME[value]}</div>
72
+ </Tooltip>
73
+ </div>
74
+ )
75
+ }
@@ -0,0 +1,168 @@
1
+ import { makeStyles } from '@material-ui/core'
2
+ import { formatDistanceToNowStrict } from 'date-fns'
3
+
4
+ import { colors } from '@postgres.ai/shared/styles/colors'
5
+ import { formatBytesIEC } from '@postgres.ai/shared/utils/units'
6
+ import { Status as PerformanceStatus } from '@postgres.ai/shared/components/Status'
7
+ import { formatUTC } from '@postgres.ai/shared/utils/date'
8
+
9
+ import { Property } from '../../components/Property'
10
+ import { ActionsMenu } from './ActionsMenu'
11
+ import { Status } from './Status'
12
+ import { Marker } from './Marker'
13
+ import { ProgressBar } from './ProgressBar'
14
+
15
+ const WARNING_THRESHOLD_PERCENT = 80
16
+
17
+ type Props = {
18
+ id: string | null
19
+ name: string
20
+ totalDataSize: number
21
+ mode: string
22
+ refreshingStartDate: Date | null
23
+ clonesCount: number
24
+ snapshotsCount: number
25
+ usedDataSize: number
26
+ freeDataSize: number
27
+ status: 'refreshing' | 'active' | 'empty'
28
+ }
29
+
30
+ const useStyles = makeStyles(
31
+ {
32
+ root: {
33
+ border: `1px solid ${colors.consoleStroke}`,
34
+ padding: '6px 8px 8px',
35
+ borderRadius: '4px',
36
+
37
+ '& + $root': {
38
+ marginTop: '8px',
39
+ },
40
+ },
41
+ header: {
42
+ display: 'flex',
43
+ justifyContent: 'space-between',
44
+ alignItems: 'center',
45
+ },
46
+ titleWrapper: {
47
+ display: 'flex',
48
+ flex: '1 1 auto',
49
+ alignItems: 'center',
50
+ marginRight: '16px',
51
+ minWidth: 0,
52
+ },
53
+ title: {
54
+ fontWeight: 700,
55
+ fontSize: '14px',
56
+ margin: '0 4px 0 0',
57
+ whiteSpace: 'nowrap',
58
+ textOverflow: 'ellipsis',
59
+ overflow: 'hidden',
60
+ },
61
+ content: {
62
+ marginTop: '8px',
63
+ },
64
+ markerUsed: {
65
+ color: colors.primary.light,
66
+ },
67
+ markerFree: {
68
+ color: colors.gray,
69
+ },
70
+ warningMessage: {
71
+ fontSize: '10px',
72
+ marginTop: '6px',
73
+ },
74
+ uppercaseContent: {
75
+ textTransform: 'uppercase',
76
+ },
77
+ },
78
+ { index: 1 },
79
+ )
80
+
81
+ const getPercent = (value: number, total: number) =>
82
+ Math.round((value / total) * 100)
83
+
84
+ export const Disk = (props: Props) => {
85
+ const classes = useStyles()
86
+
87
+ const shouldShowWarning =
88
+ props.status === 'active' &&
89
+ getPercent(props.usedDataSize, props.totalDataSize) >
90
+ WARNING_THRESHOLD_PERCENT
91
+
92
+ return (
93
+ <div className={classes.root}>
94
+ <div className={classes.header}>
95
+ <div className={classes.titleWrapper}>
96
+ <h6 title={props.name} className={classes.title}>
97
+ {props.name}
98
+ </h6>
99
+ <ActionsMenu
100
+ poolId={props.id}
101
+ poolName={props.name}
102
+ isActive={props.status === 'active'}
103
+ />
104
+ </div>
105
+
106
+ <Status value={props.status} hasWarning={shouldShowWarning} />
107
+ </div>
108
+ <Property name="Mode" classes={{ content: classes.uppercaseContent }}>
109
+ {props.mode}
110
+ </Property>
111
+
112
+ {props.status === 'refreshing' && props.refreshingStartDate && (
113
+ <div className={classes.content}>
114
+ <Property name="Refreshing started at">
115
+ {formatUTC(props.refreshingStartDate, 'yyyy-MM-dd HH:mm:ss')} UTC (
116
+ {formatDistanceToNowStrict(props.refreshingStartDate, {
117
+ addSuffix: true,
118
+ })}
119
+ )
120
+ </Property>
121
+ </div>
122
+ )}
123
+ <div className={classes.content}>
124
+ <Property name="Clones">{props.clonesCount}</Property>
125
+ <Property name="Snapshots">{props.snapshotsCount}</Property>
126
+ </div>
127
+
128
+ <div className={classes.content}>
129
+ <Property name="Size">{formatBytesIEC(props.totalDataSize)}</Property>
130
+ <Property
131
+ name={
132
+ <>
133
+ Used&nbsp;
134
+ <Marker className={classes.markerUsed} />
135
+ </>
136
+ }
137
+ >
138
+ {formatBytesIEC(props.usedDataSize)} /{' '}
139
+ {getPercent(props.usedDataSize, props.totalDataSize)} %
140
+ </Property>
141
+ <Property
142
+ name={
143
+ <>
144
+ Free&nbsp;
145
+ <Marker className={classes.markerFree} />
146
+ </>
147
+ }
148
+ >
149
+ {formatBytesIEC(props.freeDataSize)} /{' '}
150
+ {getPercent(props.freeDataSize, props.totalDataSize)} %
151
+ </Property>
152
+ </div>
153
+
154
+ <ProgressBar
155
+ value={props.usedDataSize}
156
+ total={props.totalDataSize}
157
+ thresholdPercent={WARNING_THRESHOLD_PERCENT}
158
+ />
159
+
160
+ {shouldShowWarning && (
161
+ <PerformanceStatus type="warning" className={classes.warningMessage}>
162
+ +{WARNING_THRESHOLD_PERCENT}% disk usage may result in performance
163
+ degradation
164
+ </PerformanceStatus>
165
+ )}
166
+ </div>
167
+ )
168
+ }
@@ -0,0 +1,65 @@
1
+ /*--------------------------------------------------------------------------
2
+ * Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
3
+ * All Rights Reserved. Proprietary and confidential.
4
+ * Unauthorized copying of this file, via any medium is strictly prohibited
5
+ *--------------------------------------------------------------------------
6
+ */
7
+
8
+ import { observer } from 'mobx-react-lite'
9
+
10
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
11
+
12
+ import { Section } from '../components/Section'
13
+
14
+ import { Disk } from './Disk'
15
+
16
+ export const Disks = observer(() => {
17
+ const stores = useStores()
18
+
19
+ const { instance, snapshots } = stores.main
20
+ if (!instance) return null
21
+ if (!snapshots) return null
22
+
23
+ return (
24
+ <Section title="Disks">
25
+ {instance.state?.pools?.map((pool) => {
26
+ return (
27
+ <Disk
28
+ key={pool.name}
29
+ status={pool.status}
30
+ name={pool.name}
31
+ id={pool.name}
32
+ mode={pool.mode}
33
+ clonesCount={pool.cloneList.length}
34
+ snapshotsCount={
35
+ snapshots.data?.filter((snapshot) => snapshot.pool === pool.name)
36
+ .length ?? 0
37
+ }
38
+ totalDataSize={pool.fileSystem.size}
39
+ usedDataSize={pool.fileSystem.used}
40
+ freeDataSize={pool.fileSystem.free}
41
+ refreshingStartDate={instance.state?.retrieving?.lastRefresh ?? null}
42
+ />
43
+ )
44
+ }) ??
45
+ (instance.state?.fileSystem && (
46
+ <Disk
47
+ status={'active'}
48
+ name={'Main'}
49
+ id={null}
50
+ mode="ZFS"
51
+ clonesCount={instance.state?.clones?.length ?? instance.state.cloning.clones.length}
52
+ snapshotsCount={snapshots.data?.length ?? 0}
53
+ totalDataSize={instance.state.fileSystem.size}
54
+ usedDataSize={instance.state.fileSystem.used}
55
+ freeDataSize={instance.state.fileSystem.free}
56
+ refreshingStartDate={null}
57
+ />
58
+ )) ?? (
59
+ <>
60
+ Disk information is <strong>unavailable</strong>.
61
+ </>
62
+ )}
63
+ </Section>
64
+ )
65
+ })
@@ -0,0 +1,39 @@
1
+ export const ArrowLeft = ({ className }: { className?: string }) => (
2
+ <svg
3
+ width="20"
4
+ height="21"
5
+ viewBox="0 0 20 21"
6
+ fill="none"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ className={className}
9
+ >
10
+ <path
11
+ d="M0.307554 9.50891L9.50896 0.307513C9.91902 -0.102504 10.583 -0.102504 10.9931 0.307513C11.4031 0.7172 11.4031 1.38195 10.9931 1.79163L2.53369 10.251L10.993 18.7103C11.403 19.12 11.403 19.7847 10.993 20.1944C10.788 20.3995 10.5196 20.502 10.251 20.502C9.98229 20.502 9.71356 20.3995 9.50891 20.1944L0.307507 10.993C-0.102512 10.5833 -0.10251 9.9186 0.307554 9.50891Z"
12
+ fill="white"
13
+ />
14
+ <path
15
+ d="M9.00696 9.50891L18.2084 0.307513C18.6181 -0.102504 19.2828 -0.102504 19.6925 0.307513C20.1025 0.7172 20.1025 1.38195 19.6925 1.79163L11.2335 10.251L19.6924 18.7103C20.1025 19.12 20.1025 19.7847 19.6924 20.1944C19.4878 20.3995 19.2191 20.502 18.9504 20.502C18.6817 20.502 18.413 20.3995 18.2083 20.1944L9.00692 10.993C8.59695 10.5833 8.59695 9.9186 9.00696 9.50891Z"
16
+ fill="white"
17
+ />
18
+ </svg>
19
+ )
20
+
21
+ export const ArrowRight = ({ className }: { className?: string }) => (
22
+ <svg
23
+ width="21"
24
+ height="21"
25
+ viewBox="0 0 21 21"
26
+ fill="none"
27
+ xmlns="http://www.w3.org/2000/svg"
28
+ className={className}
29
+ >
30
+ <path
31
+ d="M20.211 9.5089L10.8896 0.307513C10.4742 -0.102504 9.80151 -0.102504 9.38609 0.307513C8.97073 0.717199 8.97073 1.38195 9.38609 1.79163L17.9558 10.251L9.38614 18.7103C8.97078 19.12 8.97078 19.7847 9.38614 20.1944C9.59385 20.3994 9.8657 20.502 10.1379 20.502C10.4101 20.502 10.6823 20.3994 10.8896 20.1944L20.211 10.993C20.6264 10.5833 20.6264 9.91859 20.211 9.5089Z"
32
+ fill="white"
33
+ />
34
+ <path
35
+ d="M11.3981 9.5089L2.07672 0.307513C1.66169 -0.102504 0.988271 -0.102504 0.573242 0.307513C0.157878 0.717199 0.157878 1.38195 0.573242 1.79163L9.14256 10.251L0.57329 18.7103C0.157926 19.12 0.157926 19.7847 0.57329 20.1944C0.780613 20.3994 1.05284 20.502 1.32503 20.502C1.59721 20.502 1.86944 20.3994 2.07677 20.1944L11.3982 10.993C11.8135 10.5833 11.8135 9.91859 11.3981 9.5089Z"
36
+ fill="white"
37
+ />
38
+ </svg>
39
+ )