Skip to content

Commit 10b15bc

Browse files
committed
DB Fileupload changes
Uploading now works on a per-service basis Added new selector to get a map of services to s3 buckets Minor cleanup
1 parent cda84a8 commit 10b15bc

File tree

5 files changed

+207
-167
lines changed

5 files changed

+207
-167
lines changed

client/web/src/settings/ApplicationComponent.js

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,7 @@ import { useDispatch } from 'react-redux'
2020
import { Formik, Form } from 'formik'
2121
import { PropTypes } from 'prop-types'
2222
import * as Yup from 'yup'
23-
import {
24-
Button,
25-
Row,
26-
Col,
27-
Card,
28-
CardBody,
29-
Alert,
30-
FormFeedback,
31-
} from 'reactstrap'
23+
import { Button, Row, Col, Card, CardBody, Alert } from 'reactstrap'
3224
import LoadingOverlay from '@ronchalant/react-loading-overlay'
3325

3426
import AppSettingsSubform from './AppSettingsSubform'
@@ -64,7 +56,6 @@ export function ApplicationComponent(props) {
6456
tiers,
6557
} = props
6658

67-
console.log('App Config:', appConfig)
6859
const LINUX = 'LINUX'
6960
const WINDOWS = 'WINDOWS'
7061
const FSX = 'FSX'
@@ -233,10 +224,15 @@ export function ApplicationComponent(props) {
233224
username: Yup.string()
234225
.matches('^[a-zA-Z]+[a-zA-Z0-9_$]*$', 'Username is not valid')
235226
.required('Username is required'),
236-
password: Yup.string().when('hasEncryptedPassword', {
237-
is: false,
238-
then: Yup.string().matches('^[a-zA-Z0-9/@"\' ]{8,}$', 'Password must be longer than 8 characters and can only contain alphanumberic characters or / @ " \' and spaces')
239-
}).required('Password is required'),
227+
password: Yup.string()
228+
.when('hasEncryptedPassword', {
229+
is: false,
230+
then: Yup.string().matches(
231+
'^[a-zA-Z0-9/@"\' ]{8,}$',
232+
'Password must be longer than 8 characters and can only contain alphanumberic characters or / @ " \' and spaces'
233+
),
234+
})
235+
.required('Password is required'),
240236
database: Yup.string(),
241237
}),
242238
otherwise: Yup.object(),
@@ -323,13 +319,18 @@ export function ApplicationComponent(props) {
323319
services: Yup.array(
324320
Yup.object({
325321
public: Yup.boolean().required(),
326-
name: Yup.string().when('tombstone', (tombstone, schema) => {
327-
return requiredIfNotTombstoned(
328-
tombstone,
329-
schema,
330-
'Service Name is a required field.'
331-
)
332-
}).matches(/^[\.\-_a-zA-Z0-9]+$/, 'Name must only contain alphanumeric characters or .-_'),
322+
name: Yup.string()
323+
.when('tombstone', (tombstone, schema) => {
324+
return requiredIfNotTombstoned(
325+
tombstone,
326+
schema,
327+
'Service Name is a required field.'
328+
)
329+
})
330+
.matches(
331+
/^[\.\-_a-zA-Z0-9]+$/,
332+
'Name must only contain alphanumeric characters or .-_'
333+
),
333334
description: Yup.string(),
334335
path: Yup.string()
335336
.when(['public', 'tombstone'], (isPublic, tombstone, schema) => {
@@ -378,9 +379,8 @@ export function ApplicationComponent(props) {
378379
provisionBilling: Yup.boolean(),
379380
})
380381

381-
const onFileSelected = (databaseObject, file) => {
382-
databaseObject.bootstrapFilename = file.name
383-
props.onFileSelected(file)
382+
const onFileSelected = (serviceName, file) => {
383+
props.onFileSelected({ serviceName, file })
384384
}
385385

386386
const dismissError = () => {

client/web/src/settings/ApplicationContainer.js

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,25 +17,26 @@
1717
import React, { useEffect, useState } from 'react'
1818
import { Switch, Route } from 'react-router-dom'
1919
import { useDispatch, useSelector } from 'react-redux'
20-
20+
import {
21+
saveToPresignedBucket,
22+
selectServiceToS3BucketMap,
23+
} from '../settings/ducks'
2124
import {
2225
fetchSettings,
2326
fetchConfig,
2427
updateConfig,
25-
saveToPresignedBucket,
2628
selectAllSettings,
2729
dismissError,
2830
selectLoading,
2931
selectConfig,
3032
selectConfigLoading,
3133
selectConfigError,
3234
selectConfigMessage,
33-
createConfig,
3435
} from './ducks'
3536

3637
import { ApplicationComponent } from './ApplicationComponent'
3738
import { ConfirmModal } from './ConfirmModal'
38-
import { selectDbOptions, selectOsOptions, selectDbUploadUrl } from '../options/ducks'
39+
import { selectDbOptions, selectOsOptions } from '../options/ducks'
3940
import { fetchTenantsThunk, selectAllTenants } from '../tenant/ducks'
4041
import { fetchTiersThunk, selectAllTiers } from '../tier/ducks'
4142

@@ -53,7 +54,8 @@ export function ApplicationContainer(props) {
5354
const configLoading = useSelector(selectConfigLoading)
5455
const configMessage = useSelector(selectConfigMessage)
5556
const configError = useSelector(selectConfigError)
56-
const dbUploadUrl = useSelector(selectDbUploadUrl)
57+
const serviceToS3BucketMap = useSelector(selectServiceToS3BucketMap)
58+
5759
const hasTenants = useSelector((state) => {
5860
return selectAllTenants(state)?.length > 0
5961
})
@@ -114,6 +116,21 @@ export function ApplicationContainer(props) {
114116
}
115117
}, [dispatch])
116118

119+
useEffect(() => {
120+
Object.keys(file).forEach((fn) => {
121+
const dbFile = file[fn]
122+
const url = serviceToS3BucketMap[fn]
123+
if (dbFile && url) {
124+
dispatch(
125+
saveToPresignedBucket({
126+
dbFile,
127+
url,
128+
})
129+
)
130+
}
131+
})
132+
}, [serviceToS3BucketMap, appConfig, dispatch, file])
133+
117134
const presubmitCheck = (values) => {
118135
setFormValues(values)
119136
if (hasTenants) {
@@ -143,16 +160,8 @@ export function ApplicationContainer(props) {
143160
return encryptedPw.substring(0, 8) === pw
144161
}
145162

146-
console.log("updateConfiguration!")
147-
console.log(values)
148-
149163
try {
150-
const {
151-
services,
152-
billing,
153-
provisionBilling,
154-
...rest
155-
} = values
164+
const { services, billing, provisionBilling, ...rest } = values
156165
let cleanedServicesMap = {}
157166
for (var serviceIndex in services) {
158167
let thisService = services[serviceIndex]
@@ -169,7 +178,11 @@ export function ApplicationContainer(props) {
169178
...rest
170179
} = thisService.tiers[tierName]
171180
let { filesystemLifecycle, ...cleanedFs } = filesystem
172-
let { weeklyMaintenanceDay, weeklyMaintenanceTime: time, ...cleanedFsx } = cleanedFs.fsx
181+
let {
182+
weeklyMaintenanceDay,
183+
weeklyMaintenanceTime: time,
184+
...cleanedFsx
185+
} = cleanedFs.fsx
173186
const weeklyTime = getFormattedTime(time)
174187
const fsx = {
175188
...cleanedFsx,
@@ -180,13 +193,20 @@ export function ApplicationContainer(props) {
180193
efs: cleanedFs.fileSystemType === EFS ? cleanedFs.efs : null,
181194
fsx: cleanedFs.fileSystemType === FSX ? fsx : null,
182195
}
183-
const { port, hasEncryptedPassword, encryptedPassword, ...restDb } = database
196+
const {
197+
port,
198+
hasEncryptedPassword,
199+
encryptedPassword,
200+
bootstrapFilename,
201+
...restDb
202+
} = database
184203
// If we detected an encrypted password coming in, and it looks like they haven't changed it
185204
// then send the encrypted password back to the server. Otherwise send what they changed.
186205
const cleanedDb = {
187206
...restDb,
188207
password:
189-
hasEncryptedPassword && isMatch(restDb.password, encryptedPassword)
208+
hasEncryptedPassword &&
209+
isMatch(restDb.password, encryptedPassword)
190210
? encryptedPassword
191211
: restDb.password,
192212
}
@@ -219,21 +239,14 @@ export function ApplicationContainer(props) {
219239
billing: provisionBilling ? billing : null,
220240
services: cleanedServicesMap,
221241
}
222-
223-
// TODO this file is controlled as a single state and setter passed to all DB forms
224-
// TODO also, the settings API implementation of the DB init file will need to change for multiple services as well
225-
// if (!!file && file.name && provisionDb) {
226-
// await dispatch(saveToPresignedBucket({ dbFile: file, url: dbUploadUrl }))
227-
// }
228-
console.log('dispatching the following appConfig...')
229-
console.log(configToSend)
230-
await dispatch(updateConfig(configToSend))
242+
dispatch(updateConfig(configToSend))
231243
} catch (e) {
232244
console.error(e)
233245
}
234246
}
235247

236-
const handleFileSelected = (file) => {
248+
const handleFileSelected = (newFile) => {
249+
file[newFile.serviceName] = newFile.file
237250
setFile(file)
238251
}
239252

@@ -262,7 +275,11 @@ export function ApplicationContainer(props) {
262275
settingsObj={settingsObj}
263276
error={configError}
264277
message={configMessage}
265-
loading={loading === 'idle' && configLoading === 'idle' ? 'idle' : 'pending'}
278+
loading={
279+
loading === 'idle' && configLoading === 'idle'
280+
? 'idle'
281+
: 'pending'
282+
}
266283
updateConfiguration={presubmitCheck}
267284
tiers={tiers}
268285
{...props}

client/web/src/settings/ServicesComponent.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ const ServicesComponent = (props) => {
4141
}
4242

4343
const addService = (serviceName) => {
44-
console.log('addService ' + serviceName)
4544
let newService = initService(serviceName)
4645
formik.values.services.push(newService)
4746
setServices([...formik.values.services])
@@ -86,8 +85,8 @@ const ServicesComponent = (props) => {
8685
<TierServiceSettingsSubform
8786
tiers={tiers}
8887
isLocked={hasTenants}
88+
serviceName={service.name}
8989
serviceValues={formik.values.services[index]}
90-
setFieldValue={formik.setFieldValue}
9190
dbOptions={dbOptions}
9291
onFileSelected={onFileSelected}
9392
formikServicePrefix={'services[' + index + ']'}

client/web/src/settings/TierServiceSettingsSubform.js

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,10 @@
1515
*/
1616

1717
import React, { useState } from 'react'
18-
import {
19-
Row,
20-
Col,
21-
Card,
22-
CardBody,
23-
CardHeader,
24-
FormGroup,
25-
Label,
26-
FormFeedback,
27-
} from 'reactstrap'
28-
import { Field } from 'formik'
29-
import {
30-
SaasBoostSelect,
31-
SaasBoostCheckbox,
32-
SaasBoostInput,
33-
} from '../components/FormComponents'
18+
import { Row, Col, Card, CardBody, CardHeader } from 'reactstrap'
19+
import { SaasBoostSelect, SaasBoostInput } from '../components/FormComponents'
3420
import {
3521
CDropdown,
36-
CDropdownHeader,
3722
CDropdownItem,
3823
CDropdownMenu,
3924
CDropdownToggle,
@@ -44,13 +29,13 @@ import DatabaseSubform from './DatabaseSubform'
4429

4530
const TierServiceSettingsSubform = (props) => {
4631
const {
47-
isLocked,
48-
formikServicePrefix,
49-
serviceIndex,
5032
tiers,
33+
isLocked,
34+
serviceName,
35+
serviceValues,
5136
dbOptions,
5237
onFileSelected,
53-
serviceValues,
38+
formikServicePrefix,
5439
} = props
5540

5641
const [selectedTier, setSelectedTier] = useState(tiers[0].name)
@@ -59,7 +44,6 @@ const TierServiceSettingsSubform = (props) => {
5944
// TODO does that need to be controlled by the ApplicationContainer.. wherever the initialValues are set?
6045
// TODO I think we can override initialValues as we go along
6146
// TODO the only important thing is that it's set going back
62-
6347
return (
6448
<>
6549
<Row>
@@ -69,7 +53,7 @@ const TierServiceSettingsSubform = (props) => {
6953
<CDropdown>
7054
<CDropdownToggle>{selectedTier}</CDropdownToggle>
7155
<CDropdownMenu>
72-
{tiers.map(tier => (
56+
{tiers.map((tier) => (
7357
<CDropdownItem
7458
onClick={() => setSelectedTier(tier.name)}
7559
key={formikServicePrefix + '-' + tier.name}
@@ -169,12 +153,7 @@ const TierServiceSettingsSubform = (props) => {
169153
serviceValues?.tiers[selectedTier]?.provisionDb
170154
}
171155
values={serviceValues?.tiers[selectedTier]?.database}
172-
onFileSelected={(file) =>
173-
onFileSelected(
174-
serviceValues?.tiers[selectedTier]?.database,
175-
file
176-
)
177-
}
156+
onFileSelected={(file) => onFileSelected(serviceName, file)}
178157
></DatabaseSubform>
179158
</Col>
180159
</Row>

0 commit comments

Comments
 (0)