Merge pull request #13873 from marshmalien/10799-bug-prompt-launch-credential-type-dropdown-complete

Fix screen crash when changing credential type in launch prompt dropdown
This commit is contained in:
Sarah Akus 2023-04-28 13:25:40 -04:00 committed by GitHub
commit ee7b3470da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 14 deletions

View File

@ -43,6 +43,7 @@ function LaunchButton({ resource, children }) {
const [surveyConfig, setSurveyConfig] = useState(null);
const [labels, setLabels] = useState([]);
const [isLaunching, setIsLaunching] = useState(false);
const [resourceCredentials, setResourceCredentials] = useState([]);
const [error, setError] = useState(null);
const handleLaunch = async () => {
@ -83,6 +84,13 @@ function LaunchButton({ resource, children }) {
setLabels(allLabels);
}
if (launch.ask_credential_on_launch) {
const {
data: { results: templateCredentials },
} = await JobTemplatesAPI.readCredentials(resource.id);
setResourceCredentials(templateCredentials);
}
if (canLaunchWithoutPrompt(launch)) {
await launchWithParams({});
} else {
@ -208,6 +216,7 @@ function LaunchButton({ resource, children }) {
labels={labels}
onLaunch={launchWithParams}
onCancel={() => setShowLaunchPrompt(false)}
resourceDefaultCredentials={resourceCredentials}
/>
)}
</>

View File

@ -47,6 +47,12 @@ describe('LaunchButton', () => {
variables_needed_to_start: [],
},
});
JobTemplatesAPI.readCredentials.mockResolvedValue({
data: {
count: 0,
results: [],
},
});
});
afterEach(() => jest.clearAllMocks());

View File

@ -19,6 +19,7 @@ function PromptModalForm({
labels,
surveyConfig,
instanceGroups,
resourceDefaultCredentials,
}) {
const { setFieldTouched, values } = useFormikContext();
const [showDescription, setShowDescription] = useState(false);
@ -35,9 +36,9 @@ function PromptModalForm({
surveyConfig,
resource,
labels,
instanceGroups
instanceGroups,
resourceDefaultCredentials
);
const handleSubmit = async () => {
const postValues = {};
const setValue = (key, value) => {

View File

@ -69,6 +69,20 @@ describe('LaunchPrompt', () => {
spec: [{ type: 'text', variable: 'foo' }],
},
});
JobTemplatesAPI.readCredentials.mockResolvedValue({
data: {
results: [
{
id: 5,
name: 'cred that prompts',
credential_type: 1,
inputs: {
password: 'ASK',
},
},
],
},
});
InstanceGroupsAPI.read.mockResolvedValue({
data: {
results: [
@ -212,6 +226,16 @@ describe('LaunchPrompt', () => {
],
},
}}
resourceDefaultCredentials={[
{
id: 5,
name: 'cred that prompts',
credential_type: 1,
inputs: {
password: 'ASK',
},
},
]}
onLaunch={noop}
onCancel={noop}
surveyConfig={{
@ -289,6 +313,16 @@ describe('LaunchPrompt', () => {
resource={resource}
onLaunch={noop}
onCancel={noop}
resourceDefaultCredentials={[
{
id: 5,
name: 'cred that prompts',
credential_type: 1,
inputs: {
password: 'ASK',
},
},
]}
/>
);
});

View File

@ -1,6 +1,6 @@
import 'styled-components/macro';
import React, { useState, useCallback, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { useHistory, useLocation } from 'react-router-dom';
import { t } from '@lingui/macro';
import { useField } from 'formik';
@ -8,7 +8,7 @@ import styled from 'styled-components';
import { Alert, ToolbarItem } from '@patternfly/react-core';
import { CredentialsAPI, CredentialTypesAPI } from 'api';
import { getSearchableKeys } from 'components/PaginatedTable';
import { getQSConfig, parseQueryString } from 'util/qs';
import { getQSConfig, parseQueryString, updateQueryString } from 'util/qs';
import useRequest from 'hooks/useRequest';
import AnsibleSelect from '../../AnsibleSelect';
import OptionsList from '../../OptionsList';
@ -31,18 +31,18 @@ function CredentialsStep({
allowCredentialsWithPasswords,
defaultCredentials = [],
}) {
const history = useHistory();
const location = useLocation();
const [field, meta, helpers] = useField({
name: 'credentials',
validate: (val) =>
credentialsValidator(
allowCredentialsWithPasswords,
val,
defaultCredentials
defaultCredentials ?? []
),
});
const [selectedType, setSelectedType] = useState(null);
const history = useHistory();
const {
result: types,
error: typesError,
@ -104,12 +104,32 @@ function CredentialsStep({
credentialsValidator(
allowCredentialsWithPasswords,
field.value,
defaultCredentials
defaultCredentials ?? []
)
);
/* eslint-disable-next-line react-hooks/exhaustive-deps */
}, []);
const removeAllSearchTerms = (qsConfig) => {
const oldParams = parseQueryString(qsConfig, location.search);
Object.keys(oldParams).forEach((key) => {
oldParams[key] = null;
});
const defaultParams = {
...oldParams,
page: 1,
page_size: 5,
order_by: 'name',
};
const qs = updateQueryString(qsConfig, location.search, defaultParams);
pushHistoryState(qs);
};
const pushHistoryState = (qs) => {
const { pathname } = history.location;
history.push(qs ? `${pathname}?${qs}` : pathname);
};
if (isTypesLoading) {
return <ContentLoading />;
}
@ -154,9 +174,7 @@ function CredentialsStep({
value={selectedType && selectedType.id}
onChange={(e, id) => {
// Reset query params when the category of credentials is changed
history.replace({
search: '',
});
removeAllSearchTerms(QS_CONFIG);
setSelectedType(types.find((o) => o.id === parseInt(id, 10)));
}}
/>

View File

@ -168,7 +168,9 @@ describe('CredentialsStep', () => {
test('should reset query params (credential.page) when selected credential type is changed', async () => {
let wrapper;
const history = createMemoryHistory({
initialEntries: ['?credential.page=2'],
initialEntries: [
'?credential.page=2&credential.page_size=5&credential.order_by=name',
],
});
await act(async () => {
wrapper = mountWithContexts(

View File

@ -46,7 +46,8 @@ export default function useLaunchSteps(
surveyConfig,
resource,
labels,
instanceGroups
instanceGroups,
resourceDefaultCredentials
) {
const [visited, setVisited] = useState({});
const [isReady, setIsReady] = useState(false);
@ -56,7 +57,7 @@ export default function useLaunchSteps(
useCredentialsStep(
launchConfig,
resource,
resource.summary_fields.credentials || [],
resourceDefaultCredentials,
true
),
useCredentialPasswordsStep(