@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,131 @@
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, useRef, useLayoutEffect, useEffect } from 'react'
9
+ import { makeStyles } from '@material-ui/core'
10
+ import clsx from 'clsx'
11
+
12
+ import {
13
+ createTransitionInteractive,
14
+ borderRadius,
15
+ } from '@postgres.ai/shared/styles/vars'
16
+
17
+ import { checkIsVisibleLeftCurtain, checkIsVisibleRightCurtain } from './utils'
18
+ import { Dimensions } from './types'
19
+
20
+ const useStyles = makeStyles(
21
+ (theme) => ({
22
+ root: {
23
+ position: 'relative',
24
+ overflow: 'hidden',
25
+
26
+ [theme.breakpoints.down('xs')]: {
27
+ borderRadius,
28
+ },
29
+ },
30
+ curtain: {
31
+ position: 'absolute',
32
+ top: 0,
33
+ width: '25px',
34
+ height: '100%',
35
+ pointerEvents: 'none',
36
+ transition: createTransitionInteractive('opacity'),
37
+ },
38
+ curtainLeft: {
39
+ left: 0,
40
+ background: 'linear-gradient(to right, rgba(0,0,0,0.08), transparent);',
41
+ },
42
+ curtainRight: {
43
+ right: 0,
44
+ background: 'linear-gradient(to left, rgba(0,0,0,0.08), transparent);',
45
+ },
46
+ curtainHidden: {
47
+ opacity: 0,
48
+ },
49
+ content: {
50
+ overflow: 'auto',
51
+ },
52
+ }),
53
+ { index: 1 },
54
+ )
55
+
56
+ type Props = {
57
+ children: React.ReactNode
58
+ classes?: {
59
+ root?: string
60
+ content?: string
61
+ curtain?: string
62
+ curtainLeft?: string
63
+ curtainRight?: string
64
+ }
65
+ }
66
+
67
+ export const HorizontalScrollContainer = (props: Props) => {
68
+ const classes = useStyles()
69
+
70
+ const [dimensions, setDimensions] = useState<Dimensions | null>(null)
71
+
72
+ const contentRef = useRef<HTMLDivElement>(null)
73
+
74
+ const calcDimensions = () => {
75
+ if (!contentRef.current) {
76
+ return
77
+ }
78
+
79
+ const { offsetWidth, scrollWidth, scrollLeft } = contentRef.current
80
+
81
+ setDimensions({
82
+ offsetWidth,
83
+ scrollWidth,
84
+ scrollLeft,
85
+ })
86
+ }
87
+
88
+ // Initial calculation.
89
+ useLayoutEffect(() => {
90
+ calcDimensions()
91
+ }, [])
92
+
93
+ // Listen window resizes for the next calculations.
94
+ useEffect(() => {
95
+ window.addEventListener('resize', calcDimensions)
96
+ return () => window.removeEventListener('resize', calcDimensions)
97
+ }, [])
98
+
99
+ const isVisibleLeft = dimensions && checkIsVisibleLeftCurtain(dimensions)
100
+ const isVisibleRight = dimensions && checkIsVisibleRightCurtain(dimensions)
101
+
102
+ return (
103
+ <div className={clsx(classes.root, props.classes?.root)}>
104
+ <div
105
+ className={clsx(
106
+ classes.curtain,
107
+ classes.curtainLeft,
108
+ !isVisibleLeft && classes.curtainHidden,
109
+ props.classes?.curtain,
110
+ props.classes?.curtainLeft,
111
+ )}
112
+ />
113
+ <div
114
+ ref={contentRef}
115
+ className={clsx(classes.content, props.classes?.content)}
116
+ onScroll={calcDimensions}
117
+ >
118
+ {props.children}
119
+ </div>
120
+ <div
121
+ className={clsx(
122
+ classes.curtain,
123
+ classes.curtainRight,
124
+ !isVisibleRight && classes.curtainHidden,
125
+ props.classes?.curtain,
126
+ props.classes?.curtainRight,
127
+ )}
128
+ />
129
+ </div>
130
+ )
131
+ }
@@ -0,0 +1,12 @@
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
+ export type Dimensions = {
9
+ offsetWidth: number;
10
+ scrollWidth: number;
11
+ scrollLeft: number;
12
+ };
@@ -0,0 +1,16 @@
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 { Dimensions } from './types';
9
+
10
+ export const checkIsVisibleLeftCurtain = (dimensions: Dimensions) => {
11
+ return dimensions.scrollLeft > 0;
12
+ };
13
+
14
+ export const checkIsVisibleRightCurtain = (dimensions: Dimensions) => {
15
+ return dimensions.scrollLeft < dimensions.scrollWidth - dimensions.offsetWidth;
16
+ };
@@ -0,0 +1,29 @@
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 { makeStyles } from '@material-ui/core'
10
+
11
+ type Props = {
12
+ children: React.ReactNode
13
+ }
14
+
15
+ const useStyles = makeStyles(
16
+ {
17
+ root: {
18
+ fontWeight: 'bold',
19
+ whiteSpace: 'nowrap',
20
+ },
21
+ },
22
+ { index: 1 },
23
+ )
24
+
25
+ export const ImportantText = (props: Props) => {
26
+ const classes = useStyles()
27
+
28
+ return <span className={classes.root}>{props.children}</span>
29
+ }
@@ -0,0 +1,31 @@
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 { Link as LinkBase, LinkProps } from 'react-router-dom'
9
+ import cn from 'classnames'
10
+
11
+ import styles from './styles.module.scss'
12
+
13
+ type Props = LinkProps & { external?: boolean }
14
+
15
+ export const Link = (props: Props) => {
16
+ const { className, external, to, ...otherProps } = props
17
+
18
+ if (external) {
19
+ return (
20
+ <a
21
+ href={to as string}
22
+ {...otherProps}
23
+ className={cn(styles.root, className)}
24
+ target="_blank"
25
+ rel="noopener noreferrer"
26
+ />
27
+ )
28
+ }
29
+
30
+ return <LinkBase to={to} {...otherProps} className={cn(styles.root, className)} />
31
+ }
@@ -0,0 +1,12 @@
1
+ @import '@postgres.ai/shared/styles/vars';
2
+ @import '@postgres.ai/shared/styles/mixins';
3
+
4
+ .root {
5
+ color: $color-blue-main;
6
+
7
+ @include touch-transition(color);
8
+
9
+ &:hover {
10
+ color: $color-blue-dark;
11
+ }
12
+ }
@@ -0,0 +1,80 @@
1
+ import cn from 'classnames'
2
+ import { NavLink } from 'react-router-dom'
3
+
4
+ import { GatewayLink } from '@postgres.ai/shared/components/GatewayLink'
5
+
6
+ import styles from './styles.module.scss'
7
+
8
+ type BaseProps = {
9
+ children: React.ReactNode
10
+ className?: string
11
+ icon?: React.ReactNode
12
+ isCollapsed?: boolean
13
+ }
14
+
15
+ type ButtonProps = BaseProps & {
16
+ type?: 'button' | 'submit'
17
+ onClick?: React.MouseEventHandler<HTMLButtonElement>
18
+ disabled?: boolean
19
+ }
20
+
21
+ type LinkProps = BaseProps & {
22
+ type: 'link'
23
+ to: string
24
+ activeClassName: string
25
+ }
26
+
27
+ type GatewayLinkProps = BaseProps & {
28
+ type: 'gateway-link'
29
+ href: string
30
+ }
31
+
32
+ type Props = ButtonProps | LinkProps | GatewayLinkProps
33
+
34
+ export const Button = (props: Props) => {
35
+ const className = cn(
36
+ styles.root,
37
+ props.isCollapsed && styles.collapsed,
38
+ props.className,
39
+ )
40
+
41
+ const children = (
42
+ <>
43
+ {props.icon && (
44
+ <span
45
+ className={cn(styles.icon, props.isCollapsed && styles.collapsed)}
46
+ >
47
+ {props.icon}
48
+ </span>
49
+ )}
50
+ {!props.isCollapsed && props.children}
51
+ </>
52
+ )
53
+
54
+ if (!props.type || props.type === 'button' || props.type === 'submit')
55
+ return (
56
+ <button className={className} onClick={props.onClick} disabled={props.disabled}>
57
+ {children}
58
+ </button>
59
+ )
60
+
61
+ if (props.type === 'link')
62
+ return (
63
+ <NavLink
64
+ className={className}
65
+ to={props.to}
66
+ activeClassName={props.activeClassName}
67
+ >
68
+ {children}
69
+ </NavLink>
70
+ )
71
+
72
+ if (props.type === 'gateway-link')
73
+ return (
74
+ <GatewayLink className={className} href={props.href}>
75
+ {children}
76
+ </GatewayLink>
77
+ )
78
+
79
+ return null
80
+ }
@@ -0,0 +1,42 @@
1
+ @import '@postgres.ai/shared/styles/vars';
2
+ @import '@postgres.ai/shared/styles/mixins';
3
+
4
+ .root {
5
+ display: flex;
6
+ align-items: center;
7
+ padding: 0 10px;
8
+ background-color: $color-gray-darkest;
9
+ cursor: pointer;
10
+ border-radius: 4px;
11
+ border: 0;
12
+ height: 48px;
13
+ width: 100%;
14
+ color: inherit;
15
+ white-space: nowrap;
16
+ overflow: hidden;
17
+ font-weight: 700;
18
+ text-decoration: none;
19
+
20
+ @include touch-transition(background-color color);
21
+
22
+ &:hover {
23
+ background-color: $color-gray-darkest--hover;
24
+ color: inherit;
25
+ }
26
+
27
+ &.collapsed {
28
+ justify-content: center;
29
+ }
30
+
31
+ + .root {
32
+ margin-top: 8px;
33
+ }
34
+ }
35
+
36
+ .icon {
37
+ font-size: 0;
38
+
39
+ &:not(.collapsed) {
40
+ margin-right: 8px;
41
+ }
42
+ }
@@ -0,0 +1,93 @@
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 { makeStyles, Dialog, IconButton } from '@material-ui/core'
10
+ import { Close as CloseIcon } from '@material-ui/icons'
11
+ import clsx from 'clsx'
12
+
13
+ import { SectionTitle } from '@postgres.ai/shared/components/SectionTitle'
14
+ import { colors } from '@postgres.ai/shared/styles/colors'
15
+
16
+ type Props = {
17
+ isOpen: boolean
18
+ onClose: () => void
19
+ children: React.ReactNode
20
+ title: React.ReactNode
21
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
22
+ titleRightContent?: React.ReactNode
23
+ headerContent?: React.ReactNode
24
+ classes?: {
25
+ content?: string
26
+ }
27
+ }
28
+
29
+ const useStyles = makeStyles(
30
+ (theme) => ({
31
+ root: {
32
+ padding: '24px',
33
+ width: '100%',
34
+
35
+ [theme.breakpoints.down('xs')]: {
36
+ padding: '20px',
37
+ margin: '20px',
38
+ maxHeight: 'calc(100% - 40px)',
39
+ },
40
+ },
41
+ closeButton: {
42
+ position: 'absolute',
43
+ right: '12px',
44
+ top: '12px',
45
+ color: colors.pgaiDarkGray,
46
+ },
47
+ titleContent: {
48
+ paddingRight: '36px',
49
+ },
50
+ content: {
51
+ marginTop: '16px',
52
+ },
53
+ }),
54
+ { index: 1 },
55
+ )
56
+
57
+ export const Modal = (props: Props) => {
58
+ const {
59
+ isOpen,
60
+ onClose,
61
+ children,
62
+ title,
63
+ size = 'xs',
64
+ titleRightContent,
65
+ } = props
66
+
67
+ const classes = useStyles()
68
+
69
+ return (
70
+ <Dialog
71
+ open={isOpen}
72
+ onClose={onClose}
73
+ classes={{ paper: classes.root }}
74
+ maxWidth={size}
75
+ >
76
+ <IconButton className={classes.closeButton} onClick={onClose}>
77
+ <CloseIcon />
78
+ </IconButton>
79
+ <SectionTitle
80
+ text={title}
81
+ tag="h3"
82
+ level={1}
83
+ rightContent={titleRightContent}
84
+ contentClassName={classes.titleContent}
85
+ >
86
+ {props.headerContent}
87
+ </SectionTitle>
88
+ <div className={clsx(classes.content, props.classes?.content)}>
89
+ {children}
90
+ </div>
91
+ </Dialog>
92
+ )
93
+ }
@@ -0,0 +1,18 @@
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 { Spinner } from '@postgres.ai/shared/components/Spinner'
9
+
10
+ import styles from './styles.module.scss'
11
+
12
+ export const PageSpinner = () => {
13
+ return (
14
+ <div className={styles.root}>
15
+ <Spinner size='lg' />
16
+ </div>
17
+ )
18
+ }
@@ -0,0 +1,13 @@
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
+ .root {
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ flex: 1 1 100%;
13
+ }
@@ -0,0 +1,154 @@
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 { makeStyles } from '@material-ui/core'
10
+ import { formatDistanceToNowStrict } from 'date-fns'
11
+
12
+ import { Clone } from '@postgres.ai/shared/types/api/entities/clone'
13
+ import { Snapshot } from '@postgres.ai/shared/types/api/entities/snapshot'
14
+ import { Text } from '@postgres.ai/shared/components/Text'
15
+ import { Modal } from '@postgres.ai/shared/components/Modal'
16
+ import { Select } from '@postgres.ai/shared/components/Select'
17
+ import { ImportantText } from '@postgres.ai/shared/components/ImportantText'
18
+ import { Spinner } from '@postgres.ai/shared/components/Spinner'
19
+ import { SimpleModalControls } from '@postgres.ai/shared/components/SimpleModalControls'
20
+ import { compareSnapshotsDesc } from '@postgres.ai/shared/utils/snapshot'
21
+
22
+ type Props = {
23
+ isOpen: boolean
24
+ onClose: () => void
25
+ clone: Clone
26
+ onResetClone: (snapshotId: string) => void
27
+ snapshots: Snapshot[] | null
28
+ version: string | null | undefined
29
+ }
30
+
31
+ const useStyles = makeStyles(
32
+ {
33
+ snapshots: {
34
+ margin: '16px 0 0 0',
35
+ },
36
+ snapshotTag: {
37
+ marginLeft: '4px',
38
+ fontWeight: 700,
39
+ },
40
+ },
41
+ { index: 1 },
42
+ )
43
+
44
+ export const ResetCloneModal = (props: Props) => {
45
+ const { isOpen, onClose, clone, onResetClone, snapshots } = props
46
+
47
+ const classes = useStyles()
48
+
49
+ // `slice` here is the mobx requirement.
50
+ const sortedSnapshots = snapshots?.slice().sort(compareSnapshotsDesc)
51
+
52
+ const [selectedSnapshotId, setSelectedSnapshotId] = useState<string | null>(
53
+ null,
54
+ )
55
+
56
+ const selectCurrentSnapshot = () => {
57
+ if (!sortedSnapshots) return
58
+
59
+ const currentSnapshot = sortedSnapshots.find(
60
+ (snapshot) => snapshot.id === clone.snapshot?.id,
61
+ )
62
+
63
+ if (!currentSnapshot) return
64
+
65
+ setSelectedSnapshotId(currentSnapshot.id)
66
+ }
67
+
68
+ useEffect(selectCurrentSnapshot, [Boolean(sortedSnapshots)])
69
+
70
+ const handleClickReset = () => {
71
+ if (!selectedSnapshotId) return
72
+ onResetClone(selectedSnapshotId)
73
+ onClose()
74
+ }
75
+
76
+ const handleClickResetToLatest = () => {
77
+ if (!sortedSnapshots) return
78
+ const [latestSnapshot] = sortedSnapshots
79
+ if (!latestSnapshot) return
80
+ onResetClone(latestSnapshot.id)
81
+ onClose()
82
+ }
83
+
84
+ const isSnapshotsSelectingSupported = Boolean(props.version)
85
+
86
+ const isSnapshotsSelectingDisabled =
87
+ !sortedSnapshots || !isSnapshotsSelectingSupported
88
+
89
+ return (
90
+ <Modal
91
+ title={`Reset clone ${clone.id}`}
92
+ isOpen={isOpen}
93
+ onClose={onClose}
94
+ titleRightContent={!sortedSnapshots && <Spinner size="sm" />}
95
+ >
96
+ <Text>
97
+ All changes to the clone <ImportantText>{clone.id}</ImportantText> will
98
+ be reset to chosen data state time.
99
+ </Text>
100
+ <Select
101
+ disabled={isSnapshotsSelectingDisabled}
102
+ label="Data state time"
103
+ value={selectedSnapshotId}
104
+ items={
105
+ sortedSnapshots?.map((snapshot, i) => {
106
+ const isLatest = i === 0
107
+ const isCurrent = snapshot.id === clone.snapshot?.id
108
+
109
+ return {
110
+ value: snapshot.id,
111
+ children: (
112
+ <>
113
+ {snapshot.dataStateAt} (
114
+ {formatDistanceToNowStrict(snapshot.dataStateAtDate, {
115
+ addSuffix: true,
116
+ })}
117
+ )
118
+ {isLatest && (
119
+ <span className={classes.snapshotTag}>Latest</span>
120
+ )}
121
+ {isCurrent && (
122
+ <span className={classes.snapshotTag}>Current</span>
123
+ )}
124
+ </>
125
+ ),
126
+ }
127
+ }) ?? []
128
+ }
129
+ onChange={(e) => setSelectedSnapshotId(e.target.value)}
130
+ fullWidth={true}
131
+ className={classes.snapshots}
132
+ />
133
+ <SimpleModalControls
134
+ items={[
135
+ {
136
+ text: 'Cancel',
137
+ onClick: onClose,
138
+ },
139
+ {
140
+ text: 'Reset to latest',
141
+ onClick: handleClickResetToLatest,
142
+ isDisabled: isSnapshotsSelectingDisabled,
143
+ },
144
+ {
145
+ text: 'Reset',
146
+ isDisabled: !selectedSnapshotId,
147
+ variant: 'primary',
148
+ onClick: handleClickReset,
149
+ },
150
+ ]}
151
+ />
152
+ </Modal>
153
+ )
154
+ }