Encapsulate each scm type subform in its own component

This commit is contained in:
Marliana Lara 2019-10-30 07:55:43 -04:00
parent ae349addfe
commit a8140e86d7
No known key found for this signature in database
GPG Key ID: 38C73B40DFA809EE
9 changed files with 585 additions and 446 deletions

View File

@ -91,7 +91,7 @@ class ProjectListItem extends React.Component {
<Link
id={labelId}
to={`${detailUrl}`}
style={{ marginLeft: '10px' }}
css={{ marginLeft: '10px' }}
>
<b>{project.name}</b>
</Link>

View File

@ -1,30 +1,27 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { withRouter, Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { withFormik, Field } from 'formik';
import { Formik, Field } from 'formik';
import { Config } from '@contexts/Config';
import {
Form as _Form,
FormGroup,
Title as _Title,
} from '@patternfly/react-core';
import { Form, FormGroup } from '@patternfly/react-core';
import AnsibleSelect from '@components/AnsibleSelect';
import ContentError from '@components/ContentError';
import ContentLoading from '@components/ContentLoading';
import FormActionGroup from '@components/FormActionGroup/FormActionGroup';
import FormField, { CheckboxField, FieldTooltip } from '@components/FormField';
import FormField, { FieldTooltip } from '@components/FormField';
import FormRow from '@components/FormRow';
import OrganizationLookup from '@components/Lookup/OrganizationLookup';
import CredentialLookup from '@components/Lookup/CredentialLookup';
import { CredentialTypesAPI, ProjectsAPI } from '@api';
import { required } from '@util/validators';
import styled from 'styled-components';
const Form = styled(_Form)`
padding: 0 24px;
`;
import {
GitSubForm,
HgSubForm,
SvnSubForm,
InsightsSubForm,
SubFormTitle,
} from './ProjectSubForms';
const ScmTypeFormRow = styled(FormRow)`
background-color: #f5f5f5;
@ -33,19 +30,10 @@ const ScmTypeFormRow = styled(FormRow)`
padding: 24px;
`;
const OptionsFormGroup = styled.div`
grid-column: 1/-1;
`;
const Title = styled(_Title)`
--pf-c-title--m-md--FontWeight: 700;
grid-column: 1 / -1;
`;
function ProjectForm(props) {
const { values, handleCancel, handleSubmit, i18n } = props;
const { project, handleCancel, handleSubmit, i18n } = props;
const [contentError, setContentError] = useState(null);
const [hasContentLoading, setHasContentLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const [organization, setOrganization] = useState(null);
const [scmTypeOptions, setScmTypeOptions] = useState(null);
const [scmCredential, setScmCredential] = useState({
@ -58,45 +46,48 @@ function ProjectForm(props) {
});
useEffect(() => {
async function fetchCredTypeId(params) {
try {
const {
data: {
results: [credential],
},
} = await CredentialTypesAPI.read(params);
return credential.id;
} catch (error) {
setContentError(error);
return null;
}
}
async function fetchData() {
const insightsTypeId = await fetchCredTypeId({ name: 'Insights' });
const scmTypeId = await fetchCredTypeId({ kind: 'scm' });
const {
data: {
actions: {
GET: {
scm_type: { choices },
try {
const [
{
data: {
results: [scmCredentialType],
},
},
},
} = await ProjectsAPI.readOptions();
setInsightsCredential({ typeId: insightsTypeId });
setScmCredential({ typeId: scmTypeId });
setScmTypeOptions(choices);
setHasContentLoading(false);
{
data: {
results: [insightsCredentialType],
},
},
{
data: {
actions: {
GET: {
scm_type: { choices },
},
},
},
},
] = await Promise.all([
CredentialTypesAPI.read({ kind: 'scm' }),
CredentialTypesAPI.read({ name: 'Insights' }),
ProjectsAPI.readOptions(),
]);
setScmCredential({ typeId: scmCredentialType.id });
setInsightsCredential({ typeId: insightsCredentialType.id });
setScmTypeOptions(choices);
} catch (error) {
setContentError(error);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
const resetScmTypeFields = (value, form) => {
if (form.initialValues.scm_type === value) {
return;
}
const resetScmTypeFields = form => {
const scmFormFields = [
'scm_url',
'scm_branch',
@ -115,63 +106,7 @@ function ProjectForm(props) {
});
};
const gitScmTooltip = (
<span>
{i18n._(t`Example URLs for GIT SCM include:`)}
<ul css="margin: 10px 0 10px 20px">
<li>https://github.com/ansible/ansible.git</li>
<li>git@github.com:ansible/ansible.git</li>
<li>git://servername.example.com/ansible.git</li>
</ul>
{i18n._(t`Note: When using SSH protocol for GitHub or
Bitbucket, enter an SSH key only, do not enter a username
(other than git). Additionally, GitHub and Bitbucket do
not support password authentication when using SSH. GIT
read only protocol (git://) does not use username or
password information.`)}
</span>
);
const hgScmTooltip = (
<span>
{i18n._(t`Example URLs for Mercurial SCM include:`)}
<ul style={{ margin: '10px 0 10px 20px' }}>
<li>https://bitbucket.org/username/project</li>
<li>ssh://hg@bitbucket.org/username/project</li>
<li>ssh://server.example.com/path</li>
</ul>
{i18n._(t`Note: Mercurial does not support password authentication
for SSH. Do not put the username and key in the URL. If using
Bitbucket and SSH, do not supply your Bitbucket username.
`)}
</span>
);
const svnScmTooltip = (
<span>
{i18n._(t`Example URLs for Subversion SCM include:`)}
<ul style={{ margin: '10px 0 10px 20px' }}>
<li>https://github.com/ansible/ansible</li>
<li>svn://servername.example.com/path</li>
<li>svn+ssh://servername.example.com/path</li>
</ul>
</span>
);
const scmUrlTooltips = {
git: gitScmTooltip,
hg: hgScmTooltip,
svn: svnScmTooltip,
};
const scmBranchLabels = {
git: i18n._(t`SCM Branch/Tag/Commit`),
hg: i18n._(t`SCM Branch/Tag/Revision`),
svn: i18n._(t`Revision #`),
};
if (hasContentLoading) {
if (isLoading) {
return <ContentLoading />;
}
@ -180,343 +115,197 @@ function ProjectForm(props) {
}
return (
<Form autoComplete="off" onSubmit={handleSubmit}>
<FormRow>
<FormField
id="project-name"
label={i18n._(t`Name`)}
name="name"
type="text"
validate={required(null, i18n)}
isRequired
/>
<FormField
id="project-description"
label={i18n._(t`Description`)}
name="description"
type="text"
/>
<Field
name="organization"
validate={required(i18n._(t`Select a value for this field`), i18n)}
render={({ form }) => (
<OrganizationLookup
helperTextInvalid={form.errors.organization}
isValid={!form.touched.organization || !form.errors.organization}
onBlur={() => form.setFieldTouched('organization')}
onChange={value => {
form.setFieldValue('organization', value.id);
setOrganization(value);
}}
value={organization}
required
/>
)}
/>
<Field
name="scm_type"
validate={required(i18n._(t`Select a value for this field`), i18n)}
render={({ field, form }) => (
<FormGroup
fieldId="project-scm-type"
helperTextInvalid={form.errors.scm_type}
<Formik
initialValues={{
allow_override: project.allow_override || false,
credential: project.credential || '',
custom_virtualenv: project.custom_virtualenv || '',
description: project.description || '',
name: project.name || '',
organization: project.organization || '',
scm_branch: project.scm_branch || '',
scm_clean: project.scm_clean || false,
scm_delete_on_update: project.scm_delete_on_update || false,
scm_refspec: project.scm_refspec || '',
scm_type: project.scm_type || '',
scm_update_cache_timeout: project.scm_update_cache_timeout || 0,
scm_update_on_launch: project.scm_update_on_launch || false,
scm_url: project.scm_url || '',
}}
onSubmit={handleSubmit}
render={formik => (
<Form
autoComplete="off"
onSubmit={formik.handleSubmit}
css="padding: 0 24px"
>
<FormRow>
<FormField
id="project-name"
label={i18n._(t`Name`)}
name="name"
type="text"
validate={required(null, i18n)}
isRequired
isValid={!form.touched.scm_type || !form.errors.scm_type}
label={i18n._(t`SCM Type`)}
>
<AnsibleSelect
{...field}
id="scm_type"
data={[
{
value: '',
key: '',
label: i18n._(t`Choose an SCM Type`),
isDisabled: true,
},
...scmTypeOptions.map(option => {
if (option[1] === 'Manual') {
option[0] = 'manual';
}
return {
label: option[1],
value: option[0],
key: option[0],
};
}),
]}
onChange={(event, value) => {
form.setFieldValue('scm_type', value);
resetScmTypeFields(value, form);
}}
/>
</FormGroup>
)}
/>
{values.scm_type !== '' && (
<ScmTypeFormRow>
<Title size="md">{i18n._(t`Type Details`)}</Title>
{(values.scm_type === 'git' ||
values.scm_type === 'hg' ||
values.scm_type === 'svn') && (
<FormField
id="project-scm-url"
isRequired
label={i18n._(t`SCM URL`)}
name="scm_url"
type="text"
validate={required(null, i18n)}
tooltipMaxWidth="350px"
tooltip={scmUrlTooltips[values.scm_type]}
/>
)}
{(values.scm_type === 'git' ||
values.scm_type === 'hg' ||
values.scm_type === 'svn') && (
<FormField
id="project-scm-branch"
name="scm_branch"
type="text"
label={scmBranchLabels[values.scm_type]}
tooltip={i18n._(t`Branch to checkout. In addition to branches,
you can input tags, commit hashes, and arbitrary refs. Some
commit hashes and refs may not be availble unless you also
provide a custom refspec.`)}
/>
)}
{values.scm_type === 'git' && (
<FormField
id="project-scm-refspec"
label={i18n._(t`SCM Refspec`)}
name="scm_refspec"
type="text"
tooltipMaxWidth="400px"
tooltip={
<span>
{i18n._(t`A refspec to fetch (passed to the Ansible git
module). This parameter allows access to references via
the branch field not otherwise available.`)}
<br />
<br />
{i18n._(
t`Note: This field assumes the remote name is "origin".`
)}
<br />
<br />
{i18n._(t`Examples include:`)}
<ul style={{ margin: '10px 0 10px 20px' }}>
<li>refs/*:refs/remotes/origin/*</li>
<li>
refs/pull/62/head:refs/remotes/origin/pull/62/head
</li>
</ul>
{i18n._(t`The first fetches all references. The second
fetches the Github pull request number 62, in this example
the branch needs to be "pull/62/head".`)}
<br />
<br />
{i18n._(t`For more information, refer to the`)}{' '}
<Link to="https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#manage-playbooks-using-source-control">
{i18n._(t`Ansible Tower Documentation.`)}
</Link>
</span>
}
/>
)}
{(values.scm_type === 'git' ||
values.scm_type === 'hg' ||
values.scm_type === 'svn') && (
<Field
name="credential"
render={({ form }) => (
<CredentialLookup
credentialTypeId={scmCredential.typeId}
label={i18n._(t`SCM Credential`)}
value={scmCredential.value}
onChange={credential => {
form.setFieldValue('credential', credential.id);
setScmCredential({
...scmCredential,
value: credential,
});
}}
/>
)}
/>
)}
{values.scm_type === 'insights' && (
<Field
name="credential"
validate={required(
i18n._(t`Select a value for this field`),
i18n
)}
render={({ form }) => (
<CredentialLookup
credentialTypeId={insightsCredential.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,
});
}}
value={insightsCredential.value}
required
/>
)}
/>
)}
{/*
PF Bug: FormGroup doesn't pass down className
Workaround is to wrap FormGroup with an extra div
Cleanup when upgraded to @patternfly/react-core@3.103.4
*/}
{values.scm_type !== 'manual' && (
<OptionsFormGroup>
<FormGroup
fieldId="project-option-checkboxes"
label={i18n._(t`Options`)}
>
<FormRow>
<CheckboxField
id="option-scm-clean"
name="scm_clean"
label={i18n._(t`Clean`)}
tooltip={i18n._(
t`Remove any local modifications prior to performing an update.`
)}
/>
<CheckboxField
id="option-scm-delete-on-update"
name="scm_delete_on_update"
label={i18n._(t`Delete`)}
tooltip={i18n._(
t`Delete the local repository in its entirety prior to
performing an update. Depending on the size of the
repository this may significantly increase the amount
of time required to complete an update.`
)}
/>
<CheckboxField
id="option-scm-update-on-launch"
name="scm_update_on_launch"
label={i18n._(t`Update Revision on Launch`)}
tooltip={i18n._(
t`Each time a job runs using this project, update the
revision of the project prior to starting the job.`
)}
/>
{values.scm_type !== 'insights' && (
<CheckboxField
id="option-allow-override"
name="allow_override"
label={i18n._(t`Allow Branch Override`)}
tooltip={i18n._(
t`Allow changing the SCM branch or revision in a job
template that uses this project.`
)}
/>
)}
</FormRow>
</FormGroup>
</OptionsFormGroup>
)}
{values.scm_type !== 'manual' && values.scm_update_on_launch && (
<>
<Title size="md">{i18n._(t`Option Details`)}</Title>
<FormField
id="project-cache-timeout"
name="scm_update_cache_timeout"
type="number"
min="0"
label={i18n._(t`Cache Timeout`)}
tooltip={i18n._(t`Time in seconds to consider a project
to be current. During job runs and callbacks the task
system will evaluate the timestamp of the latest project
update. If it is older than Cache Timeout, it is not
considered current, and a new project update will be
performed.`)}
/>
<FormField
id="project-description"
label={i18n._(t`Description`)}
name="description"
type="text"
/>
<Field
name="organization"
validate={required(
i18n._(t`Select a value for this field`),
i18n
)}
render={({ form }) => (
<OrganizationLookup
helperTextInvalid={form.errors.organization}
isValid={
!form.touched.organization || !form.errors.organization
}
onBlur={() => form.setFieldTouched('organization')}
onChange={value => {
form.setFieldValue('organization', value.id);
setOrganization(value);
}}
value={organization}
required
/>
</>
)}
/>
<Field
name="scm_type"
validate={required(
i18n._(t`Select a value for this field`),
i18n
)}
render={({ field, form }) => (
<FormGroup
fieldId="project-scm-type"
helperTextInvalid={form.errors.scm_type}
isRequired
isValid={!form.touched.scm_type || !form.errors.scm_type}
label={i18n._(t`SCM Type`)}
>
<AnsibleSelect
{...field}
id="scm_type"
data={[
{
value: '',
key: '',
label: i18n._(t`Choose an SCM Type`),
isDisabled: true,
},
...scmTypeOptions.map(([value, label]) => {
if (label === 'Manual') {
value = 'manual';
}
return {
label,
value,
key: value,
};
}),
]}
onChange={(event, value) => {
form.setFieldValue('scm_type', value);
resetScmTypeFields(form);
}}
/>
</FormGroup>
)}
/>
{formik.values.scm_type !== '' && (
<ScmTypeFormRow>
<SubFormTitle size="md">{i18n._(t`Type Details`)}</SubFormTitle>
{
{
git: (
<GitSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
hg: (
<HgSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
svn: (
<SvnSubForm
setScmCredential={setScmCredential}
scmCredential={scmCredential}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
insights: (
<InsightsSubForm
setInsightsCredential={setInsightsCredential}
insightsCredential={insightsCredential}
scmUpdateOnLaunch={formik.values.scm_update_on_launch}
/>
),
}[formik.values.scm_type]
}
</ScmTypeFormRow>
)}
</ScmTypeFormRow>
)}
<Config>
{({ custom_virtualenvs }) =>
custom_virtualenvs &&
custom_virtualenvs.length > 1 && (
<Field
name="custom_virtualenv"
render={({ field }) => (
<FormGroup
fieldId="project-custom-virtualenv"
label={i18n._(t`Ansible Environment`)}
>
<FieldTooltip
content={i18n._(t`Select the playbook to be executed by
this job.`)}
/>
<AnsibleSelect
id="project-custom-virtualenv"
data={[
{
label: i18n._(t`Use Default Ansible Environment`),
value: '/venv/ansible/',
key: 'default',
},
...custom_virtualenvs
.filter(datum => datum !== '/venv/ansible/')
.map(datum => ({
label: datum,
value: datum,
key: datum,
})),
]}
{...field}
/>
</FormGroup>
)}
/>
)
}
</Config>
</FormRow>
<FormActionGroup onCancel={handleCancel} onSubmit={handleSubmit} />
</Form>
<Config>
{({ custom_virtualenvs }) =>
custom_virtualenvs &&
custom_virtualenvs.length > 1 && (
<Field
name="custom_virtualenv"
render={({ field }) => (
<FormGroup
fieldId="project-custom-virtualenv"
label={i18n._(t`Ansible Environment`)}
>
<FieldTooltip
content={i18n._(t`Select the playbook to be executed by
this job.`)}
/>
<AnsibleSelect
id="project-custom-virtualenv"
data={[
{
label: i18n._(t`Use Default Ansible Environment`),
value: '/venv/ansible/',
key: 'default',
},
...custom_virtualenvs
.filter(datum => datum !== '/venv/ansible/')
.map(datum => ({
label: datum,
value: datum,
key: datum,
})),
]}
{...field}
/>
</FormGroup>
)}
/>
)
}
</Config>
</FormRow>
<FormActionGroup
onCancel={handleCancel}
onSubmit={formik.handleSubmit}
/>
</Form>
)}
/>
);
}
const FormikApp = withFormik({
mapPropsToValues(props) {
const { project = {} } = props;
return {
credential: project.credential || '',
custom_virtualenv: project.custom_virtualenv || '',
description: project.description || '',
name: project.name || '',
organization: project.organization || '',
scm_branch: project.scm_branch || '',
scm_clean: project.scm_clean || false,
scm_delete_on_update: project.scm_delete_on_update || false,
scm_refspec: project.scm_refspec || '',
scm_type: project.scm_type || '',
scm_update_on_launch: project.scm_update_on_launch || false,
scm_url: project.scm_url || '',
scm_update_cache_timeout: project.scm_update_cache_timeout || 0,
allow_override: project.allow_override || false,
};
},
handleSubmit: (values, { props }) => props.handleSubmit(values),
})(ProjectForm);
ProjectForm.propTypes = {
handleCancel: PropTypes.func.isRequired,
handleSubmit: PropTypes.func.isRequired,
@ -527,4 +316,4 @@ ProjectForm.defaultProps = {
project: {},
};
export default withI18n()(withRouter(FormikApp));
export default withI18n()(ProjectForm);

View File

@ -243,7 +243,7 @@ describe('<ProjectAdd />', () => {
});
wrapper.update();
await act(async () => {
scmTypeSelect.props().onChange('git', { target: { name: 'insights' } });
scmTypeSelect.props().onChange('svn', { target: { name: 'Subversion' } });
});
wrapper.update();
expect(formik.state.values.scm_url).toEqual('');

View File

@ -0,0 +1,84 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import FormField from '@components/FormField';
import {
UrlFormField,
BranchFormField,
ScmCredentialFormField,
ScmTypeOptions,
} from './SharedFields';
const GitSubForm = ({
i18n,
scmCredential,
setScmCredential,
scmUpdateOnLaunch,
}) => (
<>
<UrlFormField
i18n={i18n}
tooltip={
<span>
{i18n._(t`Example URLs for GIT SCM include:`)}
<ul css="margin: 10px 0 10px 20px">
<li>https://github.com/ansible/ansible.git</li>
<li>git@github.com:ansible/ansible.git</li>
<li>git://servername.example.com/ansible.git</li>
</ul>
{i18n._(t`Note: When using SSH protocol for GitHub or
Bitbucket, enter an SSH key only, do not enter a username
(other than git). Additionally, GitHub and Bitbucket do
not support password authentication when using SSH. GIT
read only protocol (git://) does not use username or
password information.`)}
</span>
}
/>
<BranchFormField i18n={i18n} label={i18n._(t`SCM Branch/Tag/Commit`)} />
<FormField
id="project-scm-refspec"
label={i18n._(t`SCM Refspec`)}
name="scm_refspec"
type="text"
tooltipMaxWidth="400px"
tooltip={
<span>
{i18n._(t`A refspec to fetch (passed to the Ansible git
module). This parameter allows access to references via
the branch field not otherwise available.`)}
<br />
<br />
{i18n._(t`Note: This field assumes the remote name is "origin".`)}
<br />
<br />
{i18n._(t`Examples include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}>
<li>refs/*:refs/remotes/origin/*</li>
<li>refs/pull/62/head:refs/remotes/origin/pull/62/head</li>
</ul>
{i18n._(t`The first fetches all references. The second
fetches the Github pull request number 62, in this example
the branch needs to be "pull/62/head".`)}
<br />
<br />
{i18n._(t`For more information, refer to the`)}{' '}
<a
target="_blank"
rel="noopener noreferrer"
href="https://docs.ansible.com/ansible-tower/latest/html/userguide/projects.html#manage-playbooks-using-source-control"
>
{i18n._(t`Ansible Tower Documentation.`)}
</a>
</span>
}
/>
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>
);
export default withI18n()(GitSubForm);

View File

@ -0,0 +1,44 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
UrlFormField,
BranchFormField,
ScmCredentialFormField,
ScmTypeOptions,
} from './SharedFields';
const HgSubForm = ({
i18n,
scmCredential,
setScmCredential,
scmUpdateOnLaunch,
}) => (
<>
<UrlFormField
i18n={i18n}
tooltip={
<span>
{i18n._(t`Example URLs for Mercurial SCM include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}>
<li>https://bitbucket.org/username/project</li>
<li>ssh://hg@bitbucket.org/username/project</li>
<li>ssh://server.example.com/path</li>
</ul>
{i18n._(t`Note: Mercurial does not support password authentication
for SSH. Do not put the username and key in the URL. If using
Bitbucket and SSH, do not supply your Bitbucket username.
`)}
</span>
}
/>
<BranchFormField i18n={i18n} label={i18n._(t`SCM Branch/Tag/Revision`)} />
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>
);
export default withI18n()(HgSubForm);

View File

@ -0,0 +1,42 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Field } from 'formik';
import CredentialLookup from '@components/Lookup/CredentialLookup';
import { required } from '@util/validators';
import { ScmTypeOptions } from './SharedFields';
const InsightsSubForm = ({
i18n,
setInsightsCredential,
insightsCredential,
scmUpdateOnLaunch,
}) => (
<>
<Field
name="credential"
validate={required(i18n._(t`Select a value for this field`), i18n)}
render={({ form }) => (
<CredentialLookup
credentialTypeId={insightsCredential.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,
});
}}
value={insightsCredential.value}
required
/>
)}
/>
<ScmTypeOptions hideAllowOverride scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>
);
export default withI18n()(InsightsSubForm);

View File

@ -0,0 +1,135 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import { Field } from 'formik';
import CredentialLookup from '@components/Lookup/CredentialLookup';
import FormField, { CheckboxField } from '@components/FormField';
import { required } from '@util/validators';
import FormRow from '@components/FormRow';
import { FormGroup, Title } from '@patternfly/react-core';
import styled from 'styled-components';
export const SubFormTitle = styled(Title)`
--pf-c-title--m-md--FontWeight: 700;
grid-column: 1 / -1;
`;
export const UrlFormField = withI18n()(({ i18n, tooltip }) => (
<FormField
id="project-scm-url"
isRequired
label={i18n._(t`SCM URL`)}
name="scm_url"
tooltip={tooltip}
tooltipMaxWidth="350px"
type="text"
validate={required(null, i18n)}
/>
));
export const BranchFormField = withI18n()(({ i18n, label }) => (
<FormField
id="project-scm-branch"
name="scm_branch"
type="text"
label={label}
tooltip={i18n._(t`Branch to checkout. In addition to branches,
you can input tags, commit hashes, and arbitrary refs. Some
commit hashes and refs may not be availble unless you also
provide a custom refspec.`)}
/>
));
export const ScmCredentialFormField = withI18n()(
({ i18n, setScmCredential, scmCredential }) => (
<Field
name="credential"
render={({ form }) => (
<CredentialLookup
credentialTypeId={scmCredential.typeId}
label={i18n._(t`SCM Credential`)}
value={scmCredential.value}
onChange={credential => {
form.setFieldValue('credential', credential.id);
setScmCredential({
...scmCredential,
value: credential,
});
}}
/>
)}
/>
)
);
export const ScmTypeOptions = withI18n()(
({ i18n, scmUpdateOnLaunch, hideAllowOverride }) => (
<>
<FormGroup
css="grid-column: 1/-1"
fieldId="project-option-checkboxes"
label={i18n._(t`Options`)}
>
<FormRow>
<CheckboxField
id="option-scm-clean"
name="scm_clean"
label={i18n._(t`Clean`)}
tooltip={i18n._(
t`Remove any local modifications prior to performing an update.`
)}
/>
<CheckboxField
id="option-scm-delete-on-update"
name="scm_delete_on_update"
label={i18n._(t`Delete`)}
tooltip={i18n._(
t`Delete the local repository in its entirety prior to
performing an update. Depending on the size of the
repository this may significantly increase the amount
of time required to complete an update.`
)}
/>
<CheckboxField
id="option-scm-update-on-launch"
name="scm_update_on_launch"
label={i18n._(t`Update Revision on Launch`)}
tooltip={i18n._(
t`Each time a job runs using this project, update the
revision of the project prior to starting the job.`
)}
/>
{!hideAllowOverride && (
<CheckboxField
id="option-allow-override"
name="allow_override"
label={i18n._(t`Allow Branch Override`)}
tooltip={i18n._(
t`Allow changing the SCM branch or revision in a job
template that uses this project.`
)}
/>
)}
</FormRow>
</FormGroup>
{scmUpdateOnLaunch && (
<>
<SubFormTitle size="md">{i18n._(t`Option Details`)}</SubFormTitle>
<FormField
id="project-cache-timeout"
name="scm_update_cache_timeout"
type="number"
min="0"
label={i18n._(t`Cache Timeout`)}
tooltip={i18n._(t`Time in seconds to consider a project
to be current. During job runs and callbacks the task
system will evaluate the timestamp of the latest project
update. If it is older than Cache Timeout, it is not
considered current, and a new project update will be
performed.`)}
/>
</>
)}
</>
)
);

View File

@ -0,0 +1,40 @@
import React from 'react';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import {
UrlFormField,
BranchFormField,
ScmCredentialFormField,
ScmTypeOptions,
} from './SharedFields';
const SvnSubForm = ({
i18n,
scmCredential,
setScmCredential,
scmUpdateOnLaunch,
}) => (
<>
<UrlFormField
i18n={i18n}
tooltip={
<span>
{i18n._(t`Example URLs for Subversion SCM include:`)}
<ul css={{ margin: '10px 0 10px 20px' }}>
<li>https://github.com/ansible/ansible</li>
<li>svn://servername.example.com/path</li>
<li>svn+ssh://servername.example.com/path</li>
</ul>
</span>
}
/>
<BranchFormField i18n={i18n} label={i18n._(t`Revision #`)} />
<ScmCredentialFormField
setScmCredential={setScmCredential}
scmCredential={scmCredential}
/>
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
</>
);
export default withI18n()(SvnSubForm);

View File

@ -0,0 +1,5 @@
export { default as GitSubForm } from './GitSubForm';
export { default as HgSubForm } from './HgSubForm';
export { default as SvnSubForm } from './SvnSubForm';
export { default as InsightsSubForm } from './InsightsSubForm';
export { SubFormTitle } from './SharedFields';