import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { sprintf } from 'jed';
import { cloneDeep, findIndex, isEqual } from 'lodash';
import { Table, Alert } 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';
const emptyStateData = {
header: __('There are no Subscriptions to display'),
description: __('Add Subscriptions to this Allocation to manage your Entitlements.'),
documentation: {
title: __('Learn more about adding Subscriptions to Allocations'),
url: 'http://redhat.com',
},
action: {
title: __('Add Subscriptions'),
url: 'subscriptions/add',
},
};
const ErrorAlerts = ({ errors }) => {
const alerts = errors.filter(Boolean).map(e => (
{e}
));
return (
{alerts}
);
};
ErrorAlerts.propTypes = {
errors: PropTypes.arrayOf(PropTypes.string).isRequired,
};
class SubscriptionsTable extends Component {
constructor(props) {
super(props);
this.state = {
rows: undefined,
subscriptions: undefined,
groupdSubscriptions: undefined,
updatedQuantity: {},
editing: false,
showUpdateConfirmDialog: false,
showCancelConfirmDialog: false,
showErrorDialog: false,
selectedRows: [],
};
}
static getDerivedStateFromProps(nextProps, prevState) {
if (
nextProps.subscriptions !== undefined &&
!isEqual(nextProps.subscriptions, prevState.subscriptions)
) {
const groupdSubscriptions = groupSubscriptionsByProductId(nextProps.subscriptions);
const rows = buildTableRows(
groupdSubscriptions,
nextProps.subscriptions.availableQuantities,
prevState.updatedQuantity,
);
return { rows, groupdSubscriptions, subscriptions: nextProps.subscriptions };
}
return null;
}
toggleSubscriptionGroup(groupId) {
const { subscriptions } = this.props;
const { groupdSubscriptions, updatedQuantity } = this.state;
const { open } = groupdSubscriptions[groupId];
groupdSubscriptions[groupId].open = !open;
const rows = buildTableRows(
groupdSubscriptions,
subscriptions.availableQuantities,
updatedQuantity,
);
this.setState({ rows, groupdSubscriptions });
}
enableEditing(editingState) {
this.setState({
updatedQuantity: {},
editing: editingState,
});
}
updateRows(updatedQuantity) {
const { groupdSubscriptions } = this.state;
const { subscriptions } = this.props;
const rows = buildTableRows(
groupdSubscriptions,
subscriptions.availableQuantities,
updatedQuantity,
);
this.setState({ rows, updatedQuantity });
}
showUpdateConfirm(show) {
this.setState({
showUpdateConfirmDialog: show,
});
}
showCancelConfirm(show) {
this.setState({
showCancelConfirmDialog: 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));
}
this.enableEditing(false);
}
cancelEdit() {
this.showCancelConfirm(false);
this.enableEditing(false);
this.updateRows({});
}
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 } = this.props;
const { groupdSubscriptions } = this.state;
const groupingController = {
isCollapseable: ({ rowData }) =>
// it is the first subscription in the group
rowData.id === groupdSubscriptions[rowData.product_id].subscriptions[0].id &&
// the group contains more then one subscription
groupdSubscriptions[rowData.product_id].subscriptions.length > 1,
isCollapsed: ({ rowData }) => !groupdSubscriptions[rowData.product_id].open,
toggle: ({ rowData }) => this.toggleSubscriptionGroup(rowData.product_id),
};
const inlineEditController = {
isEditing: ({ rowData }) => (this.state.editing && rowData.available >= 0),
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 = () => this.state.rows.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: this.state.rows.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 (subscriptions.results.length === 0 && subscriptions.searchIsActive) {
bodyMessage = __('No subscriptions match your search criteria.');
}
const columnsDefinition = createSubscriptionsTableSchema(
inlineEditController,
selectionController,
groupingController,
);
return (
({
role: 'row',
isEditing: () => this.state.editing,
onCancel: () => inlineEditController.onCancel(),
onConfirm: () => inlineEditController.onConfirm(),
})}
/>
({
className: classNames({ 'open-grouped-row': !groupingController.isCollapsed({ rowData }) }),
})}
/>
${Object.keys(this.state.updatedQuantity).length}`,
},
),
}}
onConfirm={() => this.confirmEdit()}
onCancel={() => this.showUpdateConfirm(false)}
/>
this.cancelEdit()}
onCancel={() => this.showCancelConfirm(false)}
/>
);
}
}
SubscriptionsTable.propTypes = {
loadSubscriptions: PropTypes.func.isRequired,
updateQuantity: PropTypes.func.isRequired,
subscriptions: PropTypes.shape({
results: PropTypes.array,
}).isRequired,
subscriptionDeleteModalOpen: PropTypes.bool.isRequired,
onDeleteSubscriptions: PropTypes.func.isRequired,
onSubscriptionDeleteModalClose: PropTypes.func.isRequired,
toggleDeleteButton: PropTypes.func.isRequired,
};
export default SubscriptionsTable;