mirror of
https://github.com/lidarr/lidarr.git
synced 2025-07-16 10:03:51 -07:00
Mass Editor size and options
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
This commit is contained in:
parent
adc47c51e0
commit
796eba82ac
5 changed files with 297 additions and 163 deletions
|
@ -6,10 +6,13 @@ import FilterMenu from 'Components/Menu/FilterMenu';
|
||||||
import PageContent from 'Components/Page/PageContent';
|
import PageContent from 'Components/Page/PageContent';
|
||||||
import PageContentBody from 'Components/Page/PageContentBody';
|
import PageContentBody from 'Components/Page/PageContentBody';
|
||||||
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
|
||||||
|
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
|
||||||
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
|
||||||
|
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
|
||||||
import Table from 'Components/Table/Table';
|
import Table from 'Components/Table/Table';
|
||||||
import TableBody from 'Components/Table/TableBody';
|
import TableBody from 'Components/Table/TableBody';
|
||||||
import { align, sortDirections } from 'Helpers/Props';
|
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
|
||||||
|
import { align, icons, sortDirections } from 'Helpers/Props';
|
||||||
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
import getErrorMessage from 'Utilities/Object/getErrorMessage';
|
||||||
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
import getSelectedIds from 'Utilities/Table/getSelectedIds';
|
||||||
import selectAll from 'Utilities/Table/selectAll';
|
import selectAll from 'Utilities/Table/selectAll';
|
||||||
|
@ -20,52 +23,6 @@ import ArtistEditorRowConnector from './ArtistEditorRowConnector';
|
||||||
import RetagArtistModal from './AudioTags/RetagArtistModal';
|
import RetagArtistModal from './AudioTags/RetagArtistModal';
|
||||||
import OrganizeArtistModal from './Organize/OrganizeArtistModal';
|
import OrganizeArtistModal from './Organize/OrganizeArtistModal';
|
||||||
|
|
||||||
function getColumns(showMetadataProfile) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
name: 'status',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'sortName',
|
|
||||||
label: 'Name',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'qualityProfileId',
|
|
||||||
label: 'Quality Profile',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'metadataProfileId',
|
|
||||||
label: 'Metadata Profile',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: showMetadataProfile
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'albumFolder',
|
|
||||||
label: 'Album Folder',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'path',
|
|
||||||
label: 'Path',
|
|
||||||
isSortable: true,
|
|
||||||
isVisible: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'tags',
|
|
||||||
label: 'Tags',
|
|
||||||
isSortable: false,
|
|
||||||
isVisible: true
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
class ArtistEditor extends Component {
|
class ArtistEditor extends Component {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -80,8 +37,7 @@ class ArtistEditor extends Component {
|
||||||
lastToggled: null,
|
lastToggled: null,
|
||||||
selectedState: {},
|
selectedState: {},
|
||||||
isOrganizingArtistModalOpen: false,
|
isOrganizingArtistModalOpen: false,
|
||||||
isRetaggingArtistModalOpen: false,
|
isRetaggingArtistModalOpen: false
|
||||||
columns: getColumns(props.showMetadataProfile)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +117,7 @@ class ArtistEditor extends Component {
|
||||||
error,
|
error,
|
||||||
totalItems,
|
totalItems,
|
||||||
items,
|
items,
|
||||||
|
columns,
|
||||||
selectedFilterKey,
|
selectedFilterKey,
|
||||||
filters,
|
filters,
|
||||||
customFilters,
|
customFilters,
|
||||||
|
@ -172,7 +129,7 @@ class ArtistEditor extends Component {
|
||||||
deleteError,
|
deleteError,
|
||||||
isOrganizingArtist,
|
isOrganizingArtist,
|
||||||
isRetaggingArtist,
|
isRetaggingArtist,
|
||||||
showMetadataProfile,
|
onTableOptionChange,
|
||||||
onSortPress,
|
onSortPress,
|
||||||
onFilterSelect
|
onFilterSelect
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -180,8 +137,7 @@ class ArtistEditor extends Component {
|
||||||
const {
|
const {
|
||||||
allSelected,
|
allSelected,
|
||||||
allUnselected,
|
allUnselected,
|
||||||
selectedState,
|
selectedState
|
||||||
columns
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const selectedArtistIds = this.getSelectedIds();
|
const selectedArtistIds = this.getSelectedIds();
|
||||||
|
@ -191,6 +147,18 @@ class ArtistEditor extends Component {
|
||||||
<PageToolbar>
|
<PageToolbar>
|
||||||
<PageToolbarSection />
|
<PageToolbarSection />
|
||||||
<PageToolbarSection alignContent={align.RIGHT}>
|
<PageToolbarSection alignContent={align.RIGHT}>
|
||||||
|
<TableOptionsModalWrapper
|
||||||
|
columns={columns}
|
||||||
|
onTableOptionChange={onTableOptionChange}
|
||||||
|
>
|
||||||
|
<PageToolbarButton
|
||||||
|
label="Options"
|
||||||
|
iconName={icons.TABLE}
|
||||||
|
/>
|
||||||
|
</TableOptionsModalWrapper>
|
||||||
|
|
||||||
|
<PageToolbarSeparator />
|
||||||
|
|
||||||
<FilterMenu
|
<FilterMenu
|
||||||
alignMenu={align.RIGHT}
|
alignMenu={align.RIGHT}
|
||||||
selectedFilterKey={selectedFilterKey}
|
selectedFilterKey={selectedFilterKey}
|
||||||
|
@ -261,7 +229,8 @@ class ArtistEditor extends Component {
|
||||||
deleteError={deleteError}
|
deleteError={deleteError}
|
||||||
isOrganizingArtist={isOrganizingArtist}
|
isOrganizingArtist={isOrganizingArtist}
|
||||||
isRetaggingArtist={isRetaggingArtist}
|
isRetaggingArtist={isRetaggingArtist}
|
||||||
showMetadataProfile={showMetadataProfile}
|
columns={columns}
|
||||||
|
showMetadataProfile={columns.find((column) => column.name === 'metadataProfileId').isVisible}
|
||||||
onSaveSelected={this.onSaveSelected}
|
onSaveSelected={this.onSaveSelected}
|
||||||
onOrganizeArtistPress={this.onOrganizeArtistPress}
|
onOrganizeArtistPress={this.onOrganizeArtistPress}
|
||||||
onRetagArtistPress={this.onRetagArtistPress}
|
onRetagArtistPress={this.onRetagArtistPress}
|
||||||
|
@ -290,6 +259,7 @@ ArtistEditor.propTypes = {
|
||||||
error: PropTypes.object,
|
error: PropTypes.object,
|
||||||
totalItems: PropTypes.number.isRequired,
|
totalItems: PropTypes.number.isRequired,
|
||||||
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
items: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
sortKey: PropTypes.string,
|
sortKey: PropTypes.string,
|
||||||
sortDirection: PropTypes.oneOf(sortDirections.all),
|
sortDirection: PropTypes.oneOf(sortDirections.all),
|
||||||
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||||
|
@ -301,7 +271,7 @@ ArtistEditor.propTypes = {
|
||||||
deleteError: PropTypes.object,
|
deleteError: PropTypes.object,
|
||||||
isOrganizingArtist: PropTypes.bool.isRequired,
|
isOrganizingArtist: PropTypes.bool.isRequired,
|
||||||
isRetaggingArtist: PropTypes.bool.isRequired,
|
isRetaggingArtist: PropTypes.bool.isRequired,
|
||||||
showMetadataProfile: PropTypes.bool.isRequired,
|
onTableOptionChange: PropTypes.func.isRequired,
|
||||||
onSortPress: PropTypes.func.isRequired,
|
onSortPress: PropTypes.func.isRequired,
|
||||||
onFilterSelect: PropTypes.func.isRequired,
|
onFilterSelect: PropTypes.func.isRequired,
|
||||||
onSaveSelected: PropTypes.func.isRequired
|
onSaveSelected: PropTypes.func.isRequired
|
||||||
|
|
|
@ -3,7 +3,7 @@ import React, { Component } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
import * as commandNames from 'Commands/commandNames';
|
import * as commandNames from 'Commands/commandNames';
|
||||||
import { saveArtistEditor, setArtistEditorFilter, setArtistEditorSort } from 'Store/Actions/artistEditorActions';
|
import { saveArtistEditor, setArtistEditorFilter, setArtistEditorSort, setArtistEditorTableOption } from 'Store/Actions/artistEditorActions';
|
||||||
import { executeCommand } from 'Store/Actions/commandActions';
|
import { executeCommand } from 'Store/Actions/commandActions';
|
||||||
import { fetchRootFolders } from 'Store/Actions/settingsActions';
|
import { fetchRootFolders } from 'Store/Actions/settingsActions';
|
||||||
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
|
||||||
|
@ -12,15 +12,13 @@ import ArtistEditor from './ArtistEditor';
|
||||||
|
|
||||||
function createMapStateToProps() {
|
function createMapStateToProps() {
|
||||||
return createSelector(
|
return createSelector(
|
||||||
(state) => state.settings.metadataProfiles,
|
|
||||||
createClientSideCollectionSelector('artist', 'artistEditor'),
|
createClientSideCollectionSelector('artist', 'artistEditor'),
|
||||||
createCommandExecutingSelector(commandNames.RENAME_ARTIST),
|
createCommandExecutingSelector(commandNames.RENAME_ARTIST),
|
||||||
createCommandExecutingSelector(commandNames.RETAG_ARTIST),
|
createCommandExecutingSelector(commandNames.RETAG_ARTIST),
|
||||||
(metadataProfiles, artist, isOrganizingArtist, isRetaggingArtist) => {
|
(artist, isOrganizingArtist, isRetaggingArtist) => {
|
||||||
return {
|
return {
|
||||||
isOrganizingArtist,
|
isOrganizingArtist,
|
||||||
isRetaggingArtist,
|
isRetaggingArtist,
|
||||||
showMetadataProfile: metadataProfiles.items.length > 1,
|
|
||||||
...artist
|
...artist
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -30,6 +28,7 @@ function createMapStateToProps() {
|
||||||
const mapDispatchToProps = {
|
const mapDispatchToProps = {
|
||||||
dispatchSetArtistEditorSort: setArtistEditorSort,
|
dispatchSetArtistEditorSort: setArtistEditorSort,
|
||||||
dispatchSetArtistEditorFilter: setArtistEditorFilter,
|
dispatchSetArtistEditorFilter: setArtistEditorFilter,
|
||||||
|
dispatchSetArtistEditorTableOption: setArtistEditorTableOption,
|
||||||
dispatchSaveArtistEditor: saveArtistEditor,
|
dispatchSaveArtistEditor: saveArtistEditor,
|
||||||
dispatchFetchRootFolders: fetchRootFolders,
|
dispatchFetchRootFolders: fetchRootFolders,
|
||||||
dispatchExecuteCommand: executeCommand
|
dispatchExecuteCommand: executeCommand
|
||||||
|
@ -55,6 +54,10 @@ class ArtistEditorConnector extends Component {
|
||||||
this.props.dispatchSetArtistEditorFilter({ selectedFilterKey });
|
this.props.dispatchSetArtistEditorFilter({ selectedFilterKey });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onTableOptionChange = (payload) => {
|
||||||
|
this.props.dispatchSetArtistEditorTableOption(payload);
|
||||||
|
}
|
||||||
|
|
||||||
onSaveSelected = (payload) => {
|
onSaveSelected = (payload) => {
|
||||||
this.props.dispatchSaveArtistEditor(payload);
|
this.props.dispatchSaveArtistEditor(payload);
|
||||||
}
|
}
|
||||||
|
@ -76,6 +79,7 @@ class ArtistEditorConnector extends Component {
|
||||||
onSortPress={this.onSortPress}
|
onSortPress={this.onSortPress}
|
||||||
onFilterSelect={this.onFilterSelect}
|
onFilterSelect={this.onFilterSelect}
|
||||||
onSaveSelected={this.onSaveSelected}
|
onSaveSelected={this.onSaveSelected}
|
||||||
|
onTableOptionChange={this.onTableOptionChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -84,6 +88,7 @@ class ArtistEditorConnector extends Component {
|
||||||
ArtistEditorConnector.propTypes = {
|
ArtistEditorConnector.propTypes = {
|
||||||
dispatchSetArtistEditorSort: PropTypes.func.isRequired,
|
dispatchSetArtistEditorSort: PropTypes.func.isRequired,
|
||||||
dispatchSetArtistEditorFilter: PropTypes.func.isRequired,
|
dispatchSetArtistEditorFilter: PropTypes.func.isRequired,
|
||||||
|
dispatchSetArtistEditorTableOption: PropTypes.func.isRequired,
|
||||||
dispatchSaveArtistEditor: PropTypes.func.isRequired,
|
dispatchSaveArtistEditor: PropTypes.func.isRequired,
|
||||||
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
dispatchFetchRootFolders: PropTypes.func.isRequired,
|
||||||
dispatchExecuteCommand: PropTypes.func.isRequired
|
dispatchExecuteCommand: PropTypes.func.isRequired
|
||||||
|
|
|
@ -143,7 +143,7 @@ class ArtistEditorFooter extends Component {
|
||||||
isDeleting,
|
isDeleting,
|
||||||
isOrganizingArtist,
|
isOrganizingArtist,
|
||||||
isRetaggingArtist,
|
isRetaggingArtist,
|
||||||
showMetadataProfile,
|
columns,
|
||||||
onOrganizeArtistPress,
|
onOrganizeArtistPress,
|
||||||
onRetagArtistPress
|
onRetagArtistPress
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
@ -190,71 +190,110 @@ class ArtistEditorFooter extends Component {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.inputContainer}>
|
|
||||||
<ArtistEditorFooterLabel
|
|
||||||
label="Quality Profile"
|
|
||||||
isSaving={isSaving && qualityProfileId !== NO_CHANGE}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<QualityProfileSelectInputConnector
|
|
||||||
name="qualityProfileId"
|
|
||||||
value={qualityProfileId}
|
|
||||||
includeNoChange={true}
|
|
||||||
isDisabled={!selectedCount}
|
|
||||||
onChange={this.onInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
showMetadataProfile &&
|
columns.map((column) => {
|
||||||
<div className={styles.inputContainer}>
|
const {
|
||||||
<ArtistEditorFooterLabel
|
name,
|
||||||
label="Metadata Profile"
|
isVisible
|
||||||
isSaving={isSaving && metadataProfileId !== NO_CHANGE}
|
} = column;
|
||||||
/>
|
|
||||||
|
|
||||||
<MetadataProfileSelectInputConnector
|
if (!isVisible) {
|
||||||
name="metadataProfileId"
|
return null;
|
||||||
value={metadataProfileId}
|
}
|
||||||
includeNoChange={true}
|
|
||||||
includeNone={true}
|
if (name === 'qualityProfileId') {
|
||||||
isDisabled={!selectedCount}
|
return (
|
||||||
onChange={this.onInputChange}
|
<div
|
||||||
/>
|
key={name}
|
||||||
</div>
|
className={styles.inputContainer}
|
||||||
|
>
|
||||||
|
<ArtistEditorFooterLabel
|
||||||
|
label="Quality Profile"
|
||||||
|
isSaving={isSaving && qualityProfileId !== NO_CHANGE}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<QualityProfileSelectInputConnector
|
||||||
|
name="qualityProfileId"
|
||||||
|
value={qualityProfileId}
|
||||||
|
includeNoChange={true}
|
||||||
|
isDisabled={!selectedCount}
|
||||||
|
onChange={this.onInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'metadataProfileId') {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={name}
|
||||||
|
className={styles.inputContainer}
|
||||||
|
>
|
||||||
|
<ArtistEditorFooterLabel
|
||||||
|
label="Metadata Profile"
|
||||||
|
isSaving={isSaving && metadataProfileId !== NO_CHANGE}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MetadataProfileSelectInputConnector
|
||||||
|
name="metadataProfileId"
|
||||||
|
value={metadataProfileId}
|
||||||
|
includeNoChange={true}
|
||||||
|
isDisabled={!selectedCount}
|
||||||
|
onChange={this.onInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'albumFolder') {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={name}
|
||||||
|
className={styles.inputContainer}
|
||||||
|
>
|
||||||
|
<ArtistEditorFooterLabel
|
||||||
|
label="Album Folder"
|
||||||
|
isSaving={isSaving && albumFolder !== NO_CHANGE}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SelectInput
|
||||||
|
name="albumFolder"
|
||||||
|
value={albumFolder}
|
||||||
|
values={albumFolderOptions}
|
||||||
|
isDisabled={!selectedCount}
|
||||||
|
onChange={this.onInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'path') {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={name}
|
||||||
|
className={styles.inputContainer}
|
||||||
|
>
|
||||||
|
<ArtistEditorFooterLabel
|
||||||
|
label="Root Folder"
|
||||||
|
isSaving={isSaving && rootFolderPath !== NO_CHANGE}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<RootFolderSelectInputConnector
|
||||||
|
name="rootFolderPath"
|
||||||
|
value={rootFolderPath}
|
||||||
|
includeNoChange={true}
|
||||||
|
isDisabled={!selectedCount}
|
||||||
|
selectedValueOptions={{ includeFreeSpace: false }}
|
||||||
|
onChange={this.onInputChange}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className={styles.inputContainer}>
|
|
||||||
<ArtistEditorFooterLabel
|
|
||||||
label="Album Folder"
|
|
||||||
isSaving={isSaving && albumFolder !== NO_CHANGE}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SelectInput
|
|
||||||
name="albumFolder"
|
|
||||||
value={albumFolder}
|
|
||||||
values={albumFolderOptions}
|
|
||||||
isDisabled={!selectedCount}
|
|
||||||
onChange={this.onInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.inputContainer}>
|
|
||||||
<ArtistEditorFooterLabel
|
|
||||||
label="Root Folder"
|
|
||||||
isSaving={isSaving && rootFolderPath !== NO_CHANGE}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RootFolderSelectInputConnector
|
|
||||||
name="rootFolderPath"
|
|
||||||
value={rootFolderPath}
|
|
||||||
includeNoChange={true}
|
|
||||||
isDisabled={!selectedCount}
|
|
||||||
selectedValueOptions={{ includeFreeSpace: false }}
|
|
||||||
onChange={this.onInputChange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.buttonContainer}>
|
<div className={styles.buttonContainer}>
|
||||||
<div className={styles.buttonContainerContent}>
|
<div className={styles.buttonContainerContent}>
|
||||||
<ArtistEditorFooterLabel
|
<ArtistEditorFooterLabel
|
||||||
|
@ -342,6 +381,7 @@ ArtistEditorFooter.propTypes = {
|
||||||
isOrganizingArtist: PropTypes.bool.isRequired,
|
isOrganizingArtist: PropTypes.bool.isRequired,
|
||||||
isRetaggingArtist: PropTypes.bool.isRequired,
|
isRetaggingArtist: PropTypes.bool.isRequired,
|
||||||
showMetadataProfile: PropTypes.bool.isRequired,
|
showMetadataProfile: PropTypes.bool.isRequired,
|
||||||
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
onSaveSelected: PropTypes.func.isRequired,
|
onSaveSelected: PropTypes.func.isRequired,
|
||||||
onOrganizeArtistPress: PropTypes.func.isRequired,
|
onOrganizeArtistPress: PropTypes.func.isRequired,
|
||||||
onRetagArtistPress: PropTypes.func.isRequired
|
onRetagArtistPress: PropTypes.func.isRequired
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ArtistNameLink from 'Artist/ArtistNameLink';
|
import ArtistNameLink from 'Artist/ArtistNameLink';
|
||||||
|
@ -8,6 +7,7 @@ import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||||
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
|
||||||
import TableRow from 'Components/Table/TableRow';
|
import TableRow from 'Components/Table/TableRow';
|
||||||
import TagListConnector from 'Components/TagListConnector';
|
import TagListConnector from 'Components/TagListConnector';
|
||||||
|
import formatBytes from 'Utilities/Number/formatBytes';
|
||||||
import styles from './ArtistEditorRow.css';
|
import styles from './ArtistEditorRow.css';
|
||||||
|
|
||||||
class ArtistEditorRow extends Component {
|
class ArtistEditorRow extends Component {
|
||||||
|
@ -35,6 +35,7 @@ class ArtistEditorRow extends Component {
|
||||||
qualityProfile,
|
qualityProfile,
|
||||||
albumFolder,
|
albumFolder,
|
||||||
path,
|
path,
|
||||||
|
statistics,
|
||||||
tags,
|
tags,
|
||||||
columns,
|
columns,
|
||||||
isSaving,
|
isSaving,
|
||||||
|
@ -51,50 +52,105 @@ class ArtistEditorRow extends Component {
|
||||||
onSelectedChange={onSelectedChange}
|
onSelectedChange={onSelectedChange}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ArtistStatusCell
|
|
||||||
artistType={artistType}
|
|
||||||
monitored={monitored}
|
|
||||||
status={status}
|
|
||||||
isSaving={isSaving}
|
|
||||||
onMonitoredPress={onArtistMonitoredPress}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TableRowCell className={styles.title}>
|
|
||||||
<ArtistNameLink
|
|
||||||
foreignArtistId={foreignArtistId}
|
|
||||||
artistName={artistName}
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell>
|
|
||||||
{qualityProfile.name}
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
{
|
{
|
||||||
_.find(columns, { name: 'metadataProfileId' }).isVisible &&
|
columns.map((column) => {
|
||||||
<TableRowCell>
|
const {
|
||||||
{metadataProfile.name}
|
name,
|
||||||
</TableRowCell>
|
isVisible
|
||||||
|
} = column;
|
||||||
|
|
||||||
|
if (!isVisible) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'status') {
|
||||||
|
return (
|
||||||
|
<ArtistStatusCell
|
||||||
|
key={name}
|
||||||
|
artistType={artistType}
|
||||||
|
monitored={monitored}
|
||||||
|
status={status}
|
||||||
|
isSaving={isSaving}
|
||||||
|
onMonitoredPress={onArtistMonitoredPress}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'sortName') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.title}
|
||||||
|
>
|
||||||
|
<ArtistNameLink
|
||||||
|
foreignArtistId={foreignArtistId}
|
||||||
|
artistName={artistName}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'qualityProfileId') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
{qualityProfile.name}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'metadataProfileId') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
{metadataProfile.name}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'albumFolder') {
|
||||||
|
return (
|
||||||
|
<TableRowCell
|
||||||
|
key={name}
|
||||||
|
className={styles.albumFolder}
|
||||||
|
>
|
||||||
|
<CheckInput
|
||||||
|
name="albumFolder"
|
||||||
|
value={albumFolder}
|
||||||
|
isDisabled={true}
|
||||||
|
onChange={this.onAlbumFolderChange}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'path') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
{path}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'sizeOnDisk') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
{formatBytes(statistics.sizeOnDisk)}
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name === 'tags') {
|
||||||
|
return (
|
||||||
|
<TableRowCell key={name}>
|
||||||
|
<TagListConnector
|
||||||
|
tags={tags}
|
||||||
|
/>
|
||||||
|
</TableRowCell>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
<TableRowCell className={styles.albumFolder}>
|
|
||||||
<CheckInput
|
|
||||||
name="albumFolder"
|
|
||||||
value={albumFolder}
|
|
||||||
isDisabled={true}
|
|
||||||
onChange={this.onAlbumFolderChange}
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell>
|
|
||||||
{path}
|
|
||||||
</TableRowCell>
|
|
||||||
|
|
||||||
<TableRowCell>
|
|
||||||
<TagListConnector
|
|
||||||
tags={tags}
|
|
||||||
/>
|
|
||||||
</TableRowCell>
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -111,6 +167,7 @@ ArtistEditorRow.propTypes = {
|
||||||
qualityProfile: PropTypes.object.isRequired,
|
qualityProfile: PropTypes.object.isRequired,
|
||||||
albumFolder: PropTypes.bool.isRequired,
|
albumFolder: PropTypes.bool.isRequired,
|
||||||
path: PropTypes.string.isRequired,
|
path: PropTypes.string.isRequired,
|
||||||
|
statistics: PropTypes.object.isRequired,
|
||||||
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
tags: PropTypes.arrayOf(PropTypes.number).isRequired,
|
||||||
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
isSaving: PropTypes.bool.isRequired,
|
isSaving: PropTypes.bool.isRequired,
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { set, updateItem } from './baseActions';
|
||||||
import createHandleActions from './Creators/createHandleActions';
|
import createHandleActions from './Creators/createHandleActions';
|
||||||
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
|
||||||
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
|
||||||
|
import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Variables
|
// Variables
|
||||||
|
@ -30,6 +31,58 @@ export const defaultState = {
|
||||||
filters,
|
filters,
|
||||||
filterPredicates,
|
filterPredicates,
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
columnLabel: 'Status',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true,
|
||||||
|
isModifiable: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sortName',
|
||||||
|
label: 'Name',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'qualityProfileId',
|
||||||
|
label: 'Quality Profile',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'metadataProfileId',
|
||||||
|
label: 'Metadata Profile',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'albumFolder',
|
||||||
|
label: 'Album Folder',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'path',
|
||||||
|
label: 'Path',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sizeOnDisk',
|
||||||
|
label: 'Size on Disk',
|
||||||
|
isSortable: true,
|
||||||
|
isVisible: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'tags',
|
||||||
|
label: 'Tags',
|
||||||
|
isSortable: false,
|
||||||
|
isVisible: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
filterBuilderProps: [
|
filterBuilderProps: [
|
||||||
{
|
{
|
||||||
name: 'monitored',
|
name: 'monitored',
|
||||||
|
@ -65,6 +118,12 @@ export const defaultState = {
|
||||||
label: 'Root Folder Path',
|
label: 'Root Folder Path',
|
||||||
type: filterBuilderTypes.EXACT
|
type: filterBuilderTypes.EXACT
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'sizeOnDisk',
|
||||||
|
label: 'Size on Disk',
|
||||||
|
type: filterBuilderTypes.NUMBER,
|
||||||
|
valueType: filterBuilderValueTypes.BYTES
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
label: 'Tags',
|
label: 'Tags',
|
||||||
|
@ -90,6 +149,7 @@ export const SET_ARTIST_EDITOR_SORT = 'artistEditor/setArtistEditorSort';
|
||||||
export const SET_ARTIST_EDITOR_FILTER = 'artistEditor/setArtistEditorFilter';
|
export const SET_ARTIST_EDITOR_FILTER = 'artistEditor/setArtistEditorFilter';
|
||||||
export const SAVE_ARTIST_EDITOR = 'artistEditor/saveArtistEditor';
|
export const SAVE_ARTIST_EDITOR = 'artistEditor/saveArtistEditor';
|
||||||
export const BULK_DELETE_ARTIST = 'artistEditor/bulkDeleteArtist';
|
export const BULK_DELETE_ARTIST = 'artistEditor/bulkDeleteArtist';
|
||||||
|
export const SET_ARTIST_EDITOR_TABLE_OPTION = 'artistEditor/setArtistEditorTableOption';
|
||||||
|
|
||||||
//
|
//
|
||||||
// Action Creators
|
// Action Creators
|
||||||
|
@ -98,6 +158,7 @@ export const setArtistEditorSort = createAction(SET_ARTIST_EDITOR_SORT);
|
||||||
export const setArtistEditorFilter = createAction(SET_ARTIST_EDITOR_FILTER);
|
export const setArtistEditorFilter = createAction(SET_ARTIST_EDITOR_FILTER);
|
||||||
export const saveArtistEditor = createThunk(SAVE_ARTIST_EDITOR);
|
export const saveArtistEditor = createThunk(SAVE_ARTIST_EDITOR);
|
||||||
export const bulkDeleteArtist = createThunk(BULK_DELETE_ARTIST);
|
export const bulkDeleteArtist = createThunk(BULK_DELETE_ARTIST);
|
||||||
|
export const setArtistEditorTableOption = createAction(SET_ARTIST_EDITOR_TABLE_OPTION);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Action Handlers
|
// Action Handlers
|
||||||
|
@ -181,6 +242,7 @@ export const actionHandlers = handleThunks({
|
||||||
|
|
||||||
export const reducers = createHandleActions({
|
export const reducers = createHandleActions({
|
||||||
|
|
||||||
|
[SET_ARTIST_EDITOR_TABLE_OPTION]: createSetTableOptionReducer(section),
|
||||||
[SET_ARTIST_EDITOR_SORT]: createSetClientSideCollectionSortReducer(section),
|
[SET_ARTIST_EDITOR_SORT]: createSetClientSideCollectionSortReducer(section),
|
||||||
[SET_ARTIST_EDITOR_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
[SET_ARTIST_EDITOR_FILTER]: createSetClientSideCollectionFilterReducer(section)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue