Add Project Edit form and refactor how the form handles credentials

This commit is contained in:
Marliana Lara
2019-11-03 21:28:10 -05:00
parent 8cb32045f0
commit d77040a7a9
7 changed files with 171 additions and 74 deletions

View File

@@ -1,10 +1,62 @@
import React, { Component } from 'react';
import { CardBody } from '@patternfly/react-core';
import React, { useState } from 'react';
import { withRouter } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';
import {
Card as _Card,
CardBody,
CardHeader,
Tooltip,
} from '@patternfly/react-core';
import CardCloseButton from '@components/CardCloseButton';
import ProjectForm from '../shared/ProjectForm';
import { ProjectsAPI } from '@api';
class ProjectEdit extends Component {
render() {
return <CardBody>Coming soon :)</CardBody>;
}
const Card = styled(_Card)`
--pf-c-card--child--PaddingLeft: 0;
--pf-c-card--child--PaddingRight: 0;
`;
function ProjectEdit({ project, history, i18n }) {
const [formSubmitError, setFormSubmitError] = useState(null);
const handleSubmit = async values => {
try {
const {
data: { id },
} = await ProjectsAPI.update(project.id, values);
history.push(`/projects/${id}/details`);
} catch (error) {
setFormSubmitError(error);
}
};
const handleCancel = () => {
history.push(`/projects/${project.id}/details`);
};
return (
<Card>
<CardHeader css="text-align: right">
<Tooltip content={i18n._(t`Close`)} position="top">
<CardCloseButton onClick={handleCancel} />
</Tooltip>
</CardHeader>
<CardBody>
<ProjectForm
project={project}
handleCancel={handleCancel}
handleSubmit={handleSubmit}
/>
</CardBody>
{formSubmitError ? (
<div className="formSubmitError">formSubmitError</div>
) : (
''
)}
</Card>
);
}
export default ProjectEdit;
export default withI18n()(withRouter(ProjectEdit));

View File

