diff --git a/awx/ui_next/src/components/PromptDetail/PromptDetail.jsx b/awx/ui_next/src/components/PromptDetail/PromptDetail.jsx
index e10fc1e4a0..a8c4952460 100644
--- a/awx/ui_next/src/components/PromptDetail/PromptDetail.jsx
+++ b/awx/ui_next/src/components/PromptDetail/PromptDetail.jsx
@@ -5,7 +5,7 @@ import { withI18n } from '@lingui/react';
import { t, Trans } from '@lingui/macro';
import { Link } from 'react-router-dom';
import styled from 'styled-components';
-import { Chip, Divider } from '@patternfly/react-core';
+import { Chip, Divider, Title } from '@patternfly/react-core';
import { toTitleCase } from '../../util/strings';
import CredentialChip from '../CredentialChip';
@@ -18,9 +18,19 @@ import PromptInventorySourceDetail from './PromptInventorySourceDetail';
import PromptJobTemplateDetail from './PromptJobTemplateDetail';
import PromptWFJobTemplateDetail from './PromptWFJobTemplateDetail';
-const PromptHeader = styled.h2`
- font-weight: bold;
- margin: var(--pf-global--spacer--lg) 0;
+const PromptTitle = styled(Title)`
+ margin-top: var(--pf-global--spacer--xl);
+ --pf-c-title--m-md--FontWeight: 700;
+ grid-column: 1 / -1;
+`;
+
+const PromptDivider = styled(Divider)`
+ margin-top: var(--pf-global--spacer--lg);
+ margin-bottom: var(--pf-global--spacer--lg);
+`;
+
+const PromptDetailList = styled(DetailList)`
+ padding: 0px var(--pf-global--spacer--lg);
`;
function formatTimeout(timeout) {
@@ -136,9 +146,11 @@ function PromptDetail({ i18n, resource, launchConfig = {}, overrides = {} }) {
{hasPromptData(launchConfig) && hasOverrides && (
<>
-
- {i18n._(t`Prompted Values`)}
-
+
+ {i18n._(t`Prompted Values`)}
+
+
+
{launchConfig.ask_job_type_on_launch && (
)}
-
+
>
)}
>
diff --git a/awx/ui_next/src/components/Schedule/ScheduleDetail/ScheduleDetail.jsx b/awx/ui_next/src/components/Schedule/ScheduleDetail/ScheduleDetail.jsx
index eee6b25c32..946ac94f55 100644
--- a/awx/ui_next/src/components/Schedule/ScheduleDetail/ScheduleDetail.jsx
+++ b/awx/ui_next/src/components/Schedule/ScheduleDetail/ScheduleDetail.jsx
@@ -5,7 +5,7 @@ import { RRule, rrulestr } from 'rrule';
import styled from 'styled-components';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
-import { Chip, Title, Button } from '@patternfly/react-core';
+import { Chip, Divider, Title, Button } from '@patternfly/react-core';
import { Schedule } from '../../../types';
import AlertModal from '../../AlertModal';
import { CardBody, CardActionsRow } from '../../Card';
@@ -27,11 +27,21 @@ import ErrorDetail from '../../ErrorDetail';
import ChipGroup from '../../ChipGroup';
import { VariablesDetail } from '../../CodeMirrorInput';
+const PromptDivider = styled(Divider)`
+ margin-top: var(--pf-global--spacer--lg);
+ margin-bottom: var(--pf-global--spacer--lg);
+`;
+
const PromptTitle = styled(Title)`
+ margin-top: 40px;
--pf-c-title--m-md--FontWeight: 700;
grid-column: 1 / -1;
`;
+const PromptDetailList = styled(DetailList)`
+ padding: 0px 20px;
+`;
+
function ScheduleDetail({ schedule, i18n }) {
const {
id,
@@ -41,6 +51,7 @@ function ScheduleDetail({ schedule, i18n }) {
dtend,
dtstart,
extra_data,
+ inventory,
job_tags,
job_type,
limit,
@@ -52,12 +63,21 @@ function ScheduleDetail({ schedule, i18n }) {
skip_tags,
summary_fields,
timezone,
+ verbosity,
} = schedule;
const history = useHistory();
const { pathname } = useLocation();
const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
+ const VERBOSITY = {
+ 0: i18n._(t`0 (Normal)`),
+ 1: i18n._(t`1 (Verbose)`),
+ 2: i18n._(t`2 (More Verbose)`),
+ 3: i18n._(t`3 (Debug)`),
+ 4: i18n._(t`4 (Connection Debug)`),
+ };
+
const {
request: deleteSchedule,
isLoading: isDeleteLoading,
@@ -140,18 +160,34 @@ function ScheduleDetail({ schedule, i18n }) {
survey_enabled,
} = launchData || {};
+ const showCredentialsDetail =
+ ask_credential_on_launch && credentials.length > 0;
+ const showInventoryDetail = ask_inventory_on_launch && inventory;
+ const showVariablesDetail =
+ (ask_variables_on_launch || survey_enabled) &&
+ ((typeof extra_data === 'string' && extra_data !== '') ||
+ (typeof extra_data === 'object' && Object.keys(extra_data).length > 0));
+ const showTagsDetail = ask_tags_on_launch && job_tags && job_tags.length > 0;
+ const showSkipTagsDetail =
+ ask_skip_tags_on_launch && skip_tags && skip_tags.length > 0;
+ const showDiffModeDetail =
+ ask_diff_mode_on_launch && typeof diff_mode === 'boolean';
+ const showLimitDetail = ask_limit_on_launch && limit;
+ const showJobTypeDetail = ask_job_type_on_launch && job_type;
+ const showSCMBranchDetail = ask_scm_branch_on_launch && scm_branch;
+ const showVerbosityDetail = ask_verbosity_on_launch && VERBOSITY[verbosity];
+
const showPromptedFields =
- ask_credential_on_launch ||
- ask_diff_mode_on_launch ||
- ask_inventory_on_launch ||
- ask_job_type_on_launch ||
- ask_limit_on_launch ||
- ask_scm_branch_on_launch ||
- ask_skip_tags_on_launch ||
- ask_tags_on_launch ||
- ask_variables_on_launch ||
- ask_verbosity_on_launch ||
- survey_enabled;
+ showCredentialsDetail ||
+ showDiffModeDetail ||
+ showInventoryDetail ||
+ showJobTypeDetail ||
+ showLimitDetail ||
+ showSCMBranchDetail ||
+ showSkipTagsDetail ||
+ showTagsDetail ||
+ showVerbosityDetail ||
+ showVariablesDetail;
if (isLoading) {
return ;
@@ -189,15 +225,18 @@ function ScheduleDetail({ schedule, i18n }) {
date={modified}
user={summary_fields.modified_by}
/>
- {showPromptedFields && (
- <>
-
- {i18n._(t`Prompted Fields`)}
-
+
+ {showPromptedFields && (
+ <>
+
+ {i18n._(t`Prompted Values`)}
+
+
+
{ask_job_type_on_launch && (
)}
- {ask_inventory_on_launch && (
+ {showInventoryDetail && (
)}
- {ask_diff_mode_on_launch && typeof diff_mode === 'boolean' && (
+ {ask_verbosity_on_launch && (
+
+ )}
+ {showDiffModeDetail && (
)}
- {ask_credential_on_launch && (
+ {showCredentialsDetail && (
)}
- {ask_tags_on_launch && job_tags && job_tags.length > 0 && (
+ {showTagsDetail && (
)}
- {ask_skip_tags_on_launch && skip_tags && skip_tags.length > 0 && (
+ {showSkipTagsDetail && (
)}
- {(ask_variables_on_launch || survey_enabled) && (
+ {showVariablesDetail && (
)}
- >
- )}
-
+
+ >
+ )}
{summary_fields?.user_capabilities?.edit && (
', () => {
expect(wrapper.find('Detail[label="Repeat Frequency"]').length).toBe(1);
expect(wrapper.find('Detail[label="Created"]').length).toBe(1);
expect(wrapper.find('Detail[label="Last Modified"]').length).toBe(1);
- expect(wrapper.find('Title[children="Prompted Fields"]').length).toBe(0);
+ expect(wrapper.find('Title[children="Prompted Values"]').length).toBe(0);
expect(wrapper.find('Detail[label="Job Type"]').length).toBe(0);
expect(wrapper.find('Detail[label="Inventory"]').length).toBe(0);
expect(wrapper.find('Detail[label="Source Control Branch"]').length).toBe(
0
);
expect(wrapper.find('Detail[label="Limit"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Verbosity"]').length).toBe(0);
expect(wrapper.find('Detail[label="Show Changes"]').length).toBe(0);
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(0);
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(0);
@@ -189,18 +207,6 @@ describe('', () => {
},
});
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(allPrompts);
- const scheduleWithPrompts = {
- ...schedule,
- job_type: 'run',
- inventory: 1,
- job_tags: 'tag1',
- skip_tags: 'tag2',
- scm_branch: 'foo/branch',
- limit: 'localhost',
- diff_mode: true,
- verbosity: 1,
- extra_data: { foo: 'fii' },
- };
await act(async () => {
wrapper = mountWithContexts(
', () => {
expect(wrapper.find('Detail[label="Repeat Frequency"]').length).toBe(1);
expect(wrapper.find('Detail[label="Created"]').length).toBe(1);
expect(wrapper.find('Detail[label="Last Modified"]').length).toBe(1);
- expect(wrapper.find('Title[children="Prompted Fields"]').length).toBe(1);
+ expect(wrapper.find('Title[children="Prompted Values"]').length).toBe(1);
expect(
wrapper
.find('Detail[label="Job Type"]')
@@ -265,12 +271,102 @@ describe('', () => {
.find('dd')
.text()
).toBe('localhost');
+ expect(
+ wrapper
+ .find('Detail[label="Verbosity"]')
+ .find('dd')
+ .text()
+ ).toBe('1 (Verbose)');
expect(wrapper.find('Detail[label="Show Changes"]').length).toBe(1);
expect(wrapper.find('Detail[label="Credentials"]').length).toBe(1);
expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(1);
expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(1);
expect(wrapper.find('VariablesDetail').length).toBe(1);
});
+ test('prompt values section should be hidden if no overrides are present on the schedule but ask_ options are all true', async () => {
+ SchedulesAPI.readCredentials.mockResolvedValueOnce({
+ data: {
+ count: 0,
+ results: [],
+ },
+ });
+ JobTemplatesAPI.readLaunch.mockResolvedValueOnce(allPrompts);
+ await act(async () => {
+ wrapper = mountWithContexts(
+ }
+ />,
+ {
+ context: {
+ router: {
+ history,
+ route: {
+ location: history.location,
+ match: { params: { id: 1 } },
+ },
+ },
+ },
+ }
+ );
+ });
+ await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
+ expect(wrapper.find('Title[children="Prompted Values"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Job Type"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Inventory"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Source Control Branch"]').length).toBe(
+ 0
+ );
+ expect(wrapper.find('Detail[label="Limit"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Verbosity"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Show Changes"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Credentials"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(0);
+ expect(wrapper.find('VariablesDetail').length).toBe(0);
+ });
+ test('prompt values section should be hidden if overrides are present on the schedule but ask_ options are all false', async () => {
+ SchedulesAPI.readCredentials.mockResolvedValueOnce({
+ data: {
+ count: 0,
+ results: [],
+ },
+ });
+ JobTemplatesAPI.readLaunch.mockResolvedValueOnce(noPrompts);
+ await act(async () => {
+ wrapper = mountWithContexts(
+ }
+ />,
+ {
+ context: {
+ router: {
+ history,
+ route: {
+ location: history.location,
+ match: { params: { id: 1 } },
+ },
+ },
+ },
+ }
+ );
+ });
+ await waitForElement(wrapper, 'ContentLoading', el => el.length === 0);
+ expect(wrapper.find('Title[children="Prompted Values"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Job Type"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Inventory"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Source Control Branch"]').length).toBe(
+ 0
+ );
+ expect(wrapper.find('Detail[label="Limit"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Verbosity"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Show Changes"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Credentials"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Job Tags"]').length).toBe(0);
+ expect(wrapper.find('Detail[label="Skip Tags"]').length).toBe(0);
+ expect(wrapper.find('VariablesDetail').length).toBe(0);
+ });
test('error shown when error encountered fetching credentials', async () => {
SchedulesAPI.readCredentials.mockRejectedValueOnce(
new Error({