diff --git a/frontend/src/AlbumStudio/AlbumStudio.css b/frontend/src/AlbumStudio/AlbumStudio.css
deleted file mode 100644
index 033279591..000000000
--- a/frontend/src/AlbumStudio/AlbumStudio.css
+++ /dev/null
@@ -1,36 +0,0 @@
-.pageContentBodyWrapper {
- display: flex;
- flex: 1 0 1px;
- overflow: hidden;
-}
-
-.contentBody {
- composes: contentBody from '~Components/Page/PageContentBody.css';
-
- display: flex;
- flex-direction: column;
-}
-
-.tableInnerContentBody {
- composes: innerContentBody from '~Components/Page/PageContentBody.css';
-
- display: flex;
- flex-direction: column;
- flex-grow: 1;
-}
-
-.contentBodyContainer {
- display: flex;
- flex-direction: column;
- flex-grow: 1;
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .pageContentBodyWrapper {
- flex-basis: auto;
- }
-
- .contentBody {
- flex-basis: 1px;
- }
-}
diff --git a/frontend/src/AlbumStudio/AlbumStudio.css.d.ts b/frontend/src/AlbumStudio/AlbumStudio.css.d.ts
deleted file mode 100644
index 9937ea245..000000000
--- a/frontend/src/AlbumStudio/AlbumStudio.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'contentBody': string;
- 'contentBodyContainer': string;
- 'pageContentBodyWrapper': string;
- 'tableInnerContentBody': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/AlbumStudio/AlbumStudio.js b/frontend/src/AlbumStudio/AlbumStudio.js
deleted file mode 100644
index 200b7ffe4..000000000
--- a/frontend/src/AlbumStudio/AlbumStudio.js
+++ /dev/null
@@ -1,440 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { CellMeasurer, CellMeasurerCache } from 'react-virtualized';
-import NoArtist from 'Artist/NoArtist';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import FilterMenu from 'Components/Menu/FilterMenu';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageJumpBar from 'Components/Page/PageJumpBar';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import VirtualTable from 'Components/Table/VirtualTable';
-import VirtualTableRow from 'Components/Table/VirtualTableRow';
-import { align, sortDirections } from 'Helpers/Props';
-import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
-import getErrorMessage from 'Utilities/Object/getErrorMessage';
-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 AlbumStudioFilterModalConnector from './AlbumStudioFilterModalConnector';
-import AlbumStudioFooter from './AlbumStudioFooter';
-import AlbumStudioRowConnector from './AlbumStudioRowConnector';
-import AlbumStudioTableHeader from './AlbumStudioTableHeader';
-import styles from './AlbumStudio.css';
-
-const columns = [
- {
- name: 'status',
- isVisible: true
- },
- {
- name: 'sortName',
- label: () => translate('Name'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albumCount',
- label: () => translate('Albums'),
- isSortable: false,
- isVisible: true
- }
-];
-
-class AlbumStudio extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.scrollerRef = React.createRef();
-
- this.state = {
- estimatedRowSize: 100,
- jumpBarItems: { order: [] },
- scrollIndex: null,
- jumpCount: 0,
- allSelected: false,
- allUnselected: false,
- lastToggled: null,
- selectedState: {}
- };
-
- this.cache = new CellMeasurerCache({
- defaultHeight: 100,
- fixedWidth: true
- });
- }
-
- componentDidMount() {
- this.setSelectedState();
- }
-
- componentDidUpdate(prevProps) {
- const {
- isSaving,
- saveError
- } = this.props;
-
- const {
- scrollIndex,
- jumpCount
- } = this.state;
-
- if (prevProps.isSaving && !isSaving && !saveError) {
- this.onSelectAllChange({ value: false });
- }
-
- // nasty hack to fix react-virtualized jumping incorrectly
- // due to variable row heights
- if (scrollIndex != null && scrollIndex > 0) {
- if (jumpCount === 0) {
- this.setState({
- scrollIndex: scrollIndex - 1,
- jumpCount: 1
- });
- } else if (jumpCount === 1) {
- this.setState({
- scrollIndex: scrollIndex + 1,
- jumpCount: 2
- });
- } else {
- this.setState({
- scrollIndex: null,
- jumpCount: 0
- });
- }
- }
- }
-
- setJumpBarItems() {
- const {
- items,
- sortKey,
- sortDirection
- } = this.props;
-
- // Reset if not sorting by sortName
- if (sortKey !== 'sortName') {
- this.setState({ jumpBarItems: { order: [] } });
- return;
- }
-
- const characters = _.reduce(items, (acc, item) => {
- let char = item.sortName.charAt(0);
-
- if (!isNaN(char)) {
- char = '#';
- }
-
- if (char in acc) {
- acc[char] = acc[char] + 1;
- } else {
- acc[char] = 1;
- }
-
- return acc;
- }, {});
-
- const order = Object.keys(characters).sort();
-
- // Reverse if sorting descending
- if (sortDirection === sortDirections.DESCENDING) {
- order.reverse();
- }
-
- const jumpBarItems = {
- characters,
- order
- };
-
- this.setState({ jumpBarItems });
- }
-
- getSelectedIds = () => {
- if (this.state.allUnselected) {
- return [];
- }
- return getSelectedIds(this.state.selectedState);
- };
-
- setSelectedState = () => {
- const {
- items
- } = this.props;
-
- const {
- selectedState
- } = this.state;
-
- const newSelectedState = {};
-
- items.forEach((artist) => {
- const isItemSelected = selectedState[artist.id];
-
- if (isItemSelected) {
- newSelectedState[artist.id] = isItemSelected;
- } else {
- newSelectedState[artist.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 });
- };
-
- estimateRowHeight = (width) => {
- const {
- albumCount,
- items
- } = this.props;
-
- if (albumCount === undefined || albumCount === 0 || items.length === 0) {
- return 100;
- }
-
- // guess 250px per album entry
- // available width is total width less 186px for select, status etc
- const cols = Math.max(Math.floor((width - 186) / 250), 1);
- const albumsPerArtist = albumCount / items.length;
- const albumRowsPerArtist = albumsPerArtist / cols;
-
- // each row is 23px per album row plus 16px padding
- return albumRowsPerArtist * 23 + 16;
- };
-
- rowRenderer = ({ key, rowIndex, parent, style }) => {
- const {
- items
- } = this.props;
-
- const {
- selectedState
- } = this.state;
-
- const item = items[rowIndex];
-
- return (
-
- {({ registerChild }) => (
-
-
-
- )}
-
- );
- };
-
- //
- // 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);
- });
- };
-
- onSelectAllPress = () => {
- this.onSelectAllChange({ value: !this.state.allSelected });
- };
-
- onUpdateSelectedPress = (changes) => {
- this.props.onUpdateSelectedPress({
- artistIds: this.getSelectedIds(),
- ...changes
- });
- };
-
- onJumpBarItemPress = (jumpToCharacter) => {
- const scrollIndex = getIndexOfFirstCharacter(this.props.items, jumpToCharacter);
-
- if (scrollIndex != null) {
- this.setState({ scrollIndex });
- }
- };
-
- onGridRecompute = (width) => {
- this.setJumpBarItems();
- this.setSelectedState();
- this.setState({ estimatedRowSize: this.estimateRowHeight(width) });
- this.cache.clearAll();
- };
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- isPopulated,
- error,
- totalItems,
- items,
- selectedFilterKey,
- filters,
- customFilters,
- sortKey,
- sortDirection,
- isSaving,
- saveError,
- isSmallScreen,
- onSortPress,
- onFilterSelect
- } = this.props;
-
- const {
- allSelected,
- allUnselected,
- estimatedRowSize,
- jumpBarItems,
- scrollIndex
- } = this.state;
-
- return (
-
-
-
-
-
-
-
-
-
-
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- !isFetching && !!error &&
- {getErrorMessage(error, 'Failed to load artist from API')}
- }
-
- {
- !error &&
- isPopulated &&
- !!items.length &&
- this.scrollerRef.current ?
-
-
- }
- sortKey={sortKey}
- sortDirection={sortDirection}
- deferredMeasurementCache={this.cache}
- rowHeight={this.cache.rowHeight}
- estimatedRowSize={estimatedRowSize}
- onRecompute={this.onGridRecompute}
- />
-
:
- null
- }
-
- {
- !error && isPopulated && !items.length &&
-
- }
-
-
- {
- isPopulated && !!jumpBarItems.order.length &&
-
- }
-
-
-
-
- );
- }
-}
-
-AlbumStudio.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- totalItems: PropTypes.number.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- albumCount: PropTypes.number.isRequired,
- sortKey: PropTypes.string,
- sortDirection: PropTypes.oneOf(sortDirections.all),
- selectedFilterKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
- filters: PropTypes.arrayOf(PropTypes.object).isRequired,
- customFilters: PropTypes.arrayOf(PropTypes.object).isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- isSmallScreen: PropTypes.bool.isRequired,
- onSortPress: PropTypes.func.isRequired,
- onFilterSelect: PropTypes.func.isRequired,
- onUpdateSelectedPress: PropTypes.func.isRequired
-};
-
-export default AlbumStudio;
diff --git a/frontend/src/AlbumStudio/AlbumStudioAlbum.css b/frontend/src/AlbumStudio/AlbumStudioAlbum.css
deleted file mode 100644
index c568a2489..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioAlbum.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.album {
- display: flex;
- align-items: stretch;
- overflow: hidden;
- margin: 2px 4px;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--albumBackgroundColor);
- cursor: default;
-}
-
-.info {
- padding: 0 4px;
-}
-
-.albumType {
- padding: 0 4px;
- border-width: 0 1px;
- border-style: solid;
- border-color: var(--borderColor);
- background-color: var(--albumBackgroundColor);
- color: var(--defaultColor);
-}
-
-.tracks {
- padding: 0 4px;
- background-color: var(--trackBackgroundColor);
- color: var(--defaultColor);
-}
-
-.allTracks {
- background-color: color(#27c24c saturation(-25%));
- color: var(--white);
-}
-
-.missingWanted {
- background-color: color(#f05050 saturation(-20%));
- color: var(--white);
-}
diff --git a/frontend/src/AlbumStudio/AlbumStudioAlbum.css.d.ts b/frontend/src/AlbumStudio/AlbumStudioAlbum.css.d.ts
deleted file mode 100644
index 31142374e..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioAlbum.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'album': string;
- 'albumType': string;
- 'allTracks': string;
- 'info': string;
- 'missingWanted': string;
- 'tracks': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/AlbumStudio/AlbumStudioAlbum.js b/frontend/src/AlbumStudio/AlbumStudioAlbum.js
deleted file mode 100644
index 5dc9dc233..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioAlbum.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import MonitorToggleButton from 'Components/MonitorToggleButton';
-import translate from 'Utilities/String/translate';
-import styles from './AlbumStudioAlbum.css';
-
-class AlbumStudioAlbum extends Component {
-
- //
- // Listeners
-
- onAlbumMonitoredPress = () => {
- const {
- id,
- monitored
- } = this.props;
-
- this.props.onAlbumMonitoredPress(id, !monitored);
- };
-
- //
- // Render
-
- render() {
- const {
- title,
- disambiguation,
- albumType,
- monitored,
- statistics,
- isSaving
- } = this.props;
-
- const {
- trackFileCount,
- totalTrackCount,
- percentOfTracks
- } = statistics;
-
- return (
-
-
-
-
-
- {
- disambiguation ? `${title} (${disambiguation})` : `${title}`
- }
-
-
-
-
-
- {
- `${albumType}`
- }
-
-
-
-
- {
- totalTrackCount === 0 ? '0/0' : `${trackFileCount}/${totalTrackCount}`
- }
-
-
- );
- }
-}
-
-AlbumStudioAlbum.propTypes = {
- id: PropTypes.number.isRequired,
- title: PropTypes.string.isRequired,
- disambiguation: PropTypes.string,
- albumType: PropTypes.string.isRequired,
- monitored: PropTypes.bool.isRequired,
- statistics: PropTypes.object.isRequired,
- isSaving: PropTypes.bool.isRequired,
- onAlbumMonitoredPress: PropTypes.func.isRequired
-};
-
-AlbumStudioAlbum.defaultProps = {
- isSaving: false,
- statistics: {
- trackFileCount: 0,
- totalTrackCount: 0,
- percentOfTracks: 0
- }
-};
-
-export default AlbumStudioAlbum;
diff --git a/frontend/src/AlbumStudio/AlbumStudioConnector.js b/frontend/src/AlbumStudio/AlbumStudioConnector.js
deleted file mode 100644
index 25fedafa4..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioConnector.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearAlbums, fetchAlbums } from 'Store/Actions/albumActions';
-import { saveAlbumStudio, setAlbumStudioFilter, setAlbumStudioSort } from 'Store/Actions/albumStudioActions';
-import createArtistClientSideCollectionItemsSelector from 'Store/Selectors/createArtistClientSideCollectionItemsSelector';
-import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
-import AlbumStudio from './AlbumStudio';
-
-function createAlbumFetchStateSelector() {
- return createSelector(
- (state) => state.albums.items.length,
- (state) => state.albums.isFetching,
- (state) => state.albums.isPopulated,
- (length, isFetching, isPopulated) => {
- const albumCount = (!isFetching && isPopulated) ? length : 0;
- return {
- albumCount,
- isFetching,
- isPopulated
- };
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- createAlbumFetchStateSelector(),
- createArtistClientSideCollectionItemsSelector('albumStudio'),
- createDimensionsSelector(),
- (albums, artist, dimensionsState) => {
- const isPopulated = albums.isPopulated && artist.isPopulated;
- const isFetching = artist.isFetching || albums.isFetching;
- return {
- ...artist,
- isPopulated,
- isFetching,
- albumCount: albums.albumCount,
- isSmallScreen: dimensionsState.isSmallScreen
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchAlbums,
- clearAlbums,
- setAlbumStudioSort,
- setAlbumStudioFilter,
- saveAlbumStudio
-};
-
-class AlbumStudioConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.populate();
- }
-
- componentWillUnmount() {
- this.unpopulate();
- }
-
- //
- // Control
-
- populate = () => {
- this.props.fetchAlbums();
- };
-
- unpopulate = () => {
- this.props.clearAlbums();
- };
-
- //
- // Listeners
-
- onSortPress = (sortKey) => {
- this.props.setAlbumStudioSort({ sortKey });
- };
-
- onFilterSelect = (selectedFilterKey) => {
- this.props.setAlbumStudioFilter({ selectedFilterKey });
- };
-
- onUpdateSelectedPress = (payload) => {
- this.props.saveAlbumStudio(payload);
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-AlbumStudioConnector.propTypes = {
- setAlbumStudioSort: PropTypes.func.isRequired,
- setAlbumStudioFilter: PropTypes.func.isRequired,
- fetchAlbums: PropTypes.func.isRequired,
- clearAlbums: PropTypes.func.isRequired,
- saveAlbumStudio: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(AlbumStudioConnector);
diff --git a/frontend/src/AlbumStudio/AlbumStudioFilterModalConnector.js b/frontend/src/AlbumStudio/AlbumStudioFilterModalConnector.js
deleted file mode 100644
index db378a7f2..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioFilterModalConnector.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import FilterModal from 'Components/Filter/FilterModal';
-import { setAlbumStudioFilter } from 'Store/Actions/albumStudioActions';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.artist.items,
- (state) => state.albumStudio.filterBuilderProps,
- (sectionItems, filterBuilderProps) => {
- return {
- sectionItems,
- filterBuilderProps,
- customFilterType: 'albumStudio'
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchSetFilter: setAlbumStudioFilter
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(FilterModal);
diff --git a/frontend/src/AlbumStudio/AlbumStudioFooter.css b/frontend/src/AlbumStudio/AlbumStudioFooter.css
deleted file mode 100644
index 11ea5496a..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioFooter.css
+++ /dev/null
@@ -1,14 +0,0 @@
-.inputContainer {
- margin-right: 20px;
-}
-
-.label {
- margin-bottom: 3px;
- font-weight: bold;
-}
-
-.updateSelectedButton {
- composes: button from '~Components/Link/SpinnerButton.css';
-
- height: 35px;
-}
diff --git a/frontend/src/AlbumStudio/AlbumStudioFooter.css.d.ts b/frontend/src/AlbumStudio/AlbumStudioFooter.css.d.ts
deleted file mode 100644
index 83e60938b..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioFooter.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'inputContainer': string;
- 'label': string;
- 'updateSelectedButton': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/AlbumStudio/AlbumStudioFooter.js b/frontend/src/AlbumStudio/AlbumStudioFooter.js
deleted file mode 100644
index f579d0dd0..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioFooter.js
+++ /dev/null
@@ -1,174 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import MonitorAlbumsSelectInput from 'Components/Form/MonitorAlbumsSelectInput';
-import MonitorNewItemsSelectInput from 'Components/Form/MonitorNewItemsSelectInput';
-import SpinnerButton from 'Components/Link/SpinnerButton';
-import PageContentFooter from 'Components/Page/PageContentFooter';
-import { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './AlbumStudioFooter.css';
-
-const NO_CHANGE = 'noChange';
-
-class AlbumStudioFooter extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- monitored: NO_CHANGE,
- monitor: NO_CHANGE,
- monitorNewItems: NO_CHANGE
- };
- }
-
- componentDidUpdate(prevProps) {
- const {
- isSaving,
- saveError
- } = this.props;
-
- if (prevProps.isSaving && !isSaving && !saveError) {
- this.setState({
- monitored: NO_CHANGE,
- monitor: NO_CHANGE,
- monitorNewItems: NO_CHANGE
- });
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.setState({ [name]: value });
- };
-
- onUpdateSelectedPress = () => {
- const {
- monitor,
- monitored,
- monitorNewItems
- } = this.state;
-
- const changes = {};
-
- if (monitored !== NO_CHANGE) {
- changes.monitored = monitored === 'monitored';
- }
-
- if (monitor !== NO_CHANGE) {
- changes.monitor = monitor;
- }
-
- if (monitorNewItems !== NO_CHANGE) {
- changes.monitorNewItems = monitorNewItems;
- }
-
- this.props.onUpdateSelectedPress(changes);
- };
-
- //
- // Render
-
- render() {
- const {
- selectedCount,
- isSaving
- } = this.props;
-
- const {
- monitored,
- monitor,
- monitorNewItems
- } = this.state;
-
- const monitoredOptions = [
- { key: NO_CHANGE, value: translate('NoChange'), disabled: true },
- { key: 'monitored', value: translate('Monitored') },
- { key: 'unmonitored', value: translate('Unmonitored') }
- ];
-
- const noChanges = monitored === NO_CHANGE &&
- monitor === NO_CHANGE &&
- monitorNewItems === NO_CHANGE;
-
- return (
-
-
-
- {translate('MonitorArtist')}
-
-
-
-
-
-
-
- {translate('MonitorExistingAlbums')}
-
-
-
-
-
-
-
- {translate('MonitorNewAlbums')}
-
-
-
-
-
-
-
- {translate('CountArtistsSelected', { count: selectedCount })}
-
-
-
- {translate('UpdateSelected')}
-
-
-
- );
- }
-}
-
-AlbumStudioFooter.propTypes = {
- selectedCount: PropTypes.number.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- onUpdateSelectedPress: PropTypes.func.isRequired
-};
-
-export default AlbumStudioFooter;
diff --git a/frontend/src/AlbumStudio/AlbumStudioRow.css b/frontend/src/AlbumStudio/AlbumStudioRow.css
deleted file mode 100644
index d8def1d50..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioRow.css
+++ /dev/null
@@ -1,41 +0,0 @@
-.cell {
- composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
-
- display: flex;
- align-items: center;
-}
-
-.selectCell {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- display: flex;
- align-items: center;
-}
-
-.status {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- display: flex;
- align-items: center;
- padding: 0;
- min-width: 60px;
-}
-
-.title {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- display: flex;
- align-items: center;
-
- flex-shrink: 0;
- min-width: 110px;
-}
-
-.albums {
- composes: cell;
-
- display: flex;
- flex-grow: 4;
- flex-wrap: wrap;
- min-width: 400px;
-}
diff --git a/frontend/src/AlbumStudio/AlbumStudioRow.css.d.ts b/frontend/src/AlbumStudio/AlbumStudioRow.css.d.ts
deleted file mode 100644
index 9f9ac8eac..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioRow.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'albums': string;
- 'cell': string;
- 'selectCell': string;
- 'status': string;
- 'title': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/AlbumStudio/AlbumStudioRow.js b/frontend/src/AlbumStudio/AlbumStudioRow.js
deleted file mode 100644
index 5a13f442d..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioRow.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import ArtistNameLink from 'Artist/ArtistNameLink';
-import ArtistStatusCell from 'Artist/Index/Table/ArtistStatusCell';
-import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
-import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
-import AlbumStudioAlbum from './AlbumStudioAlbum';
-import styles from './AlbumStudioRow.css';
-
-class AlbumStudioRow extends Component {
-
- //
- // Render
-
- render() {
- const {
- artistId,
- status,
- foreignArtistId,
- artistName,
- artistType,
- monitored,
- albums,
- isSaving,
- isSelected,
- onSelectedChange,
- onArtistMonitoredPress,
- onAlbumMonitoredPress
- } = this.props;
-
- return (
- <>
-
-
-
-
-
-
-
-
-
- {
- albums.map((album) => {
- return (
-
- );
- })
- }
-
- >
- );
- }
-}
-
-AlbumStudioRow.propTypes = {
- artistId: PropTypes.number.isRequired,
- status: PropTypes.string.isRequired,
- foreignArtistId: PropTypes.string.isRequired,
- artistName: PropTypes.string.isRequired,
- artistType: PropTypes.string,
- monitored: PropTypes.bool.isRequired,
- albums: PropTypes.arrayOf(PropTypes.object).isRequired,
- isSaving: PropTypes.bool.isRequired,
- isSelected: PropTypes.bool,
- onSelectedChange: PropTypes.func.isRequired,
- onArtistMonitoredPress: PropTypes.func.isRequired,
- onAlbumMonitoredPress: PropTypes.func.isRequired
-};
-
-AlbumStudioRow.defaultProps = {
- isSaving: false
-};
-
-export default AlbumStudioRow;
diff --git a/frontend/src/AlbumStudio/AlbumStudioRowConnector.js b/frontend/src/AlbumStudio/AlbumStudioRowConnector.js
deleted file mode 100644
index fd0bd21dc..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioRowConnector.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { toggleAlbumsMonitored } from 'Store/Actions/albumActions';
-import { toggleArtistMonitored } from 'Store/Actions/artistActions';
-import createArtistSelector from 'Store/Selectors/createArtistSelector';
-import AlbumStudioRow from './AlbumStudioRow';
-
-// Use a const to share the reselect cache between instances
-const getAlbumMap = createSelector(
- (state) => state.albums.items,
- (albums) => {
- return albums.reduce((acc, curr) => {
- (acc[curr.artistId] = acc[curr.artistId] || []).push(curr);
- return acc;
- }, {});
- }
-);
-
-function createMapStateToProps() {
- return createSelector(
- createArtistSelector(),
- getAlbumMap,
- (artist, albumMap) => {
- const albumsInArtist = albumMap.hasOwnProperty(artist.id) ? albumMap[artist.id] : [];
- const sortedAlbums = _.orderBy(albumsInArtist, 'releaseDate', 'desc');
-
- return {
- ...artist,
- artistId: artist.id,
- artistName: artist.artistName,
- monitored: artist.monitored,
- status: artist.status,
- isSaving: artist.isSaving,
- albums: sortedAlbums
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- toggleArtistMonitored,
- toggleAlbumsMonitored
-};
-
-class AlbumStudioRowConnector extends Component {
-
- //
- // Listeners
-
- onArtistMonitoredPress = () => {
- const {
- artistId,
- monitored
- } = this.props;
-
- this.props.toggleArtistMonitored({
- artistId,
- monitored: !monitored
- });
- };
-
- onAlbumMonitoredPress = (albumId, monitored) => {
- const albumIds = [albumId];
- this.props.toggleAlbumsMonitored({
- albumIds,
- monitored
- });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-AlbumStudioRowConnector.propTypes = {
- artistId: PropTypes.number.isRequired,
- monitored: PropTypes.bool.isRequired,
- toggleArtistMonitored: PropTypes.func.isRequired,
- toggleAlbumsMonitored: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(AlbumStudioRowConnector);
diff --git a/frontend/src/AlbumStudio/AlbumStudioTableHeader.css b/frontend/src/AlbumStudio/AlbumStudioTableHeader.css
deleted file mode 100644
index da21f0553..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioTableHeader.css
+++ /dev/null
@@ -1,18 +0,0 @@
-.status {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- flex: 0 0 60px;
- padding: 0;
-}
-
-.sortName {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- flex: 0 0 110px;
-}
-
-.albumCount {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- padding: 12px;
-}
diff --git a/frontend/src/AlbumStudio/AlbumStudioTableHeader.css.d.ts b/frontend/src/AlbumStudio/AlbumStudioTableHeader.css.d.ts
deleted file mode 100644
index 3978a6c39..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioTableHeader.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'albumCount': string;
- 'sortName': string;
- 'status': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/AlbumStudio/AlbumStudioTableHeader.js b/frontend/src/AlbumStudio/AlbumStudioTableHeader.js
deleted file mode 100644
index 8d18babbe..000000000
--- a/frontend/src/AlbumStudio/AlbumStudioTableHeader.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
-import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
-import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
-import styles from './AlbumStudioTableHeader.css';
-
-function AlbumStudioTableHeader(props) {
- const {
- columns,
- allSelected,
- allUnselected,
- onSelectAllChange,
- ...otherProps
- } = props;
-
- return (
-
-
- {
- columns.map((column) => {
- const {
- name,
- label,
- isSortable,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- return (
-
- {typeof label === 'function' ? label() : label}
-
- );
- })
- }
-
- );
-}
-
-AlbumStudioTableHeader.propTypes = {
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- allSelected: PropTypes.bool.isRequired,
- allUnselected: PropTypes.bool.isRequired,
- onSelectAllChange: PropTypes.func.isRequired
-};
-
-export default AlbumStudioTableHeader;
diff --git a/frontend/src/App/AppRoutes.js b/frontend/src/App/AppRoutes.js
index af938fd83..0af990f43 100644
--- a/frontend/src/App/AppRoutes.js
+++ b/frontend/src/App/AppRoutes.js
@@ -5,7 +5,6 @@ import BlocklistConnector from 'Activity/Blocklist/BlocklistConnector';
import HistoryConnector from 'Activity/History/HistoryConnector';
import QueueConnector from 'Activity/Queue/QueueConnector';
import AlbumDetailsPageConnector from 'Album/Details/AlbumDetailsPageConnector';
-import AlbumStudioConnector from 'AlbumStudio/AlbumStudioConnector';
import ArtistDetailsPageConnector from 'Artist/Details/ArtistDetailsPageConnector';
import ArtistIndex from 'Artist/Index/ArtistIndex';
import CalendarPageConnector from 'Calendar/CalendarPageConnector';
@@ -90,7 +89,15 @@ function AppRoutes(props) {
{
+ return (
+
+ );
+ }}
/>
translate('AddNew'),
to: '/add/search'
},
- {
- title: () => translate('AlbumStudio'),
- to: '/albumstudio'
- },
{
title: () => translate('UnmappedFiles'),
to: '/unmapped'
diff --git a/frontend/src/Store/Actions/albumStudioActions.js b/frontend/src/Store/Actions/albumStudioActions.js
deleted file mode 100644
index 39fbe8d20..000000000
--- a/frontend/src/Store/Actions/albumStudioActions.js
+++ /dev/null
@@ -1,167 +0,0 @@
-import { createAction } from 'redux-actions';
-import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import translate from 'Utilities/String/translate';
-import { fetchAlbums } from './albumActions';
-import { filterPredicates, filters } from './artistActions';
-import { set } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-
-//
-// Variables
-
-export const section = 'albumStudio';
-
-//
-// State
-
-export const defaultState = {
- isSaving: false,
- saveError: null,
- sortKey: 'sortName',
- sortDirection: sortDirections.ASCENDING,
- secondarySortKey: 'sortName',
- secondarySortDirection: sortDirections.ASCENDING,
- selectedFilterKey: 'all',
- filters,
- filterPredicates,
-
- filterBuilderProps: [
- {
- name: 'monitored',
- label: () => translate('Monitored'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.BOOL
- },
- {
- name: 'status',
- label: () => translate('Status'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.ARTIST_STATUS
- },
- {
- name: 'artistType',
- label: () => translate('ArtistType'),
- type: filterBuilderTypes.EXACT
- },
- {
- name: 'qualityProfileId',
- label: () => translate('QualityProfile'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.QUALITY_PROFILE
- },
- {
- name: 'metadataProfileId',
- label: () => translate('MetadataProfile'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.METADATA_PROFILE
- },
- {
- name: 'rootFolderPath',
- label: () => translate('RootFolderPath'),
- type: filterBuilderTypes.EXACT
- },
- {
- name: 'tags',
- label: () => translate('Tags'),
- type: filterBuilderTypes.ARRAY,
- valueType: filterBuilderValueTypes.TAG
- }
- ]
-};
-
-export const persistState = [
- 'albumStudio.sortKey',
- 'albumStudio.sortDirection',
- 'albumStudio.selectedFilterKey',
- 'albumStudio.customFilters'
-];
-
-//
-// Actions Types
-
-export const SET_ALBUM_STUDIO_SORT = 'albumStudio/setAlbumStudioSort';
-export const SET_ALBUM_STUDIO_FILTER = 'albumStudio/setAlbumStudioFilter';
-export const SAVE_ALBUM_STUDIO = 'albumStudio/saveAlbumStudio';
-
-//
-// Action Creators
-
-export const setAlbumStudioSort = createAction(SET_ALBUM_STUDIO_SORT);
-export const setAlbumStudioFilter = createAction(SET_ALBUM_STUDIO_FILTER);
-export const saveAlbumStudio = createThunk(SAVE_ALBUM_STUDIO);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [SAVE_ALBUM_STUDIO]: function(getState, payload, dispatch) {
- const {
- artistIds,
- monitor,
- monitored,
- monitorNewItems
- } = payload;
-
- const artists = [];
-
- artistIds.forEach((id) => {
- const artistsToUpdate = { id };
-
- if (payload.hasOwnProperty('monitored')) {
- artistsToUpdate.monitored = monitored;
- }
-
- artists.push(artistsToUpdate);
- });
-
- dispatch(set({
- section,
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- url: '/albumStudio',
- method: 'POST',
- data: JSON.stringify({
- artist: artists,
- monitoringOptions: { monitor },
- monitorNewItems
- }),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(fetchAlbums());
-
- dispatch(set({
- section,
- isSaving: false,
- saveError: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ALBUM_STUDIO_SORT]: createSetClientSideCollectionSortReducer(section),
- [SET_ALBUM_STUDIO_FILTER]: createSetClientSideCollectionFilterReducer(section)
-
-}, defaultState, section);
-
diff --git a/frontend/src/Store/Actions/index.js b/frontend/src/Store/Actions/index.js
index d82b9790f..95b02d089 100644
--- a/frontend/src/Store/Actions/index.js
+++ b/frontend/src/Store/Actions/index.js
@@ -1,6 +1,5 @@
import * as albums from './albumActions';
import * as albumHistory from './albumHistoryActions';
-import * as albumStudio from './albumStudioActions';
import * as app from './appActions';
import * as artist from './artistActions';
import * as artistHistory from './artistHistoryActions';
@@ -46,7 +45,6 @@ export default [
providerOptions,
queue,
releases,
- albumStudio,
artist,
artistHistory,
artistIndex,