import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { sprintf } from 'jed';
import { cloneDeep, findIndex } from 'lodash';
import { Spinner, Table, Alert } from 'patternfly-react';
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 { columns } from './SubscriptionsTableSchema';
import { recordsValid } from './SubscriptionValidations';
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,
};
const buildTableRows = (subscriptions, updatedQuantity) =>
subscriptions.results.map((subs) => {
if (updatedQuantity[subs.id]) {
return {
...subs,
entitlementsChanged: true,
quantity: updatedQuantity[subs.id],
availableQuantity: subscriptions.availableQuantities[subs.id],
};
}
return {
...subs,
availableQuantity: subscriptions.availableQuantities[subs.id],
};
});
const buildPools = updatedQuantity =>
Object.entries(updatedQuantity)
.map(([id, quantity]) => ({
id,
quantity,
}));
class SubscriptionsTable extends Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.subscriptions !== undefined) {
return {
rows: buildTableRows(
nextProps.subscriptions,
prevState.updatedQuantity,
),
};
}
return null;
}
constructor(props) {
super(props);
this.state = {
updatedQuantity: {},
editing: false,
rows: props.subscriptions.results,
showUpdateConfirmDialog: false,
showCancelConfirmDialog: false,
showErrorDialog: false,
selectedRows: [],
};
}
enableEditing(editingState) {
this.setState({
updatedQuantity: {},
editing: editingState,
});
}
updateRows(updatedQuantity) {
const rows = buildTableRows(
this.props.subscriptions,
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 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 = columns(inlineEditController, selectionController);
return (
({
role: 'row',
isEditing: () => this.state.editing,
onCancel: () => inlineEditController.onCancel(),
onConfirm: () => inlineEditController.onConfirm(),
})}
/>
${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;