Skip to content

Commit 213955a

Browse files
committed
Convert Settings Replication Form to React
1 parent babdf56 commit 213955a

File tree

9 files changed

+519
-90
lines changed

9 files changed

+519
-90
lines changed

app/javascript/components/provider-form/validate-provider-credentials.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const ValidateProviderCredentials = ({ ...props }) => {
1212
const asyncValidate = (fields, fieldNames) => new Promise((resolve, reject) => {
1313
const url = providerId ? `/api/providers/${providerId}` : '/api/providers';
1414
const resource = pick(fields, fieldNames);
15+
16+
console.log(resource);
1517
const updatedResource = trimFieldValue(resource);
1618

1719
API.post(url, { action: 'verify_credentials', resource: updatedResource }).then(({ results: [result] = [], ...single }) => {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import { useFieldApi, useFormApi } from '@@ddf';
3+
import { Button } from 'carbon-components-react';
4+
import MiqDataTable from '../miq-data-table';
5+
6+
export const SubscriptionsTableComponent = (props) => {
7+
const {
8+
rows, onCellClick, addButtonLabel, onButtonClick,
9+
} = useFieldApi(props);
10+
const formOptions = useFormApi();
11+
12+
return (
13+
<div className="subscriptions-table">
14+
<Button
15+
kind="primary"
16+
className="subscription-add bx--btn bx--btn--primary pull-right"
17+
type="button"
18+
variant="contained"
19+
onClick={() => onButtonClick(formOptions)}
20+
>
21+
{addButtonLabel}
22+
</Button>
23+
24+
<MiqDataTable
25+
headers={[
26+
{ key: 'dbname', header: __('Database') },
27+
{ key: 'host', header: __('Host') },
28+
{ key: 'user', header: __('Username') },
29+
{ key: 'password', header: __('Password') },
30+
{ key: 'port', header: __('Port') },
31+
{ key: 'backlog', header: __('Backlog') },
32+
{ key: 'status', header: __('Status') },
33+
{ key: 'provider_region', header: __('Region') },
34+
{ key: 'edit', header: __('Edit') },
35+
{ key: 'delete', header: __('Delete') },
36+
]}
37+
rows={rows}
38+
size="md"
39+
onCellClick={(selectedRow, cellType) => onCellClick(selectedRow, cellType, formOptions)}
40+
/>
41+
</div>
42+
);
43+
};
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import React, { useState, useEffect } from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import MiqFormRenderer from '@@ddf';
5+
import createSchema from './settings-replication-form.schema';
6+
import { SubscriptionsTableComponent } from './helper';
7+
import ValidateSubscription from './validate-subscription';
8+
import miqRedirectBack from '../../helpers/miq-redirect-back';
9+
import mapper from '../../forms/mappers/componentMapper';
10+
import { http } from '../../http_api';
11+
12+
const SettingsReplicationForm = ({ pglogicalReplicationFormId }) => {
13+
const [{
14+
initialValues, subscriptions, form, replicationHelperText, isLoading,
15+
}, setState] = useState({ isLoading: !!pglogicalReplicationFormId });
16+
const submitLabel = __('Save');
17+
18+
console.log(initialValues);
19+
console.log(subscriptions);
20+
21+
const componentMapper = {
22+
...mapper,
23+
'subscriptions-table': SubscriptionsTableComponent,
24+
'validate-subscription': ValidateSubscription,
25+
};
26+
27+
// console.log(initialValues, form);
28+
29+
useEffect(() => {
30+
if (pglogicalReplicationFormId) {
31+
miqSparkleOn();
32+
http.get(`/ops/pglogical_subscriptions_form_fields/${pglogicalReplicationFormId}`).then((response) => {
33+
setState({
34+
initialValues: {
35+
replication_type: response.replication_type,
36+
subscriptions: response.subscriptions,
37+
},
38+
subscriptions: response.subscriptions,
39+
form: {
40+
type: 'replication',
41+
className: 'replication_form',
42+
action: 'edit',
43+
},
44+
replicationHelperText: '',
45+
isLoading: false,
46+
});
47+
});
48+
miqSparkleOff();
49+
}
50+
}, [pglogicalReplicationFormId]);
51+
52+
const onSubmit = (values) => {
53+
if (form.type === 'subscription') {
54+
const newSubscriptions = [];
55+
56+
newSubscriptions.push({
57+
dbname: values.dbname,
58+
host: values.host,
59+
user: values.user,
60+
password: values.password,
61+
port: values.port,
62+
});
63+
64+
setState((state) => ({
65+
...state,
66+
initialValues: {
67+
replication_type: state.initialValues.replication_type,
68+
subscriptions: state.initialValues.subscriptions,
69+
},
70+
subscriptions: subscriptions.concat(newSubscriptions),
71+
form: {
72+
type: 'replication',
73+
className: 'replication_form',
74+
action: 'edit',
75+
},
76+
}));
77+
} else {
78+
// Redirect to Settings -> Tasks
79+
80+
/* http.post(`/ops/pglogical_save_subscriptions/${pglogicalReplicationFormId}?button=${'save'}`, submitData, { skipErrors: [400] }).then(() => {
81+
const message = __('Order Request was Submitted');
82+
miqRedirectBack(message, 'success', '/miq_request/show_list?typ=service/');
83+
}).catch((err) => {
84+
console.log(err);
85+
}); */
86+
}
87+
};
88+
89+
const onCancel = () => {
90+
if (form.type === 'subscription') {
91+
setState((state) => ({
92+
...state,
93+
form: {
94+
type: 'replication',
95+
className: 'replication_form',
96+
action: 'edit',
97+
},
98+
}));
99+
} else {
100+
const message = __('Dialog Cancelled');
101+
miqRedirectBack(message, 'warning', '/ops/explorer');
102+
}
103+
};
104+
105+
return !isLoading && (
106+
<MiqFormRenderer
107+
schema={createSchema(initialValues, subscriptions, form, replicationHelperText, setState)}
108+
componentMapper={componentMapper}
109+
initialValues={initialValues}
110+
onSubmit={onSubmit}
111+
onCancel={onCancel}
112+
canReset
113+
buttonsLabels={{ submitLabel }}
114+
/>
115+
);
116+
};
117+
118+
SettingsReplicationForm.propTypes = {
119+
pglogicalReplicationFormId: PropTypes.string,
120+
};
121+
SettingsReplicationForm.defaultProps = {
122+
pglogicalReplicationFormId: undefined,
123+
};
124+
125+
export default SettingsReplicationForm;
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/* eslint-disable camelcase */
2+
import { componentTypes, validatorTypes } from '@@ddf';
3+
4+
const createSchema = (initialValues, subscriptions, form, replicationHelperText, setState) => {
5+
// Creates the rows for the 'subscriptions-table' component
6+
const createRows = () => {
7+
const rows = [];
8+
9+
subscriptions.forEach((value, index) => {
10+
rows.push({
11+
id: index.toString(),
12+
dbname: { text: value.dbname },
13+
host: { text: value.host },
14+
user: { text: value.user },
15+
password: { text: value.password },
16+
port: { text: value.port },
17+
backlog: { text: value.backlog ? value.backlog : '' },
18+
status: { text: value.status ? value.status : '' },
19+
provider_region: { text: value.provider_region || value.provider_region === 0 ? value.provider_region : '' },
20+
edit: {
21+
is_button: true,
22+
text: __('Update'),
23+
kind: 'tertiary',
24+
size: 'md',
25+
callback: 'editSubscription',
26+
},
27+
delete: {
28+
is_button: true,
29+
text: __('Delete'),
30+
kind: 'danger',
31+
size: 'md',
32+
callback: 'deleteSubscription',
33+
},
34+
});
35+
});
36+
37+
return rows;
38+
};
39+
40+
const deleteSubscription = (selectedRow, cellType, formOptions) => {
41+
subscriptions.splice(selectedRow.id, 1);
42+
43+
setState((state) => ({
44+
...state,
45+
subscriptions,
46+
}));
47+
};
48+
49+
const editSubscription = (selectedRow) => {
50+
setState((state) => ({
51+
...state,
52+
initialValues: {
53+
...state.initialValues,
54+
dbname: selectedRow.cells[0].value,
55+
host: selectedRow.cells[1].value,
56+
user: selectedRow.cells[2].value,
57+
password: selectedRow.cells[3].value,
58+
port: selectedRow.cells[4].value,
59+
},
60+
form: {
61+
type: 'subscription',
62+
className: 'subscription-form',
63+
action: 'edit',
64+
},
65+
}));
66+
};
67+
68+
const replicationFields = ({
69+
fields: [
70+
{
71+
component: componentTypes.SELECT,
72+
id: 'replication_type',
73+
name: 'replication_type',
74+
label: __('Type'),
75+
helperText: replicationHelperText,
76+
onChange: (value) => {
77+
let helperText;
78+
79+
if (initialValues.replication_type === 'none' && value === 'none') {
80+
helperText = __('No replication role has been set');
81+
} else if (initialValues.replication_type === 'remote' && value === 'none') {
82+
helperText = __('Replication will be disabled for this region');
83+
} else if (initialValues.replication_type === 'global' && value === 'none') {
84+
helperText = __('All current subscriptions will be removed');
85+
} else if (initialValues.replication_type === 'global' && value === 'remote') {
86+
helperText = __('Changing to remote replication role will remove all current subscriptions');
87+
}
88+
89+
setState((state) => ({
90+
...state,
91+
replicationHelperText: helperText,
92+
}));
93+
},
94+
options: [
95+
{
96+
label: `<${_('None')}>`,
97+
value: 'none',
98+
},
99+
{
100+
label: `Global`,
101+
value: 'global',
102+
},
103+
{
104+
label: `Remote`,
105+
value: 'remote',
106+
},
107+
],
108+
},
109+
{
110+
component: componentTypes.SUB_FORM,
111+
name: 'subscriptions_section',
112+
id: 'subscriptions_section',
113+
condition: {
114+
when: 'replication_type',
115+
is: 'global',
116+
},
117+
fields: [{
118+
component: 'subscriptions-table',
119+
name: 'subscriptions-table',
120+
id: 'subscriptions-table',
121+
rows: createRows(),
122+
onCellClick: (selectedRow, cellType, formOptions) => {
123+
switch (selectedRow.callbackAction) {
124+
case 'editSubscription':
125+
editSubscription(selectedRow);
126+
break;
127+
case 'deleteSubscription':
128+
deleteSubscription(selectedRow, cellType, formOptions);
129+
break;
130+
default:
131+
break;
132+
}
133+
},
134+
addButtonLabel: __('Add Subscription'),
135+
onButtonClick: (formOptions) => {
136+
formOptions.change('dbname', '');
137+
formOptions.change('host', '');
138+
formOptions.change('user', '');
139+
formOptions.change('password', '');
140+
formOptions.change('port', '');
141+
setState((state) => ({
142+
...state,
143+
initialValues: {
144+
replication_type: state.initialValues.replication_type,
145+
subscriptions: state.initialValues.subscriptions,
146+
},
147+
form: {
148+
type: 'subscription',
149+
className: 'subscription-form',
150+
action: 'add',
151+
},
152+
}));
153+
},
154+
}],
155+
},
156+
],
157+
});
158+
159+
const subscriptionFields = ({
160+
fields: [
161+
{
162+
component: 'validate-subscription',
163+
name: 'validate-sub',
164+
id: 'validate-sub',
165+
isRequired: true,
166+
validate: [{ type: validatorTypes.REQUIRED }],
167+
skipSubmit: true,
168+
fields: [
169+
{
170+
component: componentTypes.TEXT_FIELD,
171+
name: 'dbname',
172+
id: 'dbname',
173+
label: __('Database'),
174+
isRequired: true,
175+
validate: [{ type: validatorTypes.REQUIRED }],
176+
},
177+
{
178+
component: componentTypes.TEXT_FIELD,
179+
name: 'host',
180+
id: 'host',
181+
label: __('Host'),
182+
isRequired: true,
183+
validate: [{ type: validatorTypes.REQUIRED }],
184+
},
185+
{
186+
component: componentTypes.TEXT_FIELD,
187+
name: 'user',
188+
id: 'user',
189+
label: __('Username'),
190+
isRequired: true,
191+
validate: [{ type: validatorTypes.REQUIRED }],
192+
},
193+
{
194+
component: componentTypes.TEXT_FIELD,
195+
name: 'password',
196+
id: 'password',
197+
label: __('Password'),
198+
type: 'password',
199+
isReadOnly: form.action === 'edit',
200+
isRequired: true,
201+
validate: [{ type: validatorTypes.REQUIRED }],
202+
},
203+
{
204+
component: componentTypes.TEXT_FIELD,
205+
name: 'port',
206+
id: 'port',
207+
label: __('Port'),
208+
isRequired: true,
209+
validate: [{ type: validatorTypes.REQUIRED }],
210+
},
211+
],
212+
},
213+
],
214+
});
215+
216+
return form.type === 'subscription' ? subscriptionFields : replicationFields;
217+
};
218+
219+
export default createSchema;

0 commit comments

Comments
 (0)