mirror of
https://github.com/ansible/awx.git
synced 2026-01-19 13:41:28 -03:30
Wrap credential form submission code in useRequest to avoid the "unmounted component" errors we've seen if we try to push a new route onto the history but the coomponent is already unmounted.
This commit is contained in:
parent
b01e312b8f
commit
66df922956
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { PageSection, Card } from '@patternfly/react-core';
|
||||
import { CardBody } from '../../../components/Card';
|
||||
@ -11,14 +11,64 @@ import {
|
||||
CredentialsAPI,
|
||||
} from '../../../api';
|
||||
import CredentialForm from '../shared/CredentialForm';
|
||||
import useRequest from '../../../util/useRequest';
|
||||
|
||||
function CredentialAdd({ me }) {
|
||||
const [error, setError] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [credentialTypes, setCredentialTypes] = useState(null);
|
||||
const [formSubmitError, setFormSubmitError] = useState(null);
|
||||
const history = useHistory();
|
||||
|
||||
const {
|
||||
error: submitError,
|
||||
request: submitRequest,
|
||||
result: credentialId,
|
||||
} = useRequest(
|
||||
useCallback(
|
||||
async values => {
|
||||
const { inputs, organization, ...remainingValues } = values;
|
||||
const nonPluginInputs = {};
|
||||
const pluginInputs = {};
|
||||
Object.entries(inputs).forEach(([key, value]) => {
|
||||
if (value.credential && value.inputs) {
|
||||
pluginInputs[key] = value;
|
||||
} else {
|
||||
nonPluginInputs[key] = value;
|
||||
}
|
||||
});
|
||||
const {
|
||||
data: { id: newCredentialId },
|
||||
} = await CredentialsAPI.create({
|
||||
user: (me && me.id) || null,
|
||||
organization: (organization && organization.id) || null,
|
||||
inputs: nonPluginInputs,
|
||||
...remainingValues,
|
||||
});
|
||||
const inputSourceRequests = [];
|
||||
Object.entries(pluginInputs).forEach(([key, value]) => {
|
||||
inputSourceRequests.push(
|
||||
CredentialInputSourcesAPI.create({
|
||||
input_field_name: key,
|
||||
metadata: value.inputs,
|
||||
source_credential: value.credential.id,
|
||||
target_credential: newCredentialId,
|
||||
})
|
||||
);
|
||||
});
|
||||
await Promise.all(inputSourceRequests);
|
||||
|
||||
return newCredentialId;
|
||||
},
|
||||
[me]
|
||||
)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (credentialId) {
|
||||
history.push(`/credentials/${credentialId}/details`);
|
||||
}
|
||||
}, [credentialId, history]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
@ -42,45 +92,7 @@ function CredentialAdd({ me }) {
|
||||
};
|
||||
|
||||
const handleSubmit = async values => {
|
||||
const { inputs, organization, ...remainingValues } = values;
|
||||
const pluginInputs = [];
|
||||
Object.entries(inputs).forEach(([key, value]) => {
|
||||
if (value.credential && value.inputs) {
|
||||
pluginInputs.push([key, value]);
|
||||
delete inputs[key];
|
||||
}
|
||||
});
|
||||
|
||||
setFormSubmitError(null);
|
||||
|
||||
try {
|
||||
const {
|
||||
data: { id: credentialId },
|
||||
} = await CredentialsAPI.create({
|
||||
user: (me && me.id) || null,
|
||||
organization: (organization && organization.id) || null,
|
||||
inputs: inputs || {},
|
||||
...remainingValues,
|
||||
});
|
||||
const inputSourceRequests = [];
|
||||
pluginInputs.forEach(([key, value]) => {
|
||||
if (value.credential && value.inputs) {
|
||||
inputSourceRequests.push(
|
||||
CredentialInputSourcesAPI.create({
|
||||
input_field_name: key,
|
||||
metadata: value.inputs,
|
||||
source_credential: value.credential.id,
|
||||
target_credential: credentialId,
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
await Promise.all(inputSourceRequests);
|
||||
const url = `/credentials/${credentialId}/details`;
|
||||
history.push(`${url}`);
|
||||
} catch (err) {
|
||||
setFormSubmitError(err);
|
||||
}
|
||||
await submitRequest(values);
|
||||
};
|
||||
|
||||
if (error) {
|
||||
@ -113,7 +125,7 @@ function CredentialAdd({ me }) {
|
||||
onCancel={handleCancel}
|
||||
onSubmit={handleSubmit}
|
||||
credentialTypes={credentialTypes}
|
||||
submitError={formSubmitError}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import React, { useCallback, useState, useEffect } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { object } from 'prop-types';
|
||||
|
||||
@ -11,15 +11,84 @@ import {
|
||||
import ContentError from '../../../components/ContentError';
|
||||
import ContentLoading from '../../../components/ContentLoading';
|
||||
import CredentialForm from '../shared/CredentialForm';
|
||||
import useRequest from '../../../util/useRequest';
|
||||
|
||||
function CredentialEdit({ credential, me }) {
|
||||
const [error, setError] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [credentialTypes, setCredentialTypes] = useState(null);
|
||||
const [inputSources, setInputSources] = useState(null);
|
||||
const [formSubmitError, setFormSubmitError] = useState(null);
|
||||
const [inputSources, setInputSources] = useState({});
|
||||
const history = useHistory();
|
||||
|
||||
const { error: submitError, request: submitRequest, result } = useRequest(
|
||||
useCallback(
|
||||
async (values, inputSourceMap) => {
|
||||
const createAndUpdateInputSources = pluginInputs =>
|
||||
Object.entries(pluginInputs).map(([fieldName, fieldValue]) => {
|
||||
if (!inputSourceMap[fieldName]) {
|
||||
return CredentialInputSourcesAPI.create({
|
||||
input_field_name: fieldName,
|
||||
metadata: fieldValue.inputs,
|
||||
source_credential: fieldValue.credential.id,
|
||||
target_credential: credential.id,
|
||||
});
|
||||
}
|
||||
if (fieldValue.touched) {
|
||||
return CredentialInputSourcesAPI.update(
|
||||
inputSourceMap[fieldName].id,
|
||||
{
|
||||
metadata: fieldValue.inputs,
|
||||
source_credential: fieldValue.credential.id,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const destroyInputSources = inputs => {
|
||||
const destroyRequests = [];
|
||||
Object.values(inputSourceMap).forEach(inputSource => {
|
||||
const { id, input_field_name } = inputSource;
|
||||
if (!inputs[input_field_name]?.credential) {
|
||||
destroyRequests.push(CredentialInputSourcesAPI.destroy(id));
|
||||
}
|
||||
});
|
||||
return destroyRequests;
|
||||
};
|
||||
|
||||
const { inputs, organization, ...remainingValues } = values;
|
||||
const nonPluginInputs = {};
|
||||
const pluginInputs = {};
|
||||
Object.entries(inputs).forEach(([key, value]) => {
|
||||
if (value.credential && value.inputs) {
|
||||
pluginInputs[key] = value;
|
||||
} else {
|
||||
nonPluginInputs[key] = value;
|
||||
}
|
||||
});
|
||||
const [{ data }] = await Promise.all([
|
||||
CredentialsAPI.update(credential.id, {
|
||||
user: (me && me.id) || null,
|
||||
organization: (organization && organization.id) || null,
|
||||
inputs: nonPluginInputs,
|
||||
...remainingValues,
|
||||
}),
|
||||
...destroyInputSources(inputs),
|
||||
]);
|
||||
await Promise.all(createAndUpdateInputSources(pluginInputs));
|
||||
return data;
|
||||
},
|
||||
[credential.id, me]
|
||||
)
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (result) {
|
||||
history.push(`/credentials/${result.id}/details`);
|
||||
}
|
||||
}, [result, history]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
@ -54,67 +123,11 @@ function CredentialEdit({ credential, me }) {
|
||||
|
||||
const handleCancel = () => {
|
||||
const url = `/credentials/${credential.id}/details`;
|
||||
|
||||
history.push(`${url}`);
|
||||
};
|
||||
|
||||
const createAndUpdateInputSources = pluginInputs =>
|
||||
Object.entries(pluginInputs).map(([fieldName, fieldValue]) => {
|
||||
if (!inputSources[fieldName]) {
|
||||
return CredentialInputSourcesAPI.create({
|
||||
input_field_name: fieldName,
|
||||
metadata: fieldValue.inputs,
|
||||
source_credential: fieldValue.credential.id,
|
||||
target_credential: credential.id,
|
||||
});
|
||||
}
|
||||
if (fieldValue.touched) {
|
||||
return CredentialInputSourcesAPI.update(inputSources[fieldName].id, {
|
||||
metadata: fieldValue.inputs,
|
||||
source_credential: fieldValue.credential.id,
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const destroyInputSources = inputs => {
|
||||
const destroyRequests = [];
|
||||
Object.values(inputSources).forEach(inputSource => {
|
||||
const { id, input_field_name } = inputSource;
|
||||
if (!inputs[input_field_name]?.credential) {
|
||||
destroyRequests.push(CredentialInputSourcesAPI.destroy(id));
|
||||
}
|
||||
});
|
||||
return destroyRequests;
|
||||
};
|
||||
|
||||
const handleSubmit = async values => {
|
||||
const { inputs, organization, ...remainingValues } = values;
|
||||
const pluginInputs = {};
|
||||
Object.entries(inputs).forEach(([key, value]) => {
|
||||
if (value.credential && value.inputs) {
|
||||
pluginInputs[key] = value;
|
||||
delete inputs[key];
|
||||
}
|
||||
});
|
||||
setFormSubmitError(null);
|
||||
try {
|
||||
await Promise.all([
|
||||
CredentialsAPI.update(credential.id, {
|
||||
user: (me && me.id) || null,
|
||||
organization: (organization && organization.id) || null,
|
||||
inputs: inputs || {},
|
||||
...remainingValues,
|
||||
}),
|
||||
...destroyInputSources(pluginInputs),
|
||||
]);
|
||||
await Promise.all(createAndUpdateInputSources(pluginInputs));
|
||||
const url = `/credentials/${credential.id}/details`;
|
||||
history.push(`${url}`);
|
||||
} catch (err) {
|
||||
setFormSubmitError(err);
|
||||
}
|
||||
await submitRequest(values, inputSources);
|
||||
};
|
||||
|
||||
if (error) {
|
||||
@ -133,7 +146,7 @@ function CredentialEdit({ credential, me }) {
|
||||
credential={credential}
|
||||
credentialTypes={credentialTypes}
|
||||
inputSources={inputSources}
|
||||
submitError={formSubmitError}
|
||||
submitError={submitError}
|
||||
/>
|
||||
</CardBody>
|
||||
);
|
||||
|
||||
@ -37,9 +37,9 @@ function CredentialPluginField(props) {
|
||||
isValid={isValid}
|
||||
label={label}
|
||||
>
|
||||
{field.value.credential ? (
|
||||
{field?.value?.credential ? (
|
||||
<CredentialPluginSelected
|
||||
credential={field.value.credential}
|
||||
credential={field?.value?.credential}
|
||||
onClearPlugin={() => helpers.setValue('')}
|
||||
onEditPlugin={() => setShowPluginWizard(true)}
|
||||
/>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user