From 0fc6affe85be7974e9e3ecd7063727091a45fb06 Mon Sep 17 00:00:00 2001 From: mabashian Date: Thu, 10 Sep 2020 13:36:05 -0400 Subject: [PATCH] Refactor kebab modal tracking logic in delete/cancel buttons --- .../DataListToolbar/DataListToolbar.jsx | 21 +- .../JobList/JobListCancelButton.jsx | 166 ++++++------ .../PaginatedDataList/ToolbarDeleteButton.jsx | 240 ++++++++---------- 3 files changed, 187 insertions(+), 240 deletions(-) diff --git a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx index 73d61f7c60..79e83bda77 100644 --- a/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx +++ b/awx/ui_next/src/components/DataListToolbar/DataListToolbar.jsx @@ -1,4 +1,4 @@ -import React, { Fragment, useEffect, useState } from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; @@ -51,12 +51,6 @@ function DataListToolbar({ setKebabIsOpen(false); }; - useEffect(() => { - if (!kebabModalIsOpen) { - setKebabIsOpen(false); - } - }, [kebabModalIsOpen]); - return ( {showExpandCollapse && ( - + <> - + )} {advancedSearchShown && ( @@ -114,7 +108,12 @@ function DataListToolbar({ setKebabModalIsOpen(isOpen), + onKebabModalChange: isOpen => { + if (kebabIsOpen && kebabModalIsOpen && !isOpen) { + setKebabIsOpen(false); + } + setKebabModalIsOpen(isOpen); + }, }} > } - isOpen={kebabIsOpen} + isOpen={kebabIsOpen || kebabModalIsOpen} isPlain dropdownItems={additionalControls} /> diff --git a/awx/ui_next/src/components/JobList/JobListCancelButton.jsx b/awx/ui_next/src/components/JobList/JobListCancelButton.jsx index 1e04886de4..165b245638 100644 --- a/awx/ui_next/src/components/JobList/JobListCancelButton.jsx +++ b/awx/ui_next/src/components/JobList/JobListCancelButton.jsx @@ -1,9 +1,9 @@ -import React, { useState } from 'react'; +import React, { useContext, useState } from 'react'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import { arrayOf, func } from 'prop-types'; import { Button, DropdownItem, Tooltip } from '@patternfly/react-core'; -import { Kebabified } from '../../contexts/Kebabified'; +import { KebabifiedContext } from '../../contexts/Kebabified'; import AlertModal from '../AlertModal'; import { Job } from '../../types'; @@ -12,13 +12,21 @@ function cannotCancel(job) { } function JobListCancelButton({ i18n, jobsToCancel, onCancel }) { + const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext); const [isModalOpen, setIsModalOpen] = useState(false); const numJobsToCancel = jobsToCancel.length; const zeroOrOneJobSelected = numJobsToCancel < 2; - const handleCancel = () => { + const handleCancelJob = () => { onCancel(); - setIsModalOpen(false); + toggleModal(); + }; + + const toggleModal = () => { + if (isKebabified) { + onKebabModalChange(!isModalOpen); + } + setIsModalOpen(!isModalOpen); }; const renderTooltip = () => { @@ -61,96 +69,74 @@ function JobListCancelButton({ i18n, jobsToCancel, onCancel }) { ); return ( - - {({ isKebabified, onKebabModalChange }) => ( - <> - {isKebabified ? ( - + {isKebabified ? ( + + {cancelJobText} + + ) : ( + +
+ -
-
- )} - {isModalOpen && ( - { - if (isKebabified) { - onKebabModalChange(false); - } - setIsModalOpen(false); - }} - actions={[ - , - , - ]} - > -
- {i18n._( - '{numJobsToCancel, plural, one {This action will cancel the following job:} other {This action will cancel the following jobs:}}', - { - numJobsToCancel, - } - )} -
- {jobsToCancel.map(job => ( - - {job.name} -
-
- ))} -
- )} - + + + )} -
+ {isModalOpen && ( + + {cancelJobText} + , + , + ]} + > +
+ {i18n._( + '{numJobsToCancel, plural, one {This action will cancel the following job:} other {This action will cancel the following jobs:}}', + { + numJobsToCancel, + } + )} +
+ {jobsToCancel.map(job => ( + + {job.name} +
+
+ ))} +
+ )} + ); } diff --git a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx index 4e9b44ae70..db77aa6174 100644 --- a/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx +++ b/awx/ui_next/src/components/PaginatedDataList/ToolbarDeleteButton.jsx @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react'; +import React, { useContext, useState } from 'react'; import { func, bool, @@ -12,7 +12,7 @@ import { Button, DropdownItem, Tooltip } from '@patternfly/react-core'; import { withI18n } from '@lingui/react'; import { t } from '@lingui/macro'; import AlertModal from '../AlertModal'; -import { Kebabified } from '../../contexts/Kebabified'; +import { KebabifiedContext } from '../../contexts/Kebabified'; const requireNameOrUsername = props => { const { name, username } = props; @@ -59,53 +59,29 @@ function cannotDelete(item) { return !item.summary_fields.user_capabilities.delete; } -class ToolbarDeleteButton extends React.Component { - static propTypes = { - onDelete: func.isRequired, - itemsToDelete: arrayOf(ItemToDelete).isRequired, - pluralizedItemName: string, - errorMessage: string, - }; +function ToolbarDeleteButton({ + itemsToDelete, + pluralizedItemName, + errorMessage, + onDelete, + i18n, +}) { + const { isKebabified, onKebabModalChange } = useContext(KebabifiedContext); + const [isModalOpen, setIsModalOpen] = useState(false); - static defaultProps = { - pluralizedItemName: 'Items', - errorMessage: '', - }; - - constructor(props) { - super(props); - - this.state = { - isModalOpen: false, - }; - - this.handleConfirmDelete = this.handleConfirmDelete.bind(this); - this.handleCancelDelete = this.handleCancelDelete.bind(this); - this.handleDelete = this.handleDelete.bind(this); - } - - handleConfirmDelete() { - this.setState({ isModalOpen: true }); - } - - handleCancelDelete() { - this.setState({ isModalOpen: false }); - } - - handleDelete() { - const { onDelete } = this.props; + const handleDelete = () => { onDelete(); - this.setState({ isModalOpen: false }); - } + toggleModal(); + }; - renderTooltip() { - const { - itemsToDelete, - pluralizedItemName, - errorMessage, - i18n, - } = this.props; + const toggleModal = () => { + if (isKebabified) { + onKebabModalChange(!isModalOpen); + } + setIsModalOpen(!isModalOpen); + }; + const renderTooltip = () => { const itemsUnableToDelete = itemsToDelete .filter(cannotDelete) .map(item => item.name) @@ -125,103 +101,89 @@ class ToolbarDeleteButton extends React.Component { return i18n._(t`Delete`); } return i18n._(t`Select a row to delete`); - } + }; - render() { - const { itemsToDelete, pluralizedItemName, i18n } = this.props; - const { isModalOpen } = this.state; - const modalTitle = i18n._(t`Delete ${pluralizedItemName}?`); + const modalTitle = i18n._(t`Delete ${pluralizedItemName}?`); - const isDisabled = - itemsToDelete.length === 0 || itemsToDelete.some(cannotDelete); + const isDisabled = + itemsToDelete.length === 0 || itemsToDelete.some(cannotDelete); - // NOTE: Once PF supports tooltips on disabled elements, - // we can delete the extra
around the below. - // See: https://github.com/patternfly/patternfly-react/issues/1894 - return ( - - {({ isKebabified, onKebabModalChange }) => ( - - {isKebabified ? ( - { - onKebabModalChange(true); - this.handleConfirmDelete(); - }} - > - {i18n._(t`Delete`)} - - ) : ( - -
- -
-
- )} - {isModalOpen && ( - { - if (isKebabified) { - onKebabModalChange(false); - } - this.handleCancelDelete(); - }} - actions={[ - , - , - ]} - > -
{i18n._(t`This action will delete the following:`)}
- {itemsToDelete.map(item => ( - - {item.name || item.username} -
-
- ))} -
- )} -
- )} -
- ); - } + // NOTE: Once PF supports tooltips on disabled elements, + // we can delete the extra
around the below. + // See: https://github.com/patternfly/patternfly-react/issues/1894 + return ( + <> + {isKebabified ? ( + + {i18n._(t`Delete`)} + + ) : ( + +
+ +
+
+ )} + {isModalOpen && ( + + {i18n._(t`Delete`)} + , + , + ]} + > +
{i18n._(t`This action will delete the following:`)}
+ {itemsToDelete.map(item => ( + + {item.name || item.username} +
+
+ ))} +
+ )} + + ); } +ToolbarDeleteButton.propTypes = { + onDelete: func.isRequired, + itemsToDelete: arrayOf(ItemToDelete).isRequired, + pluralizedItemName: string, + errorMessage: string, +}; + +ToolbarDeleteButton.defaultProps = { + pluralizedItemName: 'Items', + errorMessage: '', +}; + export default withI18n()(ToolbarDeleteButton);