mirror of
https://github.com/ansible/awx.git
synced 2026-05-07 09:27:36 -02:30
Merge pull request #7960 from mabashian/6113-6703-cred-file-upload
Support file upload/drag and drop on credential mutliline fields Reviewed-by: https://github.com/apps/softwarefactory-project-zuul
This commit is contained in:
@@ -224,6 +224,7 @@ function CredentialForm({
|
|||||||
<FormFullWidthLayout>
|
<FormFullWidthLayout>
|
||||||
<ActionGroup>
|
<ActionGroup>
|
||||||
<Button
|
<Button
|
||||||
|
id="credential-form-save-button"
|
||||||
aria-label={i18n._(t`Save`)}
|
aria-label={i18n._(t`Save`)}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -235,6 +236,7 @@ function CredentialForm({
|
|||||||
credentialTypes[formik.values.credential_type]?.kind ===
|
credentialTypes[formik.values.credential_type]?.kind ===
|
||||||
'external' && (
|
'external' && (
|
||||||
<Button
|
<Button
|
||||||
|
id="credential-form-test-button"
|
||||||
aria-label={i18n._(t`Test`)}
|
aria-label={i18n._(t`Test`)}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -245,6 +247,7 @@ function CredentialForm({
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
|
id="credential-form-cancel-button"
|
||||||
aria-label={i18n._(t`Cancel`)}
|
aria-label={i18n._(t`Cancel`)}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ describe('<CredentialForm />', () => {
|
|||||||
wrapper.find('textarea#credential-ssh_key_data').prop('value')
|
wrapper.find('textarea#credential-ssh_key_data').prop('value')
|
||||||
).toBe('');
|
).toBe('');
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('FileUpload').invoke('onChange')({
|
wrapper.find('FileUpload#credential-gce-file').invoke('onChange')({
|
||||||
name: 'foo.json',
|
name: 'foo.json',
|
||||||
text: () =>
|
text: () =>
|
||||||
'{"client_email":"testemail@ansible.com","project_id":"test123","private_key":"-----BEGIN PRIVATE KEY-----\\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n-----END PRIVATE KEY-----\\n"}',
|
'{"client_email":"testemail@ansible.com","project_id":"test123","private_key":"-----BEGIN PRIVATE KEY-----\\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n-----END PRIVATE KEY-----\\n"}',
|
||||||
@@ -184,7 +184,9 @@ describe('<CredentialForm />', () => {
|
|||||||
});
|
});
|
||||||
test('should clear expected fields when file clear button clicked', async () => {
|
test('should clear expected fields when file clear button clicked', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('FileUploadField').invoke('onClearButtonClick')();
|
wrapper
|
||||||
|
.find('FileUploadField#credential-gce-file')
|
||||||
|
.invoke('onClearButtonClick')();
|
||||||
});
|
});
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(wrapper.find('input#credential-username').prop('value')).toBe('');
|
expect(wrapper.find('input#credential-username').prop('value')).toBe('');
|
||||||
@@ -193,6 +195,20 @@ describe('<CredentialForm />', () => {
|
|||||||
wrapper.find('textarea#credential-ssh_key_data').prop('value')
|
wrapper.find('textarea#credential-ssh_key_data').prop('value')
|
||||||
).toBe('');
|
).toBe('');
|
||||||
});
|
});
|
||||||
|
test('should update field when RSA Private Key file uploaded', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
wrapper.find('FileUpload#credential-ssh_key_data').invoke('onChange')(
|
||||||
|
'-----BEGIN PRIVATE KEY-----\\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\\n-----END PRIVATE KEY-----\\n',
|
||||||
|
'foo.key'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
wrapper.update();
|
||||||
|
expect(
|
||||||
|
wrapper.find('textarea#credential-ssh_key_data').prop('value')
|
||||||
|
).toBe(
|
||||||
|
'-----BEGIN PRIVATE KEY-----\\nBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\\n-----END PRIVATE KEY-----\\n'
|
||||||
|
);
|
||||||
|
});
|
||||||
test('should show error when error thrown parsing JSON', async () => {
|
test('should show error when error thrown parsing JSON', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await wrapper
|
await wrapper
|
||||||
@@ -204,7 +220,7 @@ describe('<CredentialForm />', () => {
|
|||||||
'Select a JSON formatted service account key to autopopulate the following fields.'
|
'Select a JSON formatted service account key to autopopulate the following fields.'
|
||||||
);
|
);
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
wrapper.find('FileUpload').invoke('onChange')({
|
wrapper.find('FileUpload#credential-gce-file').invoke('onChange')({
|
||||||
name: 'foo.json',
|
name: 'foo.json',
|
||||||
text: () => '{not good json}',
|
text: () => '{not good json}',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useField, useFormikContext } from 'formik';
|
import { useField, useFormikContext } from 'formik';
|
||||||
import { shape, string } from 'prop-types';
|
import { shape, string } from 'prop-types';
|
||||||
|
import styled from 'styled-components';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import {
|
import {
|
||||||
|
FileUpload as PFFileUpload,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
TextArea,
|
|
||||||
TextInput,
|
TextInput,
|
||||||
} from '@patternfly/react-core';
|
} from '@patternfly/react-core';
|
||||||
import { FieldTooltip, PasswordInput } from '../../../../components/FormField';
|
import { FieldTooltip, PasswordInput } from '../../../../components/FormField';
|
||||||
@@ -16,19 +17,32 @@ import { required } from '../../../../util/validators';
|
|||||||
import { CredentialPluginField } from './CredentialPlugins';
|
import { CredentialPluginField } from './CredentialPlugins';
|
||||||
import BecomeMethodField from './BecomeMethodField';
|
import BecomeMethodField from './BecomeMethodField';
|
||||||
|
|
||||||
|
const FileUpload = styled(PFFileUpload)`
|
||||||
|
flex-grow: 1;
|
||||||
|
`;
|
||||||
|
|
||||||
function CredentialInput({ fieldOptions, credentialKind, ...rest }) {
|
function CredentialInput({ fieldOptions, credentialKind, ...rest }) {
|
||||||
const [subFormField, meta] = useField(`inputs.${fieldOptions.id}`);
|
const [fileName, setFileName] = useState('');
|
||||||
|
const [fileIsUploading, setFileIsUploading] = useState(false);
|
||||||
|
const [subFormField, meta, helpers] = useField(`inputs.${fieldOptions.id}`);
|
||||||
const isValid = !(meta.touched && meta.error);
|
const isValid = !(meta.touched && meta.error);
|
||||||
if (fieldOptions.multiline) {
|
if (fieldOptions.multiline) {
|
||||||
|
const handleFileChange = (value, filename) => {
|
||||||
|
helpers.setValue(value);
|
||||||
|
setFileName(filename);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextArea
|
<FileUpload
|
||||||
{...subFormField}
|
{...subFormField}
|
||||||
id={`credential-${fieldOptions.id}`}
|
id={`credential-${fieldOptions.id}`}
|
||||||
rows={6}
|
type="text"
|
||||||
resizeOrientation="vertical"
|
filename={fileName}
|
||||||
onChange={(value, event) => {
|
onChange={handleFileChange}
|
||||||
subFormField.onChange(event);
|
onReadStarted={() => setFileIsUploading(true)}
|
||||||
}}
|
onReadFinished={() => setFileIsUploading(false)}
|
||||||
|
isLoading={fileIsUploading}
|
||||||
|
allowEditingUploadedText
|
||||||
validated={isValid ? 'default' : 'error'}
|
validated={isValid ? 'default' : 'error'}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user