@@ -30,19 +30,19 @@ const ScmTypeFormRow = styled(FormRow)`
padding: 24px;
`;
function ProjectForm(props) {
const { project, handleCancel, handleSubmit, i18n } = props;
function ProjectForm({ project, ...props }) {
const { i18n, handleCancel, handleSubmit } = props;
const { summary_fields = {} } = project;
const [contentError, setContentError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [organization, setOrganization] = useState(null);
const [organization, setOrganization] = useState(
summary_fields.organization || null
);
const [scmSubFormState, setScmSubFormState] = useState(null);
const [scmTypeOptions, setScmTypeOptions] = useState(null);
const [scmCredential, setScmCredential] = useState({
typeId: null,
value: null,
});
const [insightsCredential, setInsightsCredential] = useState({
typeId: null,
value: null,
const [credentials, setCredentials] = useState({
scm: { typeId: null, value: null },
insights: { typeId: null, value: null },
});
useEffect(() => {
@@ -74,9 +74,32 @@ function ProjectForm(props) {
ProjectsAPI.readOptions(),
]);
setScmCredential({ typeId: scmCredentialType.id });
setInsightsCredential({ typeId: insightsCredentialType.id });
setScmTypeOptions(choices);
const { credential } = summary_fields;
if (!credential) {
setCredentials({
scm: { typeId: scmCredentialType.id },
insights: { typeId: insightsCredentialType.id },
});
return;
}
const { credential_type_id } = credential;
setCredentials({
scm: {
typeId: scmCredentialType.id,
value:
credential_type_id === scmCredentialType.id ? credential : null,
},
insights: {
typeId: insightsCredentialType.id,
value:
credential_type_id === insightsCredentialType.id
? credential
: null,
},
});
} catch (error) {
setContentError(error);
} finally {
@@ -87,22 +110,50 @@ function ProjectForm(props) {
fetchData();
}, []);
const resetScmTypeFields = form => {
const scmFormFields = [
'scm_url',
'scm_branch',
'scm_refspec',
'credential',
'scm_clean',
'scm_delete_on_update',
'scm_update_on_launch',
'allow_override',
'scm_update_cache_timeout',
];
const scmFormFields = {
scm_url: '',
scm_branch: '',
scm_refspec: '',
credential: '',
scm_clean: false,
scm_delete_on_update: false,
scm_update_on_launch: false,
allow_override: false,
scm_update_cache_timeout: 0,
};
scmFormFields.forEach(field => {
form.setFieldValue(field, form.initialValues[field]);
form.setFieldTouched(field, false);
const saveSubFormState = form => {
const updatedScmFormFields = { ...scmFormFields };
Object.keys(updatedScmFormFields).forEach(label => {
updatedScmFormFields[label] = form.values[label];
});
setScmSubFormState(updatedScmFormFields);
};
const resetScmTypeFields = (value, form) => {
if (form.values.scm_type === form.initialValues.scm_type) {
saveSubFormState(form);
}
Object.keys(scmFormFields).forEach(label => {
if (value === form.initialValues.scm_type) {
form.setFieldValue(label, scmSubFormState[label]);
} else {
form.setFieldValue(label, scmFormFields[label]);
}
form.setFieldTouched(label, false);
});
};
const handleCredentialSelection = (type, value) => {
setCredentials({
...credentials,
[type]: {
...credentials[type],
value,
},
});
};
@@ -213,7 +264,7 @@ function ProjectForm(props) {
]}
onChange={(event, value) => {
form.setFieldValue('scm_type', value);
resetScmTypeFields(form);
resetScmTypeFields(value, form);
}}
/>
</FormGroup>
@@ -226,29 +277,29 @@ function ProjectForm(props) {
{
git: (
<GitSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credentials.scm}
onCredentialSelection={handleCredentialSelection}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
hg: (
<HgSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credentials.scm}
onCredentialSelection={handleCredentialSelection}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
svn: (
<SvnSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credentials.scm}
onCredentialSelection={handleCredentialSelection}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
insights: (
<InsightsSubForm
setInsightsCredential={setInsightsCredential}
insightsCredential={insightsCredential}
credential={credentials.insights}
onCredentialSelection={handleCredentialSelection}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),

View File

@@ -11,8 +11,8 @@ import {
const GitSubForm = ({
i18n,
scmCredential,
setScmCredential,
credential,
onCredentialSelection,
scmUpdateOnLaunch,
}) => (
<>
@@ -74,8 +74,8 @@ const GitSubForm = ({
}
/>
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credential}
onCredentialSelection={onCredentialSelection}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>

View File

@@ -10,8 +10,8 @@ import {
const HgSubForm = ({
i18n,
scmCredential,
setScmCredential,
credential,
onCredentialSelection,
scmUpdateOnLaunch,
}) => (
<>
@@ -34,8 +34,8 @@ const HgSubForm = ({
/>
<BranchFormField i18n={i18n} label={i18n._(t`SCM Branch/Tag/Revision`)} />
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credential}
onCredentialSelection={onCredentialSelection}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>

View File

@@ -8,8 +8,8 @@ import { ScmTypeOptions } from './SharedFields';
const InsightsSubForm = ({
i18n,
setInsightsCredential,
insightsCredential,
credential,
onCredentialSelection,
scmUpdateOnLaunch,
}) => (
<>
@@ -18,19 +18,16 @@ const InsightsSubForm = ({
validate={required(i18n._(t`Select a value for this field`), i18n)}
render={({ form }) => (
<CredentialLookup
credentialTypeId={insightsCredential.typeId}
credentialTypeId={credential.typeId}
label={i18n._(t`Insights Credential`)}
helperTextInvalid={form.errors.credential}
isValid={!form.touched.credential || !form.errors.credential}
onBlur={() => form.setFieldTouched('credential')}
onChange={credential => {
form.setFieldValue('credential', credential.id);
setInsightsCredential({
...insightsCredential,
value: credential,
});
onChange={value => {
onCredentialSelection('insights', value);
form.setFieldValue('credential', value.id);
}}
value={insightsCredential.value}
value={credential.value}
required
/>
)}

View File

@@ -41,20 +41,17 @@ export const BranchFormField = withI18n()(({ i18n, label }) => (
));
export const ScmCredentialFormField = withI18n()(
({ i18n, setScmCredential, scmCredential }) => (
({ i18n, credential, onCredentialSelection }) => (
<Field
name="credential"
render={({ form }) => (
<CredentialLookup
credentialTypeId={scmCredential.typeId}
credentialTypeId={credential.typeId}
label={i18n._(t`SCM Credential`)}
value={scmCredential.value}
onChange={credential => {
form.setFieldValue('credential', credential.id);
setScmCredential({
...scmCredential,
value: credential,
});
value={credential.value}
onChange={value => {
onCredentialSelection('scm', value);
form.setFieldValue('credential', value.id);
}}
/>
)}

View File

@@ -10,8 +10,8 @@ import {
const SvnSubForm = ({
i18n,
scmCredential,
setScmCredential,
credential,
onCredentialSelection,
scmUpdateOnLaunch,
}) => (
<>
@@ -30,8 +30,8 @@ const SvnSubForm = ({
/>
<BranchFormField i18n={i18n} label={i18n._(t`Revision #`)} />
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
credential={credential}
onCredentialSelection={onCredentialSelection}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>