@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,634 @@
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 { useEffect, useState } from 'react'
9
+ import copyToClipboard from 'copy-to-clipboard'
10
+ import { observer } from 'mobx-react-lite'
11
+ import { useHistory } from 'react-router-dom'
12
+ import {
13
+ makeStyles,
14
+ TextField,
15
+ Button,
16
+ FormControlLabel,
17
+ Checkbox,
18
+ IconButton,
19
+ } from '@material-ui/core'
20
+
21
+ import {
22
+ getSshPortForwardingCommand,
23
+ getPsqlConnectionStr,
24
+ getJdbcConnectionStr,
25
+ } from '@postgres.ai/shared/utils/connection'
26
+ import { formatBytesIEC } from '@postgres.ai/shared/utils/units'
27
+ import { ErrorStub } from '@postgres.ai/shared/components/ErrorStub'
28
+ import { PageSpinner } from '@postgres.ai/shared/components/PageSpinner'
29
+ import { DestroyCloneRestrictionModal } from '@postgres.ai/shared/components/DestroyCloneRestrictionModal'
30
+ import { DestroyCloneModal } from '@postgres.ai/shared/components/DestroyCloneModal'
31
+ import { ResetCloneModal } from '@postgres.ai/shared/components/ResetCloneModal'
32
+ import { Spinner } from '@postgres.ai/shared/components/Spinner'
33
+ import { round } from '@postgres.ai/shared/utils/numbers'
34
+ import { Tooltip } from '@postgres.ai/shared/components/Tooltip'
35
+ import { SectionTitle } from '@postgres.ai/shared/components/SectionTitle'
36
+ import { icons } from '@postgres.ai/shared/styles/icons'
37
+ import { styles } from '@postgres.ai/shared/styles/styles'
38
+
39
+ import { Status } from './Status'
40
+ import { useCreatedStores } from './useCreatedStores'
41
+ import { Host } from './context'
42
+
43
+ const textFieldWidth = 400
44
+
45
+ const useStyles = makeStyles(
46
+ (theme) => ({
47
+ title: {
48
+ marginTop: '16px',
49
+ },
50
+ container: {
51
+ maxWidth: '425px',
52
+ marginTop: '16px',
53
+ },
54
+ text: {
55
+ marginTop: '4px',
56
+ },
57
+ errorStub: {
58
+ marginTop: '24px',
59
+ },
60
+ spinner: {
61
+ marginLeft: '8px',
62
+ },
63
+ summary: {
64
+ marginTop: 20,
65
+ },
66
+ paramTitle: {
67
+ display: 'inline-block',
68
+ width: 200,
69
+ },
70
+ readyStatus: {
71
+ color: 'green',
72
+ },
73
+ failedStatus: {
74
+ color: 'red',
75
+ },
76
+ startingStatus: {
77
+ color: 'orange',
78
+ },
79
+ fieldBlock: {
80
+ width: '100%',
81
+ maxWidth: textFieldWidth + 25,
82
+ position: 'relative',
83
+ },
84
+ saveButton: {
85
+ padding: 8,
86
+ marginLeft: 10,
87
+ marginBottom: -56,
88
+ },
89
+ actions: {
90
+ display: 'flex',
91
+ marginRight: '-16px',
92
+ },
93
+ actionButton: {
94
+ marginRight: '16px',
95
+ },
96
+ remark: {
97
+ fontSize: '12px',
98
+ lineHeight: '14px',
99
+ maxWidth: textFieldWidth,
100
+ display: 'inline-block',
101
+ },
102
+ textField: {
103
+ ...styles.inputField,
104
+ 'max-width': textFieldWidth,
105
+ display: 'inline-block',
106
+ '& .MuiOutlinedInput-input': {
107
+ paddingRight: '32px!important',
108
+ },
109
+ },
110
+ errorMessage: {
111
+ color: 'red',
112
+ marginBottom: 10,
113
+ },
114
+ textFieldInfo: {
115
+ position: 'absolute',
116
+ top: '25px',
117
+ marginLeft: '5px',
118
+ display: 'inline-block',
119
+ [theme.breakpoints.down('sm')]: {
120
+ display: 'none',
121
+ },
122
+ },
123
+ checkBoxInfo: {
124
+ 'margin-top': '0px',
125
+ 'margin-left': '3px',
126
+ display: 'inline-block',
127
+ '& svg': {
128
+ verticalAlign: 'middle',
129
+ },
130
+ },
131
+ checkboxLabel: {
132
+ marginRight: '0px',
133
+ },
134
+ copyFieldContainer: {
135
+ position: 'relative',
136
+ display: 'inline-block',
137
+ maxWidth: textFieldWidth,
138
+ width: '100%',
139
+ },
140
+ copyButton: {
141
+ position: 'absolute',
142
+ top: 16,
143
+ right: 0,
144
+ zIndex: 100,
145
+ width: 32,
146
+ height: 32,
147
+ padding: 8,
148
+ },
149
+ status: {
150
+ maxWidth: `${textFieldWidth}px`,
151
+ },
152
+ }),
153
+ { index: 1 },
154
+ )
155
+
156
+ type Props = Host
157
+
158
+ export const Clone = observer((props: Props) => {
159
+ const classes = useStyles()
160
+ const history = useHistory()
161
+ const stores = useCreatedStores(props)
162
+
163
+ // Clone modals.
164
+ const [isOpenRestrictionModal, setIsOpenRestrictionModal] = useState(false)
165
+ const [isOpenDestroyModal, setIsOpenDestroyModal] = useState(false)
166
+ const [isOpenResetModal, setIsOpenResetModal] = useState(false)
167
+
168
+ // Initial loading data.
169
+ useEffect(() => {
170
+ stores.main.load(props.instanceId, props.cloneId)
171
+ }, [])
172
+
173
+ const {
174
+ instance,
175
+ clone,
176
+ isResettingClone,
177
+ isDestroyingClone,
178
+ isReloading,
179
+ isUpdatingClone,
180
+ isCloneStable,
181
+ } = stores.main
182
+
183
+ const headRendered = (
184
+ <>
185
+ {/* //TODO(Anton): make global reset styles. */}
186
+ <style>{'p { margin: 0;}'}</style>
187
+
188
+ {props.elements.breadcrumbs}
189
+
190
+ <SectionTitle
191
+ className={classes.title}
192
+ tag="h1"
193
+ level={1}
194
+ text={`Clone ${props.cloneId}`}
195
+ />
196
+ </>
197
+ )
198
+
199
+ // Getting instance error.
200
+ if (stores.main.instanceError)
201
+ return (
202
+ <>
203
+ {headRendered}
204
+
205
+ <ErrorStub
206
+ title={stores.main.instanceError.title}
207
+ message={stores.main.instanceError.message}
208
+ />
209
+ </>
210
+ )
211
+
212
+ // Getting clone error.
213
+ if (stores.main.cloneError)
214
+ return (
215
+ <>
216
+ {headRendered}
217
+
218
+ <ErrorStub {...stores.main.cloneError} />
219
+ </>
220
+ )
221
+
222
+ // Initial getting data spinner.
223
+ if (!instance || !clone) {
224
+ return (
225
+ <>
226
+ {headRendered}
227
+
228
+ <PageSpinner />
229
+ </>
230
+ )
231
+ }
232
+
233
+ // Clone reset.
234
+ const requestResetClone = () => setIsOpenResetModal(true)
235
+
236
+ const resetClone = (snapshotId: string) => stores.main.resetClone(snapshotId)
237
+
238
+ // Clone destroy.
239
+ const requestDestroyClone = () => {
240
+ if (clone.protected) {
241
+ setIsOpenRestrictionModal(true)
242
+ } else {
243
+ setIsOpenDestroyModal(true)
244
+ }
245
+ }
246
+
247
+ const destroyClone = async () => {
248
+ const isSuccess = await stores.main.destroyClone()
249
+ if (isSuccess) history.push(props.routes.instance())
250
+ }
251
+
252
+ // Clone reload.
253
+ const reloadClone = () => stores.main.reload()
254
+
255
+ // Data protection.
256
+ const toggleDataProtection = () => stores.main.updateClone(!clone.protected)
257
+
258
+ // Commands.
259
+ const sshPortForwardingUrl = getSshPortForwardingCommand(instance, clone)
260
+ const jdbcConnectionStr = getJdbcConnectionStr(clone)
261
+ const psqlConnectionStr = getPsqlConnectionStr(clone)
262
+
263
+ const hasConnectionInfo =
264
+ sshPortForwardingUrl || jdbcConnectionStr || psqlConnectionStr
265
+
266
+ // Controls.
267
+ const isDisabledControls =
268
+ isResettingClone ||
269
+ isDestroyingClone ||
270
+ isReloading ||
271
+ isUpdatingClone ||
272
+ !isCloneStable
273
+
274
+ return (
275
+ <>
276
+ {headRendered}
277
+ <div className={classes.container}>
278
+ <div className={classes.actions}>
279
+ <Button
280
+ variant="contained"
281
+ color="primary"
282
+ onClick={requestResetClone}
283
+ disabled={isDisabledControls}
284
+ title={'Reset clone'}
285
+ className={classes.actionButton}
286
+ >
287
+ Reset clone
288
+ {isResettingClone && (
289
+ <Spinner size="sm" className={classes.spinner} />
290
+ )}
291
+ </Button>
292
+ <Button
293
+ variant="contained"
294
+ color="primary"
295
+ onClick={requestDestroyClone}
296
+ disabled={isDisabledControls}
297
+ title={'Destroy this clone'}
298
+ className={classes.actionButton}
299
+ >
300
+ Destroy clone
301
+ {isDestroyingClone && (
302
+ <Spinner size="sm" className={classes.spinner} />
303
+ )}
304
+ </Button>
305
+ <Button
306
+ variant="outlined"
307
+ color="secondary"
308
+ onClick={reloadClone}
309
+ disabled={isDisabledControls || isReloading}
310
+ title={'Refresh clone information'}
311
+ className={classes.actionButton}
312
+ >
313
+ Reload info
314
+ {isReloading && <Spinner size="sm" className={classes.spinner} />}
315
+ </Button>
316
+ </div>
317
+
318
+ {stores.main.resetCloneError && (
319
+ <ErrorStub
320
+ title="Resetting error"
321
+ message={stores.main.resetCloneError}
322
+ className={classes.errorStub}
323
+ />
324
+ )}
325
+
326
+ {stores.main.destroyCloneError && (
327
+ <ErrorStub
328
+ title="Destroying error"
329
+ message={stores.main.destroyCloneError}
330
+ className={classes.errorStub}
331
+ />
332
+ )}
333
+
334
+ <div className={classes.summary}>
335
+ <div>
336
+ <p>
337
+ <strong>Created</strong>
338
+ </p>
339
+ <p className={classes.text}>{clone.createdAt}</p>
340
+ </div>
341
+
342
+ <br />
343
+
344
+ <div>
345
+ <p>
346
+ <strong>Data state at</strong>&nbsp;
347
+ <Tooltip
348
+ content={
349
+ <>
350
+ <strong>Data state time</strong> is a time at which data
351
+ is&nbsp; recovered for this clone.
352
+ </>
353
+ }
354
+ >
355
+ {icons.infoIcon}
356
+ </Tooltip>
357
+ </p>
358
+ <p className={classes.text}>{clone.snapshot?.dataStateAt}</p>
359
+ </div>
360
+
361
+ <br />
362
+
363
+ <div>
364
+ <p>
365
+ <strong>Status</strong>
366
+ </p>
367
+
368
+ <Status rawClone={clone} className={classes.status} />
369
+ </div>
370
+
371
+ <br />
372
+
373
+ <div>
374
+ <p>
375
+ <strong>Summary</strong>&nbsp;
376
+ <Tooltip
377
+ content={
378
+ <>
379
+ <strong>Logical data size</strong> is a logical size of
380
+ files in PGDATA which is being thin-cloned.
381
+ <br />
382
+ <br />
383
+ <strong>Physical data diff size</strong> is an actual size
384
+ of a&nbsp; thin clone. On creation there is no diff between
385
+ clone’s&nbsp; and initial data state, all data blocks match.
386
+ During work&nbsp; with the clone data diverges and data diff
387
+ size increases.
388
+ <br />
389
+ <br />
390
+ <strong>Clone creation time</strong> is time which was&nbsp;
391
+ spent to provision the clone.
392
+ </>
393
+ }
394
+ >
395
+ {icons.infoIcon}
396
+ </Tooltip>
397
+ </p>
398
+
399
+ <p className={classes.text}>
400
+ <span className={classes.paramTitle}>Logical data size:</span>
401
+ {instance.state?.dataSize
402
+ ? formatBytesIEC(instance.state.dataSize)
403
+ : '-'}
404
+ </p>
405
+
406
+ <p className={classes.text}>
407
+ <span className={classes.paramTitle}>
408
+ Physical data diff size:
409
+ </span>
410
+ {clone.metadata.cloneDiffSize
411
+ ? formatBytesIEC(clone.metadata.cloneDiffSize)
412
+ : '-'}
413
+ </p>
414
+
415
+ <p className={classes.text}>
416
+ <span className={classes.paramTitle}>Clone creation time:</span>
417
+ {clone.metadata.cloningTime
418
+ ? `${round(clone.metadata.cloningTime, 2)} s`
419
+ : '-'}
420
+ </p>
421
+ </div>
422
+
423
+ <br />
424
+
425
+ {hasConnectionInfo && (
426
+ <>
427
+ <p>
428
+ <strong>Connection info</strong>
429
+ </p>
430
+
431
+ {sshPortForwardingUrl && (
432
+ <div className={classes.fieldBlock}>
433
+ In a separate console, set up SSH port forwarding (and keep it
434
+ running):
435
+ <div className={classes.copyFieldContainer}>
436
+ <TextField
437
+ variant="outlined"
438
+ label="SSH port forwarding"
439
+ value={sshPortForwardingUrl}
440
+ className={classes.textField}
441
+ margin="normal"
442
+ fullWidth
443
+ // @ts-ignore
444
+ readOnly
445
+ InputLabelProps={{
446
+ shrink: true,
447
+ style: styles.inputFieldLabel,
448
+ }}
449
+ FormHelperTextProps={{
450
+ style: styles.inputFieldHelper,
451
+ }}
452
+ />
453
+ <IconButton
454
+ className={classes.copyButton}
455
+ aria-label="Copy"
456
+ onClick={() => copyToClipboard(sshPortForwardingUrl)}
457
+ >
458
+ {icons.copyIcon}
459
+ </IconButton>
460
+ </div>
461
+ </div>
462
+ )}
463
+
464
+ {psqlConnectionStr && (
465
+ <div className={classes.fieldBlock}>
466
+ <div className={classes.copyFieldContainer}>
467
+ <TextField
468
+ variant="outlined"
469
+ id="psqlConnStr"
470
+ label="psql connection string"
471
+ value={psqlConnectionStr}
472
+ className={classes.textField}
473
+ margin="normal"
474
+ fullWidth
475
+ // @ts-ignore
476
+ readOnly
477
+ InputLabelProps={{
478
+ shrink: true,
479
+ style: styles.inputFieldLabel,
480
+ }}
481
+ FormHelperTextProps={{
482
+ style: styles.inputFieldHelper,
483
+ }}
484
+ />
485
+ <IconButton
486
+ className={classes.copyButton}
487
+ aria-label="Copy"
488
+ onClick={() => copyToClipboard(psqlConnectionStr)}
489
+ >
490
+ {icons.copyIcon}
491
+ </IconButton>
492
+ </div>
493
+ &nbsp;
494
+ <Tooltip
495
+ content={
496
+ <>
497
+ Used to connect to Postgres using psql. Change DBNAME
498
+ to&nbsp; name of the database you want to connect. Use
499
+ PGPASSWORD&nbsp; environment variable to set database
500
+ password or type&nbsp; it when prompted.
501
+ </>
502
+ }
503
+ >
504
+ <span className={classes.textFieldInfo}>
505
+ {icons.infoIcon}
506
+ </span>
507
+ </Tooltip>
508
+ </div>
509
+ )}
510
+
511
+ {jdbcConnectionStr && (
512
+ <div className={classes.fieldBlock}>
513
+ <div className={classes.copyFieldContainer}>
514
+ <TextField
515
+ variant="outlined"
516
+ label="JDBC connection string"
517
+ value={jdbcConnectionStr}
518
+ className={classes.textField}
519
+ margin="normal"
520
+ fullWidth
521
+ // @ts-ignore
522
+ readOnly
523
+ InputLabelProps={{
524
+ shrink: true,
525
+ style: styles.inputFieldLabel,
526
+ }}
527
+ FormHelperTextProps={{
528
+ style: styles.inputFieldHelper,
529
+ }}
530
+ />
531
+ <IconButton
532
+ className={classes.copyButton}
533
+ aria-label="Copy"
534
+ onClick={() => copyToClipboard(jdbcConnectionStr)}
535
+ >
536
+ {icons.copyIcon}
537
+ </IconButton>
538
+ </div>
539
+ &nbsp;
540
+ <Tooltip
541
+ content={
542
+ <>
543
+ Used to connect to Postgres using JDBC. Change DBNAME
544
+ to&nbsp; name of the database you want to connect,
545
+ change DBPASSWORD&nbsp; to the password you’ve used on
546
+ clone creation.
547
+ </>
548
+ }
549
+ >
550
+ <span className={classes.textFieldInfo}>
551
+ {icons.infoIcon}
552
+ </span>
553
+ </Tooltip>
554
+ </div>
555
+ )}
556
+ </>
557
+ )}
558
+
559
+ <br />
560
+
561
+ <div className={classes.fieldBlock}>
562
+ <span className={classes.remark}>
563
+ Password was set during clone creation. It’s not being stored.
564
+ <br />
565
+ You would need to recreate a clone if the password is lost.
566
+ </span>
567
+ </div>
568
+
569
+ <br />
570
+
571
+ <p>
572
+ <strong>Protection</strong>
573
+ </p>
574
+
575
+ <p>
576
+ <FormControlLabel
577
+ className={classes.checkboxLabel}
578
+ control={
579
+ <Checkbox
580
+ checked={clone.protected}
581
+ onChange={toggleDataProtection}
582
+ name="protected"
583
+ disabled={isDisabledControls}
584
+ />
585
+ }
586
+ label="Enable deletion protection"
587
+ />
588
+ <br />
589
+ <span className={classes.remark}>
590
+ When enabled no one can delete this clone and automated deletion
591
+ is also disabled.
592
+ <br />
593
+ Please be careful: abandoned clones with this checkbox enabled may
594
+ cause out-of-disk-space events. Check disk space on daily basis
595
+ and delete this clone once the work is done.
596
+ </span>
597
+ </p>
598
+
599
+ {stores.main.updateCloneError && (
600
+ <ErrorStub
601
+ title="Updating error"
602
+ message={stores.main.updateCloneError}
603
+ className={classes.errorStub}
604
+ />
605
+ )}
606
+ </div>
607
+
608
+ <>
609
+ <DestroyCloneRestrictionModal
610
+ isOpen={isOpenRestrictionModal}
611
+ onClose={() => setIsOpenRestrictionModal(false)}
612
+ cloneId={clone.id}
613
+ />
614
+
615
+ <DestroyCloneModal
616
+ isOpen={isOpenDestroyModal}
617
+ onClose={() => setIsOpenDestroyModal(false)}
618
+ cloneId={clone.id}
619
+ onDestroyClone={destroyClone}
620
+ />
621
+
622
+ <ResetCloneModal
623
+ isOpen={isOpenResetModal}
624
+ onClose={() => setIsOpenResetModal(false)}
625
+ clone={clone}
626
+ snapshots={stores.main.snapshots.data}
627
+ onResetClone={resetClone}
628
+ version={instance.state?.engine.version}
629
+ />
630
+ </>
631
+ </div>
632
+ </>
633
+ )
634
+ })