mirror of
https://github.com/Radarr/Radarr.git
synced 2025-04-24 14:37:07 -04:00
New: Rework List Exclusion UI
This commit is contained in:
parent
6659bc034c
commit
74382d7250
6 changed files with 167 additions and 51 deletions
|
@ -181,12 +181,13 @@ class Blocklist extends Component {
|
|||
>
|
||||
<TableBody>
|
||||
{
|
||||
items.map((item) => {
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<BlocklistRowConnector
|
||||
key={item.id}
|
||||
isSelected={selectedState[item.id] || false}
|
||||
columns={columns}
|
||||
index={index}
|
||||
{...item}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
/>
|
||||
|
|
|
@ -15,12 +15,13 @@
|
|||
|
||||
.tmdbId,
|
||||
.movieYear {
|
||||
flex: 0 0 70px;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex: 1 0 auto;
|
||||
padding-right: 10px;
|
||||
composes: cell from '~Components/Table/Cells/TableRowCell.css';
|
||||
|
||||
width: 70px;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import ConfirmModal from 'Components/Modal/ConfirmModal';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import styles from './ImportListExclusion.css';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
|
||||
class ImportListExclusion extends Component {
|
||||
|
||||
|
@ -55,28 +58,82 @@ class ImportListExclusion extends Component {
|
|||
render() {
|
||||
const {
|
||||
id,
|
||||
isSelected,
|
||||
onSelectedChange,
|
||||
columns,
|
||||
movieTitle,
|
||||
tmdbId,
|
||||
movieYear
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
styles.importExclusion
|
||||
)}
|
||||
>
|
||||
<div className={styles.tmdbId}>{tmdbId}</div>
|
||||
<div className={styles.movieTitle}>{movieTitle}</div>
|
||||
<div className={styles.movieYear}>{movieYear}</div>
|
||||
<TableRow>
|
||||
<TableSelectCell
|
||||
id={id}
|
||||
isSelected={isSelected}
|
||||
onSelectedChange={onSelectedChange}
|
||||
/>
|
||||
|
||||
<div className={styles.actions}>
|
||||
<Link
|
||||
onPress={this.onEditImportExclusionPress}
|
||||
>
|
||||
<Icon name={icons.EDIT} />
|
||||
</Link>
|
||||
</div>
|
||||
{
|
||||
columns.map((column) => {
|
||||
const {
|
||||
name,
|
||||
isVisible
|
||||
} = column;
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (name === 'tmdbId') {
|
||||
return (
|
||||
<TableRowCell key={name}>
|
||||
{tmdbId}
|
||||
</TableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'movieTitle') {
|
||||
return (
|
||||
<TableRowCell key={name}>
|
||||
{movieTitle}
|
||||
</TableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'movieYear') {
|
||||
return (
|
||||
<TableRowCell key={name}>
|
||||
{movieYear}
|
||||
</TableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
if (name === 'actions') {
|
||||
return (
|
||||
<TableRowCell
|
||||
key={name}
|
||||
className={styles.actions}
|
||||
>
|
||||
<IconButton
|
||||
title={translate('RemoveFromBlocklist')}
|
||||
name={icons.EDIT}
|
||||
onPress={this.onEditImportExclusionPress}
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
title={translate('RemoveFromBlocklist')}
|
||||
name={icons.REMOVE}
|
||||
kind={kinds.DANGER}
|
||||
onPress={this.onDeleteImportExclusionPress}
|
||||
/>
|
||||
</TableRowCell>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
}
|
||||
|
||||
<EditImportListExclusionModalConnector
|
||||
id={id}
|
||||
|
@ -94,7 +151,7 @@ class ImportListExclusion extends Component {
|
|||
onConfirm={this.onConfirmDeleteImportExclusion}
|
||||
onCancel={this.onDeleteImportExclusionModalClose}
|
||||
/>
|
||||
</div>
|
||||
</TableRow>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -104,6 +161,9 @@ ImportListExclusion.propTypes = {
|
|||
movieTitle: PropTypes.string.isRequired,
|
||||
tmdbId: PropTypes.number.isRequired,
|
||||
movieYear: PropTypes.number.isRequired,
|
||||
isSelected: PropTypes.bool.isRequired,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onSelectedChange: PropTypes.func.isRequired,
|
||||
onConfirmDeleteImportExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
|
|
@ -4,8 +4,12 @@ import FieldSet from 'Components/FieldSet';
|
|||
import Icon from 'Components/Icon';
|
||||
import Link from 'Components/Link/Link';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import selectAll from 'Utilities/Table/selectAll';
|
||||
import toggleSelected from 'Utilities/Table/toggleSelected';
|
||||
import EditImportListExclusionModalConnector from './EditImportListExclusionModalConnector';
|
||||
import ImportListExclusion from './ImportListExclusion';
|
||||
import styles from './ImportListExclusions.css';
|
||||
|
@ -19,6 +23,10 @@ class ImportListExclusions extends Component {
|
|||
super(props, context);
|
||||
|
||||
this.state = {
|
||||
allSelected: false,
|
||||
allUnselected: false,
|
||||
lastToggled: null,
|
||||
selectedState: {},
|
||||
isAddImportExclusionModalOpen: false
|
||||
};
|
||||
}
|
||||
|
@ -26,6 +34,16 @@ class ImportListExclusions extends Component {
|
|||
//
|
||||
// Listeners
|
||||
|
||||
onSelectAllChange = ({ value }) => {
|
||||
this.setState(selectAll(this.state.selectedState, value));
|
||||
};
|
||||
|
||||
onSelectedChange = ({ id, value, shiftKey = false }) => {
|
||||
this.setState((state) => {
|
||||
return toggleSelected(state, this.props.items, id, value, shiftKey);
|
||||
});
|
||||
};
|
||||
|
||||
onAddImportExclusionPress = () => {
|
||||
this.setState({ isAddImportExclusionModalOpen: true });
|
||||
};
|
||||
|
@ -41,41 +59,50 @@ class ImportListExclusions extends Component {
|
|||
const {
|
||||
items,
|
||||
onConfirmDeleteImportExclusion,
|
||||
columns,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
allSelected,
|
||||
allUnselected,
|
||||
selectedState
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<FieldSet legend={translate('ListExclusions')}>
|
||||
<PageSectionContent
|
||||
errorMessage={translate('UnableToLoadListExclusions')}
|
||||
{...otherProps}
|
||||
>
|
||||
<div className={styles.importListExclusionsHeader}>
|
||||
<div className={styles.tmdbId}>
|
||||
TMDb Id
|
||||
</div>
|
||||
<div className={styles.title}>
|
||||
{translate('Title')}
|
||||
</div>
|
||||
<div className={styles.movieYear}>
|
||||
{translate('Year')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<ImportListExclusion
|
||||
key={item.id}
|
||||
{...item}
|
||||
{...otherProps}
|
||||
index={index}
|
||||
onConfirmDeleteImportExclusion={onConfirmDeleteImportExclusion}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
<Table
|
||||
selectAll={true}
|
||||
allSelected={allSelected}
|
||||
allUnselected={allUnselected}
|
||||
columns={columns}
|
||||
{...otherProps}
|
||||
onSelectAllChange={this.onSelectAllChange}
|
||||
>
|
||||
<TableBody>
|
||||
{
|
||||
items.map((item, index) => {
|
||||
return (
|
||||
<ImportListExclusion
|
||||
key={item.id}
|
||||
isSelected={selectedState[item.id] || false}
|
||||
{...item}
|
||||
{...otherProps}
|
||||
columns={columns}
|
||||
index={index}
|
||||
onSelectedChange={this.onSelectedChange}
|
||||
onConfirmDeleteImportExclusion={onConfirmDeleteImportExclusion}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
<div className={styles.addImportExclusion}>
|
||||
|
@ -101,6 +128,7 @@ class ImportListExclusions extends Component {
|
|||
ImportListExclusions.propTypes = {
|
||||
isFetching: PropTypes.bool.isRequired,
|
||||
error: PropTypes.object,
|
||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
onConfirmDeleteImportExclusion: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
|
@ -4,6 +4,7 @@ import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHand
|
|||
import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
|
||||
import { createThunk } from 'Store/thunks';
|
||||
import translate from 'Utilities/String/translate';
|
||||
|
||||
//
|
||||
// Variables
|
||||
|
@ -48,7 +49,34 @@ export default {
|
|||
items: [],
|
||||
isSaving: false,
|
||||
saveError: null,
|
||||
pendingChanges: {}
|
||||
pendingChanges: {},
|
||||
|
||||
columns: [
|
||||
{
|
||||
name: 'tmdbId',
|
||||
label: 'TmdbId',
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'movieTitle',
|
||||
label: translate('Title'),
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'movieYear',
|
||||
label: translate('Year'),
|
||||
isSortable: true,
|
||||
isVisible: true
|
||||
},
|
||||
{
|
||||
name: 'actions',
|
||||
columnLabel: translate('Actions'),
|
||||
isVisible: true,
|
||||
isModifiable: false
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
//
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using NzbDrone.Core.CustomFormats;
|
||||
using Radarr.Http;
|
||||
using Radarr.Http.REST;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue