@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,129 @@
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 cn from 'classnames'
9
+ import { useState } from 'react'
10
+ import { makeStyles } from '@material-ui/core'
11
+
12
+ import { Button } from '@postgres.ai/shared/components/MenuButton'
13
+ import { useWindowDimensions } from '@postgres.ai/shared/hooks/useWindowDimensions'
14
+ import { ArrowLeft, ArrowRight } from '@postgres.ai/shared/pages/Instance/Info/Icons'
15
+
16
+ import { Status } from './Status'
17
+ import { Retrieval } from './Retrieval'
18
+ import { Connection } from './Connection'
19
+ import { Disks } from './Disks'
20
+ import { Snapshots } from './Snapshots'
21
+
22
+ const SIDEBAR_COLLAPSED_PARAM = 'overviewSidebarCollapsed'
23
+ const SMALL_BREAKPOINT_PX = 937
24
+
25
+ const useStyles = makeStyles(
26
+ (theme) => ({
27
+ container: {
28
+ minHeight: 0,
29
+ minWidth: 0,
30
+ width: '437px',
31
+ transition: 'width 0.2s ease-out',
32
+
33
+ [theme.breakpoints.down('sm')]: {
34
+ width: '100%',
35
+ },
36
+ },
37
+ root: {
38
+ flex: '0 0 auto',
39
+
40
+ [theme.breakpoints.down('md')]: {
41
+ width: '300px',
42
+ },
43
+
44
+ [theme.breakpoints.down('sm')]: {
45
+ flex: '0 0 auto',
46
+ width: '100%',
47
+ marginTop: '20px',
48
+ },
49
+ },
50
+ collapsed: {
51
+ height: '100%',
52
+ width: '64px',
53
+ },
54
+ collapseBtn: {
55
+ background: '#f9f9f9 !important',
56
+ margin: '20px 0 10px 0',
57
+ fontWeight: 500,
58
+
59
+ '& svg': {
60
+ marginRight: '5px',
61
+ },
62
+
63
+ '&:hover': {
64
+ background: '#f1f1f1',
65
+ },
66
+ },
67
+ arrowImage: {
68
+ width: '16px',
69
+ height: '16px',
70
+
71
+ '& path': {
72
+ fill: '#000',
73
+ },
74
+ },
75
+ }),
76
+ { index: 1 },
77
+ )
78
+
79
+ export const Info = () => {
80
+ const classes = useStyles()
81
+ const width = useWindowDimensions()
82
+ const isMobileScreen = width <= SMALL_BREAKPOINT_PX
83
+
84
+ const [isCollapsed, setIsCollapsed] = useState(
85
+ () =>
86
+ localStorage.getItem(SIDEBAR_COLLAPSED_PARAM) === '1' && !isMobileScreen,
87
+ )
88
+
89
+ const handleClick = () => {
90
+ setIsCollapsed(!isCollapsed)
91
+ localStorage.setItem(SIDEBAR_COLLAPSED_PARAM, isCollapsed ? '0' : '1')
92
+ }
93
+
94
+ return (
95
+ <div
96
+ className={cn(
97
+ classes.container,
98
+ !isCollapsed ? classes.root : classes.collapsed,
99
+ )}
100
+ >
101
+ {!isMobileScreen && (
102
+ <Button
103
+ className={classes.collapseBtn}
104
+ onClick={handleClick}
105
+ isCollapsed={isCollapsed}
106
+ icon={
107
+ isCollapsed ? (
108
+ <ArrowLeft className={classes.arrowImage} />
109
+ ) : (
110
+ <ArrowRight className={classes.arrowImage} />
111
+ )
112
+ }
113
+ >
114
+ Collapse
115
+ </Button>
116
+ )}
117
+
118
+ {!isCollapsed && (
119
+ <div>
120
+ <Status />
121
+ <Retrieval />
122
+ <Connection />
123
+ <Disks />
124
+ <Snapshots />
125
+ </div>
126
+ )}
127
+ </div>
128
+ )
129
+ }
@@ -0,0 +1,169 @@
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
+ import { makeStyles } from '@material-ui/core'
10
+ import { formatDistanceToNowStrict } from 'date-fns'
11
+ import copy from 'copy-to-clipboard'
12
+
13
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
14
+ import { ArrowDropDownIcon } from '@postgres.ai/shared/icons/ArrowDropDown'
15
+ import { Modal as ModalBase } from '@postgres.ai/shared/components/Modal'
16
+ import { HorizontalScrollContainer } from '@postgres.ai/shared/components/HorizontalScrollContainer'
17
+ import {
18
+ Table,
19
+ TableHead,
20
+ TableRow,
21
+ TableBody,
22
+ TableHeaderCell,
23
+ TableBodyCell,
24
+ TableBodyCellMenu,
25
+ } from '@postgres.ai/shared/components/Table'
26
+ import { formatBytesIEC } from '@postgres.ai/shared/utils/units'
27
+ import { isSameDayUTC } from '@postgres.ai/shared/utils/date'
28
+
29
+ import { Tags } from '@postgres.ai/shared/pages/Instance/components/Tags'
30
+ import { ModalReloadButton } from '@postgres.ai/shared/pages/Instance/components/ModalReloadButton'
31
+
32
+ import { getTags } from './utils'
33
+
34
+ const useStyles = makeStyles(
35
+ {
36
+ root: {
37
+ fontSize: '14px',
38
+ marginTop: 0,
39
+ display: 'block',
40
+ },
41
+ container: {
42
+ maxHeight: '400px',
43
+ },
44
+ cellContentCentered: {
45
+ display: 'flex',
46
+ alignItems: 'center',
47
+ },
48
+ sortIcon: {
49
+ marginLeft: '8px',
50
+ width: '10px',
51
+ },
52
+ emptyStub: {
53
+ marginTop: '16px',
54
+ },
55
+ },
56
+ { index: 1 },
57
+ )
58
+
59
+ export const SnapshotsModal = observer(() => {
60
+ const classes = useStyles()
61
+ const stores = useStores()
62
+
63
+ const { snapshots } = stores.main
64
+ if (!snapshots.data) return null
65
+
66
+ const filteredSnapshots = snapshots.data.filter((snapshot) => {
67
+ const isMatchedByDate =
68
+ !stores.snapshotsModal.date ||
69
+ isSameDayUTC(snapshot.dataStateAtDate, stores.snapshotsModal.date)
70
+
71
+ const isMatchedByPool =
72
+ !stores.snapshotsModal.pool ||
73
+ snapshot.pool === stores.snapshotsModal.pool
74
+
75
+ return isMatchedByDate && isMatchedByPool
76
+ })
77
+
78
+ const isEmpty = !filteredSnapshots.length
79
+
80
+ return (
81
+ <ModalBase
82
+ isOpen={stores.snapshotsModal.isOpenModal}
83
+ onClose={stores.snapshotsModal.closeModal}
84
+ title={`Snapshots (${filteredSnapshots.length})`}
85
+ classes={{ content: classes.root }}
86
+ size="md"
87
+ titleRightContent={
88
+ <ModalReloadButton
89
+ isReloading={stores.main.snapshots.isLoading}
90
+ onReload={stores.main.reloadSnapshots}
91
+ />
92
+ }
93
+ headerContent={
94
+ <Tags
95
+ data={getTags({
96
+ date: stores.snapshotsModal.date,
97
+ pool: stores.snapshotsModal.pool,
98
+ })}
99
+ />
100
+ }
101
+ >
102
+ {isEmpty && <p className={classes.emptyStub}>No snapshots found</p>}
103
+
104
+ {!isEmpty && (
105
+ <HorizontalScrollContainer classes={{ content: classes.container }}>
106
+ <Table>
107
+ <TableHead>
108
+ <TableRow>
109
+ <TableHeaderCell />
110
+ <TableHeaderCell>Data state time</TableHeaderCell>
111
+ <TableHeaderCell>
112
+ <div className={classes.cellContentCentered}>
113
+ Created
114
+ <ArrowDropDownIcon className={classes.sortIcon} />
115
+ </div>
116
+ </TableHeaderCell>
117
+ <TableHeaderCell>Disk</TableHeaderCell>
118
+ <TableHeaderCell>Size</TableHeaderCell>
119
+ </TableRow>
120
+ </TableHead>
121
+ <TableBody>
122
+ {filteredSnapshots.map((snapshot) => {
123
+ return (
124
+ <TableRow key={snapshot.id}>
125
+ <TableBodyCellMenu
126
+ actions={[
127
+ {
128
+ name: 'Copy snapshot ID',
129
+ onClick: () => copy(snapshot.id),
130
+ },
131
+ {
132
+ name: 'Show related clones',
133
+ onClick: () =>
134
+ stores.clonesModal.openModal({
135
+ snapshotId: snapshot.id,
136
+ }),
137
+ },
138
+ ]}
139
+ />
140
+ <TableBodyCell>
141
+ {snapshot.dataStateAt} (
142
+ {formatDistanceToNowStrict(snapshot.dataStateAtDate, {
143
+ addSuffix: true,
144
+ })}
145
+ )
146
+ </TableBodyCell>
147
+ <TableBodyCell>
148
+ {snapshot.createdAt} (
149
+ {formatDistanceToNowStrict(snapshot.createdAtDate, {
150
+ addSuffix: true,
151
+ })}
152
+ )
153
+ </TableBodyCell>
154
+ <TableBodyCell>{snapshot.pool ?? '-'}</TableBodyCell>
155
+ <TableBodyCell>
156
+ {snapshot.physicalSize
157
+ ? formatBytesIEC(snapshot.physicalSize)
158
+ : '-'}
159
+ </TableBodyCell>
160
+ </TableRow>
161
+ )
162
+ })}
163
+ </TableBody>
164
+ </Table>
165
+ </HorizontalScrollContainer>
166
+ )}
167
+ </ModalBase>
168
+ )
169
+ })
@@ -0,0 +1,17 @@
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 { formatUTC } from '@postgres.ai/shared/utils/date'
9
+
10
+ export const getTags = ({ date, pool }: { date: Date | null, pool: string | null }) => {
11
+ const tags = []
12
+
13
+ if (date) tags.push({ name: 'Date', value: `${formatUTC(date, 'yyyy-MM-dd')} UTC` })
14
+ if (pool) tags.push({ name: 'Disk', value: pool })
15
+
16
+ return tags
17
+ }
@@ -0,0 +1,98 @@
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
+ import {
10
+ makeStyles,
11
+ Tab as TabComponent,
12
+ Tabs as TabsComponent,
13
+ } from '@material-ui/core'
14
+ import { colors } from '@postgres.ai/shared/styles/colors'
15
+
16
+ const useStyles = makeStyles(
17
+ {
18
+ tabsRoot: {
19
+ minHeight: 0,
20
+ marginTop: '-8px',
21
+ },
22
+ tabsIndicator: {
23
+ height: '3px',
24
+ },
25
+ tabRoot: {
26
+ fontWeight: 400,
27
+ minWidth: 0,
28
+ minHeight: 0,
29
+ padding: '6px 16px',
30
+ borderBottom: `3px solid ${colors.consoleStroke}`,
31
+
32
+ '& + $tabRoot': {
33
+ marginLeft: '10px',
34
+ },
35
+
36
+ '&.Mui-disabled': {
37
+ opacity: 1,
38
+ color: colors.pgaiDarkGray,
39
+ },
40
+ },
41
+ tabHidden: {
42
+ display: 'none',
43
+ },
44
+ },
45
+ { index: 1 },
46
+ )
47
+
48
+ type Props = {
49
+ value: number
50
+ handleChange: (event: React.ChangeEvent<{}>, newValue: number) => void
51
+ hasLogs: boolean
52
+ isPlatform?: boolean
53
+ }
54
+
55
+ export const Tabs = (props: Props) => {
56
+ const classes = useStyles()
57
+
58
+ const { value, handleChange, hasLogs } = props
59
+
60
+ return (
61
+ <TabsComponent
62
+ value={value}
63
+ onChange={handleChange}
64
+ classes={{ root: classes.tabsRoot, indicator: classes.tabsIndicator }}
65
+ >
66
+ <TabComponent
67
+ label="Overview"
68
+ classes={{
69
+ root: classes.tabRoot,
70
+ }}
71
+ value={0}
72
+ />
73
+ <TabComponent
74
+ label="Logs"
75
+ disabled={!hasLogs}
76
+ classes={{
77
+ root: props.isPlatform ? classes.tabHidden : classes.tabRoot,
78
+ }}
79
+ value={1}
80
+ />
81
+ <TabComponent
82
+ label="Configuration"
83
+ classes={{
84
+ root: props.isPlatform ? classes.tabHidden : classes.tabRoot,
85
+ }}
86
+ value={2}
87
+ />
88
+ {/* // TODO(Anton): Probably will be later. */}
89
+ {/* <TabComponent
90
+ label='Snapshots'
91
+ disabled
92
+ classes={{
93
+ root: classes.tabRoot
94
+ }}
95
+ /> */}
96
+ </TabsComponent>
97
+ )
98
+ }
@@ -0,0 +1,196 @@
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
+ import { makeStyles, IconButton } from '@material-ui/core'
10
+ import copy from 'copy-to-clipboard'
11
+
12
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
13
+ import { Tooltip } from '@postgres.ai/shared/components/Tooltip'
14
+ import { Modal } from '@postgres.ai/shared/components/Modal'
15
+ import { TextField } from '@postgres.ai/shared/components/TextField'
16
+ import { icons } from '@postgres.ai/shared/styles/icons'
17
+ import {
18
+ getSshPortForwardingCommand,
19
+ getPsqlConnectionStr,
20
+ getJdbcConnectionStr,
21
+ } from '@postgres.ai/shared/utils/connection'
22
+
23
+ type Props = {
24
+ isOpen: boolean
25
+ onClose: () => void
26
+ cloneId: string
27
+ }
28
+
29
+ const useStyles = makeStyles(
30
+ {
31
+ root: {
32
+ fontSize: '14px',
33
+ },
34
+ item: {
35
+ '& + $item': {
36
+ marginTop: '16px',
37
+ },
38
+ },
39
+ fieldText: {
40
+ margin: 0,
41
+ },
42
+ field: {
43
+ width: 'calc(100% - 24px)',
44
+ margin: '16px 0 0 0',
45
+ },
46
+ fieldWrapper: {
47
+ display: 'flex',
48
+ alignItems: 'flex-end',
49
+ },
50
+ fieldInfo: {
51
+ display: 'flex',
52
+ alignItems: 'center',
53
+ height: '32px',
54
+ marginLeft: '12px',
55
+ },
56
+ copyButton: {
57
+ width: '32px',
58
+ height: '32px',
59
+ padding: '8px',
60
+ },
61
+ note: {
62
+ margin: '24px 0 0 0',
63
+ fontSize: '12px',
64
+ },
65
+ },
66
+ { index: 1 },
67
+ )
68
+
69
+ export const ConnectionModal = observer((props: Props) => {
70
+ const { isOpen, onClose, cloneId } = props
71
+
72
+ const classes = useStyles()
73
+
74
+ const stores = useStores()
75
+
76
+ const { instance } = stores.main
77
+ if (!instance) return null
78
+
79
+ const clone = instance.state?.cloning.clones.find(
80
+ (clone) => clone.id === cloneId,
81
+ )
82
+ if (!clone) return null
83
+
84
+ const sshPortForwardingCommand = getSshPortForwardingCommand(instance, clone)
85
+ const psqlConnectionStr = getPsqlConnectionStr(clone)
86
+ const jdbcConnectionStr = getJdbcConnectionStr(clone)
87
+
88
+ return (
89
+ <Modal title="Clone connection info" isOpen={isOpen} onClose={onClose}>
90
+ <div className={classes.root}>
91
+ {sshPortForwardingCommand && (
92
+ <div className={classes.item}>
93
+ <p className={classes.fieldText}>
94
+ In a separate console, set up SSH port forwarding
95
+ <br />
96
+ (and keep it running):
97
+ </p>
98
+ <TextField
99
+ label="SSH port forwarding"
100
+ value={sshPortForwardingCommand}
101
+ className={classes.field}
102
+ InputProps={{
103
+ endAdornment: (
104
+ <IconButton
105
+ className={classes.copyButton}
106
+ onClick={() => copy(sshPortForwardingCommand)}
107
+ >
108
+ {icons.copyIcon}
109
+ </IconButton>
110
+ ),
111
+ }}
112
+ />
113
+ </div>
114
+ )}
115
+
116
+ {psqlConnectionStr && (
117
+ <div className={classes.item}>
118
+ <p className={classes.fieldText}>Connect to Postgres using psql:</p>
119
+ <div className={classes.fieldWrapper}>
120
+ <TextField
121
+ label="psql connection string"
122
+ value={psqlConnectionStr}
123
+ className={classes.field}
124
+ InputProps={{
125
+ endAdornment: (
126
+ <IconButton
127
+ className={classes.copyButton}
128
+ onClick={() => copy(psqlConnectionStr)}
129
+ >
130
+ {icons.copyIcon}
131
+ </IconButton>
132
+ ),
133
+ }}
134
+ />
135
+
136
+ <Tooltip
137
+ content={
138
+ <>
139
+ Used to connect to Postgres using psql. Change DBNAME
140
+ to&nbsp; name of the database you want to connect. Use
141
+ PGPASSWORD&nbsp; environment variable to set database
142
+ password or type&nbsp; it when prompted.
143
+ </>
144
+ }
145
+ >
146
+ <span className={classes.fieldInfo}>{icons.infoIcon}</span>
147
+ </Tooltip>
148
+ </div>
149
+ </div>
150
+ )}
151
+
152
+ {jdbcConnectionStr && (
153
+ <div className={classes.item}>
154
+ <p className={classes.fieldText}>Connect to Postgres using JDBC:</p>
155
+ <div className={classes.fieldWrapper}>
156
+ <TextField
157
+ label="JDBC connection string"
158
+ value={jdbcConnectionStr}
159
+ className={classes.field}
160
+ InputProps={{
161
+ endAdornment: (
162
+ <IconButton
163
+ className={classes.copyButton}
164
+ onClick={() => copy(jdbcConnectionStr)}
165
+ >
166
+ {icons.copyIcon}
167
+ </IconButton>
168
+ ),
169
+ }}
170
+ />
171
+
172
+ <Tooltip
173
+ content={
174
+ <>
175
+ Used to connect to Postgres using JDBC. Change DBNAME
176
+ to&nbsp; name of the database you want to connect, change
177
+ DBPASSWORD&nbsp; to the password you’ve used on clone
178
+ creation.
179
+ </>
180
+ }
181
+ >
182
+ <span className={classes.fieldInfo}>{icons.infoIcon}</span>
183
+ </Tooltip>
184
+ </div>
185
+ </div>
186
+ )}
187
+
188
+ <p className={classes.note}>
189
+ Password was set during clone creation. It’s not being stored.
190
+ <br />
191
+ You would need to recreate a clone if the password is lost.
192
+ </p>
193
+ </div>
194
+ </Modal>
195
+ )
196
+ })
@@ -0,0 +1,98 @@
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 { useState } from 'react'
9
+ import { observer } from 'mobx-react-lite'
10
+
11
+ import { Clone } from '@postgres.ai/shared/types/api/entities/clone'
12
+ import { useStores } from '@postgres.ai/shared/pages/Instance/context'
13
+ import { TableBodyCellMenu } from '@postgres.ai/shared/components/Table'
14
+
15
+ import { DestroyCloneModal } from '@postgres.ai/shared/components/DestroyCloneModal'
16
+ import { DestroyCloneRestrictionModal } from '@postgres.ai/shared/components/DestroyCloneRestrictionModal'
17
+ import { ResetCloneModal } from '@postgres.ai/shared/components/ResetCloneModal'
18
+
19
+ type Props = {
20
+ clone: Clone
21
+ onConnect: (cloneId: string) => void
22
+ clonePagePath: string
23
+ }
24
+
25
+ export const MenuCell = observer((props: Props) => {
26
+ const { clone, onConnect, clonePagePath } = props
27
+
28
+ const stores = useStores()
29
+
30
+ const [
31
+ isOpenCloneDestroyRestrictionModal,
32
+ setIsOpenCloneDestroyRestrictionModal,
33
+ ] = useState(false)
34
+
35
+ const [isOpenCloneDestroyModal, setIsOpenCloneDestroyModal] = useState(false)
36
+
37
+ const [isOpenResetCloneModal, setIsOpenResetCloneModal] = useState(false)
38
+
39
+ const handleClickDestroyClone = () => {
40
+ if (clone.protected) return setIsOpenCloneDestroyRestrictionModal(true)
41
+ setIsOpenCloneDestroyModal(true)
42
+ }
43
+
44
+ const handleClickResetClone = async () => {
45
+ setIsOpenResetCloneModal(true)
46
+ }
47
+
48
+ const isLoading = stores.main.unstableClones.has(clone.id)
49
+
50
+ if (!stores.main.instance) return null
51
+
52
+ const hasSnapshots = Boolean(stores.main.snapshots.data?.length)
53
+
54
+ return (
55
+ <TableBodyCellMenu
56
+ isLoading={isLoading}
57
+ isDisabled={stores.main.isDisabledInstance}
58
+ actions={[
59
+ {
60
+ name: 'Connect',
61
+ onClick: () => onConnect(clone.id),
62
+ },
63
+ {
64
+ name: 'Destroy clone',
65
+ onClick: handleClickDestroyClone,
66
+ },
67
+ {
68
+ name: 'Reset clone',
69
+ onClick: handleClickResetClone,
70
+ isDisabled: !hasSnapshots,
71
+ },
72
+ ]}
73
+ >
74
+ <DestroyCloneRestrictionModal
75
+ cloneId={clone.id}
76
+ isOpen={isOpenCloneDestroyRestrictionModal}
77
+ onClose={() => setIsOpenCloneDestroyRestrictionModal(false)}
78
+ clonePagePath={clonePagePath}
79
+ />
80
+ <DestroyCloneModal
81
+ cloneId={clone.id}
82
+ isOpen={isOpenCloneDestroyModal}
83
+ onClose={() => setIsOpenCloneDestroyModal(false)}
84
+ onDestroyClone={() => stores.main.destroyClone(clone.id)}
85
+ />
86
+ <ResetCloneModal
87
+ clone={clone}
88
+ snapshots={stores.main.snapshots.data}
89
+ isOpen={isOpenResetCloneModal}
90
+ onClose={() => setIsOpenResetCloneModal(false)}
91
+ onResetClone={(snapshotId) =>
92
+ stores.main.resetClone(clone.id, snapshotId)
93
+ }
94
+ version={stores.main.instance.state?.engine.version}
95
+ />
96
+ </TableBodyCellMenu>
97
+ )
98
+ })