mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Adds popover help text to project details, and unifies those strings (used in the form and the details view) into 1 file (#12039)
This commit is contained in:
parent
3a1268de1e
commit
ae7960e9d7
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { node, bool, string } from 'prop-types';
|
||||
|
||||
import { oneOfType, node, bool, string } from 'prop-types';
|
||||
import { TextListItem, TextListItemVariants } from '@patternfly/react-core';
|
||||
import styled from 'styled-components';
|
||||
import Popover from '../Popover';
|
||||
@ -81,7 +82,7 @@ Detail.propTypes = {
|
||||
value: node,
|
||||
fullWidth: bool,
|
||||
alwaysVisible: bool,
|
||||
helpText: string,
|
||||
helpText: oneOfType([string, node]),
|
||||
};
|
||||
Detail.defaultProps = {
|
||||
value: null,
|
||||
|
||||
@ -10,6 +10,8 @@ const PopoverButton = styled.button`
|
||||
padding: var(--pf-global--spacer--xs);
|
||||
margin: -(var(--pf-global--spacer--xs));
|
||||
font-size: var(--pf-global--FontSize--sm);
|
||||
--pf-c-form__group-label-help--Color: var(--pf-global--Color--200);
|
||||
--pf-c-form__group-label-help--hover--Color: var(--pf-global--Color--100);
|
||||
`;
|
||||
|
||||
function Popover({ ariaLabel, content, header, id, maxWidth, ...rest }) {
|
||||
|
||||
@ -27,7 +27,9 @@ import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||
import { relatedResourceDeleteRequests } from 'util/getRelatedResourceDeleteDetails';
|
||||
import StatusLabel from 'components/StatusLabel';
|
||||
import { formatDateString } from 'util/dates';
|
||||
import Popover from 'components/Popover';
|
||||
import ProjectSyncButton from '../shared/ProjectSyncButton';
|
||||
import ProjectHelpTextStrings from '../shared/Project.helptext';
|
||||
import useWsProject from './useWsProject';
|
||||
|
||||
const Label = styled.span`
|
||||
@ -57,7 +59,7 @@ function ProjectDetail({ project }) {
|
||||
summary_fields,
|
||||
} = useWsProject(project);
|
||||
const history = useHistory();
|
||||
|
||||
const projectHelpText = ProjectHelpTextStrings();
|
||||
const {
|
||||
request: deleteProject,
|
||||
isLoading,
|
||||
@ -82,29 +84,37 @@ function ProjectDetail({ project }) {
|
||||
optionsList = (
|
||||
<TextList component={TextListVariants.ul}>
|
||||
{scm_clean && (
|
||||
<TextListItem
|
||||
component={TextListItemVariants.li}
|
||||
>{t`Discard local changes before syncing`}</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.li}>
|
||||
{t`Discard local changes before syncing`}
|
||||
<Popover content={projectHelpText.options.clean} />
|
||||
</TextListItem>
|
||||
)}
|
||||
{scm_delete_on_update && (
|
||||
<TextListItem
|
||||
component={TextListItemVariants.li}
|
||||
>{t`Delete the project before syncing`}</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.li}>
|
||||
{t`Delete the project before syncing`}{' '}
|
||||
<Popover
|
||||
content={projectHelpText.options.delete}
|
||||
id="scm-delete-on-update"
|
||||
/>
|
||||
</TextListItem>
|
||||
)}
|
||||
{scm_track_submodules && (
|
||||
<TextListItem
|
||||
component={TextListItemVariants.li}
|
||||
>{t`Track submodules latest commit on branch`}</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.li}>
|
||||
{t`Track submodules latest commit on branch`}{' '}
|
||||
<Popover content={projectHelpText.options.trackSubModules} />
|
||||
</TextListItem>
|
||||
)}
|
||||
{scm_update_on_launch && (
|
||||
<TextListItem
|
||||
component={TextListItemVariants.li}
|
||||
>{t`Update revision on job launch`}</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.li}>
|
||||
{t`Update revision on job launch`}{' '}
|
||||
<Popover content={projectHelpText.options.updateOnLaunch} />
|
||||
</TextListItem>
|
||||
)}
|
||||
{allow_override && (
|
||||
<TextListItem
|
||||
component={TextListItemVariants.li}
|
||||
>{t`Allow branch override`}</TextListItem>
|
||||
<TextListItem component={TextListItemVariants.li}>
|
||||
{t`Allow branch override`}{' '}
|
||||
<Popover content={projectHelpText.options.allowBranchOverride} />
|
||||
</TextListItem>
|
||||
)}
|
||||
</TextList>
|
||||
);
|
||||
@ -134,7 +144,10 @@ function ProjectDetail({ project }) {
|
||||
} else if (summary_fields?.last_job) {
|
||||
job = summary_fields.last_job;
|
||||
}
|
||||
|
||||
const getSourceControlUrlHelpText = () =>
|
||||
scm_type === 'git'
|
||||
? projectHelpText.githubSourceControlUrl
|
||||
: projectHelpText.svnSourceControlUrl;
|
||||
return (
|
||||
<CardBody>
|
||||
<DetailList gutter="sm">
|
||||
@ -197,9 +210,25 @@ function ProjectDetail({ project }) {
|
||||
}
|
||||
alwaysVisible
|
||||
/>
|
||||
<Detail label={t`Source Control URL`} value={scm_url} />
|
||||
<Detail label={t`Source Control Branch`} value={scm_branch} />
|
||||
<Detail label={t`Source Control Refspec`} value={scm_refspec} />
|
||||
<Detail
|
||||
helpText={
|
||||
scm_type === 'git' || scm_type === 'svn'
|
||||
? getSourceControlUrlHelpText()
|
||||
: ''
|
||||
}
|
||||
label={t`Source Control URL`}
|
||||
value={scm_url}
|
||||
/>
|
||||
<Detail
|
||||
helpText={projectHelpText.branchFormField}
|
||||
label={t`Source Control Branch`}
|
||||
value={scm_branch}
|
||||
/>
|
||||
<Detail
|
||||
helpText={projectHelpText.sourceControlRefspec}
|
||||
label={t`Source Control Refspec`}
|
||||
value={scm_refspec}
|
||||
/>
|
||||
{summary_fields.credential && (
|
||||
<Detail
|
||||
label={t`Source Control Credential`}
|
||||
@ -217,16 +246,25 @@ function ProjectDetail({ project }) {
|
||||
value={`${scm_update_cache_timeout} ${t`Seconds`}`}
|
||||
/>
|
||||
<ExecutionEnvironmentDetail
|
||||
helpText={projectHelpText.executionEnvironment}
|
||||
virtualEnvironment={custom_virtualenv}
|
||||
executionEnvironment={summary_fields?.default_environment}
|
||||
isDefaultEnvironment
|
||||
/>
|
||||
<Config>
|
||||
{({ project_base_dir }) => (
|
||||
<Detail label={t`Project Base Path`} value={project_base_dir} />
|
||||
<Detail
|
||||
helpText={projectHelpText.projectBasePath}
|
||||
label={t`Project Base Path`}
|
||||
value={project_base_dir}
|
||||
/>
|
||||
)}
|
||||
</Config>
|
||||
<Detail label={t`Playbook Directory`} value={local_path} />
|
||||
<Detail
|
||||
helpText={projectHelpText.projectLocalPath}
|
||||
label={t`Playbook Directory`}
|
||||
value={local_path}
|
||||
/>
|
||||
<UserDateDetail
|
||||
label={t`Created`}
|
||||
date={created}
|
||||
|
||||
@ -20,6 +20,12 @@ jest.mock('react-router-dom', () => ({
|
||||
url: '/projects/1/details',
|
||||
}),
|
||||
}));
|
||||
jest.mock('hooks/useBrandName', () => ({
|
||||
__esModule: true,
|
||||
default: () => ({
|
||||
current: 'AWX',
|
||||
}),
|
||||
}));
|
||||
describe('<ProjectDetail />', () => {
|
||||
const mockProject = {
|
||||
id: 1,
|
||||
@ -126,16 +132,18 @@ describe('<ProjectDetail />', () => {
|
||||
'2019-10-10T01:15:06.780490Z'
|
||||
);
|
||||
expect(
|
||||
wrapper
|
||||
.find('Detail[label="Enabled Options"]')
|
||||
.containsAllMatchingElements([
|
||||
<li>Discard local changes before syncing</li>,
|
||||
<li>Delete the project before syncing</li>,
|
||||
<li>Track submodules latest commit on branch</li>,
|
||||
<li>Update revision on job launch</li>,
|
||||
<li>Allow branch override</li>,
|
||||
])
|
||||
).toEqual(true);
|
||||
wrapper.find('Detail[label="Enabled Options"]').find('li')
|
||||
).toHaveLength(5);
|
||||
const options = [
|
||||
'Discard local changes before syncing',
|
||||
'Delete the project before syncing',
|
||||
'Track submodules latest commit on branch',
|
||||
'Update revision on job launch',
|
||||
'Allow branch override',
|
||||
];
|
||||
wrapper.find('li').map((item, index) => {
|
||||
expect(item.text().includes(options[index]));
|
||||
});
|
||||
});
|
||||
|
||||
test('should hide options label when all project options return false', () => {
|
||||
@ -237,7 +245,7 @@ describe('<ProjectDetail />', () => {
|
||||
expect(history.location.pathname).toEqual('/projects/1/edit');
|
||||
});
|
||||
|
||||
test('sync button should call api to syn project', async () => {
|
||||
test('sync button should call api to sync project', async () => {
|
||||
ProjectsAPI.readSync.mockResolvedValue({ data: { can_update: true } });
|
||||
const wrapper = mountWithContexts(<ProjectDetail project={mockProject} />);
|
||||
await act(() =>
|
||||
|
||||
@ -6,7 +6,12 @@ import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import ProjectsListItem from './ProjectListItem';
|
||||
|
||||
jest.mock('../../../api/models/Projects');
|
||||
|
||||
jest.mock('hooks/useBrandName', () => ({
|
||||
__esModule: true,
|
||||
default: () => ({
|
||||
current: 'AWX',
|
||||
}),
|
||||
}));
|
||||
describe('<ProjectsListItem />', () => {
|
||||
test('launch button shown to users with start capabilities', () => {
|
||||
const wrapper = mountWithContexts(
|
||||
|
||||
142
awx/ui/src/screens/Project/shared/Project.helptext.js
Normal file
142
awx/ui/src/screens/Project/shared/Project.helptext.js
Normal file
@ -0,0 +1,142 @@
|
||||
import React from 'react';
|
||||
import { t } from '@lingui/macro';
|
||||
import getDocsBaseUrl from 'util/getDocsBaseUrl';
|
||||
import { useConfig } from 'contexts/Config';
|
||||
import useBrandName from 'hooks/useBrandName';
|
||||
|
||||
const ProjectHelpTextStrings = () => ({
|
||||
executionEnvironment: t`The execution environment that will be used for jobs that use this project. This will be used as fallback when an execution environment has not been explicitly assigned at the job template or workflow level.`,
|
||||
projectBasePath: (
|
||||
<span>
|
||||
{t`Base path used for locating playbooks. Directories
|
||||
found inside this path will be listed in the playbook directory drop-down.
|
||||
Together the base path and selected playbook directory provide the full
|
||||
path used to locate playbooks.`}
|
||||
<br />
|
||||
<br />
|
||||
{t`Change PROJECTS_ROOT when deploying
|
||||
${useBrandName()} to change this location.`}
|
||||
</span>
|
||||
),
|
||||
projectLocalPath: t`Select from the list of directories found in
|
||||
the Project Base Path. Together the base path and the playbook
|
||||
directory provide the full path used to locate playbooks.`,
|
||||
githubSourceControlUrl: (
|
||||
<span>
|
||||
{t`Example URLs for GIT Source Control include:`}
|
||||
<ul css="margin: 10px 0 10px 20px">
|
||||
<li>
|
||||
<code>https://github.com/ansible/ansible.git</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>git@github.com:ansible/ansible.git</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>git://servername.example.com/ansible.git</code>
|
||||
</li>
|
||||
</ul>
|
||||
{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>
|
||||
),
|
||||
svnSourceControlUrl: (
|
||||
<span>
|
||||
{t`Example URLs for Subversion Source Control include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>https://github.com/ansible/ansible</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>svn://servername.example.com/path</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>svn+ssh://servername.example.com/path</code>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
),
|
||||
syncButtonDisabled: t`This project is currently on sync and cannot be clicked until sync process completed`,
|
||||
archiveUrl: (
|
||||
<span>
|
||||
{t`Example URLs for Remote Archive Source Control include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>https://github.com/username/project/archive/v0.0.1.tar.gz</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>https://github.com/username/project/archive/v0.0.2.zip</code>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
),
|
||||
|
||||
sourceControlRefspec: (
|
||||
<span>
|
||||
{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 />
|
||||
{t`Note: This field assumes the remote name is "origin".`}
|
||||
<br />
|
||||
<br />
|
||||
{t`Examples include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>refs/*:refs/remotes/origin/*</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>refs/pull/62/head:refs/remotes/origin/pull/62/head</code>
|
||||
</li>
|
||||
</ul>
|
||||
{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 />
|
||||
{t`For more information, refer to the`}{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={`${getDocsBaseUrl(
|
||||
useConfig()
|
||||
)}/html/userguide/projects.html#manage-playbooks-using-source-control`}
|
||||
>
|
||||
{t`Documentation.`}
|
||||
</a>
|
||||
</span>
|
||||
),
|
||||
branchFormField: 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 available unless you also
|
||||
provide a custom refspec.`,
|
||||
options: {
|
||||
clean: t`Remove any local modifications prior to performing an update.`,
|
||||
delete: 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.`,
|
||||
trackSubModules: t`Submodules will track the latest commit on
|
||||
their master branch (or other branch specified in
|
||||
.gitmodules). If no, submodules will be kept at
|
||||
the revision specified by the main project.
|
||||
This is equivalent to specifying the --remote
|
||||
flag to git submodule update.`,
|
||||
updateOnLaunch: t`Each time a job runs using this project, update the
|
||||
revision of the project prior to starting the job.`,
|
||||
allowBranchOverride: t`Allow changing the Source Control branch or revision in a job
|
||||
template that uses this project.`,
|
||||
cacheTimeout: 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.`,
|
||||
},
|
||||
});
|
||||
|
||||
export default ProjectHelpTextStrings;
|
||||
@ -16,6 +16,7 @@ import ExecutionEnvironmentLookup from 'components/Lookup/ExecutionEnvironmentLo
|
||||
import { CredentialTypesAPI, ProjectsAPI } from 'api';
|
||||
import { required } from 'util/validators';
|
||||
import { FormColumnLayout, SubFormLayout } from 'components/FormLayout';
|
||||
import ProjectHelpTextStrings from './Project.helptext';
|
||||
import {
|
||||
GitSubForm,
|
||||
SvnSubForm,
|
||||
@ -195,7 +196,7 @@ function ProjectFormFields({
|
||||
}
|
||||
onBlur={() => executionEnvironmentHelpers.setTouched()}
|
||||
value={executionEnvironmentField.value}
|
||||
popoverContent={t`The execution environment that will be used for jobs that use this project. This will be used as fallback when an execution environment has not been explicitly assigned at the job template or workflow level.`}
|
||||
popoverContent={ProjectHelpTextStrings.execution_environment}
|
||||
onChange={handleExecutionEnvironmentUpdate}
|
||||
tooltip={t`Select an organization before editing the default execution environment.`}
|
||||
globallyAvailable
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import 'styled-components/macro';
|
||||
import React from 'react';
|
||||
import ProjectHelpTextStrings from '../Project.helptext';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import {
|
||||
UrlFormField,
|
||||
ScmCredentialFormField,
|
||||
@ -12,33 +12,18 @@ const ArchiveSubForm = ({
|
||||
credential,
|
||||
onCredentialSelection,
|
||||
scmUpdateOnLaunch,
|
||||
}) => (
|
||||
<>
|
||||
<UrlFormField
|
||||
tooltip={
|
||||
<span>
|
||||
{t`Example URLs for Remote Archive Source Control include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>
|
||||
https://github.com/username/project/archive/v0.0.1.tar.gz
|
||||
</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>
|
||||
https://github.com/username/project/archive/v0.0.2.zip
|
||||
</code>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<ScmCredentialFormField
|
||||
credential={credential}
|
||||
onCredentialSelection={onCredentialSelection}
|
||||
/>
|
||||
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
|
||||
</>
|
||||
);
|
||||
}) => {
|
||||
const projectHelpText = ProjectHelpTextStrings();
|
||||
return (
|
||||
<>
|
||||
<UrlFormField tooltip={projectHelpText.archiveUrl} />
|
||||
<ScmCredentialFormField
|
||||
credential={credential}
|
||||
onCredentialSelection={onCredentialSelection}
|
||||
/>
|
||||
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ArchiveSubForm;
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import 'styled-components/macro';
|
||||
import React from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import FormField from 'components/FormField';
|
||||
import { useConfig } from 'contexts/Config';
|
||||
import getDocsBaseUrl from 'util/getDocsBaseUrl';
|
||||
|
||||
import {
|
||||
UrlFormField,
|
||||
BranchFormField,
|
||||
@ -12,38 +10,17 @@ import {
|
||||
ScmTypeOptions,
|
||||
} from './SharedFields';
|
||||
|
||||
import ProjectHelpTextStrings from '../Project.helptext';
|
||||
|
||||
const GitSubForm = ({
|
||||
credential,
|
||||
onCredentialSelection,
|
||||
scmUpdateOnLaunch,
|
||||
}) => {
|
||||
const config = useConfig();
|
||||
const projectHelpStrings = ProjectHelpTextStrings();
|
||||
return (
|
||||
<>
|
||||
<UrlFormField
|
||||
tooltip={
|
||||
<span>
|
||||
{t`Example URLs for GIT Source Control include:`}
|
||||
<ul css="margin: 10px 0 10px 20px">
|
||||
<li>
|
||||
<code>https://github.com/ansible/ansible.git</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>git@github.com:ansible/ansible.git</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>git://servername.example.com/ansible.git</code>
|
||||
</li>
|
||||
</ul>
|
||||
{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>
|
||||
}
|
||||
/>
|
||||
<UrlFormField tooltip={projectHelpStrings.githubSourceControlUrl} />
|
||||
<BranchFormField label={t`Source Control Branch/Tag/Commit`} />
|
||||
<FormField
|
||||
id="project-scm-refspec"
|
||||
@ -51,42 +28,7 @@ const GitSubForm = ({
|
||||
name="scm_refspec"
|
||||
type="text"
|
||||
tooltipMaxWidth="400px"
|
||||
tooltip={
|
||||
<span>
|
||||
{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 />
|
||||
{t`Note: This field assumes the remote name is "origin".`}
|
||||
<br />
|
||||
<br />
|
||||
{t`Examples include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>refs/*:refs/remotes/origin/*</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>refs/pull/62/head:refs/remotes/origin/pull/62/head</code>
|
||||
</li>
|
||||
</ul>
|
||||
{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 />
|
||||
{t`For more information, refer to the`}{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={`${getDocsBaseUrl(
|
||||
config
|
||||
)}/html/userguide/projects.html#manage-playbooks-using-source-control`}
|
||||
>
|
||||
{t`Documentation.`}
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
tooltip={projectHelpStrings.sourceControlRefspec}
|
||||
/>
|
||||
<ScmCredentialFormField
|
||||
credential={credential}
|
||||
|
||||
@ -8,6 +8,7 @@ import AnsibleSelect from 'components/AnsibleSelect';
|
||||
import FormField from 'components/FormField';
|
||||
import Popover from 'components/Popover';
|
||||
import useBrandName from 'hooks/useBrandName';
|
||||
import ProjectHelpStrings from '../Project.helptext';
|
||||
|
||||
const ManualSubForm = ({
|
||||
localPath,
|
||||
@ -15,6 +16,7 @@ const ManualSubForm = ({
|
||||
project_local_paths,
|
||||
}) => {
|
||||
const brandName = useBrandName();
|
||||
const projectHelpStrings = ProjectHelpStrings();
|
||||
|
||||
const localPaths = [...new Set([...project_local_paths, localPath])];
|
||||
const options = [
|
||||
@ -61,18 +63,7 @@ const ManualSubForm = ({
|
||||
name="base_dir"
|
||||
type="text"
|
||||
isReadOnly
|
||||
tooltip={
|
||||
<span>
|
||||
{t`Base path used for locating playbooks. Directories
|
||||
found inside this path will be listed in the playbook directory drop-down.
|
||||
Together the base path and selected playbook directory provide the full
|
||||
path used to locate playbooks.`}
|
||||
<br />
|
||||
<br />
|
||||
{t`Change PROJECTS_ROOT when deploying
|
||||
${brandName} to change this location.`}
|
||||
</span>
|
||||
}
|
||||
tooltip={projectHelpStrings.projectBasePath}
|
||||
/>
|
||||
<FormGroup
|
||||
fieldId="project-local-path"
|
||||
@ -80,13 +71,7 @@ const ManualSubForm = ({
|
||||
isRequired
|
||||
validated={!pathMeta.touched || !pathMeta.error ? 'default' : 'error'}
|
||||
label={t`Playbook Directory`}
|
||||
labelIcon={
|
||||
<Popover
|
||||
content={t`Select from the list of directories found in
|
||||
the Project Base Path. Together the base path and the playbook
|
||||
directory provide the full path used to locate playbooks.`}
|
||||
/>
|
||||
}
|
||||
labelIcon={<Popover content={projectHelpStrings.projectLocalPath} />}
|
||||
>
|
||||
<AnsibleSelect
|
||||
{...pathField}
|
||||
|
||||
@ -7,6 +7,7 @@ import CredentialLookup from 'components/Lookup/CredentialLookup';
|
||||
import FormField, { CheckboxField } from 'components/FormField';
|
||||
import { required } from 'util/validators';
|
||||
import { FormCheckboxLayout, FormFullWidthLayout } from 'components/FormLayout';
|
||||
import ProjectHelpTextStrings from '../Project.helptext';
|
||||
|
||||
export const UrlFormField = ({ tooltip }) => (
|
||||
<FormField
|
||||
@ -21,18 +22,18 @@ export const UrlFormField = ({ tooltip }) => (
|
||||
/>
|
||||
);
|
||||
|
||||
export const BranchFormField = ({ label }) => (
|
||||
<FormField
|
||||
id="project-scm-branch"
|
||||
name="scm_branch"
|
||||
type="text"
|
||||
label={label}
|
||||
tooltip={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 available unless you also
|
||||
provide a custom refspec.`}
|
||||
/>
|
||||
);
|
||||
export const BranchFormField = ({ label }) => {
|
||||
const projectHelpStrings = ProjectHelpTextStrings();
|
||||
return (
|
||||
<FormField
|
||||
id="project-scm-branch"
|
||||
name="scm_branch"
|
||||
type="text"
|
||||
label={label}
|
||||
tooltip={projectHelpStrings.branchFormField}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const ScmCredentialFormField = ({
|
||||
credential,
|
||||
@ -59,74 +60,66 @@ export const ScmCredentialFormField = ({
|
||||
);
|
||||
};
|
||||
|
||||
export const ScmTypeOptions = ({ scmUpdateOnLaunch, hideAllowOverride }) => (
|
||||
<FormFullWidthLayout>
|
||||
<FormGroup fieldId="project-option-checkboxes" label={t`Options`}>
|
||||
<FormCheckboxLayout>
|
||||
<CheckboxField
|
||||
id="option-scm-clean"
|
||||
name="scm_clean"
|
||||
label={t`Clean`}
|
||||
tooltip={t`Remove any local modifications prior to performing an update.`}
|
||||
/>
|
||||
<CheckboxField
|
||||
id="option-scm-delete-on-update"
|
||||
name="scm_delete_on_update"
|
||||
label={t`Delete`}
|
||||
tooltip={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-track-submodules"
|
||||
name="scm_track_submodules"
|
||||
label={t`Track submodules`}
|
||||
tooltip={t`Submodules will track the latest commit on
|
||||
their master branch (or other branch specified in
|
||||
.gitmodules). If no, submodules will be kept at
|
||||
the revision specified by the main project.
|
||||
This is equivalent to specifying the --remote
|
||||
flag to git submodule update.`}
|
||||
/>
|
||||
<CheckboxField
|
||||
id="option-scm-update-on-launch"
|
||||
name="scm_update_on_launch"
|
||||
label={t`Update Revision on Launch`}
|
||||
tooltip={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={t`Allow Branch Override`}
|
||||
tooltip={t`Allow changing the Source Control branch or revision in a job
|
||||
template that uses this project.`}
|
||||
/>
|
||||
)}
|
||||
</FormCheckboxLayout>
|
||||
</FormGroup>
|
||||
export const ScmTypeOptions = ({ scmUpdateOnLaunch, hideAllowOverride }) => {
|
||||
const projectHelpStrings = ProjectHelpTextStrings();
|
||||
const { values } = useFormikContext();
|
||||
|
||||
{scmUpdateOnLaunch && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Option Details`}
|
||||
</Title>
|
||||
<FormField
|
||||
id="project-cache-timeout"
|
||||
name="scm_update_cache_timeout"
|
||||
type="number"
|
||||
min="0"
|
||||
label={t`Cache Timeout`}
|
||||
tooltip={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.`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormFullWidthLayout>
|
||||
);
|
||||
return (
|
||||
<FormFullWidthLayout>
|
||||
<FormGroup fieldId="project-option-checkboxes" label={t`Options`}>
|
||||
<FormCheckboxLayout>
|
||||
<CheckboxField
|
||||
id="option-scm-clean"
|
||||
name="scm_clean"
|
||||
label={t`Clean`}
|
||||
tooltip={projectHelpStrings.options.clean}
|
||||
/>
|
||||
<CheckboxField
|
||||
id="option-scm-delete-on-update"
|
||||
name="scm_delete_on_update"
|
||||
label={t`Delete`}
|
||||
tooltip={projectHelpStrings.options.delete}
|
||||
/>
|
||||
{values.scm_type === 'git' ? (
|
||||
<CheckboxField
|
||||
id="option-scm-track-submodules"
|
||||
name="scm_track_submodules"
|
||||
label={t`Track submodules`}
|
||||
tooltip={projectHelpStrings.options.trackSubModules}
|
||||
/>
|
||||
) : null}
|
||||
<CheckboxField
|
||||
id="option-scm-update-on-launch"
|
||||
name="scm_update_on_launch"
|
||||
label={t`Update Revision on Launch`}
|
||||
tooltip={projectHelpStrings.options.updateOnLaunch}
|
||||
/>
|
||||
{!hideAllowOverride && (
|
||||
<CheckboxField
|
||||
id="option-allow-override"
|
||||
name="allow_override"
|
||||
label={t`Allow Branch Override`}
|
||||
tooltip={projectHelpStrings.options.allowBranchOverride}
|
||||
/>
|
||||
)}
|
||||
</FormCheckboxLayout>
|
||||
</FormGroup>
|
||||
|
||||
{scmUpdateOnLaunch && (
|
||||
<>
|
||||
<Title size="md" headingLevel="h4">
|
||||
{t`Option Details`}
|
||||
</Title>
|
||||
<FormField
|
||||
id="project-cache-timeout"
|
||||
name="scm_update_cache_timeout"
|
||||
type="number"
|
||||
min="0"
|
||||
label={t`Cache Timeout`}
|
||||
tooltip={projectHelpStrings.options.cacheTimeout}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</FormFullWidthLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import 'styled-components/macro';
|
||||
import React from 'react';
|
||||
|
||||
import { t } from '@lingui/macro';
|
||||
import ProjectHelpTextStrings from '../Project.helptext';
|
||||
|
||||
import {
|
||||
UrlFormField,
|
||||
BranchFormField,
|
||||
@ -13,33 +14,19 @@ const SvnSubForm = ({
|
||||
credential,
|
||||
onCredentialSelection,
|
||||
scmUpdateOnLaunch,
|
||||
}) => (
|
||||
<>
|
||||
<UrlFormField
|
||||
tooltip={
|
||||
<span>
|
||||
{t`Example URLs for Subversion Source Control include:`}
|
||||
<ul css={{ margin: '10px 0 10px 20px' }}>
|
||||
<li>
|
||||
<code>https://github.com/ansible/ansible</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>svn://servername.example.com/path</code>
|
||||
</li>
|
||||
<li>
|
||||
<code>svn+ssh://servername.example.com/path</code>
|
||||
</li>
|
||||
</ul>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
<BranchFormField label={t`Revision #`} />
|
||||
<ScmCredentialFormField
|
||||
credential={credential}
|
||||
onCredentialSelection={onCredentialSelection}
|
||||
/>
|
||||
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
|
||||
</>
|
||||
);
|
||||
}) => {
|
||||
const projectHelpStrings = ProjectHelpTextStrings();
|
||||
return (
|
||||
<>
|
||||
<UrlFormField tooltip={projectHelpStrings.svnSourceControlUrl} />
|
||||
<BranchFormField label={t`Revision #`} />
|
||||
<ScmCredentialFormField
|
||||
credential={credential}
|
||||
onCredentialSelection={onCredentialSelection}
|
||||
/>
|
||||
<ScmTypeOptions scmUpdateOnLaunch={scmUpdateOnLaunch} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SvnSubForm;
|
||||
|
||||
@ -11,6 +11,7 @@ import useRequest, { useDismissableError } from 'hooks/useRequest';
|
||||
import AlertModal from 'components/AlertModal';
|
||||
import ErrorDetail from 'components/ErrorDetail';
|
||||
import { ProjectsAPI } from 'api';
|
||||
import ProjectHelpTextStrings from './Project.helptext';
|
||||
|
||||
function ProjectSyncButton({ projectId, lastJobStatus = null }) {
|
||||
const match = useRouteMatch();
|
||||
@ -21,7 +22,7 @@ function ProjectSyncButton({ projectId, lastJobStatus = null }) {
|
||||
}, [projectId]),
|
||||
null
|
||||
);
|
||||
|
||||
const projectHelpStrings = ProjectHelpTextStrings();
|
||||
const { error, dismissError } = useDismissableError(syncError);
|
||||
const isDetailsView = match.url.endsWith('/details');
|
||||
const isDisabled = ['pending', 'waiting', 'running'].includes(lastJobStatus);
|
||||
@ -29,10 +30,7 @@ function ProjectSyncButton({ projectId, lastJobStatus = null }) {
|
||||
return (
|
||||
<>
|
||||
{isDisabled ? (
|
||||
<Tooltip
|
||||
content={t`This project is currently on sync and cannot be clicked until sync process completed`}
|
||||
position="top"
|
||||
>
|
||||
<Tooltip content={projectHelpStrings.syncButtonDisabled} position="top">
|
||||
<div>
|
||||
<Button
|
||||
ouiaId={`${projectId}-sync-button`}
|
||||
|
||||
@ -6,7 +6,12 @@ import { mountWithContexts } from '../../../../testUtils/enzymeHelpers';
|
||||
import ProjectSyncButton from './ProjectSyncButton';
|
||||
|
||||
jest.mock('../../../api');
|
||||
|
||||
jest.mock('hooks/useBrandName', () => ({
|
||||
__esModule: true,
|
||||
default: () => ({
|
||||
current: 'AWX',
|
||||
}),
|
||||
}));
|
||||
describe('ProjectSyncButton', () => {
|
||||
let wrapper;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user