mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Refactors to add warning icon and disable save if schedule has missing values
This commit is contained in:
parent
c608d761a2
commit
561390d405
@ -19,7 +19,13 @@ import ScheduleEdit from './ScheduleEdit';
|
||||
import { SchedulesAPI } from '../../api';
|
||||
import useRequest from '../../util/useRequest';
|
||||
|
||||
function Schedule({ i18n, setBreadcrumb, resource }) {
|
||||
function Schedule({
|
||||
i18n,
|
||||
setBreadcrumb,
|
||||
resource,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
}) {
|
||||
const { scheduleId } = useParams();
|
||||
|
||||
const { pathname } = useLocation();
|
||||
@ -100,13 +106,18 @@ function Schedule({ i18n, setBreadcrumb, resource }) {
|
||||
/>
|
||||
{schedule && [
|
||||
<Route key="edit" path={`${pathRoot}schedules/:id/edit`}>
|
||||
<ScheduleEdit schedule={schedule} resource={resource} />
|
||||
<ScheduleEdit
|
||||
schedule={schedule}
|
||||
resource={resource}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
/>
|
||||
</Route>,
|
||||
<Route
|
||||
key="details"
|
||||
path={`${pathRoot}schedules/:scheduleId/details`}
|
||||
>
|
||||
<ScheduleDetail schedule={schedule} />
|
||||
<ScheduleDetail schedule={schedule} surveyConfig={surveyConfig} />
|
||||
</Route>,
|
||||
]}
|
||||
<Route key="not-found" path="*">
|
||||
|
||||
@ -15,14 +15,18 @@ import mergeExtraVars from '../../../util/prompt/mergeExtraVars';
|
||||
import getSurveyValues from '../../../util/prompt/getSurveyValues';
|
||||
import { getAddedAndRemoved } from '../../../util/lists';
|
||||
|
||||
function ScheduleAdd({ i18n, resource, apiModel }) {
|
||||
function ScheduleAdd({ i18n, resource, apiModel, launchConfig, surveyConfig }) {
|
||||
const [formSubmitError, setFormSubmitError] = useState(null);
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const { pathname } = location;
|
||||
const pathRoot = pathname.substr(0, pathname.indexOf('schedules'));
|
||||
|
||||
const handleSubmit = async (values, launchConfig, surveyConfig) => {
|
||||
const handleSubmit = async (
|
||||
values,
|
||||
launchConfiguration,
|
||||
surveyConfiguration
|
||||
) => {
|
||||
const {
|
||||
inventory,
|
||||
extra_vars,
|
||||
@ -51,8 +55,9 @@ function ScheduleAdd({ i18n, resource, apiModel }) {
|
||||
let extraVars;
|
||||
const surveyValues = getSurveyValues(values);
|
||||
const initialExtraVars =
|
||||
launchConfig?.ask_variables_on_launch && (values.extra_vars || '---');
|
||||
if (surveyConfig?.spec) {
|
||||
launchConfiguration?.ask_variables_on_launch &&
|
||||
(values.extra_vars || '---');
|
||||
if (surveyConfiguration?.spec) {
|
||||
extraVars = yaml.safeDump(mergeExtraVars(initialExtraVars, surveyValues));
|
||||
} else {
|
||||
extraVars = yaml.safeDump(mergeExtraVars(initialExtraVars, {}));
|
||||
@ -92,6 +97,8 @@ function ScheduleAdd({ i18n, resource, apiModel }) {
|
||||
handleCancel={() => history.push(`${pathRoot}schedules`)}
|
||||
handleSubmit={handleSubmit}
|
||||
submitError={formSubmitError}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
resource={resource}
|
||||
/>
|
||||
</CardBody>
|
||||
|
||||
@ -19,45 +19,45 @@ SchedulesAPI.readZoneInfo.mockResolvedValue({
|
||||
},
|
||||
],
|
||||
});
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||
data: {
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
defaults: {
|
||||
extra_vars: '---',
|
||||
diff_mode: false,
|
||||
limit: '',
|
||||
job_tags: '',
|
||||
skip_tags: '',
|
||||
job_type: 'run',
|
||||
verbosity: 0,
|
||||
inventory: {
|
||||
name: null,
|
||||
id: null,
|
||||
},
|
||||
scm_branch: '',
|
||||
},
|
||||
|
||||
const launchConfig = {
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
});
|
||||
defaults: {
|
||||
extra_vars: '---',
|
||||
diff_mode: false,
|
||||
limit: '',
|
||||
job_tags: '',
|
||||
skip_tags: '',
|
||||
job_type: 'run',
|
||||
verbosity: 0,
|
||||
inventory: {
|
||||
name: null,
|
||||
id: null,
|
||||
},
|
||||
scm_branch: '',
|
||||
},
|
||||
};
|
||||
|
||||
JobTemplatesAPI.createSchedule.mockResolvedValue({ data: { id: 3 } });
|
||||
|
||||
let wrapper;
|
||||
@ -74,6 +74,7 @@ describe('<ScheduleAdd />', () => {
|
||||
inventory: 2,
|
||||
summary_fields: { credentials: [] },
|
||||
}}
|
||||
launchConfig={launchConfig}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -377,7 +378,6 @@ describe('<ScheduleAdd />', () => {
|
||||
);
|
||||
wrapper.update();
|
||||
expect(wrapper.find('Wizard').length).toBe(0);
|
||||
// console.log(wrapper.debug());
|
||||
await act(async () => {
|
||||
wrapper.find('Formik').invoke('onSubmit')({
|
||||
name: 'Schedule',
|
||||
|
||||
@ -42,7 +42,7 @@ const PromptDetailList = styled(DetailList)`
|
||||
padding: 0px 20px;
|
||||
`;
|
||||
|
||||
function ScheduleDetail({ schedule, i18n }) {
|
||||
function ScheduleDetail({ schedule, i18n, surveyConfig }) {
|
||||
const {
|
||||
id,
|
||||
created,
|
||||
@ -148,6 +148,7 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
|
||||
const {
|
||||
ask_credential_on_launch,
|
||||
inventory_needed_to_start,
|
||||
ask_diff_mode_on_launch,
|
||||
ask_inventory_on_launch,
|
||||
ask_job_type_on_launch,
|
||||
@ -160,6 +161,41 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
survey_enabled,
|
||||
} = launchData || {};
|
||||
|
||||
const missingRequiredInventory = () => {
|
||||
if (!inventory_needed_to_start || schedule?.summary_fields?.inventory?.id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const hasMissingSurveyValue = () => {
|
||||
let missingValues = false;
|
||||
if (survey_enabled) {
|
||||
surveyConfig.spec.forEach(question => {
|
||||
const hasDefaultValue = Boolean(question.default);
|
||||
if (question.required && !hasDefaultValue) {
|
||||
const extraDataKeys = Object.keys(schedule?.extra_data);
|
||||
|
||||
const hasMatchingKey = extraDataKeys.includes(question.variable);
|
||||
Object.values(schedule?.extra_data).forEach(value => {
|
||||
if (!value || !hasMatchingKey) {
|
||||
missingValues = true;
|
||||
} else {
|
||||
missingValues = false;
|
||||
}
|
||||
});
|
||||
if (!Object.values(schedule.extra_data).length) {
|
||||
missingValues = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return missingValues;
|
||||
};
|
||||
const isDisabled = Boolean(
|
||||
missingRequiredInventory() || hasMissingSurveyValue()
|
||||
);
|
||||
|
||||
const showCredentialsDetail =
|
||||
ask_credential_on_launch && credentials.length > 0;
|
||||
const showInventoryDetail = ask_inventory_on_launch && inventory;
|
||||
@ -189,14 +225,6 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
showVerbosityDetail ||
|
||||
showVariablesDetail;
|
||||
|
||||
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)`),
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <ContentLoading />;
|
||||
}
|
||||
@ -207,7 +235,11 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
|
||||
return (
|
||||
<CardBody>
|
||||
<ScheduleToggle schedule={schedule} css="padding-bottom: 40px" />
|
||||
<ScheduleToggle
|
||||
schedule={schedule}
|
||||
css="padding-bottom: 40px"
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
<DetailList gutter="sm">
|
||||
<Detail label={i18n._(t`Name`)} value={name} />
|
||||
<Detail label={i18n._(t`Description`)} value={description} />
|
||||
@ -279,12 +311,6 @@ function ScheduleDetail({ schedule, i18n }) {
|
||||
{ask_limit_on_launch && (
|
||||
<Detail label={i18n._(t`Limit`)} value={limit} />
|
||||
)}
|
||||
{ask_verbosity_on_launch && (
|
||||
<Detail
|
||||
label={i18n._(t`Verbosity`)}
|
||||
value={VERBOSITY[verbosity]}
|
||||
/>
|
||||
)}
|
||||
{showDiffModeDetail && (
|
||||
<Detail
|
||||
label={i18n._(t`Show Changes`)}
|
||||
|
||||
@ -26,6 +26,7 @@ const allPrompts = {
|
||||
ask_variables_on_launch: true,
|
||||
ask_verbosity_on_launch: true,
|
||||
survey_enabled: true,
|
||||
inventory_needed_to_start: true,
|
||||
},
|
||||
};
|
||||
|
||||
@ -489,4 +490,39 @@ describe('<ScheduleDetail />', () => {
|
||||
);
|
||||
expect(SchedulesAPI.destroy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
test('should have disabled toggle', async () => {
|
||||
SchedulesAPI.readCredentials.mockResolvedValueOnce({
|
||||
data: {
|
||||
count: 0,
|
||||
results: [],
|
||||
},
|
||||
});
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValueOnce(allPrompts);
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<Route
|
||||
path="/templates/job_template/:id/schedules/:scheduleId"
|
||||
component={() => (
|
||||
<ScheduleDetail schedule={schedule} surveyConfig={{ spec: [] }} />
|
||||
)}
|
||||
/>,
|
||||
{
|
||||
context: {
|
||||
router: {
|
||||
history,
|
||||
route: {
|
||||
location: history.location,
|
||||
match: { params: { id: 1 } },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
await waitForElement(
|
||||
wrapper,
|
||||
'ScheduleToggle',
|
||||
el => el.prop('isDisabled') === true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -15,7 +15,13 @@ import { parseVariableField } from '../../../util/yaml';
|
||||
import mergeExtraVars from '../../../util/prompt/mergeExtraVars';
|
||||
import getSurveyValues from '../../../util/prompt/getSurveyValues';
|
||||
|
||||
function ScheduleEdit({ i18n, schedule, resource }) {
|
||||
function ScheduleEdit({
|
||||
i18n,
|
||||
schedule,
|
||||
resource,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
}) {
|
||||
const [formSubmitError, setFormSubmitError] = useState(null);
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
@ -24,8 +30,8 @@ function ScheduleEdit({ i18n, schedule, resource }) {
|
||||
|
||||
const handleSubmit = async (
|
||||
values,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
launchConfiguration,
|
||||
surveyConfiguration,
|
||||
scheduleCredentials = []
|
||||
) => {
|
||||
const {
|
||||
@ -36,32 +42,40 @@ function ScheduleEdit({ i18n, schedule, resource }) {
|
||||
interval,
|
||||
startDateTime,
|
||||
timezone,
|
||||
occurrences,
|
||||
occurences,
|
||||
runOn,
|
||||
runOnTheDay,
|
||||
runOnTheMonth,
|
||||
runOnDayMonth,
|
||||
runOnDayNumber,
|
||||
endDateTime,
|
||||
runOnTheOccurrence,
|
||||
runOnTheOccurence,
|
||||
daysOfWeek,
|
||||
...submitValues
|
||||
} = values;
|
||||
const { added, removed } = getAddedAndRemoved(
|
||||
[...resource?.summary_fields.credentials, ...scheduleCredentials],
|
||||
[...(resource?.summary_fields.credentials || []), ...scheduleCredentials],
|
||||
credentials
|
||||
);
|
||||
|
||||
let extraVars;
|
||||
const surveyValues = getSurveyValues(values);
|
||||
const initialExtraVars =
|
||||
launchConfig?.ask_variables_on_launch && (values.extra_vars || '---');
|
||||
if (surveyConfig?.spec) {
|
||||
launchConfiguration?.ask_variables_on_launch &&
|
||||
(values.extra_vars || '---');
|
||||
if (surveyConfiguration?.spec) {
|
||||
extraVars = yaml.safeDump(mergeExtraVars(initialExtraVars, surveyValues));
|
||||
} else {
|
||||
extraVars = yaml.safeDump(mergeExtraVars(initialExtraVars, {}));
|
||||
}
|
||||
submitValues.extra_data = extraVars && parseVariableField(extraVars);
|
||||
|
||||
if (
|
||||
Object.keys(submitValues.extra_data).length === 0 &&
|
||||
Object.keys(schedule.extra_data).length > 0
|
||||
) {
|
||||
submitValues.extra_data = schedule.extra_data;
|
||||
}
|
||||
delete values.extra_vars;
|
||||
if (inventory) {
|
||||
submitValues.inventory = inventory.id;
|
||||
@ -103,6 +117,8 @@ function ScheduleEdit({ i18n, schedule, resource }) {
|
||||
handleSubmit={handleSubmit}
|
||||
submitError={formSubmitError}
|
||||
resource={resource}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
/>
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
@ -7,7 +7,6 @@ import {
|
||||
} from '../../../../testUtils/enzymeHelpers';
|
||||
import {
|
||||
SchedulesAPI,
|
||||
JobTemplatesAPI,
|
||||
InventoriesAPI,
|
||||
CredentialsAPI,
|
||||
CredentialTypesAPI,
|
||||
@ -28,46 +27,6 @@ SchedulesAPI.readZoneInfo.mockResolvedValue({
|
||||
],
|
||||
});
|
||||
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||
data: {
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: true,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: true,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
defaults: {
|
||||
extra_vars: '---',
|
||||
diff_mode: false,
|
||||
limit: '',
|
||||
job_tags: '',
|
||||
skip_tags: '',
|
||||
job_type: 'run',
|
||||
verbosity: 0,
|
||||
inventory: {
|
||||
name: null,
|
||||
id: null,
|
||||
},
|
||||
scm_branch: '',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
SchedulesAPI.readCredentials.mockResolvedValue({
|
||||
data: {
|
||||
results: [
|
||||
@ -156,6 +115,44 @@ describe('<ScheduleEdit />', () => {
|
||||
],
|
||||
},
|
||||
}}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: true,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: true,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
defaults: {
|
||||
extra_vars: '---',
|
||||
diff_mode: false,
|
||||
limit: '',
|
||||
job_tags: '',
|
||||
skip_tags: '',
|
||||
job_type: 'run',
|
||||
verbosity: 0,
|
||||
inventory: {
|
||||
name: null,
|
||||
id: null,
|
||||
},
|
||||
scm_branch: '',
|
||||
},
|
||||
}}
|
||||
surveyConfig={{}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -202,6 +199,7 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Run every 10 minutes 10 times',
|
||||
extra_data: {},
|
||||
occurrences: 10,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200325T103000 RRULE:INTERVAL=10;FREQ=MINUTELY;COUNT=10',
|
||||
});
|
||||
@ -265,6 +263,7 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Run weekly on mon/wed/fri',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
rrule: `DTSTART;TZID=America/New_York:20200325T104500 RRULE:INTERVAL=1;FREQ=WEEKLY;BYDAY=${RRule.MO},${RRule.WE},${RRule.FR}`,
|
||||
});
|
||||
});
|
||||
@ -287,6 +286,7 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Run on the first day of the month',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200401T104500 RRULE:INTERVAL=1;FREQ=MONTHLY;BYMONTHDAY=1',
|
||||
});
|
||||
@ -312,6 +312,8 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Run monthly on the last Tuesday',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
runOnTheOccurrence: -1,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200331T110000 RRULE:INTERVAL=1;FREQ=MONTHLY;BYSETPOS=-1;BYDAY=TU',
|
||||
});
|
||||
@ -336,6 +338,7 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Yearly on the first day of March',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200301T000000 RRULE:INTERVAL=1;FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=1',
|
||||
});
|
||||
@ -361,6 +364,8 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Yearly on the second Friday in April',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
runOnTheOccurrence: 2,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200410T111500 RRULE:INTERVAL=1;FREQ=YEARLY;BYSETPOS=2;BYDAY=FR;BYMONTH=4',
|
||||
});
|
||||
@ -386,6 +391,8 @@ describe('<ScheduleEdit />', () => {
|
||||
description: 'test description',
|
||||
name: 'Yearly on the first weekday in October',
|
||||
extra_data: {},
|
||||
occurrences: 1,
|
||||
runOnTheOccurrence: 1,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200410T111500 RRULE:INTERVAL=1;FREQ=YEARLY;BYSETPOS=1;BYDAY=MO,TU,WE,TH,FR;BYMONTH=10',
|
||||
});
|
||||
@ -515,6 +522,8 @@ describe('<ScheduleEdit />', () => {
|
||||
expect(SchedulesAPI.update).toBeCalledWith(27, {
|
||||
extra_data: {},
|
||||
name: 'mock schedule',
|
||||
occurrences: 1,
|
||||
runOnTheOccurrence: 1,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20210128T141500 RRULE:COUNT=1;FREQ=MINUTELY',
|
||||
skip_tags: '',
|
||||
@ -590,8 +599,10 @@ describe('<ScheduleEdit />', () => {
|
||||
expect(SchedulesAPI.update).toBeCalledWith(27, {
|
||||
description: '',
|
||||
extra_data: {},
|
||||
inventory: 702,
|
||||
occurrences: 1,
|
||||
runOnTheOccurrence: 1,
|
||||
name: 'foo',
|
||||
inventory: 702,
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;COUNT=1;FREQ=MINUTELY',
|
||||
});
|
||||
|
||||
@ -24,6 +24,9 @@ function ScheduleList({
|
||||
loadSchedules,
|
||||
loadScheduleOptions,
|
||||
hideAddButton,
|
||||
resource,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
}) {
|
||||
const [selected, setSelected] = useState([]);
|
||||
|
||||
@ -114,6 +117,47 @@ function ScheduleList({
|
||||
actions &&
|
||||
Object.prototype.hasOwnProperty.call(actions, 'POST') &&
|
||||
!hideAddButton;
|
||||
const isTemplate =
|
||||
resource?.type === 'workflow_job_template' ||
|
||||
resource?.type === 'job_template';
|
||||
|
||||
const missingRequiredInventory = schedule => {
|
||||
if (
|
||||
!launchConfig.inventory_needed_to_start ||
|
||||
schedule?.summary_fields?.inventory?.id
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
return i18n._(t`This schedule is missing an Inventory`);
|
||||
};
|
||||
|
||||
const hasMissingSurveyValue = schedule => {
|
||||
let missingValues;
|
||||
if (launchConfig.survey_enabled) {
|
||||
surveyConfig.spec.forEach(question => {
|
||||
const hasDefaultValue = Boolean(question.default);
|
||||
if (question.required && !hasDefaultValue) {
|
||||
const extraDataKeys = Object.keys(schedule?.extra_data);
|
||||
|
||||
const hasMatchingKey = extraDataKeys.includes(question.variable);
|
||||
Object.values(schedule?.extra_data).forEach(value => {
|
||||
if (!value || !hasMatchingKey) {
|
||||
missingValues = true;
|
||||
} else {
|
||||
missingValues = false;
|
||||
}
|
||||
});
|
||||
if (!Object.values(schedule.extra_data).length) {
|
||||
missingValues = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return (
|
||||
missingValues &&
|
||||
i18n._(t`This schedule is missing required survey values`)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -139,6 +183,8 @@ function ScheduleList({
|
||||
onSelect={() => handleSelect(item)}
|
||||
schedule={item}
|
||||
rowIndex={index}
|
||||
isMissingInventory={isTemplate && missingRequiredInventory(item)}
|
||||
isMissingSurvey={isTemplate && hasMissingSurveyValue(item)}
|
||||
/>
|
||||
)}
|
||||
toolbarSearchColumns={[
|
||||
|
||||
@ -32,19 +32,22 @@ describe('ScheduleList', () => {
|
||||
});
|
||||
|
||||
describe('read call successful', () => {
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ScheduleList
|
||||
loadSchedules={loadSchedules}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
resource={{ type: 'job_template', inventory: 1 }}
|
||||
launchConfig={{ survey_enabled: false }}
|
||||
surveyConfig={{}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
afterEach(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
@ -203,6 +206,60 @@ describe('ScheduleList', () => {
|
||||
wrapper.update();
|
||||
expect(wrapper.find('ToolbarAddButton').length).toBe(0);
|
||||
});
|
||||
test('should show missing resource icon and disabled toggle', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ScheduleList
|
||||
loadSchedules={loadSchedules}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
hideAddButton
|
||||
resource={{ type: 'job_template', inventory: 1 }}
|
||||
launchConfig={{ survey_enabled: true }}
|
||||
surveyConfig={{ spec: [{ required: true, default: null }] }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
expect(
|
||||
wrapper
|
||||
.find('ScheduleListItem')
|
||||
.at(4)
|
||||
.prop('isMissingSurvey')
|
||||
).toBe('This schedule is missing required survey values');
|
||||
expect(wrapper.find('ExclamationTriangleIcon').length).toBe(5);
|
||||
expect(wrapper.find('Switch#schedule-5-toggle').prop('isDisabled')).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
test('should show missing resource icon and disabled toggle', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ScheduleList
|
||||
loadSchedules={loadSchedules}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
hideAddButton
|
||||
resource={{ type: 'job_template' }}
|
||||
launchConfig={{
|
||||
survey_enabled: true,
|
||||
inventory_needed_to_start: true,
|
||||
}}
|
||||
surveyConfig={{ spec: [] }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
wrapper.update();
|
||||
|
||||
expect(
|
||||
wrapper
|
||||
.find('ScheduleListItem')
|
||||
.at(3)
|
||||
.prop('isMissingInventory')
|
||||
).toBe('This schedule is missing an Inventory');
|
||||
expect(wrapper.find('ExclamationTriangleIcon').length).toBe(4);
|
||||
expect(wrapper.find('Switch#schedule-3-toggle').prop('isDisabled')).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('read call unsuccessful', () => {
|
||||
|
||||
@ -4,16 +4,33 @@ import { bool, func } from 'prop-types';
|
||||
import { withI18n } from '@lingui/react';
|
||||
import { t } from '@lingui/macro';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button } from '@patternfly/react-core';
|
||||
import { Button, Tooltip } from '@patternfly/react-core';
|
||||
import { Tr, Td } from '@patternfly/react-table';
|
||||
import { PencilAltIcon } from '@patternfly/react-icons';
|
||||
import {
|
||||
PencilAltIcon,
|
||||
ExclamationTriangleIcon as PFExclamationTriangleIcon,
|
||||
} from '@patternfly/react-icons';
|
||||
import styled from 'styled-components';
|
||||
import { DetailList, Detail } from '../../DetailList';
|
||||
import { ActionsTd, ActionItem } from '../../PaginatedTable';
|
||||
import { ScheduleToggle } from '..';
|
||||
import { Schedule } from '../../../types';
|
||||
import { formatDateString } from '../../../util/dates';
|
||||
|
||||
function ScheduleListItem({ i18n, isSelected, onSelect, schedule, rowIndex }) {
|
||||
const ExclamationTriangleIcon = styled(PFExclamationTriangleIcon)`
|
||||
color: #c9190b;
|
||||
margin-left: 20px;
|
||||
`;
|
||||
|
||||
function ScheduleListItem({
|
||||
i18n,
|
||||
rowIndex,
|
||||
isSelected,
|
||||
onSelect,
|
||||
schedule,
|
||||
isMissingInventory,
|
||||
isMissingSurvey,
|
||||
}) {
|
||||
const labelId = `check-action-${schedule.id}`;
|
||||
|
||||
const jobTypeLabels = {
|
||||
@ -45,6 +62,7 @@ function ScheduleListItem({ i18n, isSelected, onSelect, schedule, rowIndex }) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
const isDisabled = Boolean(isMissingInventory || isMissingSurvey);
|
||||
|
||||
return (
|
||||
<Tr id={`schedule-row-${schedule.id}`}>
|
||||
@ -61,6 +79,18 @@ function ScheduleListItem({ i18n, isSelected, onSelect, schedule, rowIndex }) {
|
||||
<Link to={`${scheduleBaseUrl}/details`}>
|
||||
<b>{schedule.name}</b>
|
||||
</Link>
|
||||
{Boolean(isMissingInventory || isMissingSurvey) && (
|
||||
<span>
|
||||
<Tooltip
|
||||
content={[isMissingInventory, isMissingSurvey].map(message => (
|
||||
<div key={message}>{message}</div>
|
||||
))}
|
||||
position="right"
|
||||
>
|
||||
<ExclamationTriangleIcon />
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
</Td>
|
||||
<Td dataLabel={i18n._(t`Type`)}>
|
||||
{
|
||||
@ -80,7 +110,7 @@ function ScheduleListItem({ i18n, isSelected, onSelect, schedule, rowIndex }) {
|
||||
)}
|
||||
</Td>
|
||||
<ActionsTd dataLabel={i18n._(t`Actions`)} gridColumns="auto 40px">
|
||||
<ScheduleToggle schedule={schedule} />
|
||||
<ScheduleToggle schedule={schedule} isDisabled={isDisabled} />
|
||||
<ActionItem
|
||||
visible={schedule.summary_fields.user_capabilities.edit}
|
||||
tooltip={i18n._(t`Edit Schedule`)}
|
||||
|
||||
@ -50,15 +50,13 @@ describe('ScheduleListItem', () => {
|
||||
describe('User has edit permissions', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mountWithContexts(
|
||||
<table>
|
||||
<tbody>
|
||||
<ScheduleListItem
|
||||
isSelected={false}
|
||||
onSelect={onSelect}
|
||||
schedule={mockSchedule}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
<ScheduleListItem
|
||||
isSelected={false}
|
||||
onSelect={onSelect}
|
||||
schedule={mockSchedule}
|
||||
isMissingSurvey={false}
|
||||
isMissingInventory={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@ -118,6 +116,9 @@ describe('ScheduleListItem', () => {
|
||||
.simulate('change');
|
||||
expect(onSelect).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
test('Toggle button is enabled', () => {
|
||||
expect(wrapper.find('ScheduleToggle').prop('isDisabled')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('User has read-only permissions', () => {
|
||||
@ -186,4 +187,35 @@ describe('ScheduleListItem', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
describe('schedule has missing prompt data', () => {
|
||||
beforeAll(() => {
|
||||
wrapper = mountWithContexts(
|
||||
<ScheduleListItem
|
||||
isSelected={false}
|
||||
onSelect={onSelect}
|
||||
schedule={{
|
||||
...mockSchedule,
|
||||
summary_fields: {
|
||||
...mockSchedule.summary_fields,
|
||||
user_capabilities: {
|
||||
edit: false,
|
||||
delete: false,
|
||||
},
|
||||
},
|
||||
}}
|
||||
isMissingInventory="Inventory Error"
|
||||
isMissingSurvey="Survey Error"
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
test('should show missing resource icon', () => {
|
||||
expect(wrapper.find('ExclamationTriangleIcon').length).toBe(1);
|
||||
expect(wrapper.find('ScheduleToggle').prop('isDisabled')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -8,7 +8,7 @@ import ErrorDetail from '../../ErrorDetail';
|
||||
import useRequest from '../../../util/useRequest';
|
||||
import { SchedulesAPI } from '../../../api';
|
||||
|
||||
function ScheduleToggle({ schedule, onToggle, className, i18n }) {
|
||||
function ScheduleToggle({ schedule, onToggle, className, i18n, isDisabled }) {
|
||||
const [isEnabled, setIsEnabled] = useState(schedule.enabled);
|
||||
const [showError, setShowError] = useState(false);
|
||||
|
||||
@ -55,7 +55,9 @@ function ScheduleToggle({ schedule, onToggle, className, i18n }) {
|
||||
labelOff={i18n._(t`Off`)}
|
||||
isChecked={isEnabled}
|
||||
isDisabled={
|
||||
isLoading || !schedule.summary_fields.user_capabilities.edit
|
||||
isLoading ||
|
||||
!schedule.summary_fields.user_capabilities.edit ||
|
||||
isDisabled
|
||||
}
|
||||
onChange={toggleSchedule}
|
||||
aria-label={i18n._(t`Toggle schedule`)}
|
||||
|
||||
@ -10,6 +10,8 @@ function Schedules({
|
||||
loadScheduleOptions,
|
||||
loadSchedules,
|
||||
setBreadcrumb,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
resource,
|
||||
}) {
|
||||
const match = useRouteMatch();
|
||||
@ -17,14 +19,27 @@ function Schedules({
|
||||
return (
|
||||
<Switch>
|
||||
<Route path={`${match.path}/add`}>
|
||||
<ScheduleAdd apiModel={apiModel} resource={resource} />
|
||||
<ScheduleAdd
|
||||
apiModel={apiModel}
|
||||
resource={resource}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
/>
|
||||
</Route>
|
||||
<Route key="details" path={`${match.path}/:scheduleId`}>
|
||||
<Schedule setBreadcrumb={setBreadcrumb} resource={resource} />
|
||||
<Schedule
|
||||
setBreadcrumb={setBreadcrumb}
|
||||
resource={resource}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
/>
|
||||
</Route>
|
||||
<Route key="list" path={`${match.path}`}>
|
||||
<ScheduleList
|
||||
resource={resource}
|
||||
loadSchedules={loadSchedules}
|
||||
launchConfig={launchConfig}
|
||||
surveyConfig={surveyConfig}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
"rrule":
|
||||
"DTSTART;TZID=America/New_York:20200220T000000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=1",
|
||||
"id": 1,
|
||||
"extra_data":{},
|
||||
"summary_fields": {
|
||||
"unified_job_template": {
|
||||
"id": 6,
|
||||
@ -27,6 +28,7 @@
|
||||
"rrule":
|
||||
"DTSTART;TZID=America/New_York:20200220T000000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=1",
|
||||
"id": 2,
|
||||
"extra_data":{},
|
||||
"summary_fields": {
|
||||
"unified_job_template": {
|
||||
"id": 7,
|
||||
@ -46,6 +48,7 @@
|
||||
"rrule":
|
||||
"DTSTART;TZID=America/New_York:20200220T000000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=1",
|
||||
"id": 3,
|
||||
"extra_data":{},
|
||||
"summary_fields": {
|
||||
"unified_job_template": {
|
||||
"id": 8,
|
||||
@ -65,6 +68,7 @@
|
||||
"rrule":
|
||||
"DTSTART;TZID=America/New_York:20200220T000000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=1",
|
||||
"id": 4,
|
||||
"extra_data":{},
|
||||
"summary_fields": {
|
||||
"unified_job_template": {
|
||||
"id": 9,
|
||||
@ -84,6 +88,7 @@
|
||||
"rrule":
|
||||
"DTSTART;TZID=America/New_York:20200220T000000 RRULE:FREQ=DAILY;INTERVAL=1;COUNT=1",
|
||||
"id": 5,
|
||||
"extra_data":{"novalue":null},
|
||||
"summary_fields": {
|
||||
"unified_job_template": {
|
||||
"id": 10,
|
||||
@ -103,4 +108,4 @@
|
||||
"next_run": "2020-02-20T05:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,11 +12,7 @@ import {
|
||||
ActionGroup,
|
||||
} from '@patternfly/react-core';
|
||||
import { Config } from '../../../contexts/Config';
|
||||
import {
|
||||
SchedulesAPI,
|
||||
JobTemplatesAPI,
|
||||
WorkflowJobTemplatesAPI,
|
||||
} from '../../../api';
|
||||
import { SchedulesAPI } from '../../../api';
|
||||
import AnsibleSelect from '../../AnsibleSelect';
|
||||
import ContentError from '../../ContentError';
|
||||
import ContentLoading from '../../ContentLoading';
|
||||
@ -194,6 +190,8 @@ function ScheduleForm({
|
||||
schedule,
|
||||
submitError,
|
||||
resource,
|
||||
launchConfig,
|
||||
surveyConfig,
|
||||
...rest
|
||||
}) {
|
||||
const [isWizardOpen, setIsWizardOpen] = useState(false);
|
||||
@ -210,37 +208,15 @@ function ScheduleForm({
|
||||
const isTemplate =
|
||||
resource.type === 'workflow_job_template' ||
|
||||
resource.type === 'job_template';
|
||||
const isWorkflowJobTemplate =
|
||||
isTemplate && resource.type === 'workflow_job_template';
|
||||
|
||||
const {
|
||||
request: loadScheduleData,
|
||||
error: contentError,
|
||||
contentLoading,
|
||||
result: { zoneOptions, surveyConfig, launchConfig, credentials },
|
||||
result: { zoneOptions, credentials },
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const readLaunch =
|
||||
isTemplate &&
|
||||
(isWorkflowJobTemplate
|
||||
? WorkflowJobTemplatesAPI.readLaunch(resource.id)
|
||||
: JobTemplatesAPI.readLaunch(resource.id));
|
||||
const [{ data }, { data: launchConfiguration }] = await Promise.all([
|
||||
SchedulesAPI.readZoneInfo(),
|
||||
readLaunch,
|
||||
]);
|
||||
const { data } = await SchedulesAPI.readZoneInfo();
|
||||
|
||||
const readSurvey = isWorkflowJobTemplate
|
||||
? WorkflowJobTemplatesAPI.readSurvey(resource.id)
|
||||
: JobTemplatesAPI.readSurvey(resource.id);
|
||||
|
||||
let surveyConfiguration = null;
|
||||
|
||||
if (isTemplate && launchConfiguration.survey_enabled) {
|
||||
const { data: survey } = await readSurvey;
|
||||
|
||||
surveyConfiguration = survey;
|
||||
}
|
||||
let creds;
|
||||
if (schedule.id) {
|
||||
const {
|
||||
@ -249,37 +225,6 @@ function ScheduleForm({
|
||||
creds = results;
|
||||
}
|
||||
|
||||
const missingRequiredInventory = Boolean(
|
||||
!resource.inventory && !schedule?.summary_fields?.inventory.id
|
||||
);
|
||||
let missingRequiredSurvey = false;
|
||||
|
||||
if (
|
||||
schedule.id &&
|
||||
isTemplate &&
|
||||
!launchConfiguration?.can_start_without_user_input
|
||||
) {
|
||||
missingRequiredSurvey = surveyConfiguration?.spec?.every(question => {
|
||||
let hasValue;
|
||||
if (Object.keys(schedule)?.length === 0) {
|
||||
hasValue = true;
|
||||
}
|
||||
Object.entries(schedule?.extra_data).forEach(([key, value]) => {
|
||||
if (
|
||||
question.required &&
|
||||
question.variable === key &&
|
||||
value.length > 0
|
||||
) {
|
||||
hasValue = false;
|
||||
}
|
||||
});
|
||||
return hasValue;
|
||||
});
|
||||
}
|
||||
if (missingRequiredInventory || missingRequiredSurvey) {
|
||||
setIsSaveDisabled(true);
|
||||
}
|
||||
|
||||
const zones = data.map(zone => {
|
||||
return {
|
||||
value: zone.name,
|
||||
@ -290,18 +235,61 @@ function ScheduleForm({
|
||||
|
||||
return {
|
||||
zoneOptions: zones,
|
||||
surveyConfig: surveyConfiguration || {},
|
||||
launchConfig: launchConfiguration,
|
||||
credentials: creds || [],
|
||||
};
|
||||
}, [isTemplate, isWorkflowJobTemplate, resource, schedule]),
|
||||
}, [schedule]),
|
||||
{
|
||||
zonesOptions: [],
|
||||
surveyConfig: {},
|
||||
launchConfig: {},
|
||||
credentials: [],
|
||||
}
|
||||
);
|
||||
const missingRequiredInventory = useCallback(() => {
|
||||
let missingInventory = false;
|
||||
if (
|
||||
launchConfig.inventory_needed_to_start &&
|
||||
!schedule?.summary_fields?.inventory?.id
|
||||
) {
|
||||
missingInventory = true;
|
||||
}
|
||||
return missingInventory;
|
||||
}, [launchConfig, schedule]);
|
||||
|
||||
const hasMissingSurveyValue = useCallback(() => {
|
||||
let missingValues = false;
|
||||
if (launchConfig?.survey_enabled) {
|
||||
surveyConfig.spec.forEach(question => {
|
||||
const hasDefaultValue = Boolean(question.default);
|
||||
const hasSchedule = Object.keys(schedule).length;
|
||||
const isRequired = question.required;
|
||||
if (isRequired && !hasDefaultValue) {
|
||||
if (!hasSchedule) {
|
||||
missingValues = true;
|
||||
} else {
|
||||
const hasMatchingKey = Object.keys(schedule?.extra_data).includes(
|
||||
question.variable
|
||||
);
|
||||
Object.values(schedule?.extra_data).forEach(value => {
|
||||
if (!value || !hasMatchingKey) {
|
||||
missingValues = true;
|
||||
} else {
|
||||
missingValues = false;
|
||||
}
|
||||
});
|
||||
if (!Object.values(schedule.extra_data).length) {
|
||||
missingValues = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return missingValues;
|
||||
}, [launchConfig, schedule, surveyConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTemplate && (missingRequiredInventory() || hasMissingSurveyValue())) {
|
||||
setIsSaveDisabled(true);
|
||||
}
|
||||
}, [isTemplate, hasMissingSurveyValue, missingRequiredInventory]);
|
||||
|
||||
useEffect(() => {
|
||||
loadScheduleData();
|
||||
@ -532,6 +520,7 @@ function ScheduleForm({
|
||||
>
|
||||
{i18n._(t`Save`)}
|
||||
</Button>
|
||||
|
||||
{isTemplate && showPromptButton && (
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
||||
@ -12,24 +12,6 @@ jest.mock('../../../api/models/Schedules');
|
||||
jest.mock('../../../api/models/JobTemplates');
|
||||
jest.mock('../../../api/models/Inventories');
|
||||
|
||||
const survey = {
|
||||
name: '',
|
||||
description: '',
|
||||
spec: [
|
||||
{
|
||||
question_name: 'new survey',
|
||||
question_description: '',
|
||||
required: true,
|
||||
type: 'text',
|
||||
variable: 'newsurveyquestion',
|
||||
min: 0,
|
||||
max: 1024,
|
||||
default: '',
|
||||
choices: '',
|
||||
new_question: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
const credentials = {
|
||||
data: {
|
||||
results: [
|
||||
@ -145,6 +127,29 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
resource={{ id: 23, type: 'job_template' }}
|
||||
/>
|
||||
);
|
||||
@ -158,7 +163,6 @@ describe('<ScheduleForm />', () => {
|
||||
const handleCancel = jest.fn();
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue(launchData);
|
||||
|
||||
JobTemplatesAPI.readSurvey.mockResolvedValue(survey);
|
||||
SchedulesAPI.readCredentials.mockResolvedValue(credentials);
|
||||
SchedulesAPI.readZoneInfo.mockResolvedValue({
|
||||
data: [
|
||||
@ -172,7 +176,30 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={handleCancel}
|
||||
resource={{ id: 23, type: 'job_template' }}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
resource={{ id: 23, type: 'job_template', inventory: 1 }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -186,31 +213,6 @@ describe('<ScheduleForm />', () => {
|
||||
describe('Prompted Schedule', () => {
|
||||
let promptWrapper;
|
||||
beforeEach(async () => {
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||
data: {
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
},
|
||||
});
|
||||
SchedulesAPI.readZoneInfo.mockResolvedValue({
|
||||
data: [
|
||||
{
|
||||
@ -231,6 +233,30 @@ describe('<ScheduleForm />', () => {
|
||||
credentials: [],
|
||||
},
|
||||
}}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
surveyConfig={{ spec: [{ required: true, default: '' }] }}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -257,6 +283,12 @@ describe('<ScheduleForm />', () => {
|
||||
expect(promptWrapper.find('WizardNavItem').length).toBe(2);
|
||||
});
|
||||
|
||||
test('should render disabled save button due to missing required surevy values', () => {
|
||||
expect(
|
||||
promptWrapper.find('Button[aria-label="Save"]').prop('isDisabled')
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('should update prompt modal data', async () => {
|
||||
InventoriesAPI.read.mockResolvedValue({
|
||||
data: {
|
||||
@ -337,6 +369,29 @@ describe('<ScheduleForm />', () => {
|
||||
id: 23,
|
||||
type: 'job_template',
|
||||
}}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: false,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: true,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: true,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -359,31 +414,6 @@ describe('<ScheduleForm />', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||
data: {
|
||||
can_start_without_user_input: true,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: false,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
@ -391,6 +421,29 @@ describe('<ScheduleForm />', () => {
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
resource={{ id: 23, type: 'job_template', inventory: 1 }}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: true,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: false,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -687,32 +740,7 @@ describe('<ScheduleForm />', () => {
|
||||
},
|
||||
],
|
||||
});
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({
|
||||
data: {
|
||||
can_start_without_user_input: true,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: false,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
},
|
||||
});
|
||||
JobTemplatesAPI.readSurvey.mockResolvedValue({});
|
||||
|
||||
SchedulesAPI.readCredentials.mockResolvedValue(credentials);
|
||||
});
|
||||
afterEach(() => {
|
||||
@ -728,21 +756,65 @@ describe('<ScheduleForm />', () => {
|
||||
handleCancel={jest.fn()}
|
||||
schedule={{ inventory: null, ...mockSchedule }}
|
||||
resource={{ id: 23, type: 'job_template' }}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: true,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: false,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
expect(JobTemplatesAPI.readLaunch).toBeCalledWith(23);
|
||||
expect(JobTemplatesAPI.readSurvey).toBeCalledWith(23);
|
||||
expect(SchedulesAPI.readCredentials).toBeCalledWith(27);
|
||||
});
|
||||
|
||||
test('should not call API to get credentials ', async () => {
|
||||
test('should not call API to get credentials ', async () => {
|
||||
await act(async () => {
|
||||
wrapper = mountWithContexts(
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
resource={{ id: 23, type: 'job_template' }}
|
||||
launchConfig={{
|
||||
can_start_without_user_input: true,
|
||||
passwords_needed_to_start: [],
|
||||
ask_scm_branch_on_launch: false,
|
||||
ask_variables_on_launch: false,
|
||||
ask_tags_on_launch: false,
|
||||
ask_diff_mode_on_launch: false,
|
||||
ask_skip_tags_on_launch: false,
|
||||
ask_job_type_on_launch: false,
|
||||
ask_limit_on_launch: false,
|
||||
ask_verbosity_on_launch: false,
|
||||
ask_inventory_on_launch: false,
|
||||
ask_credential_on_launch: false,
|
||||
survey_enabled: false,
|
||||
variables_needed_to_start: [],
|
||||
credential_needed_to_start: false,
|
||||
inventory_needed_to_start: false,
|
||||
job_template_data: {
|
||||
name: 'Demo Job Template',
|
||||
id: 7,
|
||||
description: '',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@ -782,6 +854,7 @@ describe('<ScheduleForm />', () => {
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
schedule={mockSchedule}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
resource={{ id: 23, type: 'job_template' }}
|
||||
/>
|
||||
);
|
||||
@ -806,6 +879,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=10;FREQ=MINUTELY',
|
||||
@ -839,6 +913,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;FREQ=HOURLY;COUNT=10',
|
||||
@ -874,6 +949,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;FREQ=DAILY',
|
||||
@ -908,6 +984,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20210101T050000Z',
|
||||
@ -966,6 +1043,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;FREQ=MONTHLY;BYSETPOS=-1;BYDAY=MO,TU,WE,TH,FR',
|
||||
@ -1012,6 +1090,7 @@ describe('<ScheduleForm />', () => {
|
||||
<ScheduleForm
|
||||
handleSubmit={jest.fn()}
|
||||
handleCancel={jest.fn()}
|
||||
launchConfig={{ inventory_needed_to_start: false }}
|
||||
schedule={Object.assign(mockSchedule, {
|
||||
rrule:
|
||||
'DTSTART;TZID=America/New_York:20200402T144500 RRULE:INTERVAL=1;FREQ=YEARLY;BYMONTH=5;BYMONTHDAY=6',
|
||||
|
||||
@ -22,7 +22,7 @@ export default function useSchedulePromptSteps(
|
||||
(Object.keys(schedule).length > 0 && schedule) || resource;
|
||||
|
||||
sourceOfValues.summary_fields = {
|
||||
credentials: [...resourceCredentials, ...scheduleCredentials],
|
||||
credentials: [...(resourceCredentials || []), ...scheduleCredentials],
|
||||
...sourceOfValues.summary_fields,
|
||||
};
|
||||
const { resetForm, values } = useFormikContext();
|
||||
|
||||
@ -326,11 +326,6 @@ function JobDetail({ job, i18n }) {
|
||||
user={created_by}
|
||||
/>
|
||||
<UserDateDetail label={i18n._(t`Last Modified`)} date={job.modified} />
|
||||
<Detail
|
||||
fullWidth
|
||||
label={i18n._(t`Explanation`)}
|
||||
value={job.job_explanation}
|
||||
/>
|
||||
</DetailList>
|
||||
{job.extra_vars && (
|
||||
<VariablesInput
|
||||
|
||||
@ -40,7 +40,6 @@ describe('<JobDetail />', () => {
|
||||
name: 'Test Source Workflow',
|
||||
},
|
||||
},
|
||||
job_explanation: 'It failed, bummer!',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@ -70,7 +69,6 @@ describe('<JobDetail />', () => {
|
||||
assertDetail('Job Slice', '0/1');
|
||||
assertDetail('Credentials', 'SSH: Demo Credential');
|
||||
assertDetail('Machine Credential', 'SSH: Machine cred');
|
||||
assertDetail('Explanation', 'It failed, bummer!');
|
||||
|
||||
const credentialChip = wrapper.find(
|
||||
`Detail[label="Credentials"] CredentialChip`
|
||||
|
||||
@ -32,20 +32,33 @@ function Template({ i18n, setBreadcrumb }) {
|
||||
const { me = {} } = useConfig();
|
||||
|
||||
const {
|
||||
result: { isNotifAdmin, template },
|
||||
result: { isNotifAdmin, template, surveyConfig, launchConfig },
|
||||
isLoading,
|
||||
error: contentError,
|
||||
request: loadTemplateAndRoles,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const [{ data }, actions, notifAdminRes] = await Promise.all([
|
||||
const [
|
||||
{ data },
|
||||
actions,
|
||||
notifAdminRes,
|
||||
{ data: launchConfiguration },
|
||||
] = await Promise.all([
|
||||
JobTemplatesAPI.readDetail(templateId),
|
||||
JobTemplatesAPI.readTemplateOptions(templateId),
|
||||
OrganizationsAPI.read({
|
||||
page_size: 1,
|
||||
role_level: 'notification_admin_role',
|
||||
}),
|
||||
JobTemplatesAPI.readLaunch(templateId),
|
||||
]);
|
||||
let surveyConfiguration = null;
|
||||
|
||||
if (data.survey_enabled) {
|
||||
const { data: survey } = await JobTemplatesAPI.readSurvey(templateId);
|
||||
|
||||
surveyConfiguration = survey;
|
||||
}
|
||||
if (data.summary_fields.credentials) {
|
||||
const params = {
|
||||
page: 1,
|
||||
@ -71,6 +84,8 @@ function Template({ i18n, setBreadcrumb }) {
|
||||
return {
|
||||
template: data,
|
||||
isNotifAdmin: notifAdminRes.data.results.length > 0,
|
||||
surveyConfig: surveyConfiguration,
|
||||
launchConfig: launchConfiguration,
|
||||
};
|
||||
}, [templateId]),
|
||||
{ isNotifAdmin: false, template: null }
|
||||
@ -204,6 +219,8 @@ function Template({ i18n, setBreadcrumb }) {
|
||||
resource={template}
|
||||
loadSchedules={loadSchedules}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
surveyConfig={surveyConfig}
|
||||
launchConfig={launchConfig}
|
||||
/>
|
||||
</Route>
|
||||
{canSeeNotificationsTab && (
|
||||
|
||||
@ -21,7 +21,7 @@ describe('<Template />', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
JobTemplatesAPI.readDetail.mockResolvedValue({
|
||||
data: mockJobTemplateData,
|
||||
data: { ...mockJobTemplateData, survey_enabled: false },
|
||||
});
|
||||
JobTemplatesAPI.readTemplateOptions.mockResolvedValue({
|
||||
data: {
|
||||
@ -56,6 +56,7 @@ describe('<Template />', () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
JobTemplatesAPI.readLaunch.mockResolvedValue({ data: {} });
|
||||
JobTemplatesAPI.readWebhookKey.mockResolvedValue({
|
||||
data: {
|
||||
webhook_key: 'key',
|
||||
|
||||
@ -36,21 +36,37 @@ function WorkflowJobTemplate({ i18n, setBreadcrumb }) {
|
||||
const { me = {} } = useConfig();
|
||||
|
||||
const {
|
||||
result: { isNotifAdmin, template },
|
||||
result: { isNotifAdmin, template, surveyConfig, launchConfig },
|
||||
isLoading: hasRolesandTemplateLoading,
|
||||
error: rolesAndTemplateError,
|
||||
request: loadTemplateAndRoles,
|
||||
} = useRequest(
|
||||
useCallback(async () => {
|
||||
const [{ data }, actions, notifAdminRes] = await Promise.all([
|
||||
const [
|
||||
{ data },
|
||||
actions,
|
||||
notifAdminRes,
|
||||
{ data: launchConfiguration },
|
||||
] = await Promise.all([
|
||||
WorkflowJobTemplatesAPI.readDetail(templateId),
|
||||
WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions(templateId),
|
||||
OrganizationsAPI.read({
|
||||
page_size: 1,
|
||||
role_level: 'notification_admin_role',
|
||||
}),
|
||||
WorkflowJobTemplatesAPI.readLaunch(templateId),
|
||||
]);
|
||||
|
||||
let surveyConfiguration = null;
|
||||
|
||||
if (data.survey_enabled) {
|
||||
const { data: survey } = await WorkflowJobTemplatesAPI.readSurvey(
|
||||
templateId
|
||||
);
|
||||
|
||||
surveyConfiguration = survey;
|
||||
}
|
||||
|
||||
if (actions.data.actions.PUT) {
|
||||
if (data.webhook_service && data?.related?.webhook_key) {
|
||||
const {
|
||||
@ -65,6 +81,8 @@ function WorkflowJobTemplate({ i18n, setBreadcrumb }) {
|
||||
return {
|
||||
template: data,
|
||||
isNotifAdmin: notifAdminRes.data.results.length > 0,
|
||||
launchConfig: launchConfiguration,
|
||||
surveyConfig: surveyConfiguration,
|
||||
};
|
||||
}, [setBreadcrumb, templateId]),
|
||||
{ isNotifAdmin: false, template: null }
|
||||
@ -207,6 +225,8 @@ function WorkflowJobTemplate({ i18n, setBreadcrumb }) {
|
||||
resource={template}
|
||||
loadSchedules={loadSchedules}
|
||||
loadScheduleOptions={loadScheduleOptions}
|
||||
surveyConfig={surveyConfig}
|
||||
launchConfig={launchConfig}
|
||||
/>
|
||||
</Route>
|
||||
)}
|
||||
|
||||
@ -26,7 +26,7 @@ describe('<WorkflowJobTemplate />', () => {
|
||||
let wrapper;
|
||||
beforeEach(() => {
|
||||
WorkflowJobTemplatesAPI.readDetail.mockResolvedValue({
|
||||
data: mockWorkflowJobTemplateData,
|
||||
data: { ...mockWorkflowJobTemplateData, survey_enabled: false },
|
||||
});
|
||||
WorkflowJobTemplatesAPI.readWorkflowJobTemplateOptions.mockResolvedValue({
|
||||
data: {
|
||||
@ -45,6 +45,7 @@ describe('<WorkflowJobTemplate />', () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
WorkflowJobTemplatesAPI.readLaunch.mockResolvedValue({ data: {} });
|
||||
WorkflowJobTemplatesAPI.readWebhookKey.mockResolvedValue({
|
||||
data: {
|
||||
webhook_key: 'key',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user