Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit afaa6c1

Browse files
committed
Merge branch '434-display-config-error' into 'master'
fix(ui): display configuration errors, prevent configuration requests (#434) Closes #434 See merge request postgres-ai/database-lab!612
2 parents 4b61941 + 8374e0d commit afaa6c1

File tree

5 files changed

+83
-22
lines changed

5 files changed

+83
-22
lines changed

‎ui/packages/shared/pages/Configuration/InputWithTooltip/index.tsx‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,28 @@ export const InputWithTooltip = ({
2121
error,
2222
onChange,
2323
tooltipText,
24+
disabled,
2425
}: {
2526
value?: string
2627
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
2728
tooltipText: () => React.ReactNode
2829
label: string
2930
error?: string
31+
disabled: boolean
3032
}) => {
3133
const classes = useStyles()
3234

3335
return (
3436
<Box mt={2} mb={2} display="flex" alignItems="center">
3537
<TextField
36-
className={classNames(classes.textField, styles.textField)}
38+
className={classNames(!disabled&&classes.textField, styles.textField)}
3739
label={label}
3840
variant="outlined"
3941
size="small"
4042
value={value}
4143
error={Boolean(error)}
4244
onChange={onChange}
45+
disabled={disabled}
4346
/>
4447
<Tooltip content={<p className={styles.tooltipText}>{tooltipText()}</p>}>
4548
<InfoIcon className={styles.infoIcon} />
@@ -54,6 +57,7 @@ export const InputWithChip = ({
5457
id,
5558
onChange,
5659
tooltipText,
60+
disabled,
5761
handleDeleteDatabase,
5862
}: {
5963
value: string
@@ -62,18 +66,20 @@ export const InputWithChip = ({
6266
handleDeleteDatabase: (event: any, database: string) => void
6367
label: string
6468
id: string
69+
disabled: boolean
6570
}) => {
6671
const classes = useStyles()
6772

6873
return (
6974
<Box mt={2} mb={2}>
7075
<Box display="flex" alignItems="center">
7176
<TextField
72-
className={classNames(classes.textField, styles.textField)}
77+
className={classNames(!disabled&&classes.textField, styles.textField)}
7378
variant="outlined"
7479
onChange={onChange}
7580
value={value}
7681
multiline
82+
disabled={disabled}
7783
label={label}
7884
inputProps={{
7985
name: id,

‎ui/packages/shared/pages/Configuration/index.tsx‎

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@
55
*--------------------------------------------------------------------------
66
*/
77

8-
import { Box, Checkbox, FormControlLabel, Typography } from '@material-ui/core'
8+
import {
9+
Box,
10+
Checkbox,
11+
FormControlLabel,
12+
Typography,
13+
Snackbar,
14+
} from '@material-ui/core'
915
import { useState, useEffect } from 'react'
1016
import { withStyles, makeStyles } from '@material-ui/core/styles'
1117
import { Modal } from '@postgres.ai/shared/components/Modal'
@@ -56,10 +62,13 @@ export const Configuration = observer(
5662
getFullConfig,
5763
fullConfig,
5864
testDbSource,
59-
updateConfigError,
65+
configError,
66+
dbSourceError,
6067
getFullConfigError,
68+
instanceRetrieval,
6169
} = stores.main
6270
const configData = config && JSON.parse(JSON.stringify(config))
71+
const isConfigurationActive = instanceRetrieval?.mode !== 'physical'
6372
const [submitMessage, setSubmitMessage] = useState<
6473
string | React.ReactNode | null
6574
>('')
@@ -165,6 +174,12 @@ export const Configuration = observer(
165174

166175
return (
167176
<div className={styles.root}>
177+
<Snackbar
178+
anchorOrigin={{ vertical: "bottom", horizontal: 'right' }}
179+
open={!isConfigurationActive && !isOpen}
180+
message={'Configuration editing is only available in logical mode'}
181+
className={styles.snackbar}
182+
/>
168183
<Box>
169184
<Header retrievalMode="logical" setOpen={handleModalClick} />
170185
<Box>
@@ -174,6 +189,7 @@ export const Configuration = observer(
174189
<Checkbox
175190
name="debug"
176191
checked={formik.values.debug}
192+
disabled={!isConfigurationActive}
177193
onChange={(e) =>
178194
formik.setFieldValue('debug', e.target.checked)
179195
}
@@ -196,6 +212,7 @@ export const Configuration = observer(
196212
value={formik.values.dockerImage}
197213
error={formik.errors.dockerImage}
198214
tooltipText={tooltipText.dockerImage}
215+
disabled={!isConfigurationActive}
199216
onChange={(e) =>
200217
formik.setFieldValue('dockerImage', e.target.value)
201218
}
@@ -211,6 +228,7 @@ export const Configuration = observer(
211228
label="configs.shared_buffers"
212229
value={formik.values.sharedBuffers}
213230
tooltipText={tooltipText.sharedBuffers}
231+
disabled={!isConfigurationActive}
214232
onChange={(e) =>
215233
formik.setFieldValue('sharedBuffers', e.target.value)
216234
}
@@ -219,6 +237,7 @@ export const Configuration = observer(
219237
label="configs.shared_preload_libraries"
220238
value={formik.values.sharedPreloadLibraries}
221239
tooltipText={tooltipText.sharedPreloadLibraries}
240+
disabled={!isConfigurationActive}
222241
onChange={(e) =>
223242
formik.setFieldValue('sharedPreloadLibraries', e.target.value)
224243
}
@@ -238,27 +257,31 @@ export const Configuration = observer(
238257
value={formik.values.host}
239258
error={formik.errors.host}
240259
tooltipText={tooltipText.host}
260+
disabled={!isConfigurationActive}
241261
onChange={(e) => formik.setFieldValue('host', e.target.value)}
242262
/>
243263
<InputWithTooltip
244264
label="source.connection.port"
245265
value={formik.values.port}
246266
error={formik.errors.port}
247267
tooltipText={tooltipText.port}
268+
disabled={!isConfigurationActive}
248269
onChange={(e) => formik.setFieldValue('port', e.target.value)}
249270
/>
250271
<InputWithTooltip
251272
label="source.connection.username"
252273
value={formik.values.username}
253274
error={formik.errors.username}
254275
tooltipText={tooltipText.username}
276+
disabled={!isConfigurationActive}
255277
onChange={(e) =>
256278
formik.setFieldValue('username', e.target.value)
257279
}
258280
/>
259281
<InputWithTooltip
260282
label="source.connection.password"
261283
tooltipText={tooltipText.password}
284+
disabled={!isConfigurationActive}
262285
onChange={(e) =>
263286
formik.setFieldValue('password', e.target.value)
264287
}
@@ -268,6 +291,7 @@ export const Configuration = observer(
268291
value={formik.values.dbname}
269292
error={formik.errors.dbname}
270293
tooltipText={tooltipText.dbname}
294+
disabled={!isConfigurationActive}
271295
onChange={(e) =>
272296
formik.setFieldValue('dbname', e.target.value)
273297
}
@@ -278,6 +302,7 @@ export const Configuration = observer(
278302
id="databases"
279303
tooltipText={tooltipText.databases}
280304
handleDeleteDatabase={handleDeleteDatabase}
305+
disabled={!isConfigurationActive}
281306
onChange={(e) =>
282307
formik.setFieldValue('databases', e.target.value)
283308
}
@@ -287,18 +312,20 @@ export const Configuration = observer(
287312
variant="primary"
288313
size="medium"
289314
onClick={onTestConnectionClick}
290-
isDisabled={isTestConnectionLoading}
315+
isDisabled={
316+
isTestConnectionLoading || !isConfigurationActive
317+
}
291318
>
292319
Test connection
293320
{isTestConnectionLoading && (
294321
<Spinner size="sm" className={styles.spinner} />
295322
)}
296323
</Button>
297324
</Box>
298-
{connectionStatus && connectionResponse ? (
325+
{(connectionStatus && connectionResponse)||dbSourceError ? (
299326
<ResponseMessage
300-
type={connectionStatus}
301-
message={connectionResponse}
327+
type={dbSourceError ? 'error' : connectionStatus}
328+
message={dbSourceError||connectionResponse}
302329
/>
303330
) : null}
304331
</Box>
@@ -307,12 +334,14 @@ export const Configuration = observer(
307334
label="pg_dump jobs"
308335
value={formik.values.pg_dump}
309336
tooltipText={tooltipText.pg_dump}
337+
disabled={!isConfigurationActive}
310338
onChange={(e) => formik.setFieldValue('pg_dump', e.target.value)}
311339
/>
312340
<InputWithTooltip
313341
label="pg_restore jobs"
314342
value={formik.values.pg_restore}
315343
tooltipText={tooltipText.pg_restore}
344+
disabled={!isConfigurationActive}
316345
onChange={(e) =>
317346
formik.setFieldValue('pg_restore', e.target.value)
318347
}
@@ -340,6 +369,7 @@ export const Configuration = observer(
340369
label="timetable"
341370
value={formik.values.timetable}
342371
tooltipText={tooltipText.timetable}
372+
disabled={!isConfigurationActive}
343373
onChange={(e) =>
344374
formik.setFieldValue('timetable', e.target.value)
345375
}
@@ -357,7 +387,7 @@ export const Configuration = observer(
357387
variant="primary"
358388
size="medium"
359389
onClick={formik.submitForm}
360-
isDisabled={formik.isSubmitting}
390+
isDisabled={formik.isSubmitting||!isConfigurationActive}
361391
>
362392
Apply changes
363393
{formik.isSubmitting && (
@@ -374,10 +404,10 @@ export const Configuration = observer(
374404
</Button>
375405
</Box>
376406
</Box>
377-
{(submitStatus && submitMessage) || updateConfigError ? (
407+
{(submitStatus && submitMessage) || configError ? (
378408
<ResponseMessage
379-
type={updateConfigError ? 'error' : submitStatus}
380-
message={updateConfigError || submitMessage}
409+
type={configError ? 'error' : submitStatus}
410+
message={configError || submitMessage}
381411
/>
382412
) : null}
383413
</Box>

‎ui/packages/shared/pages/Configuration/styles.module.scss‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@
1111
label {
1212
font-size: 10px;
1313
}
14+
15+
:disabled {
16+
cursor: not-allowed;
17+
color: rgba(0, 0, 0, 0.38)
18+
}
1419
}
1520

1621
.databasesContainer {
@@ -89,3 +94,11 @@
8994
.firaCodeFont {
9095
font-family: 'Fira Code', monospace !important;
9196
}
97+
98+
.snackbar {
99+
div {
100+
background-color: #ff6212;
101+
color: #fff;
102+
border-radius: 4px;
103+
}
104+
}

‎ui/packages/shared/pages/Instance/index.tsx‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,15 @@ export const Instance = observer((props: Props) => {
7676
stores.main.load(instanceId)
7777
}, [instanceId])
7878

79-
const { instance, instanceError } = stores.main
79+
const { instance, instanceError, instanceRetrieval } = stores.main
80+
const isConfigurationActive = instanceRetrieval?.mode !== 'physical'
8081

8182
useEffect(() => {
82-
if (instance && instance?.state.retrieving?.status === "pending") {
83+
if (
84+
instance &&
85+
instance?.state.retrieving?.status === 'pending' &&
86+
isConfigurationActive
87+
) {
8388
setActiveTab(2)
8489
}
8590
if (instance && !instance?.state?.pools) {
@@ -94,7 +99,7 @@ export const Instance = observer((props: Props) => {
9499

95100
const [isLogConnectionEnabled, enableLogConnection] = React.useState(false);
96101

97-
const switchTab = (_event: React.ChangeEvent<{}>, tabID: number) => {
102+
const switchTab = (_: React.ChangeEvent<{}>, tabID: number) => {
98103
if (tabID == 1 && api.initWS != undefined && !isLogConnectionEnabled) {
99104
establishConnection(api).then(() => {
100105
enableLogConnection(true)

‎ui/packages/shared/pages/Instance/stores/Main.ts‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ export class MainStore {
5555
config: Config | null = null
5656
fullConfig?: string
5757
instanceError: Error | null = null
58-
updateConfigError: string | null = null
58+
configError: string | null = null
59+
dbSourceError: string | null = null
5960
getFullConfigError: string | null = null
6061

6162
unstableClones = new Set<string>()
@@ -83,8 +84,11 @@ export class MainStore {
8384
load = (instanceId: string) => {
8485
this.instance = null
8586
this.loadInstance(instanceId)
86-
this.loadInstanceRetrieval(instanceId)
87-
this.getConfig()
87+
this.loadInstanceRetrieval(instanceId).then(() => {
88+
if (this.instanceRetrieval?.mode !== "physical") {
89+
this.getConfig()
90+
}
91+
})
8892
this.snapshots.load(instanceId)
8993
}
9094

@@ -168,9 +172,11 @@ export class MainStore {
168172
this.config = response
169173
}
170174

171-
if (error) await getTextFromUnknownApiError(error)
175+
if (error) {
176+
this.configError = await error.json().then((err) => err.message)
177+
}
172178

173-
return !!response
179+
return response
174180
}
175181

176182
updateConfig = async (values: Config) => {
@@ -179,7 +185,7 @@ export class MainStore {
179185
const { response, error } = await this.api.updateConfig({ ...values })
180186

181187
if (error)
182-
this.updateConfigError = await error.json().then((err) => err.message)
188+
this.configError = await error.json().then((err) => err.message)
183189

184190
return response
185191
}
@@ -203,7 +209,8 @@ export class MainStore {
203209

204210
const { response, error } = await this.api.testDbSource(values)
205211

206-
if (error) await getTextFromUnknownApiError(error)
212+
if (error)
213+
this.dbSourceError = await error.json().then((err) => err.message)
207214

208215
return response
209216
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /