From fbe6abfb53707b35ba1bd872e27ed4bf56300e73 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Fri, 16 Aug 2019 09:45:07 -0400 Subject: [PATCH 1/2] Allows user to hit enter to create label, fixes console errors. --- .../components/MultiSelect/MultiSelect.jsx | 31 +++++++++++++------ .../MultiSelect/MultiSelect.test.jsx | 6 ++-- .../JobTemplateAdd/JobTemplateAdd.jsx | 11 ++++--- .../Template/shared/JobTemplateForm.test.jsx | 2 +- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/awx/ui_next/src/components/MultiSelect/MultiSelect.jsx b/awx/ui_next/src/components/MultiSelect/MultiSelect.jsx index ea5a701ccd..cb386b67b6 100644 --- a/awx/ui_next/src/components/MultiSelect/MultiSelect.jsx +++ b/awx/ui_next/src/components/MultiSelect/MultiSelect.jsx @@ -86,7 +86,7 @@ class MultiSelect extends Component { this.handleSelection(e, option); } } else { - this.setState({ isExpanded: false }); + this.setState({ input: '', isExpanded: false }); } } @@ -105,17 +105,30 @@ class MultiSelect extends Component { handleAddItem(event) { const { input, chipItems } = this.state; const { onAddNewItem } = this.props; - const newChip = { name: input, id: Math.random() }; - if (event.key !== 'Tab') { + const isIncluded = chipItems.some(chipItem => chipItem.name === input); + + if (!input) { return; } - this.setState({ - chipItems: chipItems.concat(newChip), - isExpanded: false, - input: '', - }); - onAddNewItem(input); + if (isIncluded) { + // This event.preventDefault prevents the form from submitting + // if the user tries to create 2 chips of the same name + event.preventDefault(); + this.setState({ input: '', isExpanded: false }); + return; + } + if (event.key === 'Enter') { + event.preventDefault(); + this.setState({ + chipItems: chipItems.concat({ name: input, id: input }), + isExpanded: false, + input: '', + }); + onAddNewItem(input); + } else if (event.key === 'Tab') { + this.setState({ input: '' }); + } } handleInputChange(e) { diff --git a/awx/ui_next/src/components/MultiSelect/MultiSelect.test.jsx b/awx/ui_next/src/components/MultiSelect/MultiSelect.test.jsx index 422baacb84..66996fcdb7 100644 --- a/awx/ui_next/src/components/MultiSelect/MultiSelect.test.jsx +++ b/awx/ui_next/src/components/MultiSelect/MultiSelect.test.jsx @@ -40,10 +40,10 @@ describe('', () => { const component = wrapper.find('MultiSelect'); component .find('input[aria-label="labels"]') - .simulate('keydown', { key: 'Tab' }); + .simulate('keydown', { key: 'Enter' }); component.update(); await sleep(1); - expect(component.state().chipItems.length).toBe(3); + expect(component.state().chipItems.length).toBe(2); }); test('handleAddItem adds a chip only when Tab is pressed', () => { const onAddNewItem = jest.fn(); @@ -57,7 +57,7 @@ describe('', () => { ); const event = { preventDefault: () => {}, - key: 'Tab', + key: 'Enter', }; const component = wrapper.find('MultiSelect'); diff --git a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx index 5c738a942d..5baad8382a 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx @@ -19,10 +19,13 @@ function JobTemplateAdd({ history, i18n }) { const handleSubmit = async values => { setError(null); try { - const { data } = await JobTemplatesAPI.create(values); - history.push(`/templates/${data.type}/${data.id}/details`); - } catch (err) { - setError(err); + const { + data: { id, type }, + } = await JobTemplatesAPI.create(values); + await Promise.all([submitLabels(id, newLabels, removedLabels)]); + history.push(`/templates/${type}/${id}/details`); + } catch (error) { + setFormSubmitError(error); } }; diff --git a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx index d9be14e148..1d6a46adb2 100644 --- a/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx +++ b/awx/ui_next/src/screens/Template/shared/JobTemplateForm.test.jsx @@ -158,7 +158,7 @@ describe('', () => { _JobTemplateForm.prototype, 'handleNewLabel' ); - const event = { key: 'Tab' }; + const event = { key: 'Enter', preventDefault: () => {} }; const wrapper = mountWithContexts( Date: Tue, 27 Aug 2019 17:41:54 -0400 Subject: [PATCH 2/2] also make labels work for add view --- .../JobTemplateAdd/JobTemplateAdd.jsx | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx index 5baad8382a..b3b4d12f92 100644 --- a/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx +++ b/awx/ui_next/src/screens/Template/JobTemplateAdd/JobTemplateAdd.jsx @@ -14,10 +14,14 @@ import JobTemplateForm from '../shared/JobTemplateForm'; import { JobTemplatesAPI } from '@api'; function JobTemplateAdd({ history, i18n }) { - const [error, setError] = useState(null); + const [formSubmitError, setFormSubmitError] = useState(null); - const handleSubmit = async values => { - setError(null); + async function handleSubmit(values) { + const { newLabels, removedLabels } = values; + delete values.newLabels; + delete values.removedLabels; + + setFormSubmitError(null); try { const { data: { id, type }, @@ -27,11 +31,30 @@ function JobTemplateAdd({ history, i18n }) { } catch (error) { setFormSubmitError(error); } - }; + } - const handleCancel = () => { + async function submitLabels(id, newLabels = [], removedLabels = []) { + const disassociationPromises = removedLabels.map(label => + JobTemplatesAPI.disassociateLabel(id, label) + ); + const associationPromises = newLabels + .filter(label => !label.organization) + .map(label => JobTemplatesAPI.associateLabel(id, label)); + const creationPromises = newLabels + .filter(label => label.organization) + .map(label => JobTemplatesAPI.generateLabel(id, label)); + + const results = await Promise.all([ + ...disassociationPromises, + ...associationPromises, + ...creationPromises, + ]); + return results; + } + + function handleCancel() { history.push(`/templates`); - }; + } return ( @@ -47,7 +70,7 @@ function JobTemplateAdd({ history, i18n }) { handleSubmit={handleSubmit} /> - {error ?
error
: ''} + {formSubmitError ?
formSubmitError
: ''}
);