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:
softwarefactory-project-zuul[bot]
2020-09-04 17:27:43 +00:00
committed by GitHub
3 changed files with 45 additions and 12 deletions

View File

@@ -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"

View File

@@ -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}',
}); });

View File

@@ -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'}
/> />
); );