webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js in katello-3.11.2 vs webpack/scenes/Subscriptions/components/SubscriptionsTable/SubscriptionsTable.js in katello-3.12.0.rc1

- old
+ new

@@ -1,20 +1,13 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import { sprintf } from 'foremanReact/common/I18n'; import { cloneDeep, findIndex, isEqual } from 'lodash'; -import { Table } from 'patternfly-react'; import { LoadingState } from '../../../../move_to_pf/LoadingState'; -import { Table as ForemanTable, TableBody as ForemanTableBody } from '../../../../move_to_foreman/components/common/table'; -import ConfirmDialog from '../../../../move_to_foreman/components/common/ConfirmDialog'; -import Dialog from '../../../../move_to_foreman/components/common/Dialog'; import { recordsValid } from '../../SubscriptionValidations'; -import { createSubscriptionsTableSchema } from './SubscriptionsTableSchema'; -import { buildTableRows, groupSubscriptionsByProductId, buildPools } from './SubscriptionsTableHelpers'; -import { renderTaskStartedToast } from '../../../Tasks/helpers'; -import { BLOCKING_FOREMAN_TASK_TYPES } from '../../SubscriptionConstants'; +import { buildTableRows, groupSubscriptionsByProductId } from './SubscriptionsTableHelpers'; +import Table from './components/Table'; +import Dialogs from './components/Dialogs'; class SubscriptionsTable extends Component { constructor(props) { super(props); @@ -47,11 +40,170 @@ } return null; } - toggleSubscriptionGroup(groupId) { + getInlineEditController = () => ({ + isEditing: ({ rowData }) => + (this.state.editing && rowData.available >= 0 && rowData.upstream_pool_id), + hasChanged: ({ rowData }) => { + const editedValue = this.state.updatedQuantity[rowData.id]; + return this.hasQuantityChanged(rowData, editedValue); + }, + onActivate: () => { + this.enableEditing(true); + }, + onConfirm: () => { + if (recordsValid(this.state.rows)) { + this.showUpdateConfirm(true); + } else { + this.showErrorDialog(true); + } + }, + onCancel: () => { + this.showCancelConfirm(true); + }, + onChange: (value, { rowData }) => { + const updatedQuantity = cloneDeep(this.state.updatedQuantity); + + if (this.hasQuantityChanged(rowData, value)) { + updatedQuantity[rowData.id] = value; + } else { + delete updatedQuantity[rowData.id]; + } + + this.updateRows(updatedQuantity); + }, + }); + + getSelectionController = () => { + const allSubscriptionResults = this.props.subscriptions.results; + + const checkAllRowsSelected = () => + allSubscriptionResults.length === this.state.selectedRows.length; + + const updateDeleteButton = () => { + this.props.toggleDeleteButton(this.state.selectedRows.length > 0); + }; + return ({ + allRowsSelected: () => checkAllRowsSelected(), + selectAllRows: () => { + if (checkAllRowsSelected()) { + this.setState( + { selectedRows: [] }, + updateDeleteButton, + ); + } else { + this.setState( + { selectedRows: allSubscriptionResults.map(row => row.id) }, + updateDeleteButton, + ); + } + }, + selectRow: ({ rowData }) => { + let { selectedRows } = this.state; + if (selectedRows.includes(rowData.id)) { + selectedRows = selectedRows.filter(e => e !== rowData.id); + } else { + selectedRows.push(rowData.id); + } + + this.setState( + { selectedRows }, + updateDeleteButton, + ); + }, + isSelected: ({ rowData }) => this.state.selectedRows.includes(rowData.id), + }); + }; + + getTableProps = () => { + const { + subscriptions, emptyState, tableColumns, loadSubscriptions, + } = this.props; + const { groupedSubscriptions, rows, editing } = this.state; + + return { + emptyState, + editing, + groupedSubscriptions, + loadSubscriptions, + rows, + subscriptions, + tableColumns, + inlineEditController: this.getInlineEditController(), + selectionController: this.getSelectionController(), + }; + }; + + getUpdateDialogProps = () => { + const { showUpdateConfirmDialog: show, updatedQuantity } = this.state; + const { + updateQuantity, bulkSearch, organization, task, + } = this.props; + return { + bulkSearch, + organization, + show, + task, + updatedQuantity, + updateQuantity, + confirmEdit: this.confirmEdit, + enableEditing: this.enableEditing, + showUpdateConfirm: this.showUpdateConfirm, + }; + }; + + getUnsavedChangesDialogProps = () => { + const { showCancelConfirmDialog: show } = this.state; + return { + show, + cancelEdit: this.cancelEdit, + showCancelConfirm: this.showCancelConfirm, + }; + }; + + getInputsErrorsDialogProps = () => { + const { showErrorDialog: show } = this.state; + return { + show, + showErrorDialog: this.showErrorDialog, + }; + }; + + getDeleteDialogProps = () => { + const { + subscriptionDeleteModalOpen: show, + onDeleteSubscriptions, + onSubscriptionDeleteModalClose, + } = this.props; + const { selectedRows } = this.state; + return { + show, + selectedRows, + onSubscriptionDeleteModalClose, + onDeleteSubscriptions, + }; + }; + + getLoadingStateProps = () => { + const { subscriptions: { loading } } = this.props; + return { + loading, + loadingText: __('Loading'), + }; + }; + + getDialogsProps = () => ({ + updateDialog: this.getUpdateDialogProps(), + unsavedChangesDialog: this.getUnsavedChangesDialogProps(), + inputsErrorsDialog: this.getInputsErrorsDialogProps(), + deleteDialog: this.getDeleteDialogProps(), + }); + + + toggleSubscriptionGroup = (groupId) => { const { subscriptions } = this.props; const { groupedSubscriptions, updatedQuantity } = this.state; const { open } = groupedSubscriptions[groupId]; groupedSubscriptions[groupId].open = !open; @@ -62,267 +214,70 @@ subscriptions.availableQuantities, updatedQuantity, ); this.setState({ rows, groupedSubscriptions }); - } + }; - enableEditing(editingState) { + enableEditing = (editingState) => { this.setState({ updatedQuantity: {}, editing: editingState, }); - } + }; - updateRows(updatedQuantity) { + updateRows = (updatedQuantity) => { const { groupedSubscriptions } = this.state; const { subscriptions } = this.props; const rows = buildTableRows( groupedSubscriptions, subscriptions.availableQuantities, updatedQuantity, ); this.setState({ rows, updatedQuantity }); - } + }; - showUpdateConfirm(show) { + showUpdateConfirm = (show) => { this.setState({ showUpdateConfirmDialog: show, }); - } + }; - showCancelConfirm(show) { + showCancelConfirm = (show) => { this.setState({ showCancelConfirmDialog: show, }); - } + }; - showErrorDialog(show) { + showErrorDialog = (show) => { this.setState({ showErrorDialog: show, }); - } + }; - confirmEdit() { - this.showUpdateConfirm(false); - if (Object.keys(this.state.updatedQuantity).length > 0) { - this.props.updateQuantity(buildPools(this.state.updatedQuantity)) - .then(() => - this.props.bulkSearch({ - action: `organization '${this.props.organization.owner_details.displayName}'`, - result: 'pending', - label: BLOCKING_FOREMAN_TASK_TYPES.join(' or '), - })) - .then(() => renderTaskStartedToast(this.props.task)); - } - this.enableEditing(false); - } - - cancelEdit() { + cancelEdit = () => { this.showCancelConfirm(false); this.enableEditing(false); this.updateRows({}); - } + }; - hasQuantityChanged(rowData, editedValue) { + hasQuantityChanged = (rowData, editedValue) => { if (editedValue !== undefined) { const originalRows = this.props.subscriptions.results; const index = findIndex(originalRows, row => (row.id === rowData.id)); const currentValue = originalRows[index].quantity; return (`${editedValue}` !== `${currentValue}`); } return false; - } + }; render() { - const { subscriptions, emptyState, tableColumns } = this.props; - const { groupedSubscriptions } = this.state; - const allSubscriptionResults = subscriptions.results; - - const groupingController = { - isCollapseable: ({ rowData }) => - // it is the first subscription in the group - rowData.id === groupedSubscriptions[rowData.product_id].subscriptions[0].id && - // the group contains more then one subscription - groupedSubscriptions[rowData.product_id].subscriptions.length > 1, - isCollapsed: ({ rowData }) => !groupedSubscriptions[rowData.product_id].open, - toggle: ({ rowData }) => this.toggleSubscriptionGroup(rowData.product_id), - }; - - const inlineEditController = { - isEditing: ({ rowData }) => - (this.state.editing && rowData.available >= 0 && rowData.upstream_pool_id), - hasChanged: ({ rowData }) => { - const editedValue = this.state.updatedQuantity[rowData.id]; - return this.hasQuantityChanged(rowData, editedValue); - }, - onActivate: () => { - this.enableEditing(true); - }, - onConfirm: () => { - if (recordsValid(this.state.rows)) { - this.showUpdateConfirm(true); - } else { - this.showErrorDialog(true); - } - }, - onCancel: () => { - this.showCancelConfirm(true); - }, - onChange: (value, { rowData }) => { - const updatedQuantity = cloneDeep(this.state.updatedQuantity); - - if (this.hasQuantityChanged(rowData, value)) { - updatedQuantity[rowData.id] = value; - } else { - delete updatedQuantity[rowData.id]; - } - - this.updateRows(updatedQuantity); - }, - }; - - const checkAllRowsSelected = () => - allSubscriptionResults.length === this.state.selectedRows.length; - - const updateDeleteButton = () => { - this.props.toggleDeleteButton(this.state.selectedRows.length > 0); - }; - - const selectionController = { - allRowsSelected: () => checkAllRowsSelected(), - selectAllRows: () => { - if (checkAllRowsSelected()) { - this.setState( - { selectedRows: [] }, - updateDeleteButton, - ); - } else { - this.setState( - { selectedRows: allSubscriptionResults.map(row => row.id) }, - updateDeleteButton, - ); - } - }, - selectRow: ({ rowData }) => { - let { selectedRows } = this.state; - if (selectedRows.includes(rowData.id)) { - selectedRows = selectedRows.filter(e => e !== rowData.id); - } else { - selectedRows.push(rowData.id); - } - - this.setState( - { selectedRows }, - updateDeleteButton, - ); - }, - isSelected: ({ rowData }) => this.state.selectedRows.includes(rowData.id), - }; - - const onPaginationChange = (pagination) => { - this.props.loadSubscriptions({ - ...pagination, - }); - }; - - let bodyMessage; - if (allSubscriptionResults.length === 0 && subscriptions.searchIsActive) { - bodyMessage = __('No subscriptions match your search criteria.'); - } - - const alwaysDisplayColumns = ['select']; - const columnsDefinition = createSubscriptionsTableSchema( - inlineEditController, - selectionController, - groupingController, - ).filter(column => tableColumns.includes(column.property) || - alwaysDisplayColumns.includes(column.property)); - return ( - <LoadingState loading={subscriptions.loading} loadingText={__('Loading')}> - <ForemanTable - columns={columnsDefinition} - emptyState={emptyState} - bodyMessage={bodyMessage} - rows={this.state.rows} - components={{ - header: { - row: Table.TableInlineEditHeaderRow, - }, - }} - itemCount={subscriptions.itemCount} - pagination={subscriptions.pagination} - onPaginationChange={onPaginationChange} - inlineEdit - > - <Table.Header - onRow={() => ({ - role: 'row', - isEditing: () => this.state.editing, - onCancel: () => inlineEditController.onCancel(), - onConfirm: () => inlineEditController.onConfirm(), - })} - /> - <ForemanTableBody - columns={columnsDefinition} - rows={this.state.rows} - rowKey="id" - message={bodyMessage} - onRow={rowData => ({ - className: classNames({ 'open-grouped-row': !groupingController.isCollapsed({ rowData }) }), - })} - /> - </ForemanTable> - <ConfirmDialog - show={this.state.showUpdateConfirmDialog} - title={__('Editing Entitlements')} - dangerouslySetInnerHTML={{ - __html: sprintf( - __("You're making changes to %(entitlementCount)s entitlement(s)"), - { - entitlementCount: `<b>${Object.keys(this.state.updatedQuantity).length}</b>`, - }, - ), - }} - onConfirm={() => this.confirmEdit()} - onCancel={() => this.showUpdateConfirm(false)} - /> - <ConfirmDialog - show={this.state.showCancelConfirmDialog} - title={__('Editing Entitlements')} - message={__('You have unsaved changes. Do you want to exit without saving your changes?')} - confirmLabel={__('Exit')} - onConfirm={() => this.cancelEdit()} - onCancel={() => this.showCancelConfirm(false)} - /> - <Dialog - show={this.state.showErrorDialog} - title={__('Editing Entitlements')} - message={__('Some of your inputs contain errors. Please update them and save your changes again.')} - onCancel={() => this.showErrorDialog(false)} - /> - <ConfirmDialog - show={this.props.subscriptionDeleteModalOpen} - title={__('Confirm Deletion')} - dangerouslySetInnerHTML={{ - __html: sprintf( - __(`Are you sure you want to delete %(entitlementCount)s - subscription(s)? This action will remove the subscription(s) and - refresh your manifest. All systems using these subscription(s) will - lose them and also may lose access to updates and Errata.`), - { - entitlementCount: `<b>${this.state.selectedRows.length}</b>`, - }, - ), - }} - - confirmLabel={__('Delete')} - onConfirm={() => this.props.onDeleteSubscriptions(this.state.selectedRows)} - onCancel={this.props.onSubscriptionDeleteModalClose} - /> + <LoadingState {...this.getLoadingStateProps()}> + <Table {...this.getTableProps()} /> + <Dialogs {...this.getDialogsProps()} /> </LoadingState> ); } }