From 2d2108b1de5b6acdafd750701e55798ec32b0a65 Mon Sep 17 00:00:00 2001 From: mabashian Date: Fri, 21 Aug 2020 08:08:51 -0400 Subject: [PATCH 1/3] Support file upload/drag and drop on credential mutliline fields --- awx/ui_next/src/index.jsx | 6 ++-- .../Credential/shared/CredentialForm.test.jsx | 22 +++++++++++-- .../CredentialFormFields/CredentialField.jsx | 32 +++++++++++++------ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/awx/ui_next/src/index.jsx b/awx/ui_next/src/index.jsx index ad616077ef..866269098b 100644 --- a/awx/ui_next/src/index.jsx +++ b/awx/ui_next/src/index.jsx @@ -7,8 +7,8 @@ import { BrandName } from './variables'; document.title = `Ansible ${BrandName}`; ReactDOM.render( - - - , + // + , + // , document.getElementById('app') || document.createElement('div') ); diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx index f4360e75ba..1959c308e2 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialForm.test.jsx @@ -163,7 +163,7 @@ describe('', () => { wrapper.find('textarea#credential-ssh_key_data').prop('value') ).toBe(''); await act(async () => { - wrapper.find('FileUpload').invoke('onChange')({ + wrapper.find('FileUpload#credential-gce-file').invoke('onChange')({ name: 'foo.json', text: () => '{"client_email":"testemail@ansible.com","project_id":"test123","private_key":"-----BEGIN PRIVATE KEY-----\\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\n-----END PRIVATE KEY-----\\n"}', @@ -184,7 +184,9 @@ describe('', () => { }); test('should clear expected fields when file clear button clicked', async () => { await act(async () => { - wrapper.find('FileUploadField').invoke('onClearButtonClick')(); + wrapper + .find('FileUploadField#credential-gce-file') + .invoke('onClearButtonClick')(); }); wrapper.update(); expect(wrapper.find('input#credential-username').prop('value')).toBe(''); @@ -193,6 +195,20 @@ describe('', () => { wrapper.find('textarea#credential-ssh_key_data').prop('value') ).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 () => { await act(async () => { await wrapper @@ -204,7 +220,7 @@ describe('', () => { 'Select a JSON formatted service account key to autopopulate the following fields.' ); await act(async () => { - wrapper.find('FileUpload').invoke('onChange')({ + wrapper.find('FileUpload#credential-gce-file').invoke('onChange')({ name: 'foo.json', text: () => '{not good json}', }); diff --git a/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx b/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx index 51c9dfa02d..b5203bc72a 100644 --- a/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx +++ b/awx/ui_next/src/screens/Credential/shared/CredentialFormFields/CredentialField.jsx @@ -1,12 +1,13 @@ -import React from 'react'; +import React, { useState } from 'react'; import { useField, useFormikContext } from 'formik'; import { shape, string } from 'prop-types'; +import styled from 'styled-components'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { + FileUpload as PFFileUpload, FormGroup, InputGroup, - TextArea, TextInput, } from '@patternfly/react-core'; import { FieldTooltip, PasswordInput } from '../../../../components/FormField'; @@ -16,19 +17,32 @@ import { required } from '../../../../util/validators'; import { CredentialPluginField } from './CredentialPlugins'; import BecomeMethodField from './BecomeMethodField'; +const FileUpload = styled(PFFileUpload)` + flex-grow: 1; +`; + 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); if (fieldOptions.multiline) { + const handleFileChange = (value, filename) => { + helpers.setValue(value); + setFileName(filename); + }; + return ( -