From 2a722ba8d028c64aafbc9ac9b093e867e3b25e37 Mon Sep 17 00:00:00 2001 From: Alex Corey Date: Wed, 6 Nov 2019 12:03:13 -0500 Subject: [PATCH] Refactors Lookup --- .../components/Lookup/CredentialLookup.jsx | 2 +- .../Lookup/InstanceGroupsLookup.jsx | 2 +- .../src/components/Lookup/InventoryLookup.jsx | 2 +- awx/ui_next/src/components/Lookup/Lookup.jsx | 197 +++++++++++------- .../Lookup/MultiCredentialsLookup.jsx | 45 ++-- .../components/Lookup/OrganizationLookup.jsx | 2 +- .../src/components/Lookup/ProjectLookup.jsx | 2 +- .../shared/ProjectSubForms/SharedFields.jsx | 2 +- 8 files changed, 143 insertions(+), 111 deletions(-) diff --git a/awx/ui_next/src/components/Lookup/CredentialLookup.jsx b/awx/ui_next/src/components/Lookup/CredentialLookup.jsx index 6872e09784..aae1871e42 100644 --- a/awx/ui_next/src/components/Lookup/CredentialLookup.jsx +++ b/awx/ui_next/src/components/Lookup/CredentialLookup.jsx @@ -36,7 +36,7 @@ function CredentialLookup({ name="credential" value={value} onBlur={onBlur} - onLookupSave={onChange} + onChange={onChange} getItems={getCredentials} required={required} sortedColumnKey="name" diff --git a/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx b/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx index 1e58f3eafa..c720ae2363 100644 --- a/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx +++ b/awx/ui_next/src/components/Lookup/InstanceGroupsLookup.jsx @@ -39,7 +39,7 @@ class InstanceGroupsLookup extends React.Component { lookupHeader={i18n._(t`Instance Groups`)} name="instanceGroups" value={value} - onLookupSave={onChange} + onChange={onChange} getItems={getInstanceGroups} qsNamespace="instance-group" multiple diff --git a/awx/ui_next/src/components/Lookup/InventoryLookup.jsx b/awx/ui_next/src/components/Lookup/InventoryLookup.jsx index d570e79128..494b4d3069 100644 --- a/awx/ui_next/src/components/Lookup/InventoryLookup.jsx +++ b/awx/ui_next/src/components/Lookup/InventoryLookup.jsx @@ -37,7 +37,7 @@ class InventoryLookup extends React.Component { lookupHeader={i18n._(t`Inventory`)} name="inventory" value={value} - onLookupSave={onChange} + onChange={onChange} onBlur={onBlur} getItems={getInventories} required={required} diff --git a/awx/ui_next/src/components/Lookup/Lookup.jsx b/awx/ui_next/src/components/Lookup/Lookup.jsx index ce2f85f24b..b1913e0100 100644 --- a/awx/ui_next/src/components/Lookup/Lookup.jsx +++ b/awx/ui_next/src/components/Lookup/Lookup.jsx @@ -59,13 +59,13 @@ class Lookup extends React.Component { super(props); this.assertCorrectValueType(); - let lookupSelectedItems = []; + let selectedItems = []; if (props.value) { - lookupSelectedItems = props.multiple ? [...props.value] : [props.value]; + selectedItems = props.multiple ? [...props.value] : [props.value]; } this.state = { isModalOpen: false, - lookupSelectedItems, + selectedItems, results: [], count: 0, error: null, @@ -76,7 +76,8 @@ class Lookup extends React.Component { order_by: props.sortedColumnKey, }); this.handleModalToggle = this.handleModalToggle.bind(this); - this.toggleSelected = this.toggleSelected.bind(this); + this.addItem = this.addItem.bind(this); + this.removeItem = this.removeItem.bind(this); this.saveModal = this.saveModal.bind(this); this.getData = this.getData.bind(this); this.clearQSParams = this.clearQSParams.bind(this); @@ -132,46 +133,82 @@ class Lookup extends React.Component { } } - toggleSelected(row) { - const { - name, - onLookupSave, - multiple, - onToggleItem, - selectCategoryOptions, - } = this.props; - const { - lookupSelectedItems: updatedSelectedItems, - isModalOpen, - } = this.state; - - const selectedIndex = updatedSelectedItems.findIndex( - selectedRow => selectedRow.id === row.id - ); - if (multiple) { - if (selectCategoryOptions) { - onToggleItem(row, isModalOpen); - } - if (selectedIndex > -1) { - updatedSelectedItems.splice(selectedIndex, 1); - this.setState({ lookupSelectedItems: updatedSelectedItems }); - } else { - this.setState(prevState => ({ - lookupSelectedItems: [...prevState.lookupSelectedItems, row], - })); - } - } else { - this.setState({ lookupSelectedItems: [row] }); - } - - // Updates the selected items from parent state - // This handles the case where the user removes chips from the lookup input - // while the modal is closed - if (!isModalOpen) { - onLookupSave(updatedSelectedItems, name); + removeItem(row) { + const { selectedItems } = this.state; + const { onToggleItem } = this.props; + if (onToggleItem) { + this.setState({ selectedItems: onToggleItem(selectedItems, row) }); + return; } + this.setState({ + selectedItems: selectedItems.filter(item => item.id !== row.id), + }); } + addItem(row) { + const { selectedItems } = this.state; + const { multiple, onToggleItem } = this.props; + if (onToggleItem) { + this.setState({ selectedItems: onToggleItem(selectedItems, row) }); + return; + } + const index = selectedItems.findIndex(item => item.id === row.id); + + if (!multiple) { + this.setState({ selectedItems: [row] }); + return; + } + if (index > -1) { + return; + } + this.setState({ selectedItems: [...selectedItems, row] }); + } + // toggleSelected(row) { + // const { + // name, + // onChange, + // multiple, + // onToggleItem, + // selectCategoryOptions, + // onChange, + // value + // } = this.props; + // const { + // selectedItems: updatedSelectedItems, + // isModalOpen, + // } = this.state; + + // const selectedIndex = updatedSelectedItems.findIndex( + // selectedRow => selectedRow.id === row.id + // ); + // + // if (multiple) { + // + // if (selectCategoryOptions) { + // + // onToggleItem(row, isModalOpen); + // } + // if (selectedIndex > -1) { + // + // const valueToUpdate = value.filter(itemValue => itemValue.id !==row.id ); + // onChange(valueToUpdate) + // } else { + // + // onChange([...value, row]) + // } + // } else { + // + // onChange(row) + // } + + // Updates the selected items from parent state + // This handles the case where the user removes chips from the lookup input + // while the modal is closed + // if (!isModalOpen) { + // onChange(updatedSelectedItems, name); + // } + // } + handleModalToggle() { const { isModalOpen } = this.state; const { value, multiple, selectCategory } = this.props; @@ -179,11 +216,11 @@ class Lookup extends React.Component { // This handles the case where the user closes/cancels the modal and // opens it again if (!isModalOpen) { - let lookupSelectedItems = []; + let selectedItems = []; if (value) { - lookupSelectedItems = multiple ? [...value] : [value]; + selectedItems = multiple ? [...value] : [value]; } - this.setState({ lookupSelectedItems }); + this.setState({ selectedItems }); } else { this.clearQSParams(); if (selectCategory) { @@ -195,15 +232,22 @@ class Lookup extends React.Component { })); } + removeItemAndSave(row) { + const { value, onChange, multiple } = this.props; + if (multiple) { + onChange(value.filter(item => item.id !== row.id)); + } else if (value.id === row.id) { + onChange(null); + } + } + saveModal() { - const { onLookupSave, name, multiple } = this.props; - const { lookupSelectedItems } = this.state; - const value = multiple - ? lookupSelectedItems - : lookupSelectedItems[0] || null; + const { onChange, multiple } = this.props; + const { selectedItems } = this.state; + const value = multiple ? selectedItems : selectedItems[0] || null; this.handleModalToggle(); - onLookupSave(value, name); + onChange(value); } clearQSParams() { @@ -215,13 +259,7 @@ class Lookup extends React.Component { } render() { - const { - isModalOpen, - lookupSelectedItems, - error, - results, - count, - } = this.state; + const { isModalOpen, selectedItems, error, results, count } = this.state; const { form, id, @@ -245,7 +283,7 @@ class Lookup extends React.Component { {(multiple ? value : [value]).map(chip => ( this.toggleSelected(chip)} + onClick={() => this.removeItemAndSave(chip)} isReadOnly={!canDelete} credential={chip} /> @@ -256,7 +294,7 @@ class Lookup extends React.Component { {(multiple ? value : [value]).map(chip => ( this.toggleSelected(chip)} + onClick={() => this.removeItemAndSave(chip)} isReadOnly={!canDelete} > {chip.name} @@ -287,19 +325,19 @@ class Lookup extends React.Component { onClose={this.handleModalToggle} actions={[ , , ]} > @@ -318,6 +356,18 @@ class Lookup extends React.Component { /> )} + {selectedItems.length > 0 && ( + 0 + } + /> + )} i.id === item.id) - : lookupSelectedItems.some(i => i.id === item.id) - } - onSelect={() => this.toggleSelected(item)} + isSelected={selectedItems.some(i => i.id === item.id)} + onSelect={() => this.addItem(item)} isRadio={ !multiple || (selectCategoryOptions && @@ -347,17 +393,6 @@ class Lookup extends React.Component { renderToolbar={props => } showPageSizeOptions={false} /> - {lookupSelectedItems.length > 0 && ( - 0 - } - /> - )} {error ?
error
: ''} @@ -374,7 +409,7 @@ Lookup.propTypes = { getItems: func.isRequired, lookupHeader: string, name: string, - onLookupSave: func.isRequired, + onChange: func.isRequired, value: oneOfType([Item, arrayOf(Item)]), sortedColumnKey: string.isRequired, multiple: bool, diff --git a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx index 5b978b2c66..9e40ebccec 100644 --- a/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx +++ b/awx/ui_next/src/components/Lookup/MultiCredentialsLookup.jsx @@ -12,7 +12,25 @@ import Lookup from '@components/Lookup'; const QuestionCircleIcon = styled(PFQuestionCircleIcon)` margin-left: 10px; `; +function toggleCredentialSelection(credentialsToUpdate, newCredential) { + let newCredentialsList; + const isSelectedCredentialInState = + credentialsToUpdate.filter(cred => cred.id === newCredential.id).length > + 0; + if (isSelectedCredentialInState) { + newCredentialsList = credentialsToUpdate.filter( + cred => cred.id !== newCredential.id + ); + } else { + newCredentialsList = credentialsToUpdate.filter( + credential => + credential.kind === 'vault' || credential.kind !== newCredential.kind + ); + newCredentialsList = [...newCredentialsList, newCredential]; + } + return newCredentialsList; +} class MultiCredentialsLookup extends React.Component { constructor(props) { super(props); @@ -26,7 +44,6 @@ class MultiCredentialsLookup extends React.Component { this ); this.loadCredentials = this.loadCredentials.bind(this); - this.toggleCredentialSelection = this.toggleCredentialSelection.bind(this); } componentDidMount() { @@ -69,27 +86,7 @@ class MultiCredentialsLookup extends React.Component { return CredentialsAPI.read(params); } - toggleCredentialSelection(newCredential) { - const { onChange, credentials: credentialsToUpdate } = this.props; - let newCredentialsList; - const isSelectedCredentialInState = - credentialsToUpdate.filter(cred => cred.id === newCredential.id).length > - 0; - - if (isSelectedCredentialInState) { - newCredentialsList = credentialsToUpdate.filter( - cred => cred.id !== newCredential.id - ); - } else { - newCredentialsList = credentialsToUpdate.filter( - credential => - credential.kind === 'vault' || credential.kind !== newCredential.kind - ); - newCredentialsList = [...newCredentialsList, newCredential]; - } - onChange(newCredentialsList); - } handleCredentialTypeSelect(value, type) { const { credentialTypes } = this.state; @@ -99,7 +96,7 @@ class MultiCredentialsLookup extends React.Component { render() { const { selectedCredentialType, credentialTypes } = this.state; - const { tooltip, i18n, credentials } = this.props; + const { tooltip, i18n, credentials, onChange } = this.props; return ( {tooltip && ( @@ -112,14 +109,14 @@ class MultiCredentialsLookup extends React.Component { selectCategoryOptions={credentialTypes} selectCategory={this.handleCredentialTypeSelect} selectedCategory={selectedCredentialType} - onToggleItem={this.toggleCredentialSelection} + onToggleItem={toggleCredentialSelection} onloadCategories={this.loadCredentialTypes} id="multiCredential" lookupHeader={i18n._(t`Credentials`)} name="credentials" value={credentials} multiple - onLookupSave={() => {}} + onChange={onChange} getItems={this.loadCredentials} qsNamespace="credentials" columns={[ diff --git a/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx b/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx index 8efb43b091..32c93f2588 100644 --- a/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx +++ b/awx/ui_next/src/components/Lookup/OrganizationLookup.jsx @@ -32,7 +32,7 @@ function OrganizationLookup({ name="organization" value={value} onBlur={onBlur} - onLookupSave={onChange} + onChange={onChange} getItems={getOrganizations} required={required} sortedColumnKey="name" diff --git a/awx/ui_next/src/components/Lookup/ProjectLookup.jsx b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx index 90d36a64a7..f83d30eb02 100644 --- a/awx/ui_next/src/components/Lookup/ProjectLookup.jsx +++ b/awx/ui_next/src/components/Lookup/ProjectLookup.jsx @@ -45,7 +45,7 @@ class ProjectLookup extends React.Component { name="project" value={value} onBlur={onBlur} - onLookupSave={onChange} + onChange={onChange} getItems={loadProjects} required={required} sortedColumnKey="name" diff --git a/awx/ui_next/src/screens/Project/shared/ProjectSubForms/SharedFields.jsx b/awx/ui_next/src/screens/Project/shared/ProjectSubForms/SharedFields.jsx index 127ba54936..5a7e1434c1 100644 --- a/awx/ui_next/src/screens/Project/shared/ProjectSubForms/SharedFields.jsx +++ b/awx/ui_next/src/screens/Project/shared/ProjectSubForms/SharedFields.jsx @@ -51,7 +51,7 @@ export const ScmCredentialFormField = withI18n()( value={credential.value} onChange={value => { onCredentialSelection('scm', value); - form.setFieldValue('credential', value.id); + form.setFieldValue('credential', value ? value.id : ''); }} /> )}