From 74382d7250dc7d37057daa55e478b4f1560b7421 Mon Sep 17 00:00:00 2001 From: Qstick Date: Tue, 5 Jul 2022 23:10:47 -0500 Subject: [PATCH] New: Rework List Exclusion UI --- frontend/src/Activity/Blocklist/Blocklist.js | 3 +- .../ImportListExclusion.css | 11 ++- .../ImportListExclusion.js | 96 +++++++++++++++---- .../ImportListExclusions.js | 78 ++++++++++----- .../Actions/Settings/importExclusions.js | 30 +++++- .../CustomFormats/CustomFormatController.cs | 2 - 6 files changed, 168 insertions(+), 52 deletions(-) diff --git a/frontend/src/Activity/Blocklist/Blocklist.js b/frontend/src/Activity/Blocklist/Blocklist.js index 5160dae14..3d53a0c72 100644 --- a/frontend/src/Activity/Blocklist/Blocklist.js +++ b/frontend/src/Activity/Blocklist/Blocklist.js @@ -181,12 +181,13 @@ class Blocklist extends Component { > { - items.map((item) => { + items.map((item, index) => { return ( diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css index a2d508e00..a17f1c7af 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.css @@ -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; } diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js index 952cf6383..941ee7691 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusion.js @@ -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 ( -
-
{tmdbId}
-
{movieTitle}
-
{movieYear}
- -
- - - -
+ + + + { + columns.map((column) => { + const { + name, + isVisible + } = column; + + if (!isVisible) { + return null; + } + + if (name === 'tmdbId') { + return ( + + {tmdbId} + + ); + } + + if (name === 'movieTitle') { + return ( + + {movieTitle} + + ); + } + + if (name === 'movieYear') { + return ( + + {movieYear} + + ); + } + + if (name === 'actions') { + return ( + + + + + + ); + } + + return null; + }) + } -
+ ); } } @@ -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 }; diff --git a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js index 63b77c076..84a99e83c 100644 --- a/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js +++ b/frontend/src/Settings/ImportLists/ImportListExclusions/ImportListExclusions.js @@ -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 (
-
-
- TMDb Id -
-
- {translate('Title')} -
-
- {translate('Year')} -
-
-
- { - items.map((item, index) => { - return ( - - ); - }) - } + + + { + items.map((item, index) => { + return ( + + ); + }) + } + +
@@ -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 }; diff --git a/frontend/src/Store/Actions/Settings/importExclusions.js b/frontend/src/Store/Actions/Settings/importExclusions.js index 17812fa8f..8c401d7f3 100644 --- a/frontend/src/Store/Actions/Settings/importExclusions.js +++ b/frontend/src/Store/Actions/Settings/importExclusions.js @@ -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 + } + ] }, // diff --git a/src/Radarr.Api.V3/CustomFormats/CustomFormatController.cs b/src/Radarr.Api.V3/CustomFormats/CustomFormatController.cs index 30793de28..f2cea8d97 100644 --- a/src/Radarr.Api.V3/CustomFormats/CustomFormatController.cs +++ b/src/Radarr.Api.V3/CustomFormats/CustomFormatController.cs @@ -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;