mirror of
https://github.com/Radarr/Radarr.git
synced 2024-10-03 22:57:18 +02:00
New: Move Interactive search to toolbar
This commit is contained in:
parent
3e534cf8bf
commit
40eeb31a21
@ -3,13 +3,16 @@ import React, { Fragment } from 'react';
|
||||
import Alert from 'Components/Alert';
|
||||
import Icon from 'Components/Icon';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import PageMenuButton from 'Components/Menu/PageMenuButton';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { icons, kinds, sortDirections } from 'Helpers/Props';
|
||||
import { align, icons, kinds, sortDirections } from 'Helpers/Props';
|
||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import InteractiveSearchFilterModalConnector from './InteractiveSearchFilterModalConnector';
|
||||
import InteractiveSearchRowConnector from './InteractiveSearchRowConnector';
|
||||
import styles from './InteractiveSearchContent.css';
|
||||
import styles from './InteractiveSearch.css';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@ -24,23 +27,6 @@ const columns = [
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'releaseWeight',
|
||||
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
|
||||
isSortable: true,
|
||||
fixedSortDirection: sortDirections.ASCENDING,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'rejections',
|
||||
label: React.createElement(Icon, {
|
||||
name: icons.DANGER,
|
||||
title: () => translate('Rejections')
|
||||
}),
|
||||
isSortable: true,
|
||||
fixedSortDirection: sortDirections.ASCENDING,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
label: () => translate('Title'),
|
||||
@ -84,12 +70,6 @@ const columns = [
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'customFormat',
|
||||
label: () => translate('Formats'),
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'customFormatScore',
|
||||
label: React.createElement(Icon, {
|
||||
@ -107,10 +87,27 @@ const columns = [
|
||||
}),
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'releaseWeight',
|
||||
label: React.createElement(Icon, { name: icons.DOWNLOAD }),
|
||||
isSortable: true,
|
||||
fixedSortDirection: sortDirections.ASCENDING,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'rejections',
|
||||
label: React.createElement(Icon, {
|
||||
name: icons.DANGER,
|
||||
title: () => translate('Rejections')
|
||||
}),
|
||||
isSortable: true,
|
||||
fixedSortDirection: sortDirections.ASCENDING,
|
||||
isVisible: true
|
||||
}
|
||||
];
|
||||
|
||||
function InteractiveSearchContent(props) {
|
||||
function InteractiveSearch(props) {
|
||||
const {
|
||||
searchPayload,
|
||||
isFetching,
|
||||
@ -118,18 +115,36 @@ function InteractiveSearchContent(props) {
|
||||
error,
|
||||
totalReleasesCount,
|
||||
items,
|
||||
selectedFilterKey,
|
||||
filters,
|
||||
customFilters,
|
||||
sortKey,
|
||||
sortDirection,
|
||||
longDateFormat,
|
||||
timeFormat,
|
||||
onSortPress,
|
||||
onFilterSelect,
|
||||
onGrabPress
|
||||
} = props;
|
||||
|
||||
const errorMessage = getErrorMessage(error);
|
||||
const type = 'movies';
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.filterMenuContainer}>
|
||||
<FilterMenu
|
||||
alignMenu={align.RIGHT}
|
||||
selectedFilterKey={selectedFilterKey}
|
||||
filters={filters}
|
||||
customFilters={customFilters}
|
||||
buttonComponent={PageMenuButton}
|
||||
filterModalConnectorComponent={InteractiveSearchFilterModalConnector}
|
||||
filterModalConnectorComponentProps={{ type }}
|
||||
onFilterSelect={onFilterSelect}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{
|
||||
isFetching ? <LoadingIndicator /> : null
|
||||
}
|
||||
@ -203,19 +218,23 @@ function InteractiveSearchContent(props) {
|
||||
);
|
||||
}
|
||||
|
||||
InteractiveSearchContent.propTypes = {
|
||||
InteractiveSearch.propTypes = {
|
||||
searchPayload: PropTypes.object.isRequired,
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
totalReleasesCount: PropTypes.number.isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
filters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
sortKey: PropTypes.string,
|
||||
sortDirection: PropTypes.string,
|
||||
longDateFormat: PropTypes.string.isRequired,
|
||||
timeFormat: PropTypes.string.isRequired,
|
||||
onSortPress: PropTypes.func.isRequired,
|
||||
onFilterSelect: PropTypes.func.isRequired,
|
||||
onGrabPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default InteractiveSearchContent;
|
||||
export default InteractiveSearch;
|
@ -5,7 +5,7 @@ import { createSelector } from 'reselect';
|
||||
import * as releaseActions from 'Store/Actions/releaseActions';
|
||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import InteractiveSearchContent from './InteractiveSearchContent';
|
||||
import InteractiveSearch from './InteractiveSearch';
|
||||
|
||||
function createMapStateToProps(appState) {
|
||||
return createSelector(
|
||||
@ -29,17 +29,12 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
dispatch(releaseActions.fetchReleases(payload));
|
||||
},
|
||||
|
||||
dispatchClearReleases(payload) {
|
||||
dispatch(releaseActions.clearReleases(payload));
|
||||
},
|
||||
|
||||
onSortPress(sortKey, sortDirection) {
|
||||
dispatch(releaseActions.setReleasesSort({ sortKey, sortDirection }));
|
||||
},
|
||||
|
||||
onFilterSelect(selectedFilterKey) {
|
||||
const action = releaseActions.setReleasesFilter;
|
||||
dispatch(action({ selectedFilterKey }));
|
||||
dispatch(releaseActions.setReleasesFilter({ selectedFilterKey }));
|
||||
},
|
||||
|
||||
onGrabPress(payload) {
|
||||
@ -48,7 +43,7 @@ function createMapDispatchToProps(dispatch, props) {
|
||||
};
|
||||
}
|
||||
|
||||
class InteractiveSearchContentConnector extends Component {
|
||||
class InteractiveSearchConnector extends Component {
|
||||
|
||||
//
|
||||
// Lifecycle
|
||||
@ -73,24 +68,22 @@ class InteractiveSearchContentConnector extends Component {
|
||||
render() {
|
||||
const {
|
||||
dispatchFetchReleases,
|
||||
dispatchClearReleases,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
||||
<InteractiveSearchContent
|
||||
<InteractiveSearch
|
||||
{...otherProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
InteractiveSearchContentConnector.propTypes = {
|
||||
InteractiveSearchConnector.propTypes = {
|
||||
searchPayload: PropTypes.object.isRequired,
|
||||
isPopulated: PropTypes.bool.isRequired,
|
||||
dispatchFetchReleases: PropTypes.func.isRequired,
|
||||
dispatchClearReleases: PropTypes.func.isRequired
|
||||
dispatchFetchReleases: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchContentConnector);
|
||||
export default connect(createMapStateToProps, createMapDispatchToProps)(InteractiveSearchConnector);
|
@ -4,7 +4,7 @@ import FilterMenu from 'Components/Menu/FilterMenu';
|
||||
import PageMenuButton from 'Components/Menu/PageMenuButton';
|
||||
import { align } from 'Helpers/Props';
|
||||
import InteractiveSearchFilterModalConnector from './InteractiveSearchFilterModalConnector';
|
||||
import styles from './InteractiveSearchContent.css';
|
||||
import styles from './InteractiveSearch.css';
|
||||
|
||||
function InteractiveSearchFilterMenu(props) {
|
||||
const {
|
||||
|
@ -1,23 +1,25 @@
|
||||
.cell {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
}
|
||||
|
||||
.protocol {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.titleContent {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.indexer {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 85px;
|
||||
}
|
||||
|
||||
.quality,
|
||||
.customFormat,
|
||||
.languages {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
}
|
||||
|
||||
.languages {
|
||||
@ -25,7 +27,7 @@
|
||||
}
|
||||
|
||||
.customFormatScore {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 55px;
|
||||
font-weight: bold;
|
||||
@ -33,31 +35,28 @@
|
||||
}
|
||||
|
||||
.rejected,
|
||||
.indexerFlags {
|
||||
composes: cell;
|
||||
.indexerFlags,
|
||||
.download {
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.age,
|
||||
.size {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.peers {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
.titleContent {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.history {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 75px;
|
||||
}
|
||||
@ -67,7 +66,7 @@
|
||||
}
|
||||
|
||||
.download {
|
||||
composes: cell;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 80px;
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
interface CssExports {
|
||||
'age': string;
|
||||
'blocklist': string;
|
||||
'cell': string;
|
||||
'customFormat': string;
|
||||
'customFormatScore': string;
|
||||
'download': string;
|
||||
'downloadIcon': string;
|
||||
|
@ -199,53 +199,6 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
|
||||
{formatAge(age, ageHours, ageMinutes)}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.download}>
|
||||
<SpinnerIconButton
|
||||
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
|
||||
kind={getDownloadKind(isGrabbed, grabError)}
|
||||
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
||||
isSpinning={isGrabbing}
|
||||
onPress={onGrabPressWrapper}
|
||||
/>
|
||||
|
||||
<Link
|
||||
className={styles.manualDownloadContent}
|
||||
title={translate('OverrideAndAddToDownloadQueue')}
|
||||
onPress={onOverridePress}
|
||||
>
|
||||
<div className={styles.manualDownloadContent}>
|
||||
<Icon
|
||||
className={styles.interactiveIcon}
|
||||
name={icons.INTERACTIVE}
|
||||
size={12}
|
||||
/>
|
||||
|
||||
<Icon
|
||||
className={styles.downloadIcon}
|
||||
name={icons.CIRCLE_DOWN}
|
||||
size={10}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.rejected}>
|
||||
{rejections.length ? (
|
||||
<Popover
|
||||
anchor={<Icon name={icons.DANGER} kind={kinds.DANGER} />}
|
||||
title={translate('ReleaseRejected')}
|
||||
body={
|
||||
<ul>
|
||||
{rejections.map((rejection, index) => {
|
||||
return <li key={index}>{rejection}</li>;
|
||||
})}
|
||||
</ul>
|
||||
}
|
||||
position={tooltipPositions.RIGHT}
|
||||
/>
|
||||
) : null}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell>
|
||||
<div className={styles.titleContent}>
|
||||
<Link to={infoUrl} title={title}>
|
||||
@ -316,10 +269,6 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
|
||||
<MovieQuality quality={quality} />
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.customFormat}>
|
||||
<MovieFormats formats={customFormats} />
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.customFormatScore}>
|
||||
<Tooltip
|
||||
anchor={formatCustomFormatScore(
|
||||
@ -348,6 +297,53 @@ function InteractiveSearchRow(props: InteractiveSearchRowProps) {
|
||||
) : null}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.rejected}>
|
||||
{rejections.length ? (
|
||||
<Popover
|
||||
anchor={<Icon name={icons.DANGER} kind={kinds.DANGER} />}
|
||||
title={translate('ReleaseRejected')}
|
||||
body={
|
||||
<ul>
|
||||
{rejections.map((rejection, index) => {
|
||||
return <li key={index}>{rejection}</li>;
|
||||
})}
|
||||
</ul>
|
||||
}
|
||||
position={tooltipPositions.LEFT}
|
||||
/>
|
||||
) : null}
|
||||
</TableRowCell>
|
||||
|
||||
<TableRowCell className={styles.download}>
|
||||
<SpinnerIconButton
|
||||
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
|
||||
kind={getDownloadKind(isGrabbed, grabError)}
|
||||
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
|
||||
isSpinning={isGrabbing}
|
||||
onPress={onGrabPressWrapper}
|
||||
/>
|
||||
|
||||
<Link
|
||||
className={styles.manualDownloadContent}
|
||||
title={translate('OverrideAndAddToDownloadQueue')}
|
||||
onPress={onOverridePress}
|
||||
>
|
||||
<div className={styles.manualDownloadContent}>
|
||||
<Icon
|
||||
className={styles.interactiveIcon}
|
||||
name={icons.INTERACTIVE}
|
||||
size={12}
|
||||
/>
|
||||
|
||||
<Icon
|
||||
className={styles.downloadIcon}
|
||||
name={icons.CIRCLE_DOWN}
|
||||
size={10}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
</TableRowCell>
|
||||
|
||||
<ConfirmModal
|
||||
isOpen={isConfirmGrabModalOpen}
|
||||
kind={kinds.WARNING}
|
||||
|
@ -1,16 +0,0 @@
|
||||
import React from 'react';
|
||||
import InteractiveSearchContentConnector from './InteractiveSearchContentConnector';
|
||||
|
||||
function InteractiveSearchTable(props) {
|
||||
|
||||
return (
|
||||
<InteractiveSearchContentConnector
|
||||
searchPayload={props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
InteractiveSearchTable.propTypes = {
|
||||
};
|
||||
|
||||
export default InteractiveSearchTable;
|
@ -23,12 +23,11 @@ import Popover from 'Components/Tooltip/Popover';
|
||||
import Tooltip from 'Components/Tooltip/Tooltip';
|
||||
import { icons, kinds, sizes, tooltipPositions } from 'Helpers/Props';
|
||||
import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
|
||||
import InteractiveSearchFilterMenuConnector from 'InteractiveSearch/InteractiveSearchFilterMenuConnector';
|
||||
import InteractiveSearchTable from 'InteractiveSearch/InteractiveSearchTable';
|
||||
import DeleteMovieModal from 'Movie/Delete/DeleteMovieModal';
|
||||
import EditMovieModalConnector from 'Movie/Edit/EditMovieModalConnector';
|
||||
import MovieHistoryTable from 'Movie/History/MovieHistoryTable';
|
||||
import MoviePoster from 'Movie/MoviePoster';
|
||||
import MovieInteractiveSearchModalConnector from 'Movie/Search/MovieInteractiveSearchModalConnector';
|
||||
import MovieFileEditorTable from 'MovieFile/Editor/MovieFileEditorTable';
|
||||
import ExtraFileTable from 'MovieFile/Extras/ExtraFileTable';
|
||||
import OrganizePreviewModalConnector from 'Organize/OrganizePreviewModalConnector';
|
||||
@ -78,6 +77,7 @@ class MovieDetails extends Component {
|
||||
isEditMovieModalOpen: false,
|
||||
isDeleteMovieModalOpen: false,
|
||||
isInteractiveImportModalOpen: false,
|
||||
isInteractiveSearchModalOpen: false,
|
||||
allExpanded: false,
|
||||
allCollapsed: false,
|
||||
expandedState: {},
|
||||
@ -134,6 +134,14 @@ class MovieDetails extends Component {
|
||||
this.setState({ isEditMovieModalOpen: false });
|
||||
};
|
||||
|
||||
onInteractiveSearchPress = () => {
|
||||
this.setState({ isInteractiveSearchModalOpen: true });
|
||||
};
|
||||
|
||||
onInteractiveSearchModalClose = () => {
|
||||
this.setState({ isInteractiveSearchModalOpen: false });
|
||||
};
|
||||
|
||||
onDeleteMoviePress = () => {
|
||||
this.setState({
|
||||
isEditMovieModalOpen: false,
|
||||
@ -295,6 +303,7 @@ class MovieDetails extends Component {
|
||||
isEditMovieModalOpen,
|
||||
isDeleteMovieModalOpen,
|
||||
isInteractiveImportModalOpen,
|
||||
isInteractiveSearchModalOpen,
|
||||
overviewHeight,
|
||||
titleWidth,
|
||||
selectedTabIndex
|
||||
@ -324,6 +333,14 @@ class MovieDetails extends Component {
|
||||
onPress={onSearchPress}
|
||||
/>
|
||||
|
||||
<PageToolbarButton
|
||||
label={translate('InteractiveSearch')}
|
||||
iconName={icons.INTERACTIVE}
|
||||
isSpinning={isSearching}
|
||||
title={undefined}
|
||||
onPress={this.onInteractiveSearchPress}
|
||||
/>
|
||||
|
||||
<PageToolbarSeparator />
|
||||
|
||||
<PageToolbarButton
|
||||
@ -665,13 +682,6 @@ class MovieDetails extends Component {
|
||||
{translate('History')}
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
>
|
||||
{translate('Search')}
|
||||
</Tab>
|
||||
|
||||
<Tab
|
||||
className={styles.tab}
|
||||
selectedClassName={styles.selectedTab}
|
||||
@ -700,13 +710,6 @@ class MovieDetails extends Component {
|
||||
{translate('Crew')}
|
||||
</Tab>
|
||||
|
||||
{
|
||||
selectedTabIndex === 1 &&
|
||||
<div className={styles.filterIcon}>
|
||||
<InteractiveSearchFilterMenuConnector />
|
||||
</div>
|
||||
}
|
||||
|
||||
</TabList>
|
||||
|
||||
<TabPanel>
|
||||
@ -715,12 +718,6 @@ class MovieDetails extends Component {
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
<InteractiveSearchTable
|
||||
movieId={id}
|
||||
/>
|
||||
</TabPanel>
|
||||
|
||||
<TabPanel>
|
||||
<MovieFileEditorTable
|
||||
movieId={id}
|
||||
@ -780,6 +777,12 @@ class MovieDetails extends Component {
|
||||
showImportMode={false}
|
||||
onModalClose={this.onInteractiveImportModalClose}
|
||||
/>
|
||||
|
||||
<MovieInteractiveSearchModalConnector
|
||||
isOpen={isInteractiveSearchModalOpen}
|
||||
movieId={id}
|
||||
onModalClose={this.onInteractiveSearchModalClose}
|
||||
/>
|
||||
</PageContentBody>
|
||||
</PageContent>
|
||||
);
|
||||
|
35
frontend/src/Movie/Search/MovieInteractiveSearchModal.js
Normal file
35
frontend/src/Movie/Search/MovieInteractiveSearchModal.js
Normal file
@ -0,0 +1,35 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Modal from 'Components/Modal/Modal';
|
||||
import { sizes } from 'Helpers/Props';
|
||||
import MovieInteractiveSearchModalContent from './MovieInteractiveSearchModalContent';
|
||||
|
||||
function MovieInteractiveSearchModal(props) {
|
||||
const {
|
||||
isOpen,
|
||||
movieId,
|
||||
onModalClose
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
closeOnBackgroundClick={false}
|
||||
onModalClose={onModalClose}
|
||||
size={sizes.EXTRA_LARGE}
|
||||
>
|
||||
<MovieInteractiveSearchModalContent
|
||||
movieId={movieId}
|
||||
onModalClose={onModalClose}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
MovieInteractiveSearchModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
movieId: PropTypes.number.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default MovieInteractiveSearchModal;
|
@ -0,0 +1,15 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { cancelFetchReleases, clearReleases } from 'Store/Actions/releaseActions';
|
||||
import MovieInteractiveSearchModal from './MovieInteractiveSearchModal';
|
||||
|
||||
function createMapDispatchToProps(dispatch, props) {
|
||||
return {
|
||||
onModalClose() {
|
||||
dispatch(cancelFetchReleases());
|
||||
dispatch(clearReleases());
|
||||
props.onModalClose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(null, createMapDispatchToProps)(MovieInteractiveSearchModal);
|
@ -0,0 +1,44 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import Button from 'Components/Link/Button';
|
||||
import ModalBody from 'Components/Modal/ModalBody';
|
||||
import ModalContent from 'Components/Modal/ModalContent';
|
||||
import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { scrollDirections } from 'Helpers/Props';
|
||||
import InteractiveSearchConnector from 'InteractiveSearch/InteractiveSearchConnector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
function MovieInteractiveSearchModalContent(props) {
|
||||
const {
|
||||
movieId,
|
||||
onModalClose
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<ModalContent onModalClose={onModalClose}>
|
||||
<ModalHeader>
|
||||
{translate('InteractiveSearchModalHeader')}
|
||||
</ModalHeader>
|
||||
|
||||
<ModalBody scrollDirection={scrollDirections.BOTH}>
|
||||
<InteractiveSearchConnector
|
||||
searchPayload={{ movieId }}
|
||||
/>
|
||||
</ModalBody>
|
||||
|
||||
<ModalFooter>
|
||||
<Button onPress={onModalClose}>
|
||||
{translate('Close')}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</ModalContent>
|
||||
);
|
||||
}
|
||||
|
||||
MovieInteractiveSearchModalContent.propTypes = {
|
||||
movieId: PropTypes.number.isRequired,
|
||||
onModalClose: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
export default MovieInteractiveSearchModalContent;
|
@ -556,6 +556,7 @@
|
||||
"InteractiveImportNoMovie": "Movie must be chosen for each selected file",
|
||||
"InteractiveImportNoQuality": "Quality must be chosen for each selected file",
|
||||
"InteractiveSearch": "Interactive Search",
|
||||
"InteractiveSearchModalHeader": "Interactive Search",
|
||||
"InteractiveSearchResultsFailedErrorMessage": "Search failed because its {message}. Try refreshing the movie info and verify the necessary information is present before searching again.",
|
||||
"Interval": "Interval",
|
||||
"InvalidFormat": "Invalid Format",
|
||||
|
Loading…
Reference in New Issue
Block a user