Skip to content

Commit 0c92529

Browse files
committed
Merge branch '475-custom-options-for-dle' into 'master'
feat (ui) add additional fields with customOptions in DLE (#475) Closes #475 See merge request postgres-ai/database-lab!661
2 parents b8c5e93 + 4407cea commit 0c92529

File tree

10 files changed

+297
-80
lines changed

10 files changed

+297
-80
lines changed

ui/packages/ce/src/api/configs/updateConfig.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { postUniqueDatabases } from '@postgres.ai/shared/pages/Configuration/utils'
1+
import {
2+
postUniqueCustomOptions,
3+
postUniqueDatabases,
4+
} from '@postgres.ai/shared/pages/Configuration/utils'
25
import { Config } from '@postgres.ai/shared/types/api/entities/config'
36
import { request } from 'helpers/request'
47

@@ -26,7 +29,8 @@ export const updateConfig = async (req: Config) => {
2629
logicalDump: {
2730
options: {
2831
databases: postUniqueDatabases(req.databases),
29-
parallelJobs: req.pg_dump,
32+
customOptions: postUniqueCustomOptions(req.pgDumpCustomOptions),
33+
parallelJobs: req.dumpParallelJobs,
3034
source: {
3135
connection: {
3236
dbname: req.dbname,
@@ -40,7 +44,10 @@ export const updateConfig = async (req: Config) => {
4044
},
4145
logicalRestore: {
4246
options: {
43-
parallelJobs: req.pg_restore,
47+
customOptions: postUniqueCustomOptions(
48+
req.pgRestoreCustomOptions,
49+
),
50+
parallelJobs: req.restoreParallelJobs,
4451
},
4552
},
4653
},

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

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Select } from '@postgres.ai/shared/components/Select'
66
import { InfoIcon } from '@postgres.ai/shared/icons/Info'
77
import { Tooltip } from '@postgres.ai/shared/components/Tooltip'
88

9-
import { uniqueDatabases } from '../utils'
9+
import { uniqueChipValue } from '../utils'
1010

1111
import styles from '../styles.module.scss'
1212

@@ -74,14 +74,15 @@ export const InputWithChip = ({
7474
onChange,
7575
tooltipText,
7676
disabled,
77-
handleDeleteDatabase,
77+
handleDeleteChip,
7878
}: {
7979
value: string
8080
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void
8181
tooltipText: () => React.ReactNode
82-
handleDeleteDatabase: (
82+
handleDeleteChip: (
8383
event: React.FormEvent<HTMLInputElement>,
84-
database: string,
84+
uniqueValue: string,
85+
label: string
8586
) => void
8687
label: string
8788
id: string
@@ -115,19 +116,21 @@ export const InputWithChip = ({
115116
<InfoIcon className={styles.infoIcon} />
116117
</Tooltip>
117118
</Box>
118-
<div>
119+
<div className={styles.chipContainer}>
119120
{value &&
120-
uniqueDatabases(value)
121+
uniqueChipValue(value)
121122
.split(' ')
122-
.map((database, index) => {
123-
if (database !== '') {
123+
.map((uniqueValue, index) => {
124+
if (uniqueValue !== '') {
124125
return (
125126
<Chip
126127
key={index}
127128
className={styles.chip}
128-
label={database}
129+
label={uniqueValue}
129130
disabled={disabled}
130-
onDelete={(event) => handleDeleteDatabase(event, database)}
131+
onDelete={(event) =>
132+
handleDeleteChip(event, uniqueValue, id)
133+
}
131134
color="primary"
132135
/>
133136
)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
export const dockerImageOptions = [
2+
{
3+
name: 'Generic Postgres (postgresai/extended-postgres)',
4+
type: 'Generic Postgres',
5+
},
6+
{ name: 'Generic Postgres with PostGIS', type: 'postgis' },
7+
{ name: 'Amazon RDS for Postgres', type: 'rds' },
8+
{ name: 'Amazon RDS Aurora for Postgres', type: 'rdsAurora' },
9+
{ name: 'Heroku Postgres', type: 'heroku' },
10+
{ name: 'Supabase Postgres', type: 'supabase' },
11+
{ name: 'Custom image', type: 'custom' },
12+
]
13+
14+
export const defaultPgDumpOptions = [
15+
{
16+
optionType: 'Generic Postgres',
17+
addDefaultOptions: [],
18+
},
19+
{
20+
optionType: 'postgis',
21+
addDefaultOptions: [],
22+
},
23+
{
24+
optionType: 'rds',
25+
addDefaultOptions: [],
26+
},
27+
{
28+
optionType: 'rdsAurora',
29+
addDefaultOptions: [],
30+
},
31+
{
32+
optionType: 'heroku',
33+
addDefaultOptions: [],
34+
},
35+
{
36+
optionType: 'supabase',
37+
addDefaultOptions: [],
38+
},
39+
]
40+
41+
export const defaultPgRestoreOptions = [
42+
{
43+
optionType: 'Generic Postgres',
44+
addDefaultOptions: [],
45+
},
46+
{
47+
optionType: 'postgis',
48+
addDefaultOptions: [],
49+
},
50+
{
51+
optionType: 'rds',
52+
addDefaultOptions: ['---exclude-schema=awsdms'],
53+
},
54+
{
55+
optionType: 'rdsAurora',
56+
addDefaultOptions: ['---exclude-schema=awsdms'],
57+
},
58+
{
59+
optionType: 'heroku',
60+
addDefaultOptions: [],
61+
},
62+
{
63+
optionType: 'supabase',
64+
addDefaultOptions: [],
65+
},
66+
]

ui/packages/shared/pages/Configuration/imageOptions.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

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

Lines changed: 108 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ import { tooltipText } from './tooltipText'
2929
import { FormValues, useForm } from './useForm'
3030
import { ResponseMessage } from './ResponseMessage'
3131
import { ConfigSectionTitle, Header, ModalTitle } from './Header'
32-
import { imageOptions } from './imageOptions'
33-
import { formatDockerImageArray, uniqueDatabases } from './utils'
32+
import {
33+
dockerImageOptions,
34+
defaultPgDumpOptions,
35+
defaultPgRestoreOptions,
36+
} from './configOptions'
37+
import { formatDockerImageArray, FormValuesKey, uniqueChipValue } from './utils'
3438
import {
3539
SelectWithTooltip,
3640
InputWithChip,
@@ -39,6 +43,11 @@ import {
3943

4044
import styles from './styles.module.scss'
4145

46+
type PgOptionsType = {
47+
optionType: string
48+
addDefaultOptions: string[]
49+
}
50+
4251
const NON_LOGICAL_RETRIEVAL_MESSAGE =
4352
'Configuration editing is only available in logical mode'
4453
const PREVENT_MODIFYING_MESSAGE = 'Editing is disabled by admin'
@@ -149,34 +158,77 @@ export const Configuration = observer(
149158
setIsModalOpen(true)
150159
}
151160

152-
const handleDeleteDatabase = (
161+
const handleDeleteChip = (
153162
_: React.FormEvent<HTMLInputElement>,
154-
database: string,
163+
uniqueValue: string,
164+
id: string,
155165
) => {
156-
if (formik.values.databases) {
157-
let currentDatabases = uniqueDatabases(formik.values.databases)
158-
let curDividers = formik.values.databases.match(
166+
if (formik.values[id as FormValuesKey]) {
167+
let newValues = ''
168+
const currentValues = uniqueChipValue(
169+
String(formik.values[id as FormValuesKey]),
170+
)
171+
const splitValues = currentValues.split(' ')
172+
const curDividers = String(formik.values[id as FormValuesKey]).match(
159173
/[,(\s)(\n)(\r)(\t)(\r\n)]/gm,
160174
)
161-
let newDatabases = ''
162-
let splitDatabases = currentDatabases.split(' ')
163-
for (let i in splitDatabases) {
164-
if (curDividers && splitDatabases[i] !== database) {
165-
newDatabases =
166-
newDatabases +
167-
splitDatabases[i] +
175+
for (let i in splitValues) {
176+
if (curDividers && splitValues[i] !== uniqueValue) {
177+
newValues =
178+
newValues +
179+
splitValues[i] +
168180
(curDividers[i] ? curDividers[i] : '')
169181
}
170182
}
171-
formik.setFieldValue('databases', newDatabases)
183+
formik.setFieldValue(id, newValues)
172184
}
173185
}
174186

187+
const handleSelectPgOptions = (
188+
e: React.ChangeEvent<HTMLInputElement>,
189+
formikName: string,
190+
formikValue: string,
191+
initialValue: string | undefined,
192+
pgOptions: PgOptionsType[],
193+
) => {
194+
let pgValue = formikValue
195+
// set initial value on change
196+
formik.setFieldValue(formikName, initialValue)
197+
198+
const selectedPgOptions = pgOptions.filter(
199+
(pg) => e.target.value === pg.optionType,
200+
)
201+
202+
// add options to formik field
203+
selectedPgOptions.forEach((pg) => {
204+
pg.addDefaultOptions.forEach((addOption) => {
205+
if (!pgValue.includes(addOption)) {
206+
const addOptionWithSpace = addOption + ' '
207+
formik.setFieldValue(formikName, (pgValue += addOptionWithSpace))
208+
}
209+
})
210+
})
211+
}
212+
175213
const handleDockerImageSelect = (
176214
e: React.ChangeEvent<HTMLInputElement>,
177215
) => {
178216
const newDockerImages = formatDockerImageArray(e.target.value)
179217
setDockerImages(newDockerImages)
218+
handleSelectPgOptions(
219+
e,
220+
'pgDumpCustomOptions',
221+
formik.values.pgDumpCustomOptions,
222+
configData?.pgDumpCustomOptions,
223+
defaultPgDumpOptions,
224+
)
225+
handleSelectPgOptions(
226+
e,
227+
'pgRestoreCustomOptions',
228+
formik.values.pgRestoreCustomOptions,
229+
configData?.pgRestoreCustomOptions,
230+
defaultPgRestoreOptions,
231+
)
180232
formik.setFieldValue('dockerImageType', e.target.value)
181233

182234
// select latest Postgres version on dockerImage change
@@ -206,7 +258,7 @@ export const Configuration = observer(
206258
setConnectionRes(null)
207259
setSubmitMessage(null)
208260
getEngine().then((res) => {
209-
setDledition(res?.edition)
261+
setDledition(String(res?.edition))
210262
})
211263
}, [])
212264

@@ -265,7 +317,7 @@ export const Configuration = observer(
265317
error={Boolean(formik.errors.dockerImageType)}
266318
tooltipText={tooltipText.dockerImageType}
267319
disabled={isConfigurationDisabled}
268-
items={imageOptions.map((image) => {
320+
items={dockerImageOptions.map((image) => {
269321
return {
270322
value: image.type,
271323
children: image.name,
@@ -420,7 +472,7 @@ export const Configuration = observer(
420472
label="Databases"
421473
id="databases"
422474
tooltipText={tooltipText.databases}
423-
handleDeleteDatabase={handleDeleteDatabase}
475+
handleDeleteChip={handleDeleteChip}
424476
disabled={isConfigurationDisabled}
425477
onChange={(e) =>
426478
formik.setFieldValue('databases', e.target.value)
@@ -451,22 +503,54 @@ export const Configuration = observer(
451503
</Box>
452504
<InputWithTooltip
453505
label="pg_dump jobs"
454-
value={formik.values.pg_dump}
455-
tooltipText={tooltipText.pg_dump}
506+
value={formik.values.dumpParallelJobs}
507+
tooltipText={tooltipText.dumpParallelJobs}
456508
disabled={isConfigurationDisabled}
457509
onChange={(e) =>
458-
formik.setFieldValue('pg_dump', e.target.value)
510+
formik.setFieldValue('dumpParallelJobs', e.target.value)
459511
}
460512
/>
461513
<InputWithTooltip
462514
label="pg_restore jobs"
463-
value={formik.values.pg_restore}
464-
tooltipText={tooltipText.pg_restore}
515+
value={formik.values.restoreParallelJobs}
516+
tooltipText={tooltipText.restoreParallelJobs}
465517
disabled={isConfigurationDisabled}
466518
onChange={(e) =>
467-
formik.setFieldValue('pg_restore', e.target.value)
519+
formik.setFieldValue('restoreParallelJobs', e.target.value)
468520
}
469521
/>
522+
{dleEdition !== 'community' && (
523+
<>
524+
<InputWithChip
525+
value={formik.values.pgDumpCustomOptions}
526+
label="pg_dump customOptions"
527+
id="pgDumpCustomOptions"
528+
tooltipText={tooltipText.pgDumpCustomOptions}
529+
handleDeleteChip={handleDeleteChip}
530+
disabled={isConfigurationDisabled}
531+
onChange={(e) =>
532+
formik.setFieldValue(
533+
'pgDumpCustomOptions',
534+
e.target.value,
535+
)
536+
}
537+
/>
538+
<InputWithChip
539+
value={formik.values.pgRestoreCustomOptions}
540+
label="pg_restore customOptions"
541+
id="pgRestoreCustomOptions"
542+
tooltipText={tooltipText.pgRestoreCustomOptions}
543+
handleDeleteChip={handleDeleteChip}
544+
disabled={isConfigurationDisabled}
545+
onChange={(e) =>
546+
formik.setFieldValue(
547+
'pgRestoreCustomOptions',
548+
e.target.value,
549+
)
550+
}
551+
/>
552+
</>
553+
)}
470554
<Box>
471555
<Typography className={styles.subsection}>
472556
Subsection "retrieval.refresh"

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
}
1919
}
2020

21+
.chipContainer {
22+
width: 350px;
23+
max-width: 100%;
24+
margin-bottom: 1.25rem;
25+
}
26+
2127
.databasesContainer {
2228
width: 350px;
2329
max-width: 100%;

0 commit comments

Comments
 (0)