New: Combine mass editor and author editor, enable book editor

This commit is contained in:
ta264
2021-11-21 18:31:03 +00:00
parent d460cbf319
commit 615acdaebe
45 changed files with 1122 additions and 931 deletions
+216 -8
View File
@@ -2,7 +2,9 @@ import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import NoAuthor from 'Author/NoAuthor';
import BookEditorFooter from 'Book/Editor/BookEditorFooter';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import PageJumpBar from 'Components/Page/PageJumpBar';
@@ -11,10 +13,13 @@ import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import { align, icons, sortDirections } from 'Helpers/Props';
import { align, icons, kinds, sortDirections } from 'Helpers/Props';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
import translate from 'Utilities/String/translate';
import getSelectedIds from 'Utilities/Table/getSelectedIds';
import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected';
import BookIndexFooterConnector from './BookIndexFooterConnector';
import BookIndexFilterMenu from './Menus/BookIndexFilterMenu';
import BookIndexSortMenu from './Menus/BookIndexSortMenu';
@@ -52,12 +57,19 @@ class BookIndex extends Component {
jumpBarItems: { order: [] },
jumpToCharacter: null,
isPosterOptionsModalOpen: false,
isOverviewOptionsModalOpen: false
isOverviewOptionsModalOpen: false,
isConfirmSearchModalOpen: false,
isEditorActive: false,
allSelected: false,
allUnselected: false,
lastToggled: null,
selectedState: {}
};
}
componentDidMount() {
this.setJumpBarItems();
this.setSelectedState();
}
componentDidUpdate(prevProps) {
@@ -72,6 +84,7 @@ class BookIndex extends Component {
hasDifferentItemsOrOrder(prevProps.items, items)
) {
this.setJumpBarItems();
this.setSelectedState();
}
if (this.state.jumpToCharacter != null) {
@@ -86,6 +99,48 @@ class BookIndex extends Component {
this.setState({ scroller: ref });
}
getSelectedIds = () => {
if (this.state.allUnselected) {
return [];
}
return getSelectedIds(this.state.selectedState);
}
setSelectedState() {
const {
items
} = this.props;
const {
selectedState
} = this.state;
const newSelectedState = {};
items.forEach((book) => {
const isItemSelected = selectedState[book.id];
if (isItemSelected) {
newSelectedState[book.id] = isItemSelected;
} else {
newSelectedState[book.id] = false;
}
});
const selectedCount = getSelectedIds(newSelectedState).length;
const newStateCount = Object.keys(newSelectedState).length;
let isAllSelected = false;
let isAllUnselected = false;
if (selectedCount === 0) {
isAllUnselected = true;
} else if (selectedCount === newStateCount) {
isAllSelected = true;
}
this.setState({ selectedState: newSelectedState, allSelected: isAllSelected, allUnselected: isAllUnselected });
}
setJumpBarItems() {
const {
items,
@@ -150,10 +205,64 @@ class BookIndex extends Component {
this.setState({ isOverviewOptionsModalOpen: false });
}
onEditorTogglePress = () => {
if (this.state.isEditorActive) {
this.setState({ isEditorActive: false });
} else {
const newState = selectAll(this.state.selectedState, false);
newState.isEditorActive = true;
this.setState(newState);
}
}
onJumpBarItemPress = (jumpToCharacter) => {
this.setState({ jumpToCharacter });
}
onSelectAllChange = ({ value }) => {
this.setState(selectAll(this.state.selectedState, value));
}
onSelectAllPress = () => {
this.onSelectAllChange({ value: !this.state.allSelected });
}
onSelectedChange = ({ id, value, shiftKey = false }) => {
this.setState((state) => {
return toggleSelected(state, this.props.items, id, value, shiftKey);
});
}
onSaveSelected = (changes) => {
this.props.onSaveSelected({
bookIds: this.getSelectedIds(),
...changes
});
}
onSearchPress = () => {
this.setState({ isConfirmSearchModalOpen: true });
}
onRefreshBookPress = () => {
const selectedIds = this.getSelectedIds();
const refreshIds = this.state.isEditorActive && selectedIds.length > 0 ? selectedIds : [];
this.props.onRefreshBookPress(refreshIds);
}
onSearchConfirmed = () => {
const selectedMovieIds = this.getSelectedIds();
const searchIds = this.state.isMovieEditorActive && selectedMovieIds.length > 0 ? selectedMovieIds : this.props.items.map((m) => m.id);
this.props.onSearchPress(searchIds);
this.setState({ isConfirmSearchModalOpen: false });
}
onConfirmSearchModalClose = () => {
this.setState({ isConfirmSearchModalOpen: false });
}
//
// Render
@@ -173,11 +282,15 @@ class BookIndex extends Component {
view,
isRefreshingBook,
isRssSyncExecuting,
isSearching,
isSaving,
saveError,
isDeleting,
deleteError,
onScroll,
onSortSelect,
onFilterSelect,
onViewSelect,
onRefreshAuthorPress,
onRssSyncPress,
...otherProps
} = this.props;
@@ -187,23 +300,35 @@ class BookIndex extends Component {
jumpBarItems,
jumpToCharacter,
isPosterOptionsModalOpen,
isOverviewOptionsModalOpen
isOverviewOptionsModalOpen,
isConfirmSearchModalOpen,
isEditorActive,
selectedState,
allSelected,
allUnselected
} = this.state;
const selectedBookIds = this.getSelectedIds();
const ViewComponent = getViewComponent(view);
const isLoaded = !!(!error && isPopulated && items.length && scroller);
const hasNoAuthor = !totalItems;
const refreshLabel = isEditorActive && selectedBookIds.length > 0 ? translate('UpdateSelected') : translate('UpdateAll');
const searchIndexLabel = selectedFilterKey === 'all' ? translate('SearchAll') : translate('SearchFiltered');
const searchEditorLabel = selectedBookIds.length > 0 ? translate('SearchSelected') : translate('SearchAll');
const searchWarningCount = isEditorActive && selectedBookIds.length > 0 ? selectedBookIds.length : items.length;
return (
<PageContent>
<PageToolbar>
<PageToolbarSection>
<PageToolbarButton
label={translate('UpdateAll')}
label={refreshLabel}
iconName={icons.REFRESH}
spinningName={icons.REFRESH}
isSpinning={isRefreshingBook}
onPress={onRefreshAuthorPress}
onPress={this.onRefreshBookPress}
/>
<PageToolbarButton
@@ -214,6 +339,44 @@ class BookIndex extends Component {
onPress={onRssSyncPress}
/>
<PageToolbarSeparator />
<PageToolbarButton
label={isEditorActive ? searchEditorLabel : searchIndexLabel}
iconName={icons.SEARCH}
isDisabled={isSearching || !items.length}
onPress={this.onSearchPress}
/>
<PageToolbarSeparator />
{
isEditorActive ?
<PageToolbarButton
label={translate('BookIndex')}
iconName={icons.AUTHOR_CONTINUING}
isDisabled={hasNoAuthor}
onPress={this.onEditorTogglePress}
/> :
<PageToolbarButton
label={translate('BookEditor')}
iconName={icons.EDIT}
isDisabled={hasNoAuthor}
onPress={this.onEditorTogglePress}
/>
}
{
isEditorActive ?
<PageToolbarButton
label={allSelected ? translate('UnselectAll') : translate('SelectAll')}
iconName={icons.CHECK_SQUARE}
isDisabled={hasNoAuthor}
onPress={this.onSelectAllPress}
/> :
null
}
</PageToolbarSection>
<PageToolbarSection
@@ -311,6 +474,12 @@ class BookIndex extends Component {
sortKey={sortKey}
sortDirection={sortDirection}
jumpToCharacter={jumpToCharacter}
isEditorActive={isEditorActive}
allSelected={allSelected}
allUnselected={allUnselected}
onSelectedChange={this.onSelectedChange}
onSelectAllChange={this.onSelectAllChange}
selectedState={selectedState}
{...otherProps}
/>
@@ -336,6 +505,19 @@ class BookIndex extends Component {
}
</div>
{
isLoaded && isEditorActive &&
<BookEditorFooter
bookIds={selectedBookIds}
selectedCount={selectedBookIds.length}
isSaving={isSaving}
saveError={saveError}
isDeleting={isDeleting}
deleteError={deleteError}
onSaveSelected={this.onSaveSelected}
/>
}
<BookIndexPosterOptionsModal
isOpen={isPosterOptionsModalOpen}
onModalClose={this.onPosterOptionsModalClose}
@@ -346,6 +528,25 @@ class BookIndex extends Component {
onModalClose={this.onOverviewOptionsModalClose}
/>
<ConfirmModal
isOpen={isConfirmSearchModalOpen}
kind={kinds.DANGER}
title={translate('MassBookSearch')}
message={
<div>
<div>
{translate('MassBookSearchWarning', [searchWarningCount])}
</div>
<div>
{translate('ThisCannotBeCancelled')}
</div>
</div>
}
confirmLabel={translate('Search')}
onConfirm={this.onSearchConfirmed}
onCancel={this.onConfirmSearchModalClose}
/>
</PageContent>
);
}
@@ -365,14 +566,21 @@ BookIndex.propTypes = {
sortDirection: PropTypes.oneOf(sortDirections.all),
view: PropTypes.string.isRequired,
isRefreshingBook: PropTypes.bool.isRequired,
isSearching: PropTypes.bool.isRequired,
isRssSyncExecuting: PropTypes.bool.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
isDeleting: PropTypes.bool.isRequired,
deleteError: PropTypes.object,
onSortSelect: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onViewSelect: PropTypes.func.isRequired,
onRefreshAuthorPress: PropTypes.func.isRequired,
onRefreshBookPress: PropTypes.func.isRequired,
onRssSyncPress: PropTypes.func.isRequired,
onScroll: PropTypes.func.isRequired
onSearchPress: PropTypes.func.isRequired,
onScroll: PropTypes.func.isRequired,
onSaveSelected: PropTypes.func.isRequired
};
export default BookIndex;
+27 -4
View File
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition';
import { setBookFilter, setBookSort, setBookTableOption, setBookView } from 'Store/Actions/bookIndexActions';
import { saveBookEditor, setBookFilter, setBookSort, setBookTableOption, setBookView } from 'Store/Actions/bookIndexActions';
import { executeCommand } from 'Store/Actions/commandActions';
import scrollPositions from 'Store/scrollPositions';
import createBookClientSideCollectionItemsSelector from 'Store/Selectors/createBookClientSideCollectionItemsSelector';
@@ -19,12 +19,16 @@ function createMapStateToProps() {
createCommandExecutingSelector(commandNames.REFRESH_AUTHOR),
createCommandExecutingSelector(commandNames.REFRESH_BOOK),
createCommandExecutingSelector(commandNames.RSS_SYNC),
createCommandExecutingSelector(commandNames.CUTOFF_UNMET_BOOK_SEARCH),
createCommandExecutingSelector(commandNames.MISSING_BOOK_SEARCH),
createDimensionsSelector(),
(
book,
isRefreshingAuthorCommand,
isRefreshingBookCommand,
isRssSyncExecuting,
isCutoffBooksSearch,
isMissingBooksSearch,
dimensionsState
) => {
const isRefreshingBook = isRefreshingBookCommand || isRefreshingAuthorCommand;
@@ -32,6 +36,7 @@ function createMapStateToProps() {
...book,
isRefreshingBook,
isRssSyncExecuting,
isSearching: isCutoffBooksSearch || isMissingBooksSearch,
isSmallScreen: dimensionsState.isSmallScreen
};
}
@@ -56,9 +61,14 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(setBookView({ view }));
},
onRefreshAuthorPress() {
dispatchSaveBookEditor(payload) {
dispatch(saveBookEditor(payload));
},
onRefreshBookPress(items) {
dispatch(executeCommand({
name: commandNames.REFRESH_AUTHOR
name: commandNames.BULK_REFRESH_BOOK,
bookIds: items
}));
},
@@ -66,6 +76,13 @@ function createMapDispatchToProps(dispatch, props) {
dispatch(executeCommand({
name: commandNames.RSS_SYNC
}));
},
onSearchPress(items) {
dispatch(executeCommand({
name: commandNames.BOOK_SEARCH,
bookIds: items
}));
}
};
}
@@ -79,6 +96,10 @@ class BookIndexConnector extends Component {
this.props.dispatchSetBookView(view);
}
onSaveSelected = (payload) => {
this.props.dispatchSaveBookEditor(payload);
}
onScroll = ({ scrollTop }) => {
scrollPositions.bookIndex = scrollTop;
}
@@ -92,6 +113,7 @@ class BookIndexConnector extends Component {
{...this.props}
onViewSelect={this.onViewSelect}
onScroll={this.onScroll}
onSaveSelected={this.onSaveSelected}
/>
);
}
@@ -100,7 +122,8 @@ class BookIndexConnector extends Component {
BookIndexConnector.propTypes = {
isSmallScreen: PropTypes.bool.isRequired,
view: PropTypes.string.isRequired,
dispatchSetBookView: PropTypes.func.isRequired
dispatchSetBookView: PropTypes.func.isRequired,
dispatchSaveBookEditor: PropTypes.func.isRequired
};
export default withScrollPosition(
@@ -42,7 +42,7 @@ function createMapStateToProps() {
executingCommands
) => {
// If an book is deleted this selector may fire before the parent
// If a book is deleted this selector may fire before the parent
// selectors, which will result in an undefined book, if that happens
// we want to return early here and again in the render function to avoid
// trying to show an book that has no information available.
@@ -19,6 +19,13 @@ $hoverScale: 1.05;
left: 0;
}
.editorSelect {
position: absolute;
top: 0;
left: 5px;
z-index: 3;
}
.posterContainer {
position: relative;
overflow: hidden;
@@ -5,6 +5,7 @@ import AuthorPoster from 'Author/AuthorPoster';
import DeleteAuthorModal from 'Author/Delete/DeleteAuthorModal';
import EditAuthorModalConnector from 'Author/Edit/EditAuthorModalConnector';
import BookIndexProgressBar from 'Book/Index/ProgressBar/BookIndexProgressBar';
import CheckInput from 'Components/Form/CheckInput';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
@@ -67,6 +68,15 @@ class BookIndexOverview extends Component {
this.setState({ isDeleteAuthorModalOpen: false });
}
onChange = ({ value, shiftKey }) => {
const {
id,
onSelectedChange
} = this.props;
onSelectedChange({ id, value, shiftKey });
}
//
// Render
@@ -95,6 +105,8 @@ class BookIndexOverview extends Component {
isSearchingBook,
onRefreshBookPress,
onSearchPress,
isEditorActive,
isSelected,
...otherProps
} = this.props;
@@ -125,6 +137,17 @@ class BookIndexOverview extends Component {
<div className={styles.container}>
<div className={styles.content}>
<div className={styles.posterContainer}>
{
isEditorActive &&
<div className={styles.editorSelect}>
<CheckInput
className={styles.checkInput}
name={id.toString()}
value={isSelected}
onChange={this.onChange}
/>
</div>
}
{
status === 'ended' &&
<div
@@ -264,7 +287,10 @@ BookIndexOverview.propTypes = {
isRefreshingBook: PropTypes.bool.isRequired,
isSearchingBook: PropTypes.bool.isRequired,
onRefreshBookPress: PropTypes.func.isRequired,
onSearchPress: PropTypes.func.isRequired
onSearchPress: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
onSelectedChange: PropTypes.func.isRequired
};
BookIndexOverview.defaultProps = {
@@ -73,7 +73,9 @@ class BookIndexOverviews extends Component {
sortKey,
overviewOptions,
jumpToCharacter,
scrollTop
scrollTop,
isEditorActive,
selectedState
} = this.props;
const {
@@ -91,6 +93,8 @@ class BookIndexOverviews extends Component {
(prevState.width !== width ||
prevState.rowHeight !== rowHeight ||
hasDifferentItemsOrOrder(prevProps.items, items) ||
prevProps.isEditorActive !== isEditorActive ||
prevProps.selectedState !== selectedState ||
prevProps.overviewOptions !== overviewOptions)) {
// recomputeGridSize also forces Grid to discard its cache of rendered cells
this._grid.recomputeGridSize();
@@ -148,7 +152,10 @@ class BookIndexOverviews extends Component {
shortDateFormat,
longDateFormat,
timeFormat,
isSmallScreen
isSmallScreen,
selectedState,
isEditorActive,
onSelectedChange
} = this.props;
const {
@@ -183,6 +190,9 @@ class BookIndexOverviews extends Component {
isSmallScreen={isSmallScreen}
bookId={book.id}
authorId={book.authorId}
isSelected={selectedState[book.id]}
onSelectedChange={onSelectedChange}
isEditorActive={isEditorActive}
/>
</div>
);
@@ -263,7 +273,10 @@ BookIndexOverviews.propTypes = {
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
timeFormat: PropTypes.string.isRequired
timeFormat: PropTypes.string.isRequired,
selectedState: PropTypes.object.isRequired,
onSelectedChange: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired
};
export default BookIndexOverviews;
@@ -78,6 +78,13 @@ $hoverScale: 1.05;
color: $white;
}
.editorSelect {
position: absolute;
top: 10px;
left: 10px;
z-index: 4;
}
.controls {
position: absolute;
bottom: 10px;
@@ -5,6 +5,7 @@ import DeleteAuthorModal from 'Author/Delete/DeleteAuthorModal';
import EditAuthorModalConnector from 'Author/Edit/EditAuthorModalConnector';
import EditBookModalConnector from 'Book/Edit/EditBookModalConnector';
import BookIndexProgressBar from 'Book/Index/ProgressBar/BookIndexProgressBar';
import CheckInput from 'Components/Form/CheckInput';
import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
@@ -73,6 +74,15 @@ class BookIndexPoster extends Component {
}
}
onChange = ({ value, shiftKey }) => {
const {
id,
onSelectedChange
} = this.props;
onSelectedChange({ id, value, shiftKey });
}
//
// Render
@@ -103,6 +113,9 @@ class BookIndexPoster extends Component {
isSearchingBook,
onRefreshBookPress,
onSearchPress,
isEditorActive,
isSelected,
onSelectedChange,
...otherProps
} = this.props;
@@ -132,6 +145,18 @@ class BookIndexPoster extends Component {
<div>
<div className={styles.content}>
<div className={styles.posterContainer}>
{
isEditorActive &&
<div className={styles.editorSelect}>
<CheckInput
className={styles.checkInput}
name={id.toString()}
value={isSelected}
onChange={this.onChange}
/>
</div>
}
<Label className={styles.controls}>
<SpinnerIconButton
className={styles.action}
@@ -309,7 +334,10 @@ BookIndexPoster.propTypes = {
isRefreshingBook: PropTypes.bool.isRequired,
isSearchingBook: PropTypes.bool.isRequired,
onRefreshBookPress: PropTypes.func.isRequired,
onSearchPress: PropTypes.func.isRequired
onSearchPress: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
onSelectedChange: PropTypes.func.isRequired
};
BookIndexPoster.defaultProps = {
@@ -121,7 +121,9 @@ class BookIndexPosters extends Component {
posterOptions,
jumpToCharacter,
isSmallScreen,
scrollTop
isEditorActive,
scrollTop,
selectedState
} = this.props;
const {
@@ -142,7 +144,9 @@ class BookIndexPosters extends Component {
prevState.columnWidth !== columnWidth ||
prevState.columnCount !== columnCount ||
prevState.rowHeight !== rowHeight ||
hasDifferentItemsOrOrder(prevProps.items, items))) {
hasDifferentItemsOrOrder(prevProps.items, items)) ||
prevProps.isEditorActive !== isEditorActive ||
prevProps.selectedState !== selectedState) {
// recomputeGridSize also forces Grid to discard its cache of rendered cells
this._grid.recomputeGridSize();
}
@@ -202,7 +206,10 @@ class BookIndexPosters extends Component {
posterOptions,
showRelativeDates,
shortDateFormat,
timeFormat
timeFormat,
selectedState,
isEditorActive,
onSelectedChange
} = this.props;
const {
@@ -251,6 +258,9 @@ class BookIndexPosters extends Component {
style={style}
bookId={book.id}
authorId={book.authorId}
isSelected={selectedState[book.id]}
onSelectedChange={onSelectedChange}
isEditorActive={isEditorActive}
/>
</div>
);
@@ -333,7 +343,10 @@ BookIndexPosters.propTypes = {
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
timeFormat: PropTypes.string.isRequired
timeFormat: PropTypes.string.isRequired,
selectedState: PropTypes.object.isRequired,
onSelectedChange: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired
};
export default BookIndexPosters;
@@ -5,6 +5,7 @@ import IconButton from 'Components/Link/IconButton';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
import { icons } from 'Helpers/Props';
import BookIndexTableOptionsConnector from './BookIndexTableOptionsConnector';
import styles from './BookIndexHeader.css';
@@ -13,6 +14,10 @@ function BookIndexHeader(props) {
const {
columns,
onTableOptionChange,
allSelected,
allUnselected,
onSelectAllChange,
isEditorActive,
...otherProps
} = props;
@@ -31,6 +36,21 @@ function BookIndexHeader(props) {
return null;
}
if (name === 'select') {
if (isEditorActive) {
return (
<VirtualTableSelectAllHeaderCell
key={name}
allSelected={allSelected}
allUnselected={allUnselected}
onSelectAllChange={onSelectAllChange}
/>
);
}
return null;
}
if (name === 'actions') {
return (
<VirtualTableHeaderCell
@@ -75,7 +95,11 @@ function BookIndexHeader(props) {
BookIndexHeader.propTypes = {
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onTableOptionChange: PropTypes.func.isRequired
onTableOptionChange: PropTypes.func.isRequired,
allSelected: PropTypes.bool.isRequired,
allUnselected: PropTypes.bool.isRequired,
onSelectAllChange: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired
};
export default BookIndexHeader;
+22 -2
View File
@@ -11,6 +11,7 @@ import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
import TagListConnector from 'Components/TagListConnector';
import { icons } from 'Helpers/Props';
import formatBytes from 'Utilities/Number/formatBytes';
@@ -100,8 +101,11 @@ class BookIndexRow extends Component {
columns,
isRefreshingBook,
isSearchingBook,
isEditorActive,
isSelected,
onRefreshBookPress,
onSearchPress
onSearchPress,
onSelectedChange
} = this.props;
const {
@@ -128,6 +132,19 @@ class BookIndexRow extends Component {
return null;
}
if (isEditorActive && name === 'select') {
return (
<VirtualTableSelectCell
inputClassName={styles.checkInput}
id={id}
key={name}
isSelected={isSelected}
isDisabled={false}
onSelectedChange={onSelectedChange}
/>
);
}
if (name === 'status') {
return (
<BookStatusCell
@@ -368,7 +385,10 @@ BookIndexRow.propTypes = {
isRefreshingBook: PropTypes.bool.isRequired,
isSearchingBook: PropTypes.bool.isRequired,
onRefreshBookPress: PropTypes.func.isRequired,
onSearchPress: PropTypes.func.isRequired
onSearchPress: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired,
isSelected: PropTypes.bool,
onSelectedChange: PropTypes.func.isRequired
};
BookIndexRow.defaultProps = {
@@ -47,7 +47,10 @@ class BookIndexTable extends Component {
rowRenderer = ({ key, rowIndex, style }) => {
const {
items,
columns
columns,
selectedState,
onSelectedChange,
isEditorActive
} = this.props;
const book = items[rowIndex];
@@ -64,6 +67,9 @@ class BookIndexTable extends Component {
columns={columns}
authorId={book.authorId}
bookId={book.id}
isSelected={selectedState[book.id]}
onSelectedChange={onSelectedChange}
isEditorActive={isEditorActive}
/>
</VirtualTableRow>
);
@@ -81,7 +87,12 @@ class BookIndexTable extends Component {
isSmallScreen,
onSortPress,
scroller,
scrollTop
scrollTop,
allSelected,
allUnselected,
onSelectAllChange,
isEditorActive,
selectedState
} = this.props;
return (
@@ -101,8 +112,13 @@ class BookIndexTable extends Component {
sortKey={sortKey}
sortDirection={sortDirection}
onSortPress={onSortPress}
allSelected={allSelected}
allUnselected={allUnselected}
onSelectAllChange={onSelectAllChange}
isEditorActive={isEditorActive}
/>
}
selectedState={selectedState}
columns={columns}
sortKey={sortKey}
sortDirection={sortDirection}
@@ -120,7 +136,13 @@ BookIndexTable.propTypes = {
scrollTop: PropTypes.number,
scroller: PropTypes.instanceOf(Element).isRequired,
isSmallScreen: PropTypes.bool.isRequired,
onSortPress: PropTypes.func.isRequired
onSortPress: PropTypes.func.isRequired,
allSelected: PropTypes.bool.isRequired,
allUnselected: PropTypes.bool.isRequired,
selectedState: PropTypes.object.isRequired,
onSelectedChange: PropTypes.func.isRequired,
onSelectAllChange: PropTypes.func.isRequired,
isEditorActive: PropTypes.bool.isRequired
};
export default BookIndexTable;