([]);
- const [applyTags, setApplyTags] = useState('add');
-
- const indexersTags = useMemo(() => {
- const tags = ids.reduce((acc: number[], id) => {
- const s = allIndexers.items.find((s: Indexer) => s.id === id);
-
- if (s) {
- acc.push(...s.tags);
- }
-
- return acc;
- }, []);
-
- return uniq(tags);
- }, [ids, allIndexers]);
-
- const onTagsChange = useCallback(
- ({ value }: { value: number[] }) => {
- setTags(value);
- },
- [setTags]
- );
-
- const onApplyTagsChange = useCallback(
- ({ value }: { value: string }) => {
- setApplyTags(value);
- },
- [setApplyTags]
- );
-
- const onApplyPress = useCallback(() => {
- onApplyTagsPress(tags, applyTags);
- }, [tags, applyTags, onApplyTagsPress]);
-
- const applyTagsOptions = [
- {
- key: 'add',
- get value() {
- return translate('Add');
- },
- },
- {
- key: 'remove',
- get value() {
- return translate('Remove');
- },
- },
- {
- key: 'replace',
- get value() {
- return translate('Replace');
- },
- },
- ];
-
- return (
-
- {translate('Tags')}
-
-
-
-
-
-
- {translate('Cancel')}
-
-
- {translate('Apply')}
-
-
-
- );
-}
-
-export default TagsModalContent;
diff --git a/frontend/src/Settings/Indexers/Options/IndexerOptions.js b/frontend/src/Settings/Indexers/Options/IndexerOptions.js
deleted file mode 100644
index 018b8ce1d..000000000
--- a/frontend/src/Settings/Indexers/Options/IndexerOptions.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-
-function IndexerOptions(props) {
- const {
- advancedSettings,
- isFetching,
- error,
- settings,
- hasSettings,
- onInputChange
- } = props;
-
- return (
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && error &&
-
- {translate('UnableToLoadIndexerOptions')}
-
- }
-
- {
- hasSettings && !isFetching && !error &&
-
- }
-
- );
-}
-
-IndexerOptions.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- settings: PropTypes.object.isRequired,
- hasSettings: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default IndexerOptions;
diff --git a/frontend/src/Settings/Indexers/Options/IndexerOptionsConnector.js b/frontend/src/Settings/Indexers/Options/IndexerOptionsConnector.js
deleted file mode 100644
index 4e8031a99..000000000
--- a/frontend/src/Settings/Indexers/Options/IndexerOptionsConnector.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { fetchIndexerOptions, saveIndexerOptions, setIndexerOptionsValue } from 'Store/Actions/settingsActions';
-import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
-import IndexerOptions from './IndexerOptions';
-
-const SECTION = 'indexerOptions';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- createSettingsSectionSelector(SECTION),
- (advancedSettings, sectionSettings) => {
- return {
- advancedSettings,
- ...sectionSettings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchIndexerOptions: fetchIndexerOptions,
- dispatchSetIndexerOptionsValue: setIndexerOptionsValue,
- dispatchSaveIndexerOptions: saveIndexerOptions,
- dispatchClearPendingChanges: clearPendingChanges
-};
-
-class IndexerOptionsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- dispatchFetchIndexerOptions,
- dispatchSaveIndexerOptions,
- onChildMounted
- } = this.props;
-
- dispatchFetchIndexerOptions();
- onChildMounted(dispatchSaveIndexerOptions);
- }
-
- componentDidUpdate(prevProps) {
- const {
- hasPendingChanges,
- isSaving,
- onChildStateChange
- } = this.props;
-
- if (
- prevProps.isSaving !== isSaving ||
- prevProps.hasPendingChanges !== hasPendingChanges
- ) {
- onChildStateChange({
- isSaving,
- hasPendingChanges
- });
- }
- }
-
- componentWillUnmount() {
- this.props.dispatchClearPendingChanges({ section: 'settings.indexerOptions' });
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.dispatchSetIndexerOptionsValue({ name, value });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-IndexerOptionsConnector.propTypes = {
- isSaving: PropTypes.bool.isRequired,
- hasPendingChanges: PropTypes.bool.isRequired,
- dispatchFetchIndexerOptions: PropTypes.func.isRequired,
- dispatchSetIndexerOptionsValue: PropTypes.func.isRequired,
- dispatchSaveIndexerOptions: PropTypes.func.isRequired,
- dispatchClearPendingChanges: PropTypes.func.isRequired,
- onChildMounted: PropTypes.func.isRequired,
- onChildStateChange: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(IndexerOptionsConnector);
diff --git a/frontend/src/Settings/MediaManagement/MediaManagement.js b/frontend/src/Settings/MediaManagement/MediaManagement.js
deleted file mode 100644
index 627263fff..000000000
--- a/frontend/src/Settings/MediaManagement/MediaManagement.js
+++ /dev/null
@@ -1,508 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import { inputTypes, kinds, sizes } from 'Helpers/Props';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import NamingConnector from './Naming/NamingConnector';
-import RootFoldersConnector from './RootFolder/RootFoldersConnector';
-
-const rescanAfterRefreshOptions = [
- {
- key: 'always',
- get value() {
- return translate('Always');
- }
- },
- {
- key: 'afterManual',
- get value() {
- return translate('AfterManualRefresh');
- }
- },
- {
- key: 'never',
- get value() {
- return translate('Never');
- }
- }
-];
-
-const allowFingerprintingOptions = [
- {
- key: 'allFiles',
- get value() {
- return translate('Always');
- }
- },
- {
- key: 'newFiles',
- get value() {
- return translate('ForNewImportsOnly');
- }
- },
- {
- key: 'never',
- get value() {
- return translate('Never');
- }
- }
-];
-
-const downloadPropersAndRepacksOptions = [
- {
- key: 'preferAndUpgrade',
- get value() {
- return translate('PreferAndUpgrade');
- }
- },
- {
- key: 'doNotUpgrade',
- get value() {
- return translate('DoNotUpgradeAutomatically');
- }
- },
- {
- key: 'doNotPrefer',
- get value() {
- return translate('DoNotPrefer');
- }
- }
-];
-
-const fileDateOptions = [
- {
- key: 'none',
- get value() {
- return translate('None');
- }
- },
- {
- key: 'albumReleaseDate',
- get value() {
- return translate('AlbumReleaseDate');
- }
- }
-];
-
-class MediaManagement extends Component {
-
- //
- // Render
-
- render() {
- const {
- advancedSettings,
- isFetching,
- error,
- settings,
- hasSettings,
- isWindows,
- onInputChange,
- onSavePress,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
-
-
-
-
- {
- isFetching &&
-
-
-
- }
-
- {
- !isFetching && error &&
-
-
- {translate('UnableToLoadMediaManagementSettings')}
-
-
- }
-
- {
- hasSettings && !isFetching && !error &&
-
- }
-
-
- );
- }
-
-}
-
-MediaManagement.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- settings: PropTypes.object.isRequired,
- hasSettings: PropTypes.bool.isRequired,
- isWindows: PropTypes.bool.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default MediaManagement;
diff --git a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js b/frontend/src/Settings/MediaManagement/MediaManagementConnector.js
deleted file mode 100644
index 9d6f959b8..000000000
--- a/frontend/src/Settings/MediaManagement/MediaManagementConnector.js
+++ /dev/null
@@ -1,86 +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 { clearPendingChanges } from 'Store/Actions/baseActions';
-import { fetchMediaManagementSettings, saveMediaManagementSettings, saveNamingSettings, setMediaManagementSettingsValue } from 'Store/Actions/settingsActions';
-import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
-import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
-import MediaManagement from './MediaManagement';
-
-const SECTION = 'mediaManagement';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- (state) => state.settings.naming,
- createSettingsSectionSelector(SECTION),
- createSystemStatusSelector(),
- (advancedSettings, namingSettings, sectionSettings, systemStatus) => {
- return {
- advancedSettings,
- ...sectionSettings,
- hasPendingChanges: !_.isEmpty(namingSettings.pendingChanges) || sectionSettings.hasPendingChanges,
- isWindows: systemStatus.isWindows
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchMediaManagementSettings,
- setMediaManagementSettingsValue,
- saveMediaManagementSettings,
- saveNamingSettings,
- clearPendingChanges
-};
-
-class MediaManagementConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchMediaManagementSettings();
- }
-
- componentWillUnmount() {
- this.props.clearPendingChanges({ section: `settings.${SECTION}` });
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setMediaManagementSettingsValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveMediaManagementSettings();
- this.props.saveNamingSettings();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MediaManagementConnector.propTypes = {
- fetchMediaManagementSettings: PropTypes.func.isRequired,
- setMediaManagementSettingsValue: PropTypes.func.isRequired,
- saveMediaManagementSettings: PropTypes.func.isRequired,
- saveNamingSettings: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MediaManagementConnector);
diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.css b/frontend/src/Settings/MediaManagement/Naming/Naming.css
deleted file mode 100644
index 59d223e92..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/Naming.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.namingInput {
- composes: input from '~Components/Form/TextInput.css';
-
- font-family: $monoSpaceFontFamily;
-}
diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.css.d.ts b/frontend/src/Settings/MediaManagement/Naming/Naming.css.d.ts
deleted file mode 100644
index eed487132..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/Naming.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'namingInput': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/Naming/Naming.js b/frontend/src/Settings/MediaManagement/Naming/Naming.js
deleted file mode 100644
index 533c66c6b..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/Naming.js
+++ /dev/null
@@ -1,281 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputButton from 'Components/Form/FormInputButton';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import { inputTypes, kinds, sizes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import NamingModal from './NamingModal';
-import styles from './Naming.css';
-
-class Naming extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isNamingModalOpen: false,
- namingModalOptions: null
- };
- }
-
- //
- // Listeners
-
- onStandardNamingModalOpenClick = () => {
- this.setState({
- isNamingModalOpen: true,
- namingModalOptions: {
- name: 'standardTrackFormat',
- album: true,
- track: true,
- additional: true
- }
- });
- };
-
- onMultiDiscNamingModalOpenClick = () => {
- this.setState({
- isNamingModalOpen: true,
- namingModalOptions: {
- name: 'multiDiscTrackFormat',
- album: true,
- track: true,
- additional: true
- }
- });
- };
-
- onArtistFolderNamingModalOpenClick = () => {
- this.setState({
- isNamingModalOpen: true,
- namingModalOptions: {
- name: 'artistFolderFormat'
- }
- });
- };
-
- onNamingModalClose = () => {
- this.setState({ isNamingModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- advancedSettings,
- isFetching,
- error,
- settings,
- hasSettings,
- examples,
- examplesPopulated,
- onInputChange
- } = this.props;
-
- const {
- isNamingModalOpen,
- namingModalOptions
- } = this.state;
-
- const renameTracks = hasSettings && settings.renameTracks.value;
- const replaceIllegalCharacters = hasSettings && settings.replaceIllegalCharacters.value;
-
- const colonReplacementOptions = [
- { key: 0, value: translate('Delete') },
- { key: 1, value: translate('ReplaceWithDash') },
- { key: 2, value: translate('ReplaceWithSpaceDash') },
- { key: 3, value: translate('ReplaceWithSpaceDashSpace') },
- { key: 4, value: translate('SmartReplace'), hint: translate('DashOrSpaceDashDependingOnName') }
- ];
-
- const standardTrackFormatHelpTexts = [];
- const standardTrackFormatErrors = [];
- const multiDiscTrackFormatHelpTexts = [];
- const multiDiscTrackFormatErrors = [];
- const artistFolderFormatHelpTexts = [];
- const artistFolderFormatErrors = [];
-
- if (examplesPopulated) {
- if (examples.singleTrackExample) {
- standardTrackFormatHelpTexts.push(`Single Track: ${examples.singleTrackExample}`);
- } else {
- standardTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
- }
-
- if (examples.multiDiscTrackExample) {
- multiDiscTrackFormatHelpTexts.push(`Multi Disc Track: ${examples.multiDiscTrackExample}`);
- } else {
- multiDiscTrackFormatErrors.push({ message: 'Single Track: Invalid Format' });
- }
-
- if (examples.artistFolderExample) {
- artistFolderFormatHelpTexts.push(`Example: ${examples.artistFolderExample}`);
- } else {
- artistFolderFormatErrors.push({ message: 'Invalid Format' });
- }
- }
-
- return (
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && error &&
-
- {translate('UnableToLoadNamingSettings')}
-
- }
-
- {
- hasSettings && !isFetching && !error &&
-
- }
-
- );
- }
-
-}
-
-Naming.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- settings: PropTypes.object.isRequired,
- hasSettings: PropTypes.bool.isRequired,
- examples: PropTypes.object.isRequired,
- examplesPopulated: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default Naming;
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js b/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js
deleted file mode 100644
index 8f96fabfb..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingConnector.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { fetchNamingExamples, fetchNamingSettings, setNamingSettingsValue } from 'Store/Actions/settingsActions';
-import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
-import Naming from './Naming';
-
-const SECTION = 'naming';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- (state) => state.settings.namingExamples,
- createSettingsSectionSelector(SECTION),
- (advancedSettings, namingExamples, sectionSettings) => {
- return {
- advancedSettings,
- examples: namingExamples.item,
- examplesPopulated: namingExamples.isPopulated,
- ...sectionSettings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchNamingSettings,
- setNamingSettingsValue,
- fetchNamingExamples,
- clearPendingChanges
-};
-
-class NamingConnector extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this._namingExampleTimeout = null;
- }
-
- componentDidMount() {
- this.props.fetchNamingSettings();
- this.props.fetchNamingExamples();
- }
-
- componentWillUnmount() {
- this.props.clearPendingChanges({ section: 'settings.naming' });
- }
-
- //
- // Control
-
- _fetchNamingExamples = () => {
- this.props.fetchNamingExamples();
- };
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setNamingSettingsValue({ name, value });
-
- if (this._namingExampleTimeout) {
- clearTimeout(this._namingExampleTimeout);
- }
-
- this._namingExampleTimeout = setTimeout(this._fetchNamingExamples, 1000);
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-NamingConnector.propTypes = {
- fetchNamingSettings: PropTypes.func.isRequired,
- setNamingSettingsValue: PropTypes.func.isRequired,
- fetchNamingExamples: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(NamingConnector);
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css b/frontend/src/Settings/MediaManagement/Naming/NamingModal.css
deleted file mode 100644
index f65bed4df..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css
+++ /dev/null
@@ -1,35 +0,0 @@
-.groups {
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- margin-bottom: 20px;
-}
-
-.namingSelectContainer {
- display: flex;
- justify-content: flex-end;
-}
-
-.namingSelect {
- composes: select from '~Components/Form/SelectInput.css';
-
- margin-left: 10px;
- width: 200px;
-}
-
-.footNote {
- display: flex;
- color: var(--helpTextColor);
-
- .icon {
- margin-top: 3px;
- margin-right: 5px;
- padding: 2px;
- }
-
- code {
- padding: 0 1px;
- border: 1px solid var(--borderColor);
- background-color: #f7f7f7;
- }
-}
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css.d.ts b/frontend/src/Settings/MediaManagement/Naming/NamingModal.css.d.ts
deleted file mode 100644
index 5dd30b0d3..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'footNote': string;
- 'groups': string;
- 'icon': string;
- 'namingSelect': string;
- 'namingSelectContainer': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js b/frontend/src/Settings/MediaManagement/Naming/NamingModal.js
deleted file mode 100644
index dec15893f..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingModal.js
+++ /dev/null
@@ -1,608 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FieldSet from 'Components/FieldSet';
-import SelectInput from 'Components/Form/SelectInput';
-import TextInput from 'Components/Form/TextInput';
-import Button from 'Components/Link/Button';
-import Modal from 'Components/Modal/Modal';
-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 { sizes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import NamingOption from './NamingOption';
-import styles from './NamingModal.css';
-
-const separatorOptions = [
- {
- key: ' ',
- get value() {
- return `${translate('Space')} ( )`;
- }
- },
- {
- key: '.',
- get value() {
- return `${translate('Period')} (.)`;
- }
- },
- {
- key: '_',
- get value() {
- return `${translate('Underscore')} (_)`;
- }
- },
- {
- key: '-',
- get value() {
- return `${translate('Dash')} (-)`;
- }
- }
-];
-
-const caseOptions = [
- {
- key: 'title',
- get value() {
- return translate('DefaultCase');
- }
- },
- {
- key: 'lower',
- get value() {
- return translate('Lowercase');
- }
- },
- {
- key: 'upper',
- get value() {
- return translate('Uppercase');
- }
- }
-];
-
-const fileNameTokens = [
- {
- token: '{Artist Name} - {Album Title} - {track:00} - {Track Title} {Quality Full}',
- example: 'Artist Name - Album Title - 01 - Track Title MP3-320 Proper'
- },
- {
- token: '{Artist.Name}.{Album.Title}.{track:00}.{TrackClean.Title}.{Quality.Full}',
- example: 'Artist.Name.Album.Title.01.Track.Title.MP3-320'
- }
-];
-
-const artistTokens = [
- { token: '{Artist Name}', example: 'Artist Name' },
- { token: '{Artist CleanName}', example: 'Artist Name' },
- { token: '{Artist NameThe}', example: 'Artist Name, The' },
- { token: '{Artist CleanNameThe}', example: 'Artist Name, The' },
- { token: '{Artist NameFirstCharacter}', example: 'A' },
- { token: '{Artist Disambiguation}', example: 'Disambiguation' },
- { token: '{Artist Genre}', example: 'Pop' },
- { token: '{Artist MbId}', example: 'db92a151-1ac2-438b-bc43-b82e149ddd50' }
-];
-
-const albumTokens = [
- { token: '{Album Title}', example: 'Album Title' },
- { token: '{Album CleanTitle}', example: 'Album Title' },
- { token: '{Album TitleThe}', example: 'Album Title, The' },
- { token: '{Album CleanTitleThe}', example: 'Album Title, The' },
- { token: '{Album Type}', example: 'Album Type' },
- { token: '{Album Disambiguation}', example: 'Disambiguation' },
- { token: '{Album Genre}', example: 'Rock' },
- { token: '{Album MbId}', example: '082c6aff-a7cc-36e0-a960-35a578ecd937' }
-];
-
-const mediumTokens = [
- { token: '{medium:0}', example: '1' },
- { token: '{medium:00}', example: '01' }
-];
-
-const mediumFormatTokens = [
- { token: '{Medium Name}', example: 'First Medium' },
- { token: '{Medium Format}', example: 'CD' }
-];
-
-const trackTokens = [
- { token: '{track:0}', example: '1' },
- { token: '{track:00}', example: '01' }
-];
-
-const releaseDateTokens = [
- { token: '{Release Year}', example: '2016' }
-];
-
-const trackTitleTokens = [
- { token: '{Track Title}', example: 'Track Title' },
- { token: '{Track CleanTitle}', example: 'Track Title' }
-];
-
-const trackArtistTokens = [
- { token: '{Track ArtistName}', example: 'Artist Name' },
- { token: '{Track ArtistCleanName}', example: 'Artist Name' },
- { token: '{Track ArtistNameThe}', example: 'Artist Name, The' },
- { token: '{Track ArtistCleanNameThe}', example: 'Artist Name, The' },
- { token: '{Track ArtistMbId}', example: 'db92a151-1ac2-438b-bc43-b82e149ddd50' }
-];
-
-const qualityTokens = [
- { token: '{Quality Full}', example: 'FLAC Proper' },
- { token: '{Quality Title}', example: 'FLAC' }
-];
-
-const mediaInfoTokens = [
- { token: '{MediaInfo AudioCodec}', example: 'FLAC' },
- { token: '{MediaInfo AudioChannels}', example: '2.0' },
- { token: '{MediaInfo AudioBitRate}', example: '320kbps' },
- { token: '{MediaInfo AudioBitsPerSample}', example: '24bit' },
- { token: '{MediaInfo AudioSampleRate}', example: '44.1kHz' }
-];
-
-const otherTokens = [
- { token: '{Release Group}', example: 'Rls Grp' },
- { token: '{Custom Formats}', example: 'iNTERNAL' }
-];
-
-const originalTokens = [
- { token: '{Original Title}', example: 'Artist.Name.Album.Name.2018.FLAC-EVOLVE' },
- { token: '{Original Filename}', example: '01 - track name' }
-];
-
-class NamingModal extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this._selectionStart = null;
- this._selectionEnd = null;
-
- this.state = {
- separator: ' ',
- case: 'title'
- };
- }
-
- //
- // Listeners
-
- onTokenSeparatorChange = (event) => {
- this.setState({ separator: event.value });
- };
-
- onTokenCaseChange = (event) => {
- this.setState({ case: event.value });
- };
-
- onInputSelectionChange = (selectionStart, selectionEnd) => {
- this._selectionStart = selectionStart;
- this._selectionEnd = selectionEnd;
- };
-
- onOptionPress = ({ isFullFilename, tokenValue }) => {
- const {
- name,
- value,
- onInputChange
- } = this.props;
-
- const selectionStart = this._selectionStart;
- const selectionEnd = this._selectionEnd;
-
- if (isFullFilename) {
- onInputChange({ name, value: tokenValue });
- } else if (selectionStart == null) {
- onInputChange({
- name,
- value: `${value}${tokenValue}`
- });
- } else {
- const start = value.substring(0, selectionStart);
- const end = value.substring(selectionEnd);
- const newValue = `${start}${tokenValue}${end}`;
-
- onInputChange({ name, value: newValue });
- this._selectionStart = newValue.length - 1;
- this._selectionEnd = newValue.length - 1;
- }
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- value,
- isOpen,
- advancedSettings,
- album,
- track,
- additional,
- onInputChange,
- onModalClose
- } = this.props;
-
- const {
- separator: tokenSeparator,
- case: tokenCase
- } = this.state;
-
- return (
-
-
-
- {translate('FileNameTokens')}
-
-
-
-
-
-
-
-
-
- {
- !advancedSettings &&
-
-
- {
- fileNameTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
- }
-
-
-
- {
- artistTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
- {
- album &&
-
-
-
- {
- albumTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- releaseDateTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
- }
-
- {
- track &&
-
-
-
- {
- mediumTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- mediumFormatTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- trackTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
- }
-
- {
- additional &&
-
-
-
- {
- trackTitleTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- trackArtistTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- qualityTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- mediaInfoTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- otherTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
-
-
- {
- originalTokens.map(({ token, example }) => {
- return (
-
- );
- }
- )
- }
-
-
-
- }
-
-
-
-
-
- {translate('Close')}
-
-
-
-
- );
- }
-}
-
-NamingModal.propTypes = {
- name: PropTypes.string.isRequired,
- value: PropTypes.string.isRequired,
- isOpen: PropTypes.bool.isRequired,
- advancedSettings: PropTypes.bool.isRequired,
- album: PropTypes.bool.isRequired,
- track: PropTypes.bool.isRequired,
- additional: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-NamingModal.defaultProps = {
- album: false,
- track: false,
- additional: false
-};
-
-export default NamingModal;
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css b/frontend/src/Settings/MediaManagement/Naming/NamingOption.css
deleted file mode 100644
index 204c93d0e..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css
+++ /dev/null
@@ -1,74 +0,0 @@
-.option {
- display: flex;
- align-items: stretch;
- flex-wrap: wrap;
- margin: 3px;
- border: 1px solid var(--borderColor);
-
- &:hover {
- .token {
- background-color: #ddd;
- }
-
- .example {
- background-color: #ccc;
- }
- }
-}
-
-.small {
- width: 490px;
-}
-
-.large {
- width: 100%;
-}
-
-.token {
- flex: 0 0 50%;
- padding: 6px;
- background-color: var(--popoverTitleBackgroundColor);
- font-family: $monoSpaceFontFamily;
-}
-
-.example {
- display: flex;
- align-items: center;
- justify-content: space-between;
- flex: 0 0 50%;
- padding: 6px;
- background-color: var(--popoverBodyBackgroundColor);
-
- .footNote {
- padding: 2px;
- color: #aaa;
- }
-}
-
-.lower {
- text-transform: lowercase;
-}
-
-.upper {
- text-transform: uppercase;
-}
-
-.isFullFilename {
- .token,
- .example {
- flex: 1 0 auto;
- }
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .option.small {
- width: 100%;
- }
-}
-
-@media only screen and (max-width: $breakpointExtraSmall) {
- .token,
- .example {
- flex: 1 0 auto;
- }
-}
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css.d.ts b/frontend/src/Settings/MediaManagement/Naming/NamingOption.css.d.ts
deleted file mode 100644
index a060f6218..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingOption.css.d.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'example': string;
- 'footNote': string;
- 'isFullFilename': string;
- 'large': string;
- 'lower': string;
- 'option': string;
- 'small': string;
- 'token': string;
- 'upper': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/Naming/NamingOption.js b/frontend/src/Settings/MediaManagement/Naming/NamingOption.js
deleted file mode 100644
index 29bf9d3bb..000000000
--- a/frontend/src/Settings/MediaManagement/Naming/NamingOption.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Link from 'Components/Link/Link';
-import { sizes } from 'Helpers/Props';
-import styles from './NamingOption.css';
-
-class NamingOption extends Component {
-
- //
- // Listeners
-
- onPress = () => {
- const {
- token,
- tokenSeparator,
- tokenCase,
- isFullFilename,
- onPress
- } = this.props;
-
- let tokenValue = token;
-
- tokenValue = tokenValue.replace(/ /g, tokenSeparator);
-
- if (tokenCase === 'lower') {
- tokenValue = token.toLowerCase();
- } else if (tokenCase === 'upper') {
- tokenValue = token.toUpperCase();
- }
-
- onPress({ isFullFilename, tokenValue });
- };
-
- //
- // Render
- render() {
- const {
- token,
- tokenSeparator,
- example,
- tokenCase,
- isFullFilename,
- size
- } = this.props;
-
- return (
-
-
- {token.replace(/ /g, tokenSeparator)}
-
-
-
- {example.replace(/ /g, tokenSeparator)}
-
-
- );
- }
-}
-
-NamingOption.propTypes = {
- token: PropTypes.string.isRequired,
- example: PropTypes.string.isRequired,
- tokenSeparator: PropTypes.string.isRequired,
- tokenCase: PropTypes.string.isRequired,
- isFullFilename: PropTypes.bool.isRequired,
- size: PropTypes.oneOf([sizes.SMALL, sizes.LARGE]),
- onPress: PropTypes.func.isRequired
-};
-
-NamingOption.defaultProps = {
- size: sizes.SMALL,
- isFullFilename: false
-};
-
-export default NamingOption;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModal.js b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModal.js
deleted file mode 100644
index 6adc8046c..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModal.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import EditRootFolderModalContentConnector from './EditRootFolderModalContentConnector';
-
-function EditRootFolderModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditRootFolderModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditRootFolderModal;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalConnector.js b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalConnector.js
deleted file mode 100644
index b3aaea069..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalConnector.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { cancelSaveRootFolder } from 'Store/Actions/settingsActions';
-import EditRootFolderModal from './EditRootFolderModal';
-
-function createMapDispatchToProps(dispatch, props) {
- const section = 'settings.rootFolders';
-
- return {
- dispatchClearPendingChanges() {
- dispatch(clearPendingChanges({ section }));
- },
-
- dispatchCancelSaveRootFolder() {
- dispatch(cancelSaveRootFolder({ section }));
- }
- };
-}
-
-class EditRootFolderModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.dispatchClearPendingChanges();
- this.props.dispatchCancelSaveRootFolder();
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- const {
- dispatchClearPendingChanges,
- dispatchCancelSaveRootFolder,
- ...otherProps
- } = this.props;
-
- return (
-
- );
- }
-}
-
-EditRootFolderModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- dispatchClearPendingChanges: PropTypes.func.isRequired,
- dispatchCancelSaveRootFolder: PropTypes.func.isRequired
-};
-
-export default connect(null, createMapDispatchToProps)(EditRootFolderModalConnector);
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css
deleted file mode 100644
index 23e22b6dc..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
-
-.hideMetadataProfile {
- composes: group from '~Components/Form/FormGroup.css';
-
- display: none;
-}
-
-.labelIcon {
- margin-left: 8px;
-}
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css.d.ts b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css.d.ts
deleted file mode 100644
index 995399ce7..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
- 'hideMetadataProfile': string;
- 'labelIcon': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.js b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.js
deleted file mode 100644
index 3aab11085..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContent.js
+++ /dev/null
@@ -1,255 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import ArtistMetadataProfilePopoverContent from 'AddArtist/ArtistMetadataProfilePopoverContent';
-import ArtistMonitoringOptionsPopoverContent from 'AddArtist/ArtistMonitoringOptionsPopoverContent';
-import ArtistMonitorNewItemsOptionsPopoverContent from 'AddArtist/ArtistMonitorNewItemsOptionsPopoverContent';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Icon from 'Components/Icon';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 Popover from 'Components/Tooltip/Popover';
-import { icons, inputTypes, kinds, tooltipPositions } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './EditRootFolderModalContent.css';
-
-function EditRootFolderModalContent(props) {
-
- const {
- advancedSettings,
- isFetching,
- error,
- isSaving,
- saveError,
- item,
- onInputChange,
- onModalClose,
- onSavePress,
- onDeleteRootFolderPress,
- showMetadataProfile,
- ...otherProps
- } = props;
-
- const {
- id,
- name,
- path,
- defaultQualityProfileId,
- defaultMetadataProfileId,
- defaultMonitorOption,
- defaultNewItemMonitorOption,
- defaultTags
- } = item;
-
- return (
-
-
- {id ? translate('EditRootFolder') : translate('AddRootFolder')}
-
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && !!error &&
-
- {translate('UnableToAddANewRootFolderPleaseTryAgain')}
-
- }
-
- {
- !isFetching && !error &&
-
- }
-
-
- {
- id &&
-
- {translate('Delete')}
-
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditRootFolderModalContent.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- showMetadataProfile: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onDeleteRootFolderPress: PropTypes.func
-};
-
-export default EditRootFolderModalContent;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContentConnector.js b/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContentConnector.js
deleted file mode 100644
index 0562e269b..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/EditRootFolderModalContentConnector.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { saveRootFolder, setRootFolderValue } from 'Store/Actions/settingsActions';
-import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
-import EditRootFolderModalContent from './EditRootFolderModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state, { id }) => id,
- (state) => state.settings.advancedSettings,
- (state) => state.settings.metadataProfiles,
- (state) => state.settings.rootFolders,
- createProviderSettingsSelector('rootFolders'),
- (id, advancedSettings, metadataProfiles, rootFolders, rootFolderSettings) => {
- return {
- advancedSettings,
- showMetadataProfile: metadataProfiles.items.length > 1,
- ...rootFolderSettings,
- isFetching: rootFolders.isFetching
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setRootFolderValue,
- saveRootFolder
-};
-
-class EditRootFolderModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setRootFolderValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveRootFolder({ id: this.props.id });
-
- if (this.props.onRootFolderAdded) {
- this.props.onRootFolderAdded(this.props.item.path);
- }
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditRootFolderModalContentConnector.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setRootFolderValue: PropTypes.func.isRequired,
- saveRootFolder: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onRootFolderAdded: PropTypes.func
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditRootFolderModalContentConnector);
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css
deleted file mode 100644
index 0506cc9c6..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css
+++ /dev/null
@@ -1,19 +0,0 @@
-.rootFolder {
- composes: card from '~Components/Card.css';
-
- width: 290px;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.enabled {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
-}
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css.d.ts b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css.d.ts
deleted file mode 100644
index 7f6c11c57..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'enabled': string;
- 'name': string;
- 'rootFolder': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js b/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js
deleted file mode 100644
index dc91e4622..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolder.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditRootFolderModalConnector from './EditRootFolderModalConnector';
-import styles from './RootFolder.css';
-
-class RootFolder extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditRootFolderModalOpen: false,
- isDeleteRootFolderModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditRootFolderPress = () => {
- this.setState({ isEditRootFolderModalOpen: true });
- };
-
- onEditRootFolderModalClose = () => {
- this.setState({ isEditRootFolderModalOpen: false });
- };
-
- onDeleteRootFolderPress = () => {
- this.setState({
- isEditRootFolderModalOpen: false,
- isDeleteRootFolderModalOpen: true
- });
- };
-
- onDeleteRootFolderModalClose= () => {
- this.setState({ isDeleteRootFolderModalOpen: false });
- };
-
- onConfirmDeleteRootFolder = () => {
- this.props.onConfirmDeleteRootFolder(this.props.id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- path,
- qualityProfile,
- metadataProfile
- } = this.props;
-
- return (
-
-
- {name}
-
-
-
-
- {path}
-
-
-
- {qualityProfile?.name || translate('None')}
-
-
-
- {metadataProfile?.name || translate('None')}
-
-
-
-
-
-
-
- );
- }
-}
-
-RootFolder.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- path: PropTypes.string.isRequired,
- qualityProfile: PropTypes.object.isRequired,
- metadataProfile: PropTypes.object.isRequired,
- onConfirmDeleteRootFolder: PropTypes.func.isRequired
-};
-
-export default RootFolder;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css b/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css
deleted file mode 100644
index 3b3bcc17a..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.rootFolders {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addRootFolder {
- composes: rootFolder from '~./RootFolder.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css.d.ts b/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css.d.ts
deleted file mode 100644
index 124ece64f..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addRootFolder': string;
- 'center': string;
- 'rootFolders': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.js b/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.js
deleted file mode 100644
index a945a805e..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFolders.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditRootFolderModalConnector from './EditRootFolderModalConnector';
-import RootFolder from './RootFolder';
-import styles from './RootFolders.css';
-
-class RootFolders extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isAddRootFolderModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onAddRootFolderPress = () => {
- this.setState({ isAddRootFolderModalOpen: true });
- };
-
- onAddRootFolderModalClose = () => {
- this.setState({ isAddRootFolderModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- items,
- qualityProfiles,
- metadataProfiles,
- onConfirmDeleteRootFolder,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
- {
- items.map((item) => {
- const qualityProfile = qualityProfiles.find((profile) => profile.id === item.defaultQualityProfileId);
- const metadataProfile = metadataProfiles.find((profile) => profile.id === item.defaultMetadataProfileId);
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-RootFolders.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- qualityProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
- metadataProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteRootFolder: PropTypes.func.isRequired
-};
-
-export default RootFolders;
diff --git a/frontend/src/Settings/MediaManagement/RootFolder/RootFoldersConnector.js b/frontend/src/Settings/MediaManagement/RootFolder/RootFoldersConnector.js
deleted file mode 100644
index e1e8807bb..000000000
--- a/frontend/src/Settings/MediaManagement/RootFolder/RootFoldersConnector.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { deleteRootFolder, fetchRootFolders } from 'Store/Actions/settingsActions';
-import createRootFoldersSelector from 'Store/Selectors/createRootFoldersSelector';
-import RootFolders from './RootFolders';
-
-function createMapStateToProps() {
- return createSelector(
- createRootFoldersSelector(),
- (state) => state.settings.qualityProfiles,
- (state) => state.settings.metadataProfiles,
- (rootFolders, quality, metadata) => {
- return {
- qualityProfiles: quality.items,
- metadataProfiles: metadata.items,
- ...rootFolders
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchRootFolders: fetchRootFolders,
- dispatchDeleteRootFolder: deleteRootFolder
-};
-
-class RootFoldersConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchRootFolders();
- }
-
- //
- // Listeners
-
- onConfirmDeleteRootFolder = (id) => {
- this.props.dispatchDeleteRootFolder({ id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-RootFoldersConnector.propTypes = {
- dispatchFetchRootFolders: PropTypes.func.isRequired,
- dispatchDeleteRootFolder: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(RootFoldersConnector);
diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js
deleted file mode 100644
index 4b33df528..000000000
--- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditMetadataModalContentConnector from './EditMetadataModalContentConnector';
-
-function EditMetadataModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditMetadataModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditMetadataModal;
diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js
deleted file mode 100644
index 6e415b80c..000000000
--- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalConnector.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditMetadataModal from './EditMetadataModal';
-
-function createMapDispatchToProps(dispatch, props) {
- const section = 'settings.metadata';
-
- return {
- dispatchClearPendingChanges() {
- dispatch(clearPendingChanges({ section }));
- }
- };
-}
-
-class EditMetadataModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.dispatchClearPendingChanges();
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditMetadataModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- dispatchClearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(null, createMapDispatchToProps)(EditMetadataModalConnector);
diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js
deleted file mode 100644
index 812478d23..000000000
--- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContent.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-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 { inputTypes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-
-function EditMetadataModalContent(props) {
- const {
- isSaving,
- saveError,
- item,
- onInputChange,
- onFieldChange,
- onModalClose,
- onSavePress,
- ...otherProps
- } = props;
-
- const {
- name,
- enable,
- fields
- } = item;
-
- return (
-
-
- {translate('EditMetadata')} - {name.value}
-
-
-
-
-
-
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditMetadataModalContent.propTypes = {
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onFieldChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onDeleteMetadataPress: PropTypes.func
-};
-
-export default EditMetadataModalContent;
diff --git a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js b/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js
deleted file mode 100644
index f36ac6807..000000000
--- a/frontend/src/Settings/Metadata/Metadata/EditMetadataModalContentConnector.js
+++ /dev/null
@@ -1,93 +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 { saveMetadata, setMetadataFieldValue, setMetadataValue } from 'Store/Actions/settingsActions';
-import selectSettings from 'Store/Selectors/selectSettings';
-import EditMetadataModalContent from './EditMetadataModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state, { id }) => id,
- (state) => state.settings.metadata,
- (id, metadata) => {
- const {
- isSaving,
- saveError,
- pendingChanges,
- items
- } = metadata;
-
- const settings = selectSettings(_.find(items, { id }), pendingChanges, saveError);
-
- return {
- id,
- isSaving,
- saveError,
- item: settings.settings,
- ...settings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setMetadataValue,
- setMetadataFieldValue,
- saveMetadata
-};
-
-class EditMetadataModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setMetadataValue({ name, value });
- };
-
- onFieldChange = ({ name, value }) => {
- this.props.setMetadataFieldValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveMetadata({ id: this.props.id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditMetadataModalContentConnector.propTypes = {
- id: PropTypes.number,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setMetadataValue: PropTypes.func.isRequired,
- setMetadataFieldValue: PropTypes.func.isRequired,
- saveMetadata: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditMetadataModalContentConnector);
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.css b/frontend/src/Settings/Metadata/Metadata/Metadata.css
deleted file mode 100644
index f87b92a81..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadata.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.metadata {
- composes: card from '~Components/Card.css';
-
- width: 290px;
-}
-
-.name {
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.section {
- margin-top: 10px;
-}
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.css.d.ts b/frontend/src/Settings/Metadata/Metadata/Metadata.css.d.ts
deleted file mode 100644
index d3d1af505..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadata.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'metadata': string;
- 'name': string;
- 'section': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadata.js b/frontend/src/Settings/Metadata/Metadata/Metadata.js
deleted file mode 100644
index 7135c87bd..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadata.js
+++ /dev/null
@@ -1,149 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import { kinds } from 'Helpers/Props';
-import EditMetadataModalConnector from './EditMetadataModalConnector';
-import styles from './Metadata.css';
-
-class Metadata extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditMetadataModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditMetadataPress = () => {
- this.setState({ isEditMetadataModalOpen: true });
- };
-
- onEditMetadataModalClose = () => {
- this.setState({ isEditMetadataModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- enable,
- fields
- } = this.props;
-
- const metadataFields = [];
- const imageFields = [];
-
- fields.forEach((field) => {
- if (field.section === 'metadata') {
- metadataFields.push(field);
- } else {
- imageFields.push(field);
- }
- });
-
- return (
-
-
- {name}
-
-
-
- {
- enable ?
-
- Enabled
- :
-
- Disabled
-
- }
-
-
- {
- enable && !!metadataFields.length &&
-
-
- Metadata
-
-
- {
- metadataFields.map((field) => {
- if (!field.value) {
- return null;
- }
-
- return (
-
- {field.label}
-
- );
- })
- }
-
- }
-
- {
- enable && !!imageFields.length &&
-
-
- Images
-
-
- {
- imageFields.map((field) => {
- if (!field.value) {
- return null;
- }
-
- return (
-
- {field.label}
-
- );
- })
- }
-
- }
-
-
-
- );
- }
-}
-
-Metadata.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- enable: PropTypes.bool.isRequired,
- fields: PropTypes.arrayOf(PropTypes.object).isRequired
-};
-
-export default Metadata;
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadatas.css b/frontend/src/Settings/Metadata/Metadata/Metadatas.css
deleted file mode 100644
index fb1bd6080..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadatas.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.metadatas {
- display: flex;
- flex-wrap: wrap;
-}
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadatas.css.d.ts b/frontend/src/Settings/Metadata/Metadata/Metadatas.css.d.ts
deleted file mode 100644
index 4c9d41dba..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadatas.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'metadatas': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Metadata/Metadata/Metadatas.js b/frontend/src/Settings/Metadata/Metadata/Metadatas.js
deleted file mode 100644
index d6842149a..000000000
--- a/frontend/src/Settings/Metadata/Metadata/Metadatas.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import FieldSet from 'Components/FieldSet';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import translate from 'Utilities/String/translate';
-import Metadata from './Metadata';
-import styles from './Metadatas.css';
-
-function Metadatas(props) {
- const {
- items,
- ...otherProps
- } = props;
-
- return (
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
- );
-}
-
-Metadatas.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired
-};
-
-export default Metadatas;
diff --git a/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js b/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js
deleted file mode 100644
index 8675f4742..000000000
--- a/frontend/src/Settings/Metadata/Metadata/MetadatasConnector.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchMetadata } from 'Store/Actions/settingsActions';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import Metadatas from './Metadatas';
-
-function createMapStateToProps() {
- return createSelector(
- createSortedSectionSelector('settings.metadata', sortByProp('name')),
- (metadata) => metadata
- );
-}
-
-const mapDispatchToProps = {
- fetchMetadata
-};
-
-class MetadatasConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchMetadata();
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MetadatasConnector.propTypes = {
- fetchMetadata: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector);
diff --git a/frontend/src/Settings/Metadata/MetadataProvider/MetadataProvider.js b/frontend/src/Settings/Metadata/MetadataProvider/MetadataProvider.js
deleted file mode 100644
index 10448892c..000000000
--- a/frontend/src/Settings/Metadata/MetadataProvider/MetadataProvider.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-
-const writeAudioTagOptions = [
- { key: 'sync', value: 'All files; keep in sync with MusicBrainz' },
- { key: 'allFiles', value: 'All files; initial import only' },
- { key: 'newFiles', value: 'For new downloads only' },
- { key: 'no', value: 'Never' }
-];
-
-function MetadataProvider(props) {
- const {
- isFetching,
- error,
- settings,
- hasSettings,
- onInputChange
- } = props;
-
- return (
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && error &&
-
- {translate('UnableToLoadMetadataProviderSettings')}
-
- }
-
- {
- hasSettings && !isFetching && !error &&
-
- }
-
-
- );
-}
-
-MetadataProvider.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- settings: PropTypes.object.isRequired,
- hasSettings: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default MetadataProvider;
diff --git a/frontend/src/Settings/Metadata/MetadataProvider/MetadataProviderConnector.js b/frontend/src/Settings/Metadata/MetadataProvider/MetadataProviderConnector.js
deleted file mode 100644
index d88807580..000000000
--- a/frontend/src/Settings/Metadata/MetadataProvider/MetadataProviderConnector.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { fetchMetadataProvider, saveMetadataProvider, setMetadataProviderValue } from 'Store/Actions/settingsActions';
-import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
-import MetadataProvider from './MetadataProvider';
-
-const SECTION = 'metadataProvider';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- createSettingsSectionSelector(SECTION),
- (advancedSettings, sectionSettings) => {
- return {
- advancedSettings,
- ...sectionSettings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchMetadataProvider: fetchMetadataProvider,
- dispatchSetMetadataProviderValue: setMetadataProviderValue,
- dispatchSaveMetadataProvider: saveMetadataProvider,
- dispatchClearPendingChanges: clearPendingChanges
-};
-
-class MetadataProviderConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- dispatchFetchMetadataProvider,
- dispatchSaveMetadataProvider,
- onChildMounted
- } = this.props;
-
- dispatchFetchMetadataProvider();
- onChildMounted(dispatchSaveMetadataProvider);
- }
-
- componentDidUpdate(prevProps) {
- const {
- hasPendingChanges,
- isSaving,
- onChildStateChange
- } = this.props;
-
- if (
- prevProps.isSaving !== isSaving ||
- prevProps.hasPendingChanges !== hasPendingChanges
- ) {
- onChildStateChange({
- isSaving,
- hasPendingChanges
- });
- }
- }
-
- componentWillUnmount() {
- this.props.dispatchClearPendingChanges({ section: 'settings.metadataProvider' });
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.dispatchSetMetadataProviderValue({ name, value });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MetadataProviderConnector.propTypes = {
- isSaving: PropTypes.bool.isRequired,
- hasPendingChanges: PropTypes.bool.isRequired,
- dispatchFetchMetadataProvider: PropTypes.func.isRequired,
- dispatchSetMetadataProviderValue: PropTypes.func.isRequired,
- dispatchSaveMetadataProvider: PropTypes.func.isRequired,
- dispatchClearPendingChanges: PropTypes.func.isRequired,
- onChildMounted: PropTypes.func.isRequired,
- onChildStateChange: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MetadataProviderConnector);
diff --git a/frontend/src/Settings/Metadata/MetadataSettings.js b/frontend/src/Settings/Metadata/MetadataSettings.js
deleted file mode 100644
index 82fe8ec3a..000000000
--- a/frontend/src/Settings/Metadata/MetadataSettings.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import React, { Component } from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import MetadatasConnector from './Metadata/MetadatasConnector';
-import MetadataProviderConnector from './MetadataProvider/MetadataProviderConnector';
-
-class MetadataSettings extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this._saveCallback = null;
-
- this.state = {
- isSaving: false,
- hasPendingChanges: false
- };
- }
-
- //
- // Listeners
-
- onChildMounted = (saveCallback) => {
- this._saveCallback = saveCallback;
- };
-
- onChildStateChange = (payload) => {
- this.setState(payload);
- };
-
- onSavePress = () => {
- if (this._saveCallback) {
- this._saveCallback();
- }
- };
-
- //
- // Render
- render() {
- const {
- isSaving,
- hasPendingChanges
- } = this.state;
-
- return (
-
-
-
-
-
-
-
-
- );
- }
-}
-
-export default MetadataSettings;
diff --git a/frontend/src/Settings/Notifications/NotificationSettings.js b/frontend/src/Settings/Notifications/NotificationSettings.js
deleted file mode 100644
index 991624463..000000000
--- a/frontend/src/Settings/Notifications/NotificationSettings.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import NotificationsConnector from './Notifications/NotificationsConnector';
-
-function NotificationSettings() {
- return (
-
-
-
-
-
-
-
- );
-}
-
-export default NotificationSettings;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css b/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css
deleted file mode 100644
index a9e416098..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css
+++ /dev/null
@@ -1,44 +0,0 @@
-.notification {
- composes: card from '~Components/Card.css';
-
- position: relative;
- width: 300px;
- height: 100px;
-}
-
-.underlay {
- @add-mixin cover;
-}
-
-.overlay {
- @add-mixin linkOverlay;
-
- padding: 10px;
-}
-
-.name {
- text-align: center;
- font-weight: lighter;
- font-size: 24px;
-}
-
-.actions {
- margin-top: 20px;
- text-align: right;
-}
-
-.presetsMenu {
- composes: menu from '~Components/Menu/Menu.css';
-
- display: inline-block;
- margin: 0 5px;
-}
-
-.presetsMenuButton {
- composes: button from '~Components/Link/Button.css';
-
- &::after {
- margin-left: 5px;
- content: '\25BE';
- }
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css.d.ts b/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css.d.ts
deleted file mode 100644
index 952689303..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'name': string;
- 'notification': string;
- 'overlay': string;
- 'presetsMenu': string;
- 'presetsMenuButton': string;
- 'underlay': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.js b/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.js
deleted file mode 100644
index 4cf8a6d57..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationItem.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Button from 'Components/Link/Button';
-import Link from 'Components/Link/Link';
-import Menu from 'Components/Menu/Menu';
-import MenuContent from 'Components/Menu/MenuContent';
-import { sizes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import AddNotificationPresetMenuItem from './AddNotificationPresetMenuItem';
-import styles from './AddNotificationItem.css';
-
-class AddNotificationItem extends Component {
-
- //
- // Listeners
-
- onNotificationSelect = () => {
- const {
- implementation
- } = this.props;
-
- this.props.onNotificationSelect({ implementation });
- };
-
- //
- // Render
-
- render() {
- const {
- implementation,
- implementationName,
- infoLink,
- presets,
- onNotificationSelect
- } = this.props;
-
- const hasPresets = !!presets && !!presets.length;
-
- return (
-
-
-
-
-
- {implementationName}
-
-
-
- {
- hasPresets &&
-
-
- {translate('Custom')}
-
-
-
-
- {translate('Presets')}
-
-
-
- {
- presets.map((preset) => {
- return (
-
- );
- })
- }
-
-
-
- }
-
-
- {translate('MoreInfo')}
-
-
-
-
- );
- }
-}
-
-AddNotificationItem.propTypes = {
- implementation: PropTypes.string.isRequired,
- implementationName: PropTypes.string.isRequired,
- infoLink: PropTypes.string.isRequired,
- presets: PropTypes.arrayOf(PropTypes.object),
- onNotificationSelect: PropTypes.func.isRequired
-};
-
-export default AddNotificationItem;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationModal.js b/frontend/src/Settings/Notifications/Notifications/AddNotificationModal.js
deleted file mode 100644
index 45f5e14b6..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationModal.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import AddNotificationModalContentConnector from './AddNotificationModalContentConnector';
-
-function AddNotificationModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-AddNotificationModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default AddNotificationModal;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css b/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css
deleted file mode 100644
index 8744e516c..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.notifications {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css.d.ts b/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css.d.ts
deleted file mode 100644
index 172f4fc5b..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'notifications': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.js b/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.js
deleted file mode 100644
index 705ae58e4..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContent.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Button from 'Components/Link/Button';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 translate from 'Utilities/String/translate';
-import AddNotificationItem from './AddNotificationItem';
-import styles from './AddNotificationModalContent.css';
-
-class AddNotificationModalContent extends Component {
-
- //
- // Render
-
- render() {
- const {
- isSchemaFetching,
- isSchemaPopulated,
- schemaError,
- schema,
- onNotificationSelect,
- onModalClose
- } = this.props;
-
- return (
-
-
- {translate('AddConnection')}
-
-
-
- {
- isSchemaFetching &&
-
- }
-
- {
- !isSchemaFetching && !!schemaError &&
-
- {translate('UnableToAddANewNotificationPleaseTryAgain')}
-
- }
-
- {
- isSchemaPopulated && !schemaError &&
-
-
- {
- schema.map((notification) => {
- return (
-
- );
- })
- }
-
-
- }
-
-
-
- Close
-
-
-
- );
- }
-}
-
-AddNotificationModalContent.propTypes = {
- isSchemaFetching: PropTypes.bool.isRequired,
- isSchemaPopulated: PropTypes.bool.isRequired,
- schemaError: PropTypes.object,
- schema: PropTypes.arrayOf(PropTypes.object).isRequired,
- onNotificationSelect: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default AddNotificationModalContent;
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContentConnector.js b/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContentConnector.js
deleted file mode 100644
index 749038688..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationModalContentConnector.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchNotificationSchema, selectNotificationSchema } from 'Store/Actions/settingsActions';
-import AddNotificationModalContent from './AddNotificationModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.notifications,
- (notifications) => {
- const {
- isSchemaFetching,
- isSchemaPopulated,
- schemaError,
- schema
- } = notifications;
-
- return {
- isSchemaFetching,
- isSchemaPopulated,
- schemaError,
- schema
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchNotificationSchema,
- selectNotificationSchema
-};
-
-class AddNotificationModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchNotificationSchema();
- }
-
- //
- // Listeners
-
- onNotificationSelect = ({ implementation, name }) => {
- this.props.selectNotificationSchema({ implementation, presetName: name });
- this.props.onModalClose({ notificationSelected: true });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-AddNotificationModalContentConnector.propTypes = {
- fetchNotificationSchema: PropTypes.func.isRequired,
- selectNotificationSchema: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(AddNotificationModalContentConnector);
diff --git a/frontend/src/Settings/Notifications/Notifications/AddNotificationPresetMenuItem.js b/frontend/src/Settings/Notifications/Notifications/AddNotificationPresetMenuItem.js
deleted file mode 100644
index dd325906f..000000000
--- a/frontend/src/Settings/Notifications/Notifications/AddNotificationPresetMenuItem.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import MenuItem from 'Components/Menu/MenuItem';
-
-class AddNotificationPresetMenuItem extends Component {
-
- //
- // Listeners
-
- onPress = () => {
- const {
- name,
- implementation
- } = this.props;
-
- this.props.onPress({
- name,
- implementation
- });
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- implementation,
- ...otherProps
- } = this.props;
-
- return (
-
- {name}
-
- );
- }
-}
-
-AddNotificationPresetMenuItem.propTypes = {
- name: PropTypes.string.isRequired,
- implementation: PropTypes.string.isRequired,
- onPress: PropTypes.func.isRequired
-};
-
-export default AddNotificationPresetMenuItem;
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModal.js b/frontend/src/Settings/Notifications/Notifications/EditNotificationModal.js
deleted file mode 100644
index bc7f4ab18..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditNotificationModalContentConnector from './EditNotificationModalContentConnector';
-
-function EditNotificationModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditNotificationModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditNotificationModal;
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalConnector.js b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalConnector.js
deleted file mode 100644
index 91070a979..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalConnector.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { cancelSaveNotification, cancelTestNotification } from 'Store/Actions/settingsActions';
-import EditNotificationModal from './EditNotificationModal';
-
-function createMapDispatchToProps(dispatch, props) {
- const section = 'settings.notifications';
-
- return {
- dispatchClearPendingChanges() {
- dispatch(clearPendingChanges({ section }));
- },
-
- dispatchCancelTestNotification() {
- dispatch(cancelTestNotification({ section }));
- },
-
- dispatchCancelSaveNotification() {
- dispatch(cancelSaveNotification({ section }));
- }
- };
-}
-
-class EditNotificationModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.dispatchClearPendingChanges();
- this.props.dispatchCancelTestNotification();
- this.props.dispatchCancelSaveNotification();
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- const {
- dispatchClearPendingChanges,
- dispatchCancelTestNotification,
- dispatchCancelSaveNotification,
- ...otherProps
- } = this.props;
-
- return (
-
- );
- }
-}
-
-EditNotificationModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- dispatchClearPendingChanges: PropTypes.func.isRequired,
- dispatchCancelTestNotification: PropTypes.func.isRequired,
- dispatchCancelSaveNotification: PropTypes.func.isRequired
-};
-
-export default connect(null, createMapDispatchToProps)(EditNotificationModalConnector);
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css
deleted file mode 100644
index 8e1c16507..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css
+++ /dev/null
@@ -1,11 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
-
-.message {
- composes: alert from '~Components/Alert.css';
-
- margin-bottom: 30px;
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css.d.ts b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css.d.ts
deleted file mode 100644
index 37d918628..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
- 'message': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js
deleted file mode 100644
index ee51799f2..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContent.js
+++ /dev/null
@@ -1,194 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import AdvancedSettingsButton from 'Settings/AdvancedSettingsButton';
-import translate from 'Utilities/String/translate';
-import NotificationEventItems from './NotificationEventItems';
-import styles from './EditNotificationModalContent.css';
-
-function EditNotificationModalContent(props) {
- const {
- advancedSettings,
- isFetching,
- error,
- isSaving,
- isTesting,
- saveError,
- item,
- onInputChange,
- onFieldChange,
- onModalClose,
- onSavePress,
- onTestPress,
- onAdvancedSettingsPress,
- onDeleteNotificationPress,
- ...otherProps
- } = props;
-
- const {
- id,
- implementationName,
- name,
- tags,
- fields,
- message
- } = item;
-
- return (
-
-
- {id ? translate('EditConnectionImplementation', { implementationName }) : translate('AddConnectionImplementation', { implementationName })}
-
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && !!error &&
-
- {translate('UnableToAddANewNotificationPleaseTryAgain')}
-
- }
-
- {
- !isFetching && !error &&
-
- }
-
-
- {
- id &&
-
- {translate('Delete')}
-
- }
-
-
-
-
- {translate('Test')}
-
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditNotificationModalContent.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- isTesting: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onFieldChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onTestPress: PropTypes.func.isRequired,
- onAdvancedSettingsPress: PropTypes.func.isRequired,
- onDeleteNotificationPress: PropTypes.func
-};
-
-export default EditNotificationModalContent;
diff --git a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContentConnector.js b/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContentConnector.js
deleted file mode 100644
index 658d72da8..000000000
--- a/frontend/src/Settings/Notifications/Notifications/EditNotificationModalContentConnector.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import {
- saveNotification,
- setNotificationFieldValue,
- setNotificationValue,
- testNotification,
- toggleAdvancedSettings
-} from 'Store/Actions/settingsActions';
-import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
-import EditNotificationModalContent from './EditNotificationModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- createProviderSettingsSelector('notifications'),
- (advancedSettings, notification) => {
- return {
- advancedSettings,
- ...notification
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setNotificationValue,
- setNotificationFieldValue,
- saveNotification,
- testNotification,
- toggleAdvancedSettings
-};
-
-class EditNotificationModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setNotificationValue({ name, value });
- };
-
- onFieldChange = ({ name, value }) => {
- this.props.setNotificationFieldValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveNotification({ id: this.props.id });
- };
-
- onTestPress = () => {
- this.props.testNotification({ id: this.props.id });
- };
-
- onAdvancedSettingsPress = () => {
- this.props.toggleAdvancedSettings();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditNotificationModalContentConnector.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setNotificationValue: PropTypes.func.isRequired,
- setNotificationFieldValue: PropTypes.func.isRequired,
- saveNotification: PropTypes.func.isRequired,
- testNotification: PropTypes.func.isRequired,
- toggleAdvancedSettings: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditNotificationModalContentConnector);
diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.css b/frontend/src/Settings/Notifications/Notifications/Notification.css
deleted file mode 100644
index d7717d8c9..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notification.css
+++ /dev/null
@@ -1,19 +0,0 @@
-.notification {
- composes: card from '~Components/Card.css';
-
- width: 290px;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.enabled {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.css.d.ts b/frontend/src/Settings/Notifications/Notifications/Notification.css.d.ts
deleted file mode 100644
index 5c52ad42f..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notification.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'enabled': string;
- 'name': string;
- 'notification': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/Notification.js b/frontend/src/Settings/Notifications/Notifications/Notification.js
deleted file mode 100644
index 21f0e5ca8..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notification.js
+++ /dev/null
@@ -1,274 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import TagList from 'Components/TagList';
-import { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditNotificationModalConnector from './EditNotificationModalConnector';
-import styles from './Notification.css';
-
-class Notification extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditNotificationModalOpen: false,
- isDeleteNotificationModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditNotificationPress = () => {
- this.setState({ isEditNotificationModalOpen: true });
- };
-
- onEditNotificationModalClose = () => {
- this.setState({ isEditNotificationModalOpen: false });
- };
-
- onDeleteNotificationPress = () => {
- this.setState({
- isEditNotificationModalOpen: false,
- isDeleteNotificationModalOpen: true
- });
- };
-
- onDeleteNotificationModalClose= () => {
- this.setState({ isDeleteNotificationModalOpen: false });
- };
-
- onConfirmDeleteNotification = () => {
- this.props.onConfirmDeleteNotification(this.props.id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- onGrab,
- onReleaseImport,
- onUpgrade,
- onRename,
- onArtistAdd,
- onArtistDelete,
- onAlbumDelete,
- onHealthIssue,
- onHealthRestored,
- onDownloadFailure,
- onImportFailure,
- onTrackRetag,
- onApplicationUpdate,
- supportsOnGrab,
- supportsOnReleaseImport,
- supportsOnUpgrade,
- supportsOnRename,
- supportsOnArtistAdd,
- supportsOnArtistDelete,
- supportsOnAlbumDelete,
- supportsOnHealthIssue,
- supportsOnHealthRestored,
- supportsOnDownloadFailure,
- supportsOnImportFailure,
- supportsOnTrackRetag,
- supportsOnApplicationUpdate,
- tags,
- tagList
- } = this.props;
-
- return (
-
-
- {name}
-
-
- {
- supportsOnGrab && onGrab ?
-
- {translate('OnGrab')}
- :
- null
- }
-
- {
- supportsOnReleaseImport && onReleaseImport ?
-
- {translate('OnReleaseImport')}
- :
- null
- }
-
- {
- supportsOnUpgrade && onReleaseImport && onUpgrade ?
-
- {translate('OnUpgrade')}
- :
- null
- }
-
- {
- supportsOnRename && onRename ?
-
- {translate('OnRename')}
- :
- null
- }
-
- {
- supportsOnTrackRetag && onTrackRetag ?
-
- {translate('OnTrackRetag')}
- :
- null
- }
-
- {
- supportsOnArtistAdd && onArtistAdd ?
-
- {translate('OnArtistAdd')}
- :
- null
- }
-
- {
- supportsOnArtistDelete && onArtistDelete ?
-
- {translate('OnArtistDelete')}
- :
- null
- }
-
- {
- supportsOnAlbumDelete && onAlbumDelete ?
-
- {translate('OnAlbumDelete')}
- :
- null
- }
-
- {
- supportsOnHealthIssue && onHealthIssue ?
-
- {translate('OnHealthIssue')}
- :
- null
- }
-
- {
- supportsOnHealthRestored && onHealthRestored ?
-
- {translate('OnHealthRestored')}
- :
- null
- }
-
- {
- supportsOnDownloadFailure && onDownloadFailure ?
-
- {translate('OnDownloadFailure')}
- :
- null
- }
-
- {
- supportsOnImportFailure && onImportFailure ?
-
- {translate('OnImportFailure')}
- :
- null
- }
-
- {
- supportsOnApplicationUpdate && onApplicationUpdate ?
-
- {translate('OnApplicationUpdate')}
- :
- null
- }
-
- {
- !onGrab && !onReleaseImport && !onRename && !onTrackRetag && !onArtistAdd && !onArtistDelete && !onAlbumDelete && !onHealthIssue && !onHealthRestored && !onDownloadFailure && !onImportFailure && !onApplicationUpdate ?
-
- {translate('Disabled')}
- :
- null
- }
-
-
-
-
-
-
-
- );
- }
-}
-
-Notification.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- onGrab: PropTypes.bool.isRequired,
- onReleaseImport: PropTypes.bool.isRequired,
- onUpgrade: PropTypes.bool.isRequired,
- onRename: PropTypes.bool.isRequired,
- onArtistAdd: PropTypes.bool.isRequired,
- onArtistDelete: PropTypes.bool.isRequired,
- onAlbumDelete: PropTypes.bool.isRequired,
- onHealthIssue: PropTypes.bool.isRequired,
- onHealthRestored: PropTypes.bool.isRequired,
- onDownloadFailure: PropTypes.bool.isRequired,
- onImportFailure: PropTypes.bool.isRequired,
- onTrackRetag: PropTypes.bool.isRequired,
- onApplicationUpdate: PropTypes.bool.isRequired,
- supportsOnGrab: PropTypes.bool.isRequired,
- supportsOnReleaseImport: PropTypes.bool.isRequired,
- supportsOnUpgrade: PropTypes.bool.isRequired,
- supportsOnRename: PropTypes.bool.isRequired,
- supportsOnArtistAdd: PropTypes.bool.isRequired,
- supportsOnArtistDelete: PropTypes.bool.isRequired,
- supportsOnAlbumDelete: PropTypes.bool.isRequired,
- supportsOnHealthIssue: PropTypes.bool.isRequired,
- supportsOnHealthRestored: PropTypes.bool.isRequired,
- supportsOnDownloadFailure: PropTypes.bool.isRequired,
- supportsOnImportFailure: PropTypes.bool.isRequired,
- supportsOnTrackRetag: PropTypes.bool.isRequired,
- supportsOnApplicationUpdate: PropTypes.bool.isRequired,
- tags: PropTypes.arrayOf(PropTypes.number).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteNotification: PropTypes.func.isRequired
-};
-
-export default Notification;
diff --git a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css b/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css
deleted file mode 100644
index b3f6aa717..000000000
--- a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.events {
- margin-top: 10px;
- user-select: none;
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css.d.ts b/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css.d.ts
deleted file mode 100644
index 931fd2781..000000000
--- a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'events': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js b/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js
deleted file mode 100644
index bff7b5ef7..000000000
--- a/frontend/src/Settings/Notifications/Notifications/NotificationEventItems.js
+++ /dev/null
@@ -1,228 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import { inputTypes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './NotificationEventItems.css';
-
-function NotificationEventItems(props) {
- const {
- item,
- onInputChange
- } = props;
-
- const {
- onGrab,
- onReleaseImport,
- onUpgrade,
- onRename,
- onArtistAdd,
- onArtistDelete,
- onAlbumDelete,
- onHealthIssue,
- onHealthRestored,
- onDownloadFailure,
- onImportFailure,
- onTrackRetag,
- onApplicationUpdate,
- supportsOnGrab,
- supportsOnReleaseImport,
- supportsOnUpgrade,
- supportsOnRename,
- supportsOnArtistAdd,
- supportsOnArtistDelete,
- supportsOnAlbumDelete,
- supportsOnHealthIssue,
- supportsOnHealthRestored,
- includeHealthWarnings,
- supportsOnDownloadFailure,
- supportsOnImportFailure,
- supportsOnTrackRetag,
- supportsOnApplicationUpdate
- } = item;
-
- return (
-
-
- {translate('NotificationTriggers')}
-
-
-
-
-
-
-
-
-
-
-
-
- {
- onReleaseImport.value &&
-
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- (onHealthIssue.value || onHealthRestored.value) &&
-
-
-
- }
-
-
-
- );
-}
-
-NotificationEventItems.propTypes = {
- item: PropTypes.object.isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default NotificationEventItems;
diff --git a/frontend/src/Settings/Notifications/Notifications/Notifications.css b/frontend/src/Settings/Notifications/Notifications/Notifications.css
deleted file mode 100644
index 986226ad8..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notifications.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.notifications {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addNotification {
- composes: notification from '~./Notification.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/Notifications/Notifications/Notifications.css.d.ts b/frontend/src/Settings/Notifications/Notifications/Notifications.css.d.ts
deleted file mode 100644
index 2607f835d..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notifications.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addNotification': string;
- 'center': string;
- 'notifications': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Notifications/Notifications/Notifications.js b/frontend/src/Settings/Notifications/Notifications/Notifications.js
deleted file mode 100644
index 81b1b90b3..000000000
--- a/frontend/src/Settings/Notifications/Notifications/Notifications.js
+++ /dev/null
@@ -1,118 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import AddNotificationModal from './AddNotificationModal';
-import EditNotificationModalConnector from './EditNotificationModalConnector';
-import Notification from './Notification';
-import styles from './Notifications.css';
-
-class Notifications extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isAddNotificationModalOpen: false,
- isEditNotificationModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onAddNotificationPress = () => {
- this.setState({ isAddNotificationModalOpen: true });
- };
-
- onAddNotificationModalClose = ({ notificationSelected = false } = {}) => {
- this.setState({
- isAddNotificationModalOpen: false,
- isEditNotificationModalOpen: notificationSelected
- });
- };
-
- onEditNotificationModalClose = () => {
- this.setState({ isEditNotificationModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- items,
- tagList,
- onConfirmDeleteNotification,
- ...otherProps
- } = this.props;
-
- const {
- isAddNotificationModalOpen,
- isEditNotificationModalOpen
- } = this.state;
-
- return (
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-Notifications.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteNotification: PropTypes.func.isRequired
-};
-
-export default Notifications;
diff --git a/frontend/src/Settings/Notifications/Notifications/NotificationsConnector.js b/frontend/src/Settings/Notifications/Notifications/NotificationsConnector.js
deleted file mode 100644
index 6351c6f8a..000000000
--- a/frontend/src/Settings/Notifications/Notifications/NotificationsConnector.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { deleteNotification, fetchNotifications } from 'Store/Actions/settingsActions';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import createTagsSelector from 'Store/Selectors/createTagsSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import Notifications from './Notifications';
-
-function createMapStateToProps() {
- return createSelector(
- createSortedSectionSelector('settings.notifications', sortByProp('name')),
- createTagsSelector(),
- (notifications, tagList) => {
- return {
- ...notifications,
- tagList
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchNotifications,
- deleteNotification
-};
-
-class NotificationsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchNotifications();
- }
-
- //
- // Listeners
-
- onConfirmDeleteNotification = (id) => {
- this.props.deleteNotification({ id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-NotificationsConnector.propTypes = {
- fetchNotifications: PropTypes.func.isRequired,
- deleteNotification: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(NotificationsConnector);
diff --git a/frontend/src/Settings/PendingChangesModal.js b/frontend/src/Settings/PendingChangesModal.js
deleted file mode 100644
index 900022ca1..000000000
--- a/frontend/src/Settings/PendingChangesModal.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useEffect } from 'react';
-import keyboardShortcuts from 'Components/keyboardShortcuts';
-import Button from 'Components/Link/Button';
-import Modal from 'Components/Modal/Modal';
-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 { kinds } from 'Helpers/Props';
-
-function PendingChangesModal(props) {
- const {
- isOpen,
- onConfirm,
- onCancel,
- bindShortcut,
- unbindShortcut
- } = props;
-
- useEffect(() => {
- if (isOpen) {
- bindShortcut('enter', onConfirm);
-
- return () => unbindShortcut('enter', onConfirm);
- }
- }, [bindShortcut, unbindShortcut, isOpen, onConfirm]);
-
- return (
-
-
- Unsaved Changes
-
-
- You have unsaved changes, are you sure you want to leave this page?
-
-
-
-
- Stay and review changes
-
-
-
- Discard changes and leave
-
-
-
-
- );
-}
-
-PendingChangesModal.propTypes = {
- className: PropTypes.string,
- isOpen: PropTypes.bool.isRequired,
- kind: PropTypes.oneOf(kinds.all),
- onConfirm: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired,
- bindShortcut: PropTypes.func.isRequired,
- unbindShortcut: PropTypes.func.isRequired
-};
-
-PendingChangesModal.defaultProps = {
- kind: kinds.PRIMARY
-};
-
-export default keyboardShortcuts(PendingChangesModal);
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfile.css b/frontend/src/Settings/Profiles/Delay/DelayProfile.css
deleted file mode 100644
index e2d6cd199..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfile.css
+++ /dev/null
@@ -1,40 +0,0 @@
-.delayProfile {
- display: flex;
- align-items: stretch;
- margin-bottom: 10px;
- height: 30px;
- border-bottom: 1px solid var(--borderColor);
- line-height: 30px;
-}
-
-.column {
- flex: 0 0 200px;
-}
-
-.actions {
- display: flex;
-}
-
-.dragHandle {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- margin-left: auto;
- width: $dragHandleWidth;
- text-align: center;
- cursor: grab;
-}
-
-.dragIcon {
- top: 0;
-}
-
-.isDragging {
- opacity: 0.25;
-}
-
-.editButton {
- width: $dragHandleWidth;
- text-align: center;
-}
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfile.css.d.ts b/frontend/src/Settings/Profiles/Delay/DelayProfile.css.d.ts
deleted file mode 100644
index 4ec05c2d6..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfile.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'column': string;
- 'delayProfile': string;
- 'dragHandle': string;
- 'dragIcon': string;
- 'editButton': string;
- 'isDragging': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfile.js b/frontend/src/Settings/Profiles/Delay/DelayProfile.js
deleted file mode 100644
index ab646dd91..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfile.js
+++ /dev/null
@@ -1,173 +0,0 @@
-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 TagList from 'Components/TagList';
-import { icons, kinds } from 'Helpers/Props';
-import titleCase from 'Utilities/String/titleCase';
-import translate from 'Utilities/String/translate';
-import EditDelayProfileModalConnector from './EditDelayProfileModalConnector';
-import styles from './DelayProfile.css';
-
-function getDelay(enabled, delay) {
- if (!enabled) {
- return '-';
- }
-
- if (!delay) {
- return 'No Delay';
- }
-
- if (delay === 1) {
- return '1 Minute';
- }
-
- // TODO: use better units of time than just minutes
- return `${delay} Minutes`;
-}
-
-class DelayProfile extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditDelayProfileModalOpen: false,
- isDeleteDelayProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditDelayProfilePress = () => {
- this.setState({ isEditDelayProfileModalOpen: true });
- };
-
- onEditDelayProfileModalClose = () => {
- this.setState({ isEditDelayProfileModalOpen: false });
- };
-
- onDeleteDelayProfilePress = () => {
- this.setState({
- isEditDelayProfileModalOpen: false,
- isDeleteDelayProfileModalOpen: true
- });
- };
-
- onDeleteDelayProfileModalClose = () => {
- this.setState({ isDeleteDelayProfileModalOpen: false });
- };
-
- onConfirmDeleteDelayProfile = () => {
- this.props.onConfirmDeleteDelayProfile(this.props.id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- enableUsenet,
- enableTorrent,
- preferredProtocol,
- usenetDelay,
- torrentDelay,
- tags,
- tagList,
- isDragging,
- connectDragSource
- } = this.props;
-
- let preferred = titleCase(translate('PreferProtocol', { preferredProtocol }));
-
- if (!enableUsenet) {
- preferred = translate('OnlyTorrent');
- } else if (!enableTorrent) {
- preferred = translate('OnlyUsenet');
- }
-
- return (
-
-
{preferred}
-
{getDelay(enableUsenet, usenetDelay)}
-
{getDelay(enableTorrent, torrentDelay)}
-
-
-
-
-
-
-
-
- {
- id !== 1 &&
- connectDragSource(
-
-
-
- )
- }
-
-
-
-
-
-
- );
- }
-}
-
-DelayProfile.propTypes = {
- id: PropTypes.number.isRequired,
- enableUsenet: PropTypes.bool.isRequired,
- enableTorrent: PropTypes.bool.isRequired,
- preferredProtocol: PropTypes.string.isRequired,
- usenetDelay: PropTypes.number.isRequired,
- torrentDelay: PropTypes.number.isRequired,
- tags: PropTypes.arrayOf(PropTypes.number).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- isDragging: PropTypes.bool.isRequired,
- connectDragSource: PropTypes.func,
- onConfirmDeleteDelayProfile: PropTypes.func.isRequired
-};
-
-DelayProfile.defaultProps = {
- // The drag preview will not connect the drag handle.
- connectDragSource: (node) => node
-};
-
-export default DelayProfile;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css b/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css
deleted file mode 100644
index cc5a92830..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.dragPreview {
- opacity: 0.75;
-}
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css.d.ts b/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css.d.ts
deleted file mode 100644
index 1f1f3c320..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'dragPreview': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js b/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js
deleted file mode 100644
index 1ebb32a95..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragPreview.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { DragLayer } from 'react-dnd';
-import DragPreviewLayer from 'Components/DragPreviewLayer';
-import { DELAY_PROFILE } from 'Helpers/dragTypes';
-import dimensions from 'Styles/Variables/dimensions.js';
-import DelayProfile from './DelayProfile';
-import styles from './DelayProfileDragPreview.css';
-
-const dragHandleWidth = parseInt(dimensions.dragHandleWidth);
-
-function collectDragLayer(monitor) {
- return {
- item: monitor.getItem(),
- itemType: monitor.getItemType(),
- currentOffset: monitor.getSourceClientOffset()
- };
-}
-
-class DelayProfileDragPreview extends Component {
-
- //
- // Render
-
- render() {
- const {
- width,
- item,
- itemType,
- currentOffset
- } = this.props;
-
- if (!currentOffset || itemType !== DELAY_PROFILE) {
- return null;
- }
-
- // The offset is shifted because the drag handle is on the right edge of the
- // list item and the preview is wider than the drag handle.
-
- const { x, y } = currentOffset;
- const handleOffset = width - dragHandleWidth;
- const transform = `translate3d(${x - handleOffset}px, ${y}px, 0)`;
-
- const style = {
- width,
- position: 'absolute',
- WebkitTransform: transform,
- msTransform: transform,
- transform
- };
-
- return (
-
-
-
-
-
- );
- }
-}
-
-DelayProfileDragPreview.propTypes = {
- width: PropTypes.number.isRequired,
- item: PropTypes.object,
- itemType: PropTypes.string,
- currentOffset: PropTypes.shape({
- x: PropTypes.number.isRequired,
- y: PropTypes.number.isRequired
- })
-};
-
-export default DragLayer(collectDragLayer)(DelayProfileDragPreview);
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css b/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css
deleted file mode 100644
index 835250678..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.delayProfileDragSource {
- padding: 4px 0;
-}
-
-.delayProfilePlaceholder {
- width: 100%;
- height: 30px;
- border-bottom: 1px dotted #aaa;
-}
-
-.delayProfilePlaceholderBefore {
- margin-bottom: 8px;
-}
-
-.delayProfilePlaceholderAfter {
- margin-top: 8px;
-}
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css.d.ts b/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css.d.ts
deleted file mode 100644
index 0554ea7e8..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'delayProfileDragSource': string;
- 'delayProfilePlaceholder': string;
- 'delayProfilePlaceholderAfter': string;
- 'delayProfilePlaceholderBefore': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js b/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js
deleted file mode 100644
index 8bf739ceb..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfileDragSource.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { DragSource, DropTarget } from 'react-dnd';
-import { findDOMNode } from 'react-dom';
-import { DELAY_PROFILE } from 'Helpers/dragTypes';
-import DelayProfile from './DelayProfile';
-import styles from './DelayProfileDragSource.css';
-
-const delayProfileDragSource = {
- beginDrag(item) {
- return item;
- },
-
- endDrag(props, monitor, component) {
- props.onDelayProfileDragEnd(monitor.getItem(), monitor.didDrop());
- }
-};
-
-const delayProfileDropTarget = {
- hover(props, monitor, component) {
- const dragIndex = monitor.getItem().order;
- const hoverIndex = props.order;
-
- const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
- const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
- const clientOffset = monitor.getClientOffset();
- const hoverClientY = clientOffset.y - hoverBoundingRect.top;
-
- if (dragIndex === hoverIndex) {
- return;
- }
-
- // When moving up, only trigger if drag position is above 50% and
- // when moving down, only trigger if drag position is below 50%.
- // If we're moving down the hoverIndex needs to be increased
- // by one so it's ordered properly. Otherwise the hoverIndex will work.
-
- if (dragIndex < hoverIndex && hoverClientY > hoverMiddleY) {
- props.onDelayProfileDragMove(dragIndex, hoverIndex + 1);
- } else if (dragIndex > hoverIndex && hoverClientY < hoverMiddleY) {
- props.onDelayProfileDragMove(dragIndex, hoverIndex);
- }
- }
-};
-
-function collectDragSource(connect, monitor) {
- return {
- connectDragSource: connect.dragSource(),
- isDragging: monitor.isDragging()
- };
-}
-
-function collectDropTarget(connect, monitor) {
- return {
- connectDropTarget: connect.dropTarget(),
- isOver: monitor.isOver()
- };
-}
-
-class DelayProfileDragSource extends Component {
-
- //
- // Render
-
- render() {
- const {
- id,
- order,
- isDragging,
- isDraggingUp,
- isDraggingDown,
- isOver,
- connectDragSource,
- connectDropTarget,
- ...otherProps
- } = this.props;
-
- const isBefore = !isDragging && isDraggingUp && isOver;
- const isAfter = !isDragging && isDraggingDown && isOver;
-
- // if (isDragging && !isOver) {
- // return null;
- // }
-
- return connectDropTarget(
-
- {
- isBefore &&
-
- }
-
-
-
- {
- isAfter &&
-
- }
-
- );
- }
-}
-
-DelayProfileDragSource.propTypes = {
- id: PropTypes.number.isRequired,
- order: PropTypes.number.isRequired,
- isDragging: PropTypes.bool,
- isDraggingUp: PropTypes.bool,
- isDraggingDown: PropTypes.bool,
- isOver: PropTypes.bool,
- connectDragSource: PropTypes.func,
- connectDropTarget: PropTypes.func,
- onDelayProfileDragMove: PropTypes.func.isRequired,
- onDelayProfileDragEnd: PropTypes.func.isRequired
-};
-
-export default DropTarget(
- DELAY_PROFILE,
- delayProfileDropTarget,
- collectDropTarget
-)(DragSource(
- DELAY_PROFILE,
- delayProfileDragSource,
- collectDragSource
-)(DelayProfileDragSource));
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css b/frontend/src/Settings/Profiles/Delay/DelayProfiles.css
deleted file mode 100644
index efc0b14fa..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.horizontalScroll {
- overflow-x: auto;
-}
-
-.delayProfiles {
- user-select: none;
-}
-
-.delayProfilesHeader {
- display: flex;
- margin-bottom: 10px;
- font-weight: bold;
-}
-
-.column {
- flex: 0 0 200px;
-}
-
-.tags {
- flex: 1 0 auto;
-}
-
-.addDelayProfile {
- display: flex;
- justify-content: flex-end;
-}
-
-.addButton {
- width: $dragHandleWidth;
- text-align: center;
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .horizontalScroll {
- overflow-y: hidden;
- width: 100%;
- }
-}
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css.d.ts b/frontend/src/Settings/Profiles/Delay/DelayProfiles.css.d.ts
deleted file mode 100644
index 3b7f0ee69..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfiles.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addButton': string;
- 'addDelayProfile': string;
- 'column': string;
- 'delayProfiles': string;
- 'delayProfilesHeader': string;
- 'horizontalScroll': string;
- 'tags': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfiles.js b/frontend/src/Settings/Profiles/Delay/DelayProfiles.js
deleted file mode 100644
index 83ac09bf8..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfiles.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import Link from 'Components/Link/Link';
-import Measure from 'Components/Measure';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import Scroller from 'Components/Scroller/Scroller';
-import { icons, scrollDirections } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import DelayProfile from './DelayProfile';
-import DelayProfileDragPreview from './DelayProfileDragPreview';
-import DelayProfileDragSource from './DelayProfileDragSource';
-import EditDelayProfileModalConnector from './EditDelayProfileModalConnector';
-import styles from './DelayProfiles.css';
-
-class DelayProfiles extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isAddDelayProfileModalOpen: false,
- width: 0
- };
- }
-
- //
- // Listeners
-
- onAddDelayProfilePress = () => {
- this.setState({ isAddDelayProfileModalOpen: true });
- };
-
- onModalClose = () => {
- this.setState({ isAddDelayProfileModalOpen: false });
- };
-
- onMeasure = ({ width }) => {
- this.setState({ width });
- };
-
- //
- // Render
-
- render() {
- const {
- defaultProfile,
- items,
- tagList,
- dragIndex,
- dropIndex,
- onConfirmDeleteDelayProfile,
- ...otherProps
- } = this.props;
-
- const {
- isAddDelayProfileModalOpen,
- width
- } = this.state;
-
- const isDragging = dropIndex !== null;
- const isDraggingUp = isDragging && dropIndex < dragIndex;
- const isDraggingDown = isDragging && dropIndex > dragIndex;
-
- return (
-
-
-
-
-
-
-
- {translate('PreferredProtocol')}
-
-
- {translate('UsenetDelay')}
-
-
- {translate('TorrentDelay')}
-
-
- {translate('Tags')}
-
-
-
-
- {
- items.map((item, index) => {
- return (
-
- );
- })
- }
-
-
-
-
- {
- defaultProfile ?
-
-
-
:
- null
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-DelayProfiles.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- defaultProfile: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- dragIndex: PropTypes.number,
- dropIndex: PropTypes.number,
- onConfirmDeleteDelayProfile: PropTypes.func.isRequired
-};
-
-export default DelayProfiles;
diff --git a/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js b/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js
deleted file mode 100644
index b2f822a5a..000000000
--- a/frontend/src/Settings/Profiles/Delay/DelayProfilesConnector.js
+++ /dev/null
@@ -1,105 +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 { deleteDelayProfile, fetchDelayProfiles, reorderDelayProfile } from 'Store/Actions/settingsActions';
-import createTagsSelector from 'Store/Selectors/createTagsSelector';
-import DelayProfiles from './DelayProfiles';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.delayProfiles,
- createTagsSelector(),
- (delayProfiles, tagList) => {
- const defaultProfile = _.find(delayProfiles.items, { id: 1 });
- const items = _.sortBy(_.reject(delayProfiles.items, { id: 1 }), ['order']);
-
- return {
- defaultProfile,
- ...delayProfiles,
- items,
- tagList
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchDelayProfiles,
- deleteDelayProfile,
- reorderDelayProfile
-};
-
-class DelayProfilesConnector extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- dragIndex: null,
- dropIndex: null
- };
- }
-
- componentDidMount() {
- this.props.fetchDelayProfiles();
- }
-
- //
- // Listeners
-
- onConfirmDeleteDelayProfile = (id) => {
- this.props.deleteDelayProfile({ id });
- };
-
- onDelayProfileDragMove = (dragIndex, dropIndex) => {
- if (this.state.dragIndex !== dragIndex || this.state.dropIndex !== dropIndex) {
- this.setState({
- dragIndex,
- dropIndex
- });
- }
- };
-
- onDelayProfileDragEnd = ({ id }, didDrop) => {
- const {
- dropIndex
- } = this.state;
-
- if (didDrop && dropIndex !== null) {
- this.props.reorderDelayProfile({ id, moveIndex: dropIndex - 1 });
- }
-
- this.setState({
- dragIndex: null,
- dropIndex: null
- });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-DelayProfilesConnector.propTypes = {
- fetchDelayProfiles: PropTypes.func.isRequired,
- deleteDelayProfile: PropTypes.func.isRequired,
- reorderDelayProfile: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(DelayProfilesConnector);
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js
deleted file mode 100644
index ddcd8cf7f..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditDelayProfileModalContentConnector from './EditDelayProfileModalContentConnector';
-
-function EditDelayProfileModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditDelayProfileModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditDelayProfileModal;
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js
deleted file mode 100644
index 5eb8ce871..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalConnector.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditDelayProfileModal from './EditDelayProfileModal';
-
-function mapStateToProps() {
- return {};
-}
-
-const mapDispatchToProps = {
- clearPendingChanges
-};
-
-class EditDelayProfileModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.clearPendingChanges({ section: 'settings.delayProfiles' });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditDelayProfileModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(EditDelayProfileModalConnector);
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css
deleted file mode 100644
index a2b6014df..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css.d.ts b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css.d.ts
deleted file mode 100644
index c5f0ef8a7..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js
deleted file mode 100644
index 0d1225a93..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContent.js
+++ /dev/null
@@ -1,266 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import { boolSettingShape, numberSettingShape, tagSettingShape } from 'Helpers/Props/Shapes/settingShape';
-import translate from 'Utilities/String/translate';
-import styles from './EditDelayProfileModalContent.css';
-
-const protocolOptions = [
- {
- key: 'preferUsenet',
- get value() {
- return translate('PreferUsenet');
- }
- },
- {
- key: 'preferTorrent',
- get value() {
- return translate('PreferTorrent');
- }
- },
- {
- key: 'onlyUsenet',
- get value() {
- return translate('OnlyUsenet');
- }
- },
- {
- key: 'onlyTorrent',
- get value() {
- return translate('OnlyTorrent');
- }
- }
-];
-
-function EditDelayProfileModalContent(props) {
- const {
- id,
- isFetching,
- error,
- isSaving,
- saveError,
- item,
- protocol,
- onInputChange,
- onProtocolChange,
- onSavePress,
- onModalClose,
- onDeleteDelayProfilePress,
- ...otherProps
- } = props;
-
- const {
- enableUsenet,
- enableTorrent,
- usenetDelay,
- torrentDelay,
- bypassIfHighestQuality,
- bypassIfAboveCustomFormatScore,
- minimumCustomFormatScore,
- tags
- } = item;
-
- return (
-
-
- {id ? translate('EditDelayProfile') : translate('AddDelayProfile')}
-
-
-
- {
- isFetching ?
- :
- null
- }
-
- {
- !isFetching && !!error ?
-
- {translate('AddDelayProfileError')}
- :
- null
- }
-
- {
- !isFetching && !error ?
- :
- null
- }
-
-
- {
- id && id > 1 ?
-
- {translate('Delete')}
- :
- null
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-const delayProfileShape = {
- enableUsenet: PropTypes.shape(boolSettingShape).isRequired,
- enableTorrent: PropTypes.shape(boolSettingShape).isRequired,
- usenetDelay: PropTypes.shape(numberSettingShape).isRequired,
- torrentDelay: PropTypes.shape(numberSettingShape).isRequired,
- bypassIfHighestQuality: PropTypes.shape(boolSettingShape).isRequired,
- bypassIfAboveCustomFormatScore: PropTypes.shape(boolSettingShape).isRequired,
- minimumCustomFormatScore: PropTypes.shape(numberSettingShape).isRequired,
- order: PropTypes.shape(numberSettingShape),
- tags: PropTypes.shape(tagSettingShape).isRequired
-};
-
-EditDelayProfileModalContent.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.shape(delayProfileShape).isRequired,
- protocol: PropTypes.string.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onProtocolChange: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onDeleteDelayProfilePress: PropTypes.func
-};
-
-export default EditDelayProfileModalContent;
diff --git a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js
deleted file mode 100644
index a1e3d85a1..000000000
--- a/frontend/src/Settings/Profiles/Delay/EditDelayProfileModalContentConnector.js
+++ /dev/null
@@ -1,173 +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 { saveDelayProfile, setDelayProfileValue } from 'Store/Actions/settingsActions';
-import selectSettings from 'Store/Selectors/selectSettings';
-import EditDelayProfileModalContent from './EditDelayProfileModalContent';
-
-const newDelayProfile = {
- enableUsenet: true,
- enableTorrent: true,
- preferredProtocol: 'usenet',
- usenetDelay: 0,
- torrentDelay: 0,
- bypassIfHighestQuality: false,
- bypassIfAboveCustomFormatScore: false,
- minimumCustomFormatScore: 0,
- tags: []
-};
-
-function createDelayProfileSelector() {
- return createSelector(
- (state, { id }) => id,
- (state) => state.settings.delayProfiles,
- (id, delayProfiles) => {
- const {
- isFetching,
- error,
- isSaving,
- saveError,
- pendingChanges,
- items
- } = delayProfiles;
-
- const profile = id ? _.find(items, { id }) : newDelayProfile;
- const settings = selectSettings(profile, pendingChanges, saveError);
-
- return {
- id,
- isFetching,
- error,
- isSaving,
- saveError,
- item: settings.settings,
- ...settings
- };
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- createDelayProfileSelector(),
- (delayProfile) => {
- const enableUsenet = delayProfile.item.enableUsenet.value;
- const enableTorrent = delayProfile.item.enableTorrent.value;
- const preferredProtocol = delayProfile.item.preferredProtocol.value;
- let protocol = 'preferUsenet';
-
- if (preferredProtocol === 'usenet') {
- protocol = 'preferUsenet';
- } else {
- protocol = 'preferTorrent';
- }
-
- if (!enableUsenet) {
- protocol = 'onlyTorrent';
- }
-
- if (!enableTorrent) {
- protocol = 'onlyUsenet';
- }
-
- return {
- protocol,
- ...delayProfile
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setDelayProfileValue,
- saveDelayProfile
-};
-
-class EditDelayProfileModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- if (!this.props.id) {
- Object.keys(newDelayProfile).forEach((name) => {
- this.props.setDelayProfileValue({
- name,
- value: newDelayProfile[name]
- });
- });
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setDelayProfileValue({ name, value });
- };
-
- onProtocolChange = ({ value }) => {
- switch (value) {
- case 'preferUsenet':
- this.props.setDelayProfileValue({ name: 'enableUsenet', value: true });
- this.props.setDelayProfileValue({ name: 'enableTorrent', value: true });
- this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'usenet' });
- break;
- case 'preferTorrent':
- this.props.setDelayProfileValue({ name: 'enableUsenet', value: true });
- this.props.setDelayProfileValue({ name: 'enableTorrent', value: true });
- this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'torrent' });
- break;
- case 'onlyUsenet':
- this.props.setDelayProfileValue({ name: 'enableUsenet', value: true });
- this.props.setDelayProfileValue({ name: 'enableTorrent', value: false });
- this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'usenet' });
- break;
- case 'onlyTorrent':
- this.props.setDelayProfileValue({ name: 'enableUsenet', value: false });
- this.props.setDelayProfileValue({ name: 'enableTorrent', value: true });
- this.props.setDelayProfileValue({ name: 'preferredProtocol', value: 'torrent' });
- break;
- default:
- throw Error(`Unknown protocol option: ${value}`);
- }
- };
-
- onSavePress = () => {
- this.props.saveDelayProfile({ id: this.props.id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditDelayProfileModalContentConnector.propTypes = {
- id: PropTypes.number,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setDelayProfileValue: PropTypes.func.isRequired,
- saveDelayProfile: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditDelayProfileModalContentConnector);
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModal.js b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModal.js
deleted file mode 100644
index b167ae60b..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditMetadataProfileModalContentConnector from './EditMetadataProfileModalContentConnector';
-
-function EditMetadataProfileModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditMetadataProfileModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditMetadataProfileModal;
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalConnector.js b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalConnector.js
deleted file mode 100644
index cece2c82c..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalConnector.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditMetadataProfileModal from './EditMetadataProfileModal';
-
-function mapStateToProps() {
- return {};
-}
-
-const mapDispatchToProps = {
- clearPendingChanges
-};
-
-class EditMetadataProfileModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.clearPendingChanges({ section: 'settings.metadataProfiles' });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditMetadataProfileModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(EditMetadataProfileModalConnector);
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css
deleted file mode 100644
index 74dd1c8b7..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.deleteButtonContainer {
- margin-right: auto;
-}
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css.d.ts b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css.d.ts
deleted file mode 100644
index 24232a842..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButtonContainer': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.js b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.js
deleted file mode 100644
index c6b9c4464..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContent.js
+++ /dev/null
@@ -1,159 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import PrimaryTypeItems from './PrimaryTypeItems';
-import ReleaseStatusItems from './ReleaseStatusItems';
-import SecondaryTypeItems from './SecondaryTypeItems';
-import styles from './EditMetadataProfileModalContent.css';
-
-function EditMetadataProfileModalContent(props) {
- const {
- isFetching,
- error,
- isSaving,
- saveError,
- primaryAlbumTypes,
- secondaryAlbumTypes,
- item,
- isInUse,
- onInputChange,
- onSavePress,
- onModalClose,
- onDeleteMetadataProfilePress,
- ...otherProps
- } = props;
-
- const {
- id,
- name,
- primaryAlbumTypes: itemPrimaryAlbumTypes,
- secondaryAlbumTypes: itemSecondaryAlbumTypes,
- releaseStatuses: itemReleaseStatuses
- } = item;
-
- return (
-
-
- {id ? translate('EditMetadataProfile') : translate('AddMetadataProfile')}
-
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && !!error &&
-
- {translate('UnableToAddANewMetadataProfilePleaseTryAgain')}
-
- }
-
- {
- !isFetching && !error &&
-
- }
-
-
- {
- id &&
-
-
- {translate('Delete')}
-
-
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditMetadataProfileModalContent.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- primaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
- secondaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
- releaseStatuses: PropTypes.arrayOf(PropTypes.object).isRequired,
- item: PropTypes.object.isRequired,
- isInUse: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onDeleteMetadataProfilePress: PropTypes.func
-};
-
-export default EditMetadataProfileModalContent;
diff --git a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContentConnector.js
deleted file mode 100644
index ae9c8f4ce..000000000
--- a/frontend/src/Settings/Profiles/Metadata/EditMetadataProfileModalContentConnector.js
+++ /dev/null
@@ -1,213 +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 { fetchMetadataProfileSchema, saveMetadataProfile, setMetadataProfileValue } from 'Store/Actions/settingsActions';
-import createProfileInUseSelector from 'Store/Selectors/createProfileInUseSelector';
-import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
-import EditMetadataProfileModalContent from './EditMetadataProfileModalContent';
-
-function createPrimaryAlbumTypesSelector() {
- return createSelector(
- createProviderSettingsSelector('metadataProfiles'),
- (metadataProfile) => {
- const primaryAlbumTypes = metadataProfile.item.primaryAlbumTypes;
- if (!primaryAlbumTypes || !primaryAlbumTypes.value) {
- return [];
- }
-
- return _.reduceRight(primaryAlbumTypes.value, (result, { allowed, albumType }) => {
- if (allowed) {
- result.push({
- key: albumType.id,
- value: albumType.name
- });
- }
-
- return result;
- }, []);
- }
- );
-}
-
-function createSecondaryAlbumTypesSelector() {
- return createSelector(
- createProviderSettingsSelector('metadataProfiles'),
- (metadataProfile) => {
- const secondaryAlbumTypes = metadataProfile.item.secondaryAlbumTypes;
- if (!secondaryAlbumTypes || !secondaryAlbumTypes.value) {
- return [];
- }
-
- return _.reduceRight(secondaryAlbumTypes.value, (result, { allowed, albumType }) => {
- if (allowed) {
- result.push({
- key: albumType.id,
- value: albumType.name
- });
- }
-
- return result;
- }, []);
- }
- );
-}
-
-function createReleaseStatusesSelector() {
- return createSelector(
- createProviderSettingsSelector('metadataProfiles'),
- (metadataProfile) => {
- const releaseStatuses = metadataProfile.item.releaseStatuses;
- if (!releaseStatuses || !releaseStatuses.value) {
- return [];
- }
-
- return _.reduceRight(releaseStatuses.value, (result, { allowed, releaseStatus }) => {
- if (allowed) {
- result.push({
- key: releaseStatus.id,
- value: releaseStatus.name
- });
- }
-
- return result;
- }, []);
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- createProviderSettingsSelector('metadataProfiles'),
- createPrimaryAlbumTypesSelector(),
- createSecondaryAlbumTypesSelector(),
- createReleaseStatusesSelector(),
- createProfileInUseSelector('metadataProfileId'),
- (metadataProfile, primaryAlbumTypes, secondaryAlbumTypes, releaseStatuses, isInUse) => {
- return {
- primaryAlbumTypes,
- secondaryAlbumTypes,
- releaseStatuses,
- ...metadataProfile,
- isInUse
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchMetadataProfileSchema,
- setMetadataProfileValue,
- saveMetadataProfile
-};
-
-class EditMetadataProfileModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- dragIndex: null,
- dropIndex: null
- };
- }
-
- componentDidMount() {
- if (!this.props.id && !this.props.isPopulated) {
- this.props.fetchMetadataProfileSchema();
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setMetadataProfileValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveMetadataProfile({ id: this.props.id });
- };
-
- onMetadataPrimaryTypeItemAllowedChange = (id, allowed) => {
- const metadataProfile = _.cloneDeep(this.props.item);
-
- const item = _.find(metadataProfile.primaryAlbumTypes.value, (i) => i.albumType.id === id);
- item.allowed = allowed;
-
- this.props.setMetadataProfileValue({
- name: 'primaryAlbumTypes',
- value: metadataProfile.primaryAlbumTypes.value
- });
- };
-
- onMetadataSecondaryTypeItemAllowedChange = (id, allowed) => {
- const metadataProfile = _.cloneDeep(this.props.item);
-
- const item = _.find(metadataProfile.secondaryAlbumTypes.value, (i) => i.albumType.id === id);
- item.allowed = allowed;
-
- this.props.setMetadataProfileValue({
- name: 'secondaryAlbumTypes',
- value: metadataProfile.secondaryAlbumTypes.value
- });
- };
-
- onMetadataReleaseStatusItemAllowedChange = (id, allowed) => {
- const metadataProfile = _.cloneDeep(this.props.item);
-
- const item = _.find(metadataProfile.releaseStatuses.value, (i) => i.releaseStatus.id === id);
- item.allowed = allowed;
-
- this.props.setMetadataProfileValue({
- name: 'releaseStatuses',
- value: metadataProfile.releaseStatuses.value
- });
- };
-
- //
- // Render
-
- render() {
- if (_.isEmpty(this.props.item.primaryAlbumTypes) && !this.props.isFetching) {
- return null;
- }
-
- return (
-
- );
- }
-}
-
-EditMetadataProfileModalContentConnector.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setMetadataProfileValue: PropTypes.func.isRequired,
- fetchMetadataProfileSchema: PropTypes.func.isRequired,
- saveMetadataProfile: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditMetadataProfileModalContentConnector);
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css b/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css
deleted file mode 100644
index 880788343..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css
+++ /dev/null
@@ -1,31 +0,0 @@
-.metadataProfile {
- composes: card from '~Components/Card.css';
-
- width: 300px;
-}
-
-.nameContainer {
- display: flex;
- justify-content: space-between;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.cloneButton {
- composes: button from '~Components/Link/IconButton.css';
-
- height: 36px;
-}
-
-.albumTypes {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
- pointer-events: all;
-}
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css.d.ts b/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css.d.ts
deleted file mode 100644
index 6d3f21d57..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'albumTypes': string;
- 'cloneButton': string;
- 'metadataProfile': string;
- 'name': string;
- 'nameContainer': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.js b/frontend/src/Settings/Profiles/Metadata/MetadataProfile.js
deleted file mode 100644
index c3cfefa1d..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfile.js
+++ /dev/null
@@ -1,165 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditMetadataProfileModalConnector from './EditMetadataProfileModalConnector';
-import styles from './MetadataProfile.css';
-
-class MetadataProfile extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditMetadataProfileModalOpen: false,
- isDeleteMetadataProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditMetadataProfilePress = () => {
- this.setState({ isEditMetadataProfileModalOpen: true });
- };
-
- onEditMetadataProfileModalClose = () => {
- this.setState({ isEditMetadataProfileModalOpen: false });
- };
-
- onDeleteMetadataProfilePress = () => {
- this.setState({
- isEditMetadataProfileModalOpen: false,
- isDeleteMetadataProfileModalOpen: true
- });
- };
-
- onDeleteMetadataProfileModalClose = () => {
- this.setState({ isDeleteMetadataProfileModalOpen: false });
- };
-
- onConfirmDeleteMetadataProfile = () => {
- this.props.onConfirmDeleteMetadataProfile(this.props.id);
- };
-
- onCloneMetadataProfilePress = () => {
- const {
- id,
- onCloneMetadataProfilePress
- } = this.props;
-
- onCloneMetadataProfilePress(id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- primaryAlbumTypes,
- secondaryAlbumTypes,
- isDeleting
- } = this.props;
-
- return (
-
-
-
-
- {
- primaryAlbumTypes.map((item) => {
- if (!item.allowed) {
- return null;
- }
-
- return (
-
- {item.albumType.name}
-
- );
- })
- }
-
-
-
- {
- secondaryAlbumTypes.map((item) => {
- if (!item.allowed) {
- return null;
- }
-
- return (
-
- {item.albumType.name}
-
- );
- })
- }
-
-
-
-
-
-
- );
- }
-}
-
-MetadataProfile.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- primaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
- secondaryAlbumTypes: PropTypes.arrayOf(PropTypes.object).isRequired,
- isDeleting: PropTypes.bool.isRequired,
- onConfirmDeleteMetadataProfile: PropTypes.func.isRequired,
- onCloneMetadataProfilePress: PropTypes.func.isRequired
-
-};
-
-export default MetadataProfile;
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css b/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css
deleted file mode 100644
index f5b69a80e..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css
+++ /dev/null
@@ -1,21 +0,0 @@
-.metadataProfiles {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addMetadataProfile {
- composes: metadataProfile from '~./MetadataProfile.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
- font-size: 45px;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css.d.ts b/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css.d.ts
deleted file mode 100644
index c9469d5f3..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addMetadataProfile': string;
- 'center': string;
- 'metadataProfiles': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.js b/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.js
deleted file mode 100644
index 5e719517f..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfiles.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons, metadataProfileNames } from 'Helpers/Props';
-import sortByProp from 'Utilities/Array/sortByProp';
-import translate from 'Utilities/String/translate';
-import EditMetadataProfileModalConnector from './EditMetadataProfileModalConnector';
-import MetadataProfile from './MetadataProfile';
-import styles from './MetadataProfiles.css';
-
-class MetadataProfiles extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isMetadataProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onCloneMetadataProfilePress = (id) => {
- this.props.onCloneMetadataProfilePress(id);
- this.setState({ isMetadataProfileModalOpen: true });
- };
-
- onEditMetadataProfilePress = () => {
- this.setState({ isMetadataProfileModalOpen: true });
- };
-
- onModalClose = () => {
- this.setState({ isMetadataProfileModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- items,
- isDeleting,
- onConfirmDeleteMetadataProfile,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
- {
- items
- .filter((item) => item.name !== metadataProfileNames.NONE)
- .sort(sortByProp('name'))
- .map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-MetadataProfiles.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- isDeleting: PropTypes.bool.isRequired,
- onConfirmDeleteMetadataProfile: PropTypes.func.isRequired,
- onCloneMetadataProfilePress: PropTypes.func.isRequired
-};
-
-export default MetadataProfiles;
diff --git a/frontend/src/Settings/Profiles/Metadata/MetadataProfilesConnector.js b/frontend/src/Settings/Profiles/Metadata/MetadataProfilesConnector.js
deleted file mode 100644
index b4c8c2037..000000000
--- a/frontend/src/Settings/Profiles/Metadata/MetadataProfilesConnector.js
+++ /dev/null
@@ -1,67 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { cloneMetadataProfile, deleteMetadataProfile, fetchMetadataProfiles } from 'Store/Actions/settingsActions';
-import MetadataProfiles from './MetadataProfiles';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- (state) => state.settings.metadataProfiles,
- (advancedSettings, metadataProfiles) => {
- return {
- advancedSettings,
- ...metadataProfiles
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchMetadataProfiles: fetchMetadataProfiles,
- dispatchDeleteMetadataProfile: deleteMetadataProfile,
- dispatchCloneMetadataProfile: cloneMetadataProfile
-};
-
-class MetadataProfilesConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchMetadataProfiles();
- }
-
- //
- // Listeners
-
- onConfirmDeleteMetadataProfile = (id) => {
- this.props.dispatchDeleteMetadataProfile({ id });
- };
-
- onCloneMetadataProfilePress = (id) => {
- this.props.dispatchCloneMetadataProfile({ id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MetadataProfilesConnector.propTypes = {
- dispatchFetchMetadataProfiles: PropTypes.func.isRequired,
- dispatchDeleteMetadataProfile: PropTypes.func.isRequired,
- dispatchCloneMetadataProfile: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MetadataProfilesConnector);
diff --git a/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItem.js b/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItem.js
deleted file mode 100644
index 551eb999c..000000000
--- a/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItem.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import CheckInput from 'Components/Form/CheckInput';
-import styles from './TypeItem.css';
-
-class PrimaryTypeItem extends Component {
-
- //
- // Listeners
-
- onAllowedChange = ({ value }) => {
- const {
- albumTypeId,
- onMetadataPrimaryTypeItemAllowedChange
- } = this.props;
-
- onMetadataPrimaryTypeItemAllowedChange(albumTypeId, value);
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- allowed
- } = this.props;
-
- return (
-
-
-
- {name}
-
-
- );
- }
-}
-
-PrimaryTypeItem.propTypes = {
- albumTypeId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- sortIndex: PropTypes.number.isRequired,
- onMetadataPrimaryTypeItemAllowedChange: PropTypes.func
-};
-
-export default PrimaryTypeItem;
diff --git a/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItems.js b/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItems.js
deleted file mode 100644
index e70b831b3..000000000
--- a/frontend/src/Settings/Profiles/Metadata/PrimaryTypeItems.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import translate from 'Utilities/String/translate';
-import PrimaryTypeItem from './PrimaryTypeItem';
-import styles from './TypeItems.css';
-
-class PrimaryTypeItems extends Component {
-
- //
- // Render
-
- render() {
- const {
- metadataProfileItems,
- errors,
- warnings,
- ...otherProps
- } = this.props;
-
- return (
-
-
- {translate('PrimaryTypes')}
-
-
-
- {
- errors.map((error, index) => {
- return (
-
- );
- })
- }
-
- {
- warnings.map((warning, index) => {
- return (
-
- );
- })
- }
-
-
- {
- metadataProfileItems.map(({ allowed, albumType }, index) => {
- return (
-
- );
- }).reverse()
- }
-
-
-
- );
- }
-}
-
-PrimaryTypeItems.propTypes = {
- metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
- errors: PropTypes.arrayOf(PropTypes.object),
- warnings: PropTypes.arrayOf(PropTypes.object),
- formLabel: PropTypes.string
-};
-
-PrimaryTypeItems.defaultProps = {
- errors: [],
- warnings: []
-};
-
-export default PrimaryTypeItems;
diff --git a/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItem.js b/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItem.js
deleted file mode 100644
index a80c72f6a..000000000
--- a/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItem.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import CheckInput from 'Components/Form/CheckInput';
-import styles from './TypeItem.css';
-
-class ReleaseStatusItem extends Component {
-
- //
- // Listeners
-
- onAllowedChange = ({ value }) => {
- const {
- albumTypeId,
- onMetadataReleaseStatusItemAllowedChange
- } = this.props;
-
- onMetadataReleaseStatusItemAllowedChange(albumTypeId, value);
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- allowed
- } = this.props;
-
- return (
-
-
-
- {name}
-
-
- );
- }
-}
-
-ReleaseStatusItem.propTypes = {
- albumTypeId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- sortIndex: PropTypes.number.isRequired,
- onMetadataReleaseStatusItemAllowedChange: PropTypes.func
-};
-
-export default ReleaseStatusItem;
diff --git a/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItems.js b/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItems.js
deleted file mode 100644
index 8fbea3499..000000000
--- a/frontend/src/Settings/Profiles/Metadata/ReleaseStatusItems.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import translate from 'Utilities/String/translate';
-import ReleaseStatusItem from './ReleaseStatusItem';
-import styles from './TypeItems.css';
-
-class ReleaseStatusItems extends Component {
-
- //
- // Render
-
- render() {
- const {
- metadataProfileItems,
- errors,
- warnings,
- ...otherProps
- } = this.props;
-
- return (
-
-
- {translate('ReleaseStatuses')}
-
-
-
- {
- errors.map((error, index) => {
- return (
-
- );
- })
- }
-
- {
- warnings.map((warning, index) => {
- return (
-
- );
- })
- }
-
-
- {
- metadataProfileItems.map(({ allowed, releaseStatus }, index) => {
- return (
-
- );
- })
- }
-
-
-
- );
- }
-}
-
-ReleaseStatusItems.propTypes = {
- metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
- errors: PropTypes.arrayOf(PropTypes.object),
- warnings: PropTypes.arrayOf(PropTypes.object),
- formLabel: PropTypes.string
-};
-
-ReleaseStatusItems.defaultProps = {
- errors: [],
- warnings: []
-};
-
-export default ReleaseStatusItems;
diff --git a/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItem.js b/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItem.js
deleted file mode 100644
index 52fdd0192..000000000
--- a/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItem.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import CheckInput from 'Components/Form/CheckInput';
-import styles from './TypeItem.css';
-
-class SecondaryTypeItem extends Component {
-
- //
- // Listeners
-
- onAllowedChange = ({ value }) => {
- const {
- albumTypeId,
- onMetadataSecondaryTypeItemAllowedChange
- } = this.props;
-
- onMetadataSecondaryTypeItemAllowedChange(albumTypeId, value);
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- allowed
- } = this.props;
-
- return (
-
-
-
- {name}
-
-
- );
- }
-}
-
-SecondaryTypeItem.propTypes = {
- albumTypeId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- sortIndex: PropTypes.number.isRequired,
- onMetadataSecondaryTypeItemAllowedChange: PropTypes.func
-};
-
-export default SecondaryTypeItem;
diff --git a/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItems.js b/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItems.js
deleted file mode 100644
index 24ca76cf3..000000000
--- a/frontend/src/Settings/Profiles/Metadata/SecondaryTypeItems.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import translate from 'Utilities/String/translate';
-import SecondaryTypeItem from './SecondaryTypeItem';
-import styles from './TypeItems.css';
-
-class SecondaryTypeItems extends Component {
-
- //
- // Render
-
- render() {
- const {
- metadataProfileItems,
- errors,
- warnings,
- ...otherProps
- } = this.props;
-
- return (
-
-
- {translate('SecondaryTypes')}
-
-
-
- {
- errors.map((error, index) => {
- return (
-
- );
- })
- }
-
- {
- warnings.map((warning, index) => {
- return (
-
- );
- })
- }
-
-
- {
- metadataProfileItems.map(({ allowed, albumType }, index) => {
- return (
-
- );
- })
- }
-
-
-
- );
- }
-}
-
-SecondaryTypeItems.propTypes = {
- metadataProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
- errors: PropTypes.arrayOf(PropTypes.object),
- warnings: PropTypes.arrayOf(PropTypes.object),
- formLabel: PropTypes.string
-};
-
-SecondaryTypeItems.defaultProps = {
- errors: [],
- warnings: []
-};
-
-export default SecondaryTypeItems;
diff --git a/frontend/src/Settings/Profiles/Metadata/TypeItem.css b/frontend/src/Settings/Profiles/Metadata/TypeItem.css
deleted file mode 100644
index 908f3bde6..000000000
--- a/frontend/src/Settings/Profiles/Metadata/TypeItem.css
+++ /dev/null
@@ -1,25 +0,0 @@
-.metadataProfileItem {
- display: flex;
- align-items: stretch;
- width: 100%;
-}
-
-.checkContainer {
- position: relative;
- margin-right: 4px;
- margin-bottom: 7px;
- margin-left: 8px;
-}
-
-.albumTypeName {
- display: flex;
- flex-grow: 1;
- margin-bottom: 0;
- margin-left: 2px;
- font-weight: normal;
- line-height: 36px;
-}
-
-.isDragging {
- opacity: 0.25;
-}
diff --git a/frontend/src/Settings/Profiles/Metadata/TypeItem.css.d.ts b/frontend/src/Settings/Profiles/Metadata/TypeItem.css.d.ts
deleted file mode 100644
index 618c15cee..000000000
--- a/frontend/src/Settings/Profiles/Metadata/TypeItem.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'albumTypeName': string;
- 'checkContainer': string;
- 'isDragging': string;
- 'metadataProfileItem': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Metadata/TypeItems.css b/frontend/src/Settings/Profiles/Metadata/TypeItems.css
deleted file mode 100644
index 3bce22799..000000000
--- a/frontend/src/Settings/Profiles/Metadata/TypeItems.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.albumTypes {
- margin-top: 10px;
- /* TODO: This should consider the number of types in the list */
- min-height: 200px;
- user-select: none;
-}
diff --git a/frontend/src/Settings/Profiles/Metadata/TypeItems.css.d.ts b/frontend/src/Settings/Profiles/Metadata/TypeItems.css.d.ts
deleted file mode 100644
index 5ab3f9ea1..000000000
--- a/frontend/src/Settings/Profiles/Metadata/TypeItems.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'albumTypes': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Profiles.js b/frontend/src/Settings/Profiles/Profiles.js
deleted file mode 100644
index 985214fc1..000000000
--- a/frontend/src/Settings/Profiles/Profiles.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import React, { Component } from 'react';
-import { DndProvider } from 'react-dnd-multi-backend';
-import HTML5toTouch from 'react-dnd-multi-backend/dist/esm/HTML5toTouch';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import DelayProfilesConnector from './Delay/DelayProfilesConnector';
-import MetadataProfilesConnector from './Metadata/MetadataProfilesConnector';
-import QualityProfilesConnector from './Quality/QualityProfilesConnector';
-import ReleaseProfilesConnector from './Release/ReleaseProfilesConnector';
-
-// Only a single DragDrop Context can exist so it's done here to allow editing
-// quality profiles and reordering delay profiles to work.
-
-class Profiles extends Component {
-
- //
- // Render
-
- render() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-export default Profiles;
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js
deleted file mode 100644
index d6f2b8ed0..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModal.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditQualityProfileModalContentConnector from './EditQualityProfileModalContentConnector';
-
-class EditQualityProfileModal extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- height: 'auto'
- };
- }
-
- //
- // Listeners
-
- onContentHeightChange = (height) => {
- if (this.state.height === 'auto' || height > this.state.height) {
- this.setState({ height });
- }
- };
-
- //
- // Render
-
- render() {
- const {
- isOpen,
- onModalClose,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
- );
- }
-}
-
-EditQualityProfileModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditQualityProfileModal;
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js
deleted file mode 100644
index 5d7f48d29..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalConnector.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditQualityProfileModal from './EditQualityProfileModal';
-
-function mapStateToProps() {
- return {};
-}
-
-const mapDispatchToProps = {
- clearPendingChanges
-};
-
-class EditQualityProfileModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.clearPendingChanges({ section: 'settings.qualityProfiles' });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditQualityProfileModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(EditQualityProfileModalConnector);
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css
deleted file mode 100644
index 586f99e70..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css
+++ /dev/null
@@ -1,31 +0,0 @@
-.formGroupsContainer {
- display: flex;
- flex-wrap: wrap;
-}
-
-.formGroupWrapper,
-.formatItemLarge {
- flex: 0 0 calc($formGroupSmallWidth - 100px);
-}
-
-.deleteButtonContainer {
- margin-right: auto;
-}
-
-.formatItemSmall {
- display: none;
-}
-
-@media only screen and (max-width: calc($breakpointLarge + 100px)) {
- .formGroupsContainer {
- display: block;
- }
-
- .formatItemSmall {
- display: block;
- }
-
- .formatItemLarge {
- display: none;
- }
-}
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css.d.ts b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css.d.ts
deleted file mode 100644
index 689c2e723..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButtonContainer': string;
- 'formGroupWrapper': string;
- 'formGroupsContainer': string;
- 'formatItemLarge': string;
- 'formatItemSmall': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js
deleted file mode 100644
index 69b18a021..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContent.js
+++ /dev/null
@@ -1,331 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import Measure from 'Components/Measure';
-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 { inputTypes, kinds, sizes } from 'Helpers/Props';
-import dimensions from 'Styles/Variables/dimensions';
-import translate from 'Utilities/String/translate';
-import QualityProfileFormatItems from './QualityProfileFormatItems';
-import QualityProfileItems from './QualityProfileItems';
-import styles from './EditQualityProfileModalContent.css';
-
-const MODAL_BODY_PADDING = parseInt(dimensions.modalBodyPadding);
-
-function getCustomFormatRender(formatItems, otherProps) {
- return (
-
- );
-}
-
-class EditQualityProfileModalContent extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- headerHeight: 0,
- bodyHeight: 0,
- footerHeight: 0
- };
- }
-
- componentDidUpdate(prevProps, prevState) {
- const {
- headerHeight,
- bodyHeight,
- footerHeight
- } = this.state;
-
- if (
- headerHeight > 0 &&
- bodyHeight > 0 &&
- footerHeight > 0 &&
- (
- headerHeight !== prevState.headerHeight ||
- bodyHeight !== prevState.bodyHeight ||
- footerHeight !== prevState.footerHeight
- )
- ) {
- const padding = MODAL_BODY_PADDING * 2;
-
- this.props.onContentHeightChange(
- headerHeight + bodyHeight + footerHeight + padding
- );
- }
- }
-
- //
- // Listeners
-
- onHeaderMeasure = ({ height }) => {
- if (height > this.state.headerHeight) {
- this.setState({ headerHeight: height });
- }
- };
-
- onBodyMeasure = ({ height }) => {
-
- if (height > this.state.bodyHeight) {
- this.setState({ bodyHeight: height });
- }
- };
-
- onFooterMeasure = ({ height }) => {
- if (height > this.state.footerHeight) {
- this.setState({ footerHeight: height });
- }
- };
-
- //
- // Render
-
- render() {
- const {
- editGroups,
- isFetching,
- error,
- isSaving,
- saveError,
- qualities,
- customFormats,
- item,
- isInUse,
- onInputChange,
- onCutoffChange,
- onSavePress,
- onModalClose,
- onDeleteQualityProfilePress,
- ...otherProps
- } = this.props;
-
- const {
- id,
- name,
- upgradeAllowed,
- cutoff,
- minFormatScore,
- cutoffFormatScore,
- items,
- formatItems
- } = item;
-
- return (
-
-
-
- {id ? translate('EditQualityProfile') : translate('AddQualityProfile')}
-
-
-
-
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && !!error &&
-
- {translate('UnableToAddANewQualityProfilePleaseTryAgain')}
-
- }
-
- {
- !isFetching && !error &&
-
-
- }
-
-
-
-
-
-
- {
- id ?
-
-
- {translate('Delete')}
-
-
:
- null
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
-
- );
- }
-}
-
-EditQualityProfileModalContent.propTypes = {
- editGroups: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
- customFormats: PropTypes.arrayOf(PropTypes.object).isRequired,
- item: PropTypes.object.isRequired,
- isInUse: PropTypes.bool.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onCutoffChange: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onContentHeightChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onDeleteQualityProfilePress: PropTypes.func
-};
-
-export default EditQualityProfileModalContent;
diff --git a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js
deleted file mode 100644
index de92e998b..000000000
--- a/frontend/src/Settings/Profiles/Quality/EditQualityProfileModalContentConnector.js
+++ /dev/null
@@ -1,488 +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 { fetchQualityProfileSchema, saveQualityProfile, setQualityProfileValue } from 'Store/Actions/settingsActions';
-import createProfileInUseSelector from 'Store/Selectors/createProfileInUseSelector';
-import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
-import EditQualityProfileModalContent from './EditQualityProfileModalContent';
-
-function getQualityItemGroupId(qualityProfile) {
- // Get items with an `id` and filter out null/undefined values
- const ids = _.filter(_.map(qualityProfile.items.value, 'id'), (i) => i != null);
-
- return Math.max(1000, ...ids) + 1;
-}
-
-function parseIndex(index) {
- const split = index.split('.');
-
- if (split.length === 1) {
- return [
- null,
- parseInt(split[0]) - 1
- ];
- }
-
- return [
- parseInt(split[0]) - 1,
- parseInt(split[1]) - 1
- ];
-}
-
-function createQualitiesSelector() {
- return createSelector(
- createProviderSettingsSelector('qualityProfiles'),
- (qualityProfile) => {
- const items = qualityProfile.item.items;
- if (!items || !items.value) {
- return [];
- }
-
- return _.reduceRight(items.value, (result, { allowed, id, name, quality }) => {
- if (allowed) {
- if (id) {
- result.push({
- key: id,
- value: name
- });
- } else {
- result.push({
- key: quality.id,
- value: quality.name
- });
- }
- }
-
- return result;
- }, []);
- }
- );
-}
-
-function createFormatsSelector() {
- return createSelector(
- createProviderSettingsSelector('qualityProfiles'),
- (customFormat) => {
- const items = customFormat.item.formatItems;
- if (!items || !items.value) {
- return [];
- }
-
- return _.reduceRight(items.value, (result, { id, name, format, score }) => {
- if (id) {
- result.push({
- key: id,
- value: name,
- score
- });
- } else {
- result.push({
- key: format,
- value: name,
- score
- });
- }
-
- return result;
- }, []);
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- createProviderSettingsSelector('qualityProfiles'),
- createQualitiesSelector(),
- createFormatsSelector(),
- createProfileInUseSelector('qualityProfileId'),
- (qualityProfile, qualities, customFormats, isInUse) => {
- return {
- qualities,
- customFormats,
- ...qualityProfile,
- isInUse
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchQualityProfileSchema,
- setQualityProfileValue,
- saveQualityProfile
-};
-
-class EditQualityProfileModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- dragQualityIndex: null,
- dropQualityIndex: null,
- dropPosition: null,
- editGroups: false
- };
- }
-
- componentDidMount() {
- if (!this.props.id && !this.props.isPopulated) {
- this.props.fetchQualityProfileSchema();
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Control
-
- ensureCutoff = (qualityProfile) => {
- const cutoff = qualityProfile.cutoff.value;
-
- const cutoffItem = _.find(qualityProfile.items.value, (i) => {
- if (!cutoff) {
- return false;
- }
-
- return i.id === cutoff || (i.quality && i.quality.id === cutoff);
- });
-
- // If the cutoff isn't allowed anymore or there isn't a cutoff set one
- if (!cutoff || !cutoffItem || !cutoffItem.allowed) {
- const firstAllowed = _.find(qualityProfile.items.value, { allowed: true });
- let cutoffId = null;
-
- if (firstAllowed) {
- cutoffId = firstAllowed.quality ? firstAllowed.quality.id : firstAllowed.id;
- }
-
- this.props.setQualityProfileValue({ name: 'cutoff', value: cutoffId });
- }
- };
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setQualityProfileValue({ name, value });
- };
-
- onCutoffChange = ({ name, value }) => {
- const id = parseInt(value);
- const item = _.find(this.props.item.items.value, (i) => {
- if (i.quality) {
- return i.quality.id === id;
- }
-
- return i.id === id;
- });
-
- const cutoffId = item.quality ? item.quality.id : item.id;
-
- this.props.setQualityProfileValue({ name, value: cutoffId });
- };
-
- onSavePress = () => {
- this.props.saveQualityProfile({ id: this.props.id });
- };
-
- onQualityProfileItemAllowedChange = (id, allowed) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const item = _.find(qualityProfile.items.value, (i) => i.quality && i.quality.id === id);
-
- item.allowed = allowed;
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
-
- this.ensureCutoff(qualityProfile);
- };
-
- onQualityProfileFormatItemScoreChange = (id, score) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const formatItems = qualityProfile.formatItems.value;
- const item = _.find(qualityProfile.formatItems.value, (i) => i.format === id);
-
- item.score = score;
-
- this.props.setQualityProfileValue({
- name: 'formatItems',
- value: formatItems
- });
- };
-
- onItemGroupAllowedChange = (id, allowed) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const item = _.find(qualityProfile.items.value, (i) => i.id === id);
-
- item.allowed = allowed;
-
- // Update each item in the group (for consistency only)
- item.items.forEach((i) => {
- i.allowed = allowed;
- });
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
-
- this.ensureCutoff(qualityProfile);
- };
-
- onItemGroupNameChange = (id, name) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const group = _.find(items, (i) => i.id === id);
-
- group.name = name;
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
- };
-
- onCreateGroupPress = (id) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const item = _.find(items, (i) => i.quality && i.quality.id === id);
- const index = items.indexOf(item);
- const groupId = getQualityItemGroupId(qualityProfile);
-
- const group = {
- id: groupId,
- name: item.quality.name,
- allowed: item.allowed,
- items: [
- item
- ]
- };
-
- // Add the group in the same location the quality item was in.
- items.splice(index, 1, group);
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
-
- this.ensureCutoff(qualityProfile);
- };
-
- onDeleteGroupPress = (id) => {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const group = _.find(items, (i) => i.id === id);
- const index = items.indexOf(group);
-
- // Add the items in the same location the group was in
- items.splice(index, 1, ...group.items);
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
-
- this.ensureCutoff(qualityProfile);
- };
-
- onQualityProfileItemDragMove = (options) => {
- const {
- dragQualityIndex,
- dropQualityIndex,
- dropPosition
- } = options;
-
- const [dragGroupIndex, dragItemIndex] = parseIndex(dragQualityIndex);
- const [dropGroupIndex, dropItemIndex] = parseIndex(dropQualityIndex);
-
- if (
- (dropPosition === 'below' && dropItemIndex - 1 === dragItemIndex) ||
- (dropPosition === 'above' && dropItemIndex + 1 === dragItemIndex)
- ) {
- if (
- this.state.dragQualityIndex != null &&
- this.state.dropQualityIndex != null &&
- this.state.dropPosition != null
- ) {
- this.setState({
- dragQualityIndex: null,
- dropQualityIndex: null,
- dropPosition: null
- });
- }
-
- return;
- }
-
- let adjustedDropQualityIndex = dropQualityIndex;
-
- // Correct dragging out of a group to the position above
- if (
- dropPosition === 'above' &&
- dragGroupIndex !== dropGroupIndex &&
- dropGroupIndex != null
- ) {
- // Add 1 to the group index and 2 to the item index so it's inserted above in the correct group
- adjustedDropQualityIndex = `${dropGroupIndex + 1}.${dropItemIndex + 2}`;
- }
-
- // Correct inserting above outside a group
- if (
- dropPosition === 'above' &&
- dragGroupIndex !== dropGroupIndex &&
- dropGroupIndex == null
- ) {
- // Add 2 to the item index so it's entered in the correct place
- adjustedDropQualityIndex = `${dropItemIndex + 2}`;
- }
-
- // Correct inserting below a quality within the same group (when moving a lower item)
- if (
- dropPosition === 'below' &&
- dragGroupIndex === dropGroupIndex &&
- dropGroupIndex != null &&
- dragItemIndex < dropItemIndex
- ) {
- // Add 1 to the group index leave the item index
- adjustedDropQualityIndex = `${dropGroupIndex + 1}.${dropItemIndex}`;
- }
-
- // Correct inserting below a quality outside a group (when moving a lower item)
- if (
- dropPosition === 'below' &&
- dragGroupIndex === dropGroupIndex &&
- dropGroupIndex == null &&
- dragItemIndex < dropItemIndex
- ) {
- // Leave the item index so it's inserted below the item
- adjustedDropQualityIndex = `${dropItemIndex}`;
- }
-
- if (
- dragQualityIndex !== this.state.dragQualityIndex ||
- adjustedDropQualityIndex !== this.state.dropQualityIndex ||
- dropPosition !== this.state.dropPosition
- ) {
- this.setState({
- dragQualityIndex,
- dropQualityIndex: adjustedDropQualityIndex,
- dropPosition
- });
- }
- };
-
- onQualityProfileItemDragEnd = (didDrop) => {
- const {
- dragQualityIndex,
- dropQualityIndex
- } = this.state;
-
- if (didDrop && dropQualityIndex != null) {
- const qualityProfile = _.cloneDeep(this.props.item);
- const items = qualityProfile.items.value;
- const [dragGroupIndex, dragItemIndex] = parseIndex(dragQualityIndex);
- const [dropGroupIndex, dropItemIndex] = parseIndex(dropQualityIndex);
-
- let item = null;
- let dropGroup = null;
-
- // Get the group before moving anything so we know the correct place to drop it.
- if (dropGroupIndex != null) {
- dropGroup = items[dropGroupIndex];
- }
-
- if (dragGroupIndex == null) {
- item = items.splice(dragItemIndex, 1)[0];
- } else {
- const group = items[dragGroupIndex];
- item = group.items.splice(dragItemIndex, 1)[0];
-
- // If the group is now empty, destroy it.
- if (!group.items.length) {
- items.splice(dragGroupIndex, 1);
- }
- }
-
- if (dropGroupIndex == null) {
- items.splice(dropItemIndex, 0, item);
- } else {
- dropGroup.items.splice(dropItemIndex, 0, item);
- }
-
- this.props.setQualityProfileValue({
- name: 'items',
- value: items
- });
-
- this.ensureCutoff(qualityProfile);
- }
-
- this.setState({
- dragQualityIndex: null,
- dropQualityIndex: null,
- dropPosition: null
- });
- };
-
- onToggleEditGroupsMode = () => {
- this.setState({ editGroups: !this.state.editGroups });
- };
-
- //
- // Render
-
- render() {
- if (_.isEmpty(this.props.item.items) && !this.props.isFetching) {
- return null;
- }
-
- return (
-
- );
- }
-}
-
-EditQualityProfileModalContentConnector.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setQualityProfileValue: PropTypes.func.isRequired,
- fetchQualityProfileSchema: PropTypes.func.isRequired,
- saveQualityProfile: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditQualityProfileModalContentConnector);
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.css b/frontend/src/Settings/Profiles/Quality/QualityProfile.css
deleted file mode 100644
index 2513577a1..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfile.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.qualityProfile {
- composes: card from '~Components/Card.css';
-
- width: 300px;
-}
-
-.nameContainer {
- display: flex;
- justify-content: space-between;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.cloneButton {
- composes: button from '~Components/Link/IconButton.css';
-
- height: 36px;
-}
-
-.qualities {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
- pointer-events: all;
-}
-
-.tooltipLabel {
- composes: label from '~Components/Label.css';
-
- margin: 0;
- border: none;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfile.css.d.ts
deleted file mode 100644
index 9eed097eb..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfile.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'cloneButton': string;
- 'name': string;
- 'nameContainer': string;
- 'qualities': string;
- 'qualityProfile': string;
- 'tooltipLabel': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfile.js b/frontend/src/Settings/Profiles/Quality/QualityProfile.js
deleted file mode 100644
index b28d31b98..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfile.js
+++ /dev/null
@@ -1,187 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import Tooltip from 'Components/Tooltip/Tooltip';
-import { icons, kinds, tooltipPositions } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditQualityProfileModalConnector from './EditQualityProfileModalConnector';
-import styles from './QualityProfile.css';
-
-class QualityProfile extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditQualityProfileModalOpen: false,
- isDeleteQualityProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditQualityProfilePress = () => {
- this.setState({ isEditQualityProfileModalOpen: true });
- };
-
- onEditQualityProfileModalClose = () => {
- this.setState({ isEditQualityProfileModalOpen: false });
- };
-
- onDeleteQualityProfilePress = () => {
- this.setState({
- isEditQualityProfileModalOpen: false,
- isDeleteQualityProfileModalOpen: true
- });
- };
-
- onDeleteQualityProfileModalClose = () => {
- this.setState({ isDeleteQualityProfileModalOpen: false });
- };
-
- onConfirmDeleteQualityProfile = () => {
- this.props.onConfirmDeleteQualityProfile(this.props.id);
- };
-
- onCloneQualityProfilePress = () => {
- const {
- id,
- onCloneQualityProfilePress
- } = this.props;
-
- onCloneQualityProfilePress(id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- upgradeAllowed,
- cutoff,
- items,
- isDeleting
- } = this.props;
-
- return (
-
-
-
-
- {
- items.map((item) => {
- if (!item.allowed) {
- return null;
- }
-
- if (item.quality) {
- const isCutoff = upgradeAllowed && item.quality.id === cutoff;
-
- return (
-
- {item.quality.name}
-
- );
- }
-
- const isCutoff = upgradeAllowed && item.id === cutoff;
-
- return (
-
- {item.name}
-
- }
- tooltip={
-
- {
- item.items.map((groupItem) => {
- return (
-
- {groupItem.quality.name}
-
- );
- })
- }
-
- }
- kind={kinds.INVERSE}
- position={tooltipPositions.TOP}
- />
- );
- })
- }
-
-
-
-
-
-
- );
- }
-}
-
-QualityProfile.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- upgradeAllowed: PropTypes.bool.isRequired,
- cutoff: PropTypes.number.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- isDeleting: PropTypes.bool.isRequired,
- onConfirmDeleteQualityProfile: PropTypes.func.isRequired,
- onCloneQualityProfilePress: PropTypes.func.isRequired
-};
-
-export default QualityProfile;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css
deleted file mode 100644
index 4f235ba35..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css
+++ /dev/null
@@ -1,45 +0,0 @@
-.qualityProfileFormatItemContainer {
- display: flex;
- padding: $qualityProfileItemDragSourcePadding 0;
- width: 100%;
-}
-
-.qualityProfileFormatItem {
- display: flex;
- align-items: stretch;
- width: 100%;
- border: 1px solid #aaa;
- border-radius: 4px;
- background: var(--inputBackgroundColor);
-}
-
-.formatNameContainer {
- display: flex;
- flex-grow: 1;
- margin-bottom: 0;
- margin-left: 14px;
- width: 100%;
- font-weight: normal;
- line-height: $qualityProfileItemHeight;
- cursor: text;
-}
-
-.formatName {
- display: flex;
- flex-grow: 1;
-}
-
-.scoreContainer {
- display: flex;
- flex-grow: 0;
-}
-
-.scoreInput {
- composes: input from '~Components/Form/Input.css';
-
- width: 100px;
- height: 30px;
- border: unset;
- border-radius: unset;
- background-color: unset;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css.d.ts
deleted file mode 100644
index faa350dcd..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'formatName': string;
- 'formatNameContainer': string;
- 'qualityProfileFormatItem': string;
- 'qualityProfileFormatItemContainer': string;
- 'scoreContainer': string;
- 'scoreInput': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js
deleted file mode 100644
index 5ef4add2d..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItem.js
+++ /dev/null
@@ -1,68 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import NumberInput from 'Components/Form/NumberInput';
-import styles from './QualityProfileFormatItem.css';
-
-class QualityProfileFormatItem extends Component {
-
- //
- // Listeners
-
- onScoreChange = ({ value }) => {
- const {
- formatId
- } = this.props;
-
- this.props.onScoreChange(formatId, value);
- };
-
- //
- // Render
-
- render() {
- const {
- name,
- score
- } = this.props;
-
- return (
-
- );
- }
-}
-
-QualityProfileFormatItem.propTypes = {
- formatId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- score: PropTypes.number.isRequired,
- onScoreChange: PropTypes.func
-};
-
-QualityProfileFormatItem.defaultProps = {
- // To handle the case score is deleted during edit
- score: 0
-};
-
-export default QualityProfileFormatItem;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css
deleted file mode 100644
index def839960..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css
+++ /dev/null
@@ -1,31 +0,0 @@
-.formats {
- margin-top: 10px;
- /* TODO: This should consider the number of languages in the list */
- user-select: none;
-}
-
-.headerContainer {
- display: flex;
- font-weight: bold;
- line-height: 35px;
-}
-
-.headerTitle {
- display: flex;
- flex-grow: 1;
-}
-
-.headerScore {
- display: flex;
- flex-grow: 0;
- padding-left: 16px;
- width: 100px;
-}
-
-.addCustomFormatMessage {
- max-width: $formGroupExtraSmallWidth;
- color: var(--helpTextColor);
- text-align: center;
- font-weight: 300;
- font-size: 20px;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css.d.ts
deleted file mode 100644
index 75c081099..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addCustomFormatMessage': string;
- 'formats': string;
- 'headerContainer': string;
- 'headerScore': string;
- 'headerTitle': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js b/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js
deleted file mode 100644
index 9ec4bb841..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileFormatItems.js
+++ /dev/null
@@ -1,160 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import Link from 'Components/Link/Link';
-import { sizes } from 'Helpers/Props';
-import QualityProfileFormatItem from './QualityProfileFormatItem';
-import styles from './QualityProfileFormatItems.css';
-
-function calcOrder(profileFormatItems) {
- const items = profileFormatItems.reduce((acc, cur, index) => {
- acc[cur.format] = index;
- return acc;
- }, {});
-
- return [...profileFormatItems].sort((a, b) => {
- if (b.score !== a.score) {
- return b.score - a.score;
- }
-
- return a.name.localeCompare(b.name, undefined, { numeric: true });
- }).map((x) => items[x.format]);
-}
-
-class QualityProfileFormatItems extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- order: calcOrder(this.props.profileFormatItems)
- };
- }
-
- //
- // Listeners
-
- onScoreChange = (formatId, value) => {
- const {
- onQualityProfileFormatItemScoreChange
- } = this.props;
-
- onQualityProfileFormatItemScoreChange(formatId, value);
- this.reorderItems();
- };
-
- reorderItems = _.debounce(() => this.setState({ order: calcOrder(this.props.profileFormatItems) }), 1000);
-
- //
- // Render
-
- render() {
- const {
- profileFormatItems,
- errors,
- warnings
- } = this.props;
-
- const {
- order
- } = this.state;
-
- if (profileFormatItems.length < 1) {
- return (
-
- {'Want more control over which downloads are preferred? Add a'}
- Custom Format
-
- );
- }
-
- return (
-
-
- Custom Formats
-
-
-
-
-
- {
- errors.map((error, index) => {
- return (
-
- );
- })
- }
-
- {
- warnings.map((warning, index) => {
- return (
-
- );
- })
- }
-
-
-
-
- Custom Format
-
-
- Score
-
-
- {
- order.map((index) => {
- const {
- format,
- name,
- score
- } = profileFormatItems[index];
- return (
-
- );
- })
- }
-
-
-
- );
- }
-}
-
-QualityProfileFormatItems.propTypes = {
- profileFormatItems: PropTypes.arrayOf(PropTypes.object).isRequired,
- errors: PropTypes.arrayOf(PropTypes.object),
- warnings: PropTypes.arrayOf(PropTypes.object),
- onQualityProfileFormatItemScoreChange: PropTypes.func
-};
-
-QualityProfileFormatItems.defaultProps = {
- errors: [],
- warnings: []
-};
-
-export default QualityProfileFormatItems;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css
deleted file mode 100644
index c10bcd200..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css
+++ /dev/null
@@ -1,86 +0,0 @@
-.qualityProfileItem {
- display: flex;
- align-items: stretch;
- width: 100%;
- border: 1px solid #aaa;
- border-radius: 4px;
- background: var(--inputBackgroundColor);
-
- &.isInGroup {
- border-style: dashed;
- }
-}
-
-.checkInputContainer {
- position: relative;
- margin-right: 4px;
- margin-bottom: 5px;
- margin-left: 8px;
-}
-
-.checkInput {
- composes: input from '~Components/Form/CheckInput.css';
-
- margin-top: 5px;
-}
-
-.qualityNameContainer {
- display: flex;
- flex-grow: 1;
- margin-bottom: 0;
- margin-left: 2px;
- font-weight: normal;
- line-height: $qualityProfileItemHeight;
- cursor: pointer;
-}
-
-.qualityName {
- &.isInGroup {
- margin-left: 14px;
- }
-
- &.notAllowed {
- color: #c6c6c6;
- }
-}
-
-.createGroupButton {
- composes: buton from '~Components/Link/IconButton.css';
-
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- margin-right: 5px;
- margin-left: 8px;
- width: 20px;
-}
-
-.dragHandle {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- margin-left: auto;
- width: $dragHandleWidth;
- text-align: center;
- cursor: grab;
-}
-
-.dragIcon {
- top: 0;
-}
-
-.isDragging {
- opacity: 0.25;
-}
-
-.isPreview {
- .qualityName {
- margin-left: 14px;
-
- &.isInGroup {
- margin-left: 28px;
- }
- }
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css.d.ts
deleted file mode 100644
index 2f18ba539..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.css.d.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'checkInput': string;
- 'checkInputContainer': string;
- 'createGroupButton': string;
- 'dragHandle': string;
- 'dragIcon': string;
- 'isDragging': string;
- 'isInGroup': string;
- 'isPreview': string;
- 'notAllowed': string;
- 'qualityName': string;
- 'qualityNameContainer': string;
- 'qualityProfileItem': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js
deleted file mode 100644
index 5550464cb..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItem.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import CheckInput from 'Components/Form/CheckInput';
-import Icon from 'Components/Icon';
-import IconButton from 'Components/Link/IconButton';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './QualityProfileItem.css';
-
-class QualityProfileItem extends Component {
-
- //
- // Listeners
-
- onAllowedChange = ({ value }) => {
- const {
- qualityId,
- onQualityProfileItemAllowedChange
- } = this.props;
-
- onQualityProfileItemAllowedChange(qualityId, value);
- };
-
- onCreateGroupPress = () => {
- const {
- qualityId,
- onCreateGroupPress
- } = this.props;
-
- onCreateGroupPress(qualityId);
- };
-
- //
- // Render
-
- render() {
- const {
- editGroups,
- isPreview,
- groupId,
- name,
- allowed,
- isDragging,
- isOverCurrent,
- connectDragSource
- } = this.props;
-
- return (
-
-
- {
- editGroups && !groupId && !isPreview &&
-
- }
-
- {
- !editGroups &&
-
- }
-
-
- {name}
-
-
-
- {
- connectDragSource(
-
-
-
- )
- }
-
- );
- }
-}
-
-QualityProfileItem.propTypes = {
- editGroups: PropTypes.bool,
- isPreview: PropTypes.bool,
- groupId: PropTypes.number,
- qualityId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- isDragging: PropTypes.bool.isRequired,
- isOverCurrent: PropTypes.bool.isRequired,
- isInGroup: PropTypes.bool,
- connectDragSource: PropTypes.func,
- onCreateGroupPress: PropTypes.func,
- onQualityProfileItemAllowedChange: PropTypes.func
-};
-
-QualityProfileItem.defaultProps = {
- isPreview: false,
- isOverCurrent: false,
- // The drag preview will not connect the drag handle.
- connectDragSource: (node) => node
-};
-
-export default QualityProfileItem;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css
deleted file mode 100644
index b927d9bce..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.dragPreview {
- width: 380px;
- opacity: 0.75;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css.d.ts
deleted file mode 100644
index 1f1f3c320..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'dragPreview': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js
deleted file mode 100644
index 31290baa9..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragPreview.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { DragLayer } from 'react-dnd';
-import DragPreviewLayer from 'Components/DragPreviewLayer';
-import { QUALITY_PROFILE_ITEM } from 'Helpers/dragTypes';
-import dimensions from 'Styles/Variables/dimensions.js';
-import QualityProfileItem from './QualityProfileItem';
-import styles from './QualityProfileItemDragPreview.css';
-
-const formGroupExtraSmallWidth = parseInt(dimensions.formGroupExtraSmallWidth);
-const formLabelSmallWidth = parseInt(dimensions.formLabelSmallWidth);
-const formLabelRightMarginWidth = parseInt(dimensions.formLabelRightMarginWidth);
-const dragHandleWidth = parseInt(dimensions.dragHandleWidth);
-
-function collectDragLayer(monitor) {
- return {
- item: monitor.getItem(),
- itemType: monitor.getItemType(),
- currentOffset: monitor.getSourceClientOffset()
- };
-}
-
-class QualityProfileItemDragPreview extends Component {
-
- //
- // Render
-
- render() {
- const {
- item,
- itemType,
- currentOffset
- } = this.props;
-
- if (!currentOffset || itemType !== QUALITY_PROFILE_ITEM) {
- return null;
- }
-
- // The offset is shifted because the drag handle is on the right edge of the
- // list item and the preview is wider than the drag handle.
-
- const { x, y } = currentOffset;
- const handleOffset = formGroupExtraSmallWidth - formLabelSmallWidth - formLabelRightMarginWidth - dragHandleWidth;
- const transform = `translate3d(${x - handleOffset}px, ${y}px, 0)`;
-
- const style = {
- position: 'absolute',
- WebkitTransform: transform,
- msTransform: transform,
- transform
- };
-
- const {
- editGroups,
- groupId,
- qualityId,
- name,
- allowed
- } = item;
-
- // TODO: Show a different preview for groups
-
- return (
-
-
-
-
-
- );
- }
-}
-
-QualityProfileItemDragPreview.propTypes = {
- item: PropTypes.object,
- itemType: PropTypes.string,
- currentOffset: PropTypes.shape({
- x: PropTypes.number.isRequired,
- y: PropTypes.number.isRequired
- })
-};
-
-export default DragLayer(collectDragLayer)(QualityProfileItemDragPreview);
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css
deleted file mode 100644
index d5061cc95..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css
+++ /dev/null
@@ -1,18 +0,0 @@
-.qualityProfileItemDragSource {
- padding: $qualityProfileItemDragSourcePadding 0;
-}
-
-.qualityProfileItemPlaceholder {
- width: 100%;
- height: $qualityProfileItemHeight;
- border: 1px dotted #aaa;
- border-radius: 4px;
-}
-
-.qualityProfileItemPlaceholderBefore {
- margin-bottom: 8px;
-}
-
-.qualityProfileItemPlaceholderAfter {
- margin-top: 8px;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css.d.ts
deleted file mode 100644
index 32d2e00a7..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'qualityProfileItemDragSource': string;
- 'qualityProfileItemPlaceholder': string;
- 'qualityProfileItemPlaceholderAfter': string;
- 'qualityProfileItemPlaceholderBefore': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js
deleted file mode 100644
index b47470171..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemDragSource.js
+++ /dev/null
@@ -1,241 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { DragSource, DropTarget } from 'react-dnd';
-import { findDOMNode } from 'react-dom';
-import { QUALITY_PROFILE_ITEM } from 'Helpers/dragTypes';
-import QualityProfileItem from './QualityProfileItem';
-import QualityProfileItemGroup from './QualityProfileItemGroup';
-import styles from './QualityProfileItemDragSource.css';
-
-const qualityProfileItemDragSource = {
- beginDrag(props) {
- const {
- editGroups,
- qualityIndex,
- groupId,
- qualityId,
- name,
- allowed
- } = props;
-
- return {
- editGroups,
- qualityIndex,
- groupId,
- qualityId,
- isGroup: !qualityId,
- name,
- allowed
- };
- },
-
- endDrag(props, monitor, component) {
- props.onQualityProfileItemDragEnd(monitor.didDrop());
- }
-};
-
-const qualityProfileItemDropTarget = {
- hover(props, monitor, component) {
- const {
- qualityIndex: dragQualityIndex,
- isGroup: isDragGroup
- } = monitor.getItem();
-
- const dropQualityIndex = props.qualityIndex;
- const isDropGroupItem = !!(props.qualityId && props.groupId);
-
- // Use childNodeIndex to select the correct node to get the middle of so
- // we don't bounce between above and below causing rapid setState calls.
- const childNodeIndex = component.props.isOverCurrent && component.props.isDraggingUp ? 1 :0;
- const componentDOMNode = findDOMNode(component).children[childNodeIndex];
- const hoverBoundingRect = componentDOMNode.getBoundingClientRect();
- const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
- const clientOffset = monitor.getClientOffset();
- const hoverClientY = clientOffset.y - hoverBoundingRect.top;
-
- // If we're hovering over a child don't trigger on the parent
- if (!monitor.isOver({ shallow: true })) {
- return;
- }
-
- // Don't show targets for dropping on self
- if (dragQualityIndex === dropQualityIndex) {
- return;
- }
-
- // Don't allow a group to be dropped inside a group
- if (isDragGroup && isDropGroupItem) {
- return;
- }
-
- let dropPosition = null;
-
- // Determine drop position based on position over target
- if (hoverClientY > hoverMiddleY) {
- dropPosition = 'below';
- } else if (hoverClientY < hoverMiddleY) {
- dropPosition = 'above';
- } else {
- return;
- }
-
- props.onQualityProfileItemDragMove({
- dragQualityIndex,
- dropQualityIndex,
- dropPosition
- });
- }
-};
-
-function collectDragSource(connect, monitor) {
- return {
- connectDragSource: connect.dragSource(),
- isDragging: monitor.isDragging()
- };
-}
-
-function collectDropTarget(connect, monitor) {
- return {
- connectDropTarget: connect.dropTarget(),
- isOver: monitor.isOver(),
- isOverCurrent: monitor.isOver({ shallow: true })
- };
-}
-
-class QualityProfileItemDragSource extends Component {
-
- //
- // Render
-
- render() {
- const {
- editGroups,
- groupId,
- qualityId,
- name,
- allowed,
- items,
- qualityIndex,
- isDragging,
- isDraggingUp,
- isDraggingDown,
- isOverCurrent,
- connectDragSource,
- connectDropTarget,
- onCreateGroupPress,
- onDeleteGroupPress,
- onQualityProfileItemAllowedChange,
- onItemGroupAllowedChange,
- onItemGroupNameChange,
- onQualityProfileItemDragMove,
- onQualityProfileItemDragEnd
- } = this.props;
-
- const isBefore = !isDragging && isDraggingUp && isOverCurrent;
- const isAfter = !isDragging && isDraggingDown && isOverCurrent;
-
- return connectDropTarget(
-
- {
- isBefore &&
-
- }
-
- {
- !!groupId && qualityId == null &&
-
- }
-
- {
- qualityId != null &&
-
- }
-
- {
- isAfter &&
-
- }
-
- );
- }
-}
-
-QualityProfileItemDragSource.propTypes = {
- editGroups: PropTypes.bool.isRequired,
- groupId: PropTypes.number,
- qualityId: PropTypes.number,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- items: PropTypes.arrayOf(PropTypes.object),
- qualityIndex: PropTypes.string.isRequired,
- isDragging: PropTypes.bool,
- isDraggingUp: PropTypes.bool,
- isDraggingDown: PropTypes.bool,
- isOverCurrent: PropTypes.bool,
- isInGroup: PropTypes.bool,
- connectDragSource: PropTypes.func,
- connectDropTarget: PropTypes.func,
- onCreateGroupPress: PropTypes.func,
- onDeleteGroupPress: PropTypes.func,
- onQualityProfileItemAllowedChange: PropTypes.func.isRequired,
- onItemGroupAllowedChange: PropTypes.func,
- onItemGroupNameChange: PropTypes.func,
- onQualityProfileItemDragMove: PropTypes.func.isRequired,
- onQualityProfileItemDragEnd: PropTypes.func.isRequired
-};
-
-export default DropTarget(
- QUALITY_PROFILE_ITEM,
- qualityProfileItemDropTarget,
- collectDropTarget
-)(DragSource(
- QUALITY_PROFILE_ITEM,
- qualityProfileItemDragSource,
- collectDragSource
-)(QualityProfileItemDragSource));
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css
deleted file mode 100644
index 772bd9a80..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css
+++ /dev/null
@@ -1,106 +0,0 @@
-.qualityProfileItemGroup {
- width: 100%;
- border: 1px solid #aaa;
- border-radius: 4px;
- background: var(--inputBackgroundColor);
-
- &.editGroups {
- background: var(--inputBackgroundColor);
- }
-}
-
-.qualityProfileItemGroupInfo {
- display: flex;
- align-items: stretch;
- width: 100%;
-}
-
-.checkInputContainer {
- composes: checkInputContainer from '~./QualityProfileItem.css';
-
- display: flex;
- align-items: center;
-}
-
-.checkInput {
- composes: checkInput from '~./QualityProfileItem.css';
-}
-
-.nameInput {
- composes: input from '~Components/Form/TextInput.css';
-
- margin-top: 4px;
- margin-right: 10px;
-}
-
-.nameContainer {
- display: flex;
- align-items: center;
- flex-grow: 1;
-}
-
-.name {
- flex-shrink: 0;
-
- &.notAllowed {
- color: #c6c6c6;
- }
-}
-
-.groupQualities {
- display: flex;
- justify-content: flex-end;
- flex-grow: 1;
- flex-wrap: wrap;
- margin: 2px 0 2px 10px;
-}
-
-.qualityNameContainer {
- display: flex;
- align-items: stretch;
- flex-grow: 1;
- margin-bottom: 0;
- margin-left: 2px;
- font-weight: normal;
-}
-
-.qualityNameLabel {
- composes: qualityNameContainer;
-
- cursor: pointer;
-}
-
-.deleteGroupButton {
- composes: buton from '~Components/Link/IconButton.css';
-
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- margin-right: 5px;
- margin-left: 8px;
- width: 20px;
-}
-
-.dragHandle {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- margin-left: auto;
- width: $dragHandleWidth;
- text-align: center;
- cursor: grab;
-}
-
-.dragIcon {
- top: 0;
-}
-
-.isDragging {
- opacity: 0.25;
-}
-
-.items {
- margin: 0 50px 0 35px;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css.d.ts
deleted file mode 100644
index 73ffeb3e5..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.css.d.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'checkInput': string;
- 'checkInputContainer': string;
- 'deleteGroupButton': string;
- 'dragHandle': string;
- 'dragIcon': string;
- 'editGroups': string;
- 'groupQualities': string;
- 'isDragging': string;
- 'items': string;
- 'name': string;
- 'nameContainer': string;
- 'nameInput': string;
- 'notAllowed': string;
- 'qualityNameContainer': string;
- 'qualityNameLabel': string;
- 'qualityProfileItemGroup': string;
- 'qualityProfileItemGroupInfo': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js
deleted file mode 100644
index 499b62016..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItemGroup.js
+++ /dev/null
@@ -1,201 +0,0 @@
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import CheckInput from 'Components/Form/CheckInput';
-import TextInput from 'Components/Form/TextInput';
-import Icon from 'Components/Icon';
-import Label from 'Components/Label';
-import IconButton from 'Components/Link/IconButton';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import QualityProfileItemDragSource from './QualityProfileItemDragSource';
-import styles from './QualityProfileItemGroup.css';
-
-class QualityProfileItemGroup extends Component {
-
- //
- // Listeners
-
- onAllowedChange = ({ value }) => {
- const {
- groupId,
- onItemGroupAllowedChange
- } = this.props;
-
- onItemGroupAllowedChange(groupId, value);
- };
-
- onNameChange = ({ value }) => {
- const {
- groupId,
- onItemGroupNameChange
- } = this.props;
-
- onItemGroupNameChange(groupId, value);
- };
-
- onDeleteGroupPress = ({ value }) => {
- const {
- groupId,
- onDeleteGroupPress
- } = this.props;
-
- onDeleteGroupPress(groupId, value);
- };
-
- //
- // Render
-
- render() {
- const {
- editGroups,
- groupId,
- name,
- allowed,
- items,
- qualityIndex,
- isDragging,
- isDraggingUp,
- isDraggingDown,
- connectDragSource,
- onQualityProfileItemAllowedChange,
- onQualityProfileItemDragMove,
- onQualityProfileItemDragEnd
- } = this.props;
-
- return (
-
-
- {
- editGroups &&
-
-
-
-
-
- }
-
- {
- !editGroups &&
-
-
-
-
-
- {name}
-
-
-
- {
- items.map(({ quality }) => {
- return (
-
- {quality.name}
-
- );
- }).reverse()
- }
-
-
-
- }
-
- {
- connectDragSource(
-
-
-
- )
- }
-
-
- {
- editGroups &&
-
- {
- items.map(({ quality }, index) => {
- return (
-
- );
- }).reverse()
- }
-
- }
-
- );
- }
-}
-
-QualityProfileItemGroup.propTypes = {
- editGroups: PropTypes.bool,
- groupId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- allowed: PropTypes.bool.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- qualityIndex: PropTypes.string.isRequired,
- isDragging: PropTypes.bool.isRequired,
- isDraggingUp: PropTypes.bool.isRequired,
- isDraggingDown: PropTypes.bool.isRequired,
- connectDragSource: PropTypes.func,
- onItemGroupAllowedChange: PropTypes.func.isRequired,
- onQualityProfileItemAllowedChange: PropTypes.func.isRequired,
- onItemGroupNameChange: PropTypes.func.isRequired,
- onDeleteGroupPress: PropTypes.func.isRequired,
- onQualityProfileItemDragMove: PropTypes.func.isRequired,
- onQualityProfileItemDragEnd: PropTypes.func.isRequired
-};
-
-QualityProfileItemGroup.defaultProps = {
- // The drag preview will not connect the drag handle.
- connectDragSource: (node) => node
-};
-
-export default QualityProfileItemGroup;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css b/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css
deleted file mode 100644
index 002e555a7..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css
+++ /dev/null
@@ -1,15 +0,0 @@
-.editGroupsButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-top: 10px;
-}
-
-.editGroupsButtonIcon {
- margin-right: 8px;
-}
-
-.qualities {
- margin-top: 10px;
- transition: min-height 200ms;
- user-select: none;
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css.d.ts
deleted file mode 100644
index 159ce7759..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'editGroupsButton': string;
- 'editGroupsButtonIcon': string;
- 'qualities': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js b/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js
deleted file mode 100644
index 87d112545..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileItems.js
+++ /dev/null
@@ -1,182 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputHelpText from 'Components/Form/FormInputHelpText';
-import FormLabel from 'Components/Form/FormLabel';
-import Icon from 'Components/Icon';
-import Button from 'Components/Link/Button';
-import Measure from 'Components/Measure';
-import { icons, kinds, sizes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import QualityProfileItemDragPreview from './QualityProfileItemDragPreview';
-import QualityProfileItemDragSource from './QualityProfileItemDragSource';
-import styles from './QualityProfileItems.css';
-
-class QualityProfileItems extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- qualitiesHeight: 0,
- qualitiesHeightEditGroups: 0
- };
- }
-
- //
- // Listeners
-
- onMeasure = ({ height }) => {
- if (this.props.editGroups) {
- this.setState({
- qualitiesHeightEditGroups: height
- });
- } else {
- this.setState({ qualitiesHeight: height });
- }
- };
-
- onToggleEditGroupsMode = () => {
- this.props.onToggleEditGroupsMode();
- };
-
- //
- // Render
-
- render() {
- const {
- editGroups,
- dropQualityIndex,
- dropPosition,
- qualityProfileItems,
- errors,
- warnings,
- ...otherProps
- } = this.props;
-
- const {
- qualitiesHeight,
- qualitiesHeightEditGroups
- } = this.state;
-
- const isDragging = dropQualityIndex !== null;
- const isDraggingUp = isDragging && dropPosition === 'above';
- const isDraggingDown = isDragging && dropPosition === 'below';
- const minHeight = editGroups ? qualitiesHeightEditGroups : qualitiesHeight;
-
- return (
-
-
- Qualities
-
-
-
-
-
- {
- errors.map((error, index) => {
- return (
-
- );
- })
- }
-
- {
- warnings.map((warning, index) => {
- return (
-
- );
- })
- }
-
-
-
-
-
- {
- editGroups ? translate('DoneEditingGroups') : translate('EditGroups')
- }
-
-
-
-
-
- {
- qualityProfileItems.map(({ id, name, allowed, quality, items }, index) => {
- const identifier = quality ? quality.id : id;
-
- return (
-
- );
- }).reverse()
- }
-
-
-
-
-
-
- );
- }
-}
-
-QualityProfileItems.propTypes = {
- editGroups: PropTypes.bool.isRequired,
- dragQualityIndex: PropTypes.string,
- dropQualityIndex: PropTypes.string,
- dropPosition: PropTypes.string,
- qualityProfileItems: PropTypes.arrayOf(PropTypes.object).isRequired,
- errors: PropTypes.arrayOf(PropTypes.object),
- warnings: PropTypes.arrayOf(PropTypes.object),
- onToggleEditGroupsMode: PropTypes.func.isRequired
-};
-
-QualityProfileItems.defaultProps = {
- errors: [],
- warnings: []
-};
-
-export default QualityProfileItems;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js b/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js
deleted file mode 100644
index bf13815ff..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfileNameConnector.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import createQualityProfileSelector from 'Store/Selectors/createQualityProfileSelector';
-
-function createMapStateToProps() {
- return createSelector(
- createQualityProfileSelector(),
- (qualityProfile) => {
- return {
- name: qualityProfile.name
- };
- }
- );
-}
-
-function QualityProfileNameConnector({ name, ...otherProps }) {
- return (
-
- {name}
-
- );
-}
-
-QualityProfileNameConnector.propTypes = {
- qualityProfileId: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired
-};
-
-export default connect(createMapStateToProps)(QualityProfileNameConnector);
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css b/frontend/src/Settings/Profiles/Quality/QualityProfiles.css
deleted file mode 100644
index 32dad3fac..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css
+++ /dev/null
@@ -1,21 +0,0 @@
-.qualityProfiles {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addQualityProfile {
- composes: qualityProfile from '~./QualityProfile.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
- font-size: 45px;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css.d.ts b/frontend/src/Settings/Profiles/Quality/QualityProfiles.css.d.ts
deleted file mode 100644
index f3033cab2..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfiles.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addQualityProfile': string;
- 'center': string;
- 'qualityProfiles': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfiles.js b/frontend/src/Settings/Profiles/Quality/QualityProfiles.js
deleted file mode 100644
index c2405447b..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfiles.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditQualityProfileModalConnector from './EditQualityProfileModalConnector';
-import QualityProfile from './QualityProfile';
-import styles from './QualityProfiles.css';
-
-class QualityProfiles extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isQualityProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onCloneQualityProfilePress = (id) => {
- this.props.onCloneQualityProfilePress(id);
- this.setState({ isQualityProfileModalOpen: true });
- };
-
- onEditQualityProfilePress = () => {
- this.setState({ isQualityProfileModalOpen: true });
- };
-
- onModalClose = () => {
- this.setState({ isQualityProfileModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- items,
- isDeleting,
- onConfirmDeleteQualityProfile,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-QualityProfiles.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- isDeleting: PropTypes.bool.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteQualityProfile: PropTypes.func.isRequired,
- onCloneQualityProfilePress: PropTypes.func.isRequired
-};
-
-export default QualityProfiles;
diff --git a/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js b/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js
deleted file mode 100644
index 4cb318463..000000000
--- a/frontend/src/Settings/Profiles/Quality/QualityProfilesConnector.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { cloneQualityProfile, deleteQualityProfile, fetchQualityProfiles } from 'Store/Actions/settingsActions';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import QualityProfiles from './QualityProfiles';
-
-function createMapStateToProps() {
- return createSelector(
- createSortedSectionSelector('settings.qualityProfiles', sortByProp('name')),
- (qualityProfiles) => qualityProfiles
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchQualityProfiles: fetchQualityProfiles,
- dispatchDeleteQualityProfile: deleteQualityProfile,
- dispatchCloneQualityProfile: cloneQualityProfile
-};
-
-class QualityProfilesConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchQualityProfiles();
- }
-
- //
- // Listeners
-
- onConfirmDeleteQualityProfile = (id) => {
- this.props.dispatchDeleteQualityProfile({ id });
- };
-
- onCloneQualityProfilePress = (id) => {
- this.props.dispatchCloneQualityProfile({ id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-QualityProfilesConnector.propTypes = {
- dispatchFetchQualityProfiles: PropTypes.func.isRequired,
- dispatchDeleteQualityProfile: PropTypes.func.isRequired,
- dispatchCloneQualityProfile: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(QualityProfilesConnector);
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModal.js b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModal.js
deleted file mode 100644
index a948ab123..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModal.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import EditReleaseProfileModalContentConnector from './EditReleaseProfileModalContentConnector';
-
-function EditReleaseProfileModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-EditReleaseProfileModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditReleaseProfileModal;
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalConnector.js b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalConnector.js
deleted file mode 100644
index e846ff6ff..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalConnector.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditReleaseProfileModal from './EditReleaseProfileModal';
-
-const mapDispatchToProps = {
- clearPendingChanges
-};
-
-class EditReleaseProfileModalConnector extends Component {
-
- //
- // Listeners
-
- onModalClose = () => {
- this.props.clearPendingChanges({ section: 'settings.releaseProfiles' });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditReleaseProfileModalConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(null, mapDispatchToProps)(EditReleaseProfileModalConnector);
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css
deleted file mode 100644
index a2b6014df..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css.d.ts b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css.d.ts
deleted file mode 100644
index c5f0ef8a7..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js
deleted file mode 100644
index e1c695c42..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContent.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './EditReleaseProfileModalContent.css';
-
-const tagInputDelimiters = ['Tab', 'Enter'];
-
-function EditReleaseProfileModalContent(props) {
- const {
- isSaving,
- saveError,
- item,
- onInputChange,
- onModalClose,
- onSavePress,
- onDeleteReleaseProfilePress,
- ...otherProps
- } = props;
-
- const {
- id,
- enabled,
- required,
- ignored,
- tags,
- indexerId
- } = item;
-
- return (
-
-
- {id ? translate('EditReleaseProfile') : translate('AddReleaseProfile')}
-
-
-
-
-
-
- {
- id &&
-
- {translate('Delete')}
-
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditReleaseProfileModalContent.propTypes = {
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- onInputChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired,
- onSavePress: PropTypes.func.isRequired,
- onDeleteReleaseProfilePress: PropTypes.func
-};
-
-export default EditReleaseProfileModalContent;
diff --git a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContentConnector.js b/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContentConnector.js
deleted file mode 100644
index b14d72269..000000000
--- a/frontend/src/Settings/Profiles/Release/EditReleaseProfileModalContentConnector.js
+++ /dev/null
@@ -1,114 +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 { saveReleaseProfile, setReleaseProfileValue } from 'Store/Actions/settingsActions';
-import selectSettings from 'Store/Selectors/selectSettings';
-import EditReleaseProfileModalContent from './EditReleaseProfileModalContent';
-
-const newReleaseProfile = {
- enabled: true,
- required: [],
- ignored: [],
- includePreferredWhenRenaming: false,
- tags: [],
- indexerId: 0
-};
-
-function createMapStateToProps() {
- return createSelector(
- (state, { id }) => id,
- (state) => state.settings.releaseProfiles,
- (id, releaseProfiles) => {
- const {
- isFetching,
- error,
- isSaving,
- saveError,
- pendingChanges,
- items
- } = releaseProfiles;
-
- const profile = id ? _.find(items, { id }) : newReleaseProfile;
- const settings = selectSettings(profile, pendingChanges, saveError);
-
- return {
- id,
- isFetching,
- error,
- isSaving,
- saveError,
- item: settings.settings,
- ...settings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setReleaseProfileValue,
- saveReleaseProfile
-};
-
-class EditReleaseProfileModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- if (!this.props.id) {
- Object.keys(newReleaseProfile).forEach((name) => {
- this.props.setReleaseProfileValue({
- name,
- value: newReleaseProfile[name]
- });
- });
- }
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
- this.props.onModalClose();
- }
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setReleaseProfileValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveReleaseProfile({ id: this.props.id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditReleaseProfileModalContentConnector.propTypes = {
- id: PropTypes.number,
- isFetching: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- saveError: PropTypes.object,
- item: PropTypes.object.isRequired,
- setReleaseProfileValue: PropTypes.func.isRequired,
- saveReleaseProfile: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditReleaseProfileModalContentConnector);
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfile.css b/frontend/src/Settings/Profiles/Release/ReleaseProfile.css
deleted file mode 100644
index 09ba2b0c7..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfile.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.releaseProfile {
- composes: card from '~Components/Card.css';
-
- width: 290px;
-}
-
-.enabled {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
-}
-
-.label {
- composes: label from '~Components/Label.css';
-
- max-width: 100%;
-}
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfile.css.d.ts b/frontend/src/Settings/Profiles/Release/ReleaseProfile.css.d.ts
deleted file mode 100644
index 4245884cc..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfile.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'enabled': string;
- 'label': string;
- 'releaseProfile': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfile.js b/frontend/src/Settings/Profiles/Release/ReleaseProfile.js
deleted file mode 100644
index 7883158d7..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfile.js
+++ /dev/null
@@ -1,197 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import MiddleTruncate from 'react-middle-truncate';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import TagList from 'Components/TagList';
-import { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditReleaseProfileModalConnector from './EditReleaseProfileModalConnector';
-import styles from './ReleaseProfile.css';
-
-class ReleaseProfile extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isEditReleaseProfileModalOpen: false,
- isDeleteReleaseProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onEditReleaseProfilePress = () => {
- this.setState({ isEditReleaseProfileModalOpen: true });
- };
-
- onEditReleaseProfileModalClose = () => {
- this.setState({ isEditReleaseProfileModalOpen: false });
- };
-
- onDeleteReleaseProfilePress = () => {
- this.setState({
- isEditReleaseProfileModalOpen: false,
- isDeleteReleaseProfileModalOpen: true
- });
- };
-
- onDeleteReleaseProfileModalClose= () => {
- this.setState({ isDeleteReleaseProfileModalOpen: false });
- };
-
- onConfirmDeleteReleaseProfile = () => {
- this.props.onConfirmDeleteReleaseProfile(this.props.id);
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- enabled,
- required,
- ignored,
- tags,
- indexerId,
- tagList,
- indexerList
- } = this.props;
-
- const {
- isEditReleaseProfileModalOpen,
- isDeleteReleaseProfileModalOpen
- } = this.state;
-
- const indexer = indexerId !== 0 && _.find(indexerList, { id: indexerId });
-
- return (
-
-
- {
- required.map((item) => {
- if (!item) {
- return null;
- }
-
- return (
-
-
-
- );
- })
- }
-
-
-
- {
- ignored.map((item) => {
- if (!item) {
- return null;
- }
-
- return (
-
-
-
- );
- })
- }
-
-
-
-
-
- {
- !enabled &&
-
- Disabled
-
- }
-
- {
- indexer &&
-
- {indexer.name}
-
- }
-
-
-
-
-
-
- );
- }
-}
-
-ReleaseProfile.propTypes = {
- id: PropTypes.number.isRequired,
- enabled: PropTypes.bool.isRequired,
- required: PropTypes.arrayOf(PropTypes.string).isRequired,
- ignored: PropTypes.arrayOf(PropTypes.string).isRequired,
- tags: PropTypes.arrayOf(PropTypes.number).isRequired,
- indexerId: PropTypes.number.isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- indexerList: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteReleaseProfile: PropTypes.func.isRequired
-};
-
-ReleaseProfile.defaultProps = {
- enabled: true,
- required: [],
- ignored: [],
- indexerId: 0
-};
-
-export default ReleaseProfile;
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css b/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css
deleted file mode 100644
index 9e9715e77..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.releaseProfiles {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addReleaseProfile {
- composes: releaseProfile from '~./ReleaseProfile.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css.d.ts b/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css.d.ts
deleted file mode 100644
index be1ba4596..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addReleaseProfile': string;
- 'center': string;
- 'releaseProfiles': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.js b/frontend/src/Settings/Profiles/Release/ReleaseProfiles.js
deleted file mode 100644
index b04e24eae..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfiles.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditReleaseProfileModalConnector from './EditReleaseProfileModalConnector';
-import ReleaseProfile from './ReleaseProfile';
-import styles from './ReleaseProfiles.css';
-
-class ReleaseProfiles extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isAddReleaseProfileModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onAddReleaseProfilePress = () => {
- this.setState({ isAddReleaseProfileModalOpen: true });
- };
-
- onAddReleaseProfileModalClose = () => {
- this.setState({ isAddReleaseProfileModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- items,
- tagList,
- indexerList,
- onConfirmDeleteReleaseProfile,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
-
-
-
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
- );
- }
-}
-
-ReleaseProfiles.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- indexerList: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteReleaseProfile: PropTypes.func.isRequired
-};
-
-export default ReleaseProfiles;
diff --git a/frontend/src/Settings/Profiles/Release/ReleaseProfilesConnector.js b/frontend/src/Settings/Profiles/Release/ReleaseProfilesConnector.js
deleted file mode 100644
index 0c0d81c77..000000000
--- a/frontend/src/Settings/Profiles/Release/ReleaseProfilesConnector.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { deleteReleaseProfile, fetchIndexers, fetchReleaseProfiles } from 'Store/Actions/settingsActions';
-import createTagsSelector from 'Store/Selectors/createTagsSelector';
-import ReleaseProfiles from './ReleaseProfiles';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.releaseProfiles,
- (state) => state.settings.indexers,
- createTagsSelector(),
- (releaseProfiles, indexers, tagList) => {
- return {
- ...releaseProfiles,
- tagList,
- isIndexersPopulated: indexers.isPopulated,
- indexerList: indexers.items
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchIndexers,
- fetchReleaseProfiles,
- deleteReleaseProfile
-};
-
-class ReleaseProfilesConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchReleaseProfiles();
- if (!this.props.isIndexersPopulated) {
- this.props.fetchIndexers();
- }
- }
-
- //
- // Listeners
-
- onConfirmDeleteReleaseProfile = (id) => {
- this.props.deleteReleaseProfile({ id });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-ReleaseProfilesConnector.propTypes = {
- isIndexersPopulated: PropTypes.bool.isRequired,
- fetchReleaseProfiles: PropTypes.func.isRequired,
- deleteReleaseProfile: PropTypes.func.isRequired,
- fetchIndexers: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(ReleaseProfilesConnector);
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.css b/frontend/src/Settings/Quality/Definition/QualityDefinition.css
deleted file mode 100644
index 860333725..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.css
+++ /dev/null
@@ -1,93 +0,0 @@
-.qualityDefinition {
- display: flex;
- align-content: stretch;
- margin: 5px 0;
- padding-top: 5px;
- height: 45px;
- border-top: 1px solid var(--borderColor);
-}
-
-.quality,
-.title {
- flex: 0 1 250px;
- padding-right: 20px;
- line-height: 40px;
-}
-
-.sizeLimit {
- flex: 0 1 500px;
- padding-right: 30px;
-}
-
-.slider {
- width: 100%;
- height: 20px;
-}
-
-.track {
- top: 9px;
- margin: 0 5px;
- height: 3px;
- background-color: var(--sliderAccentColor);
- box-shadow: 0 0 0 #000;
-
- &:nth-child(3n + 1) {
- background-color: #ddd;
- }
-}
-
-.thumb {
- top: 1px;
- z-index: 0 !important;
- width: 18px;
- height: 18px;
- border: 3px solid var(--sliderAccentColor);
- border-radius: 50%;
- background-color: var(--white);
- text-align: center;
- cursor: pointer;
-}
-
-.sizes {
- display: flex;
- justify-content: space-between;
-}
-
-.kilobitsPerSecond {
- display: flex;
- justify-content: space-between;
- flex: 0 0 400px;
-}
-
-.sizeInput {
- composes: input from '~Components/Form/TextInput.css';
-
- display: inline-block;
- margin-left: 5px;
- padding: 6px;
- width: 75px;
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .qualityDefinition {
- flex-wrap: wrap;
- height: auto;
-
- &:first-child {
- border-top: none;
- }
- }
-
- .qualityDefinition:first-child {
- border-top: none;
- }
-
- .quality {
- font-weight: bold;
- line-height: inherit;
- }
-
- .sizeLimit {
- margin-top: 10px;
- }
-}
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts b/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts
deleted file mode 100644
index 9c9e8393a..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.css.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'kilobitsPerSecond': string;
- 'quality': string;
- 'qualityDefinition': string;
- 'sizeInput': string;
- 'sizeLimit': string;
- 'sizes': string;
- 'slider': string;
- 'thumb': string;
- 'title': string;
- 'track': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinition.js b/frontend/src/Settings/Quality/Definition/QualityDefinition.js
deleted file mode 100644
index 48251abfb..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinition.js
+++ /dev/null
@@ -1,331 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import ReactSlider from 'react-slider';
-import NumberInput from 'Components/Form/NumberInput';
-import TextInput from 'Components/Form/TextInput';
-import Label from 'Components/Label';
-import Popover from 'Components/Tooltip/Popover';
-import { kinds, tooltipPositions } from 'Helpers/Props';
-import formatBytes from 'Utilities/Number/formatBytes';
-import roundNumber from 'Utilities/Number/roundNumber';
-import translate from 'Utilities/String/translate';
-import QualityDefinitionLimits from './QualityDefinitionLimits';
-import styles from './QualityDefinition.css';
-
-const MIN = 0;
-const MAX = 1500;
-const MIN_DISTANCE = 1;
-
-const slider = {
- min: MIN,
- max: roundNumber(Math.pow(MAX, 1 / 1.1)),
- step: 0.1
-};
-
-function getValue(inputValue) {
- if (inputValue < MIN) {
- return MIN;
- }
-
- if (inputValue > MAX) {
- return MAX;
- }
-
- return roundNumber(inputValue);
-}
-
-function getSliderValue(value, defaultValue) {
- const sliderValue = value ? Math.pow(value, 1 / 1.1) : defaultValue;
-
- return roundNumber(sliderValue);
-}
-
-class QualityDefinition extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- sliderMinSize: getSliderValue(props.minSize, slider.min),
- sliderMaxSize: getSliderValue(props.maxSize, slider.max),
- sliderPreferredSize: getSliderValue(props.preferredSize, (slider.max - 3))
- };
- }
-
- //
- // Control
-
- trackRenderer(props, state) {
- return (
-
- );
- }
-
- thumbRenderer(props, state) {
- return (
-
- );
- }
-
- //
- // Listeners
-
- onSliderChange = ([sliderMinSize, sliderPreferredSize, sliderMaxSize]) => {
- this.setState({
- sliderMinSize,
- sliderMaxSize,
- sliderPreferredSize
- });
-
- this.props.onSizeChange({
- minSize: roundNumber(Math.pow(sliderMinSize, 1.1)),
- preferredSize: sliderPreferredSize === (slider.max - 3) ? null : roundNumber(Math.pow(sliderPreferredSize, 1.1)),
- maxSize: sliderMaxSize === slider.max ? null : roundNumber(Math.pow(sliderMaxSize, 1.1))
- });
- };
-
- onAfterSliderChange = () => {
- const {
- minSize,
- maxSize,
- preferredSize
- } = this.props;
-
- this.setState({
- sliderMiSize: getSliderValue(minSize, slider.min),
- sliderMaxSize: getSliderValue(maxSize, slider.max),
- sliderPreferredSize: getSliderValue(preferredSize, (slider.max - 3)) // fix
- });
- };
-
- onMinSizeChange = ({ value }) => {
- const minSize = getValue(value);
-
- this.setState({
- sliderMinSize: getSliderValue(minSize, slider.min)
- });
-
- this.props.onSizeChange({
- minSize,
- maxSize: this.props.maxSize,
- preferredSize: this.props.preferredSize
- });
- };
-
- onPreferredSizeChange = ({ value }) => {
- const preferredSize = value === (MAX - 3) ? null : getValue(value);
-
- this.setState({
- sliderPreferredSize: getSliderValue(preferredSize, slider.preferred)
- });
-
- this.props.onSizeChange({
- minSize: this.props.minSize,
- maxSize: this.props.maxSize,
- preferredSize
- });
- };
-
- onMaxSizeChange = ({ value }) => {
- const maxSize = value === MAX ? null : getValue(value);
-
- this.setState({
- sliderMaxSize: getSliderValue(maxSize, slider.max)
- });
-
- this.props.onSizeChange({
- minSize: this.props.minSize,
- maxSize,
- preferredSize: this.props.preferredSize
- });
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- quality,
- title,
- minSize,
- maxSize,
- preferredSize,
- advancedSettings,
- onTitleChange
- } = this.props;
-
- const {
- sliderMinSize,
- sliderMaxSize,
- sliderPreferredSize
- } = this.state;
-
- const minBytes = minSize * 128;
- const minRate = `${formatBytes(minBytes, true)}/s`;
-
- const preferredBytes = preferredSize * 128;
- const preferredRate = preferredBytes ? `${formatBytes(preferredBytes, true)}/s` : translate('Unlimited');
-
- const maxBytes = maxSize && maxSize * 128;
- const maxRate = maxBytes ? `${formatBytes(maxBytes, true)}/s` : translate('Unlimited');
-
- return (
-
-
- {quality.name}
-
-
-
-
-
-
-
-
-
-
-
-
{minRate}
- }
- title={translate('MinimumLimits')}
- body={
-
- }
- position={tooltipPositions.BOTTOM}
- />
-
-
-
-
{preferredRate}
- }
- title={translate('PreferredSize')}
- body={
-
- }
- position={tooltipPositions.BOTTOM}
- />
-
-
-
-
{maxRate}
- }
- title={translate('MaximumLimits')}
- body={
-
- }
- position={tooltipPositions.BOTTOM}
- />
-
-
-
-
- {
- advancedSettings &&
-
-
- {translate('Min')}
-
-
-
-
-
- {translate('Preferred')}
-
-
-
-
-
- {translate('Max')}
-
-
-
-
- }
-
- );
- }
-}
-
-QualityDefinition.propTypes = {
- id: PropTypes.number.isRequired,
- quality: PropTypes.object.isRequired,
- title: PropTypes.string.isRequired,
- minSize: PropTypes.number,
- maxSize: PropTypes.number,
- preferredSize: PropTypes.number,
- advancedSettings: PropTypes.bool.isRequired,
- onTitleChange: PropTypes.func.isRequired,
- onSizeChange: PropTypes.func.isRequired
-};
-
-export default QualityDefinition;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js b/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js
deleted file mode 100644
index eee0558f1..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitionConnector.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { setQualityDefinitionValue } from 'Store/Actions/settingsActions';
-import QualityDefinition from './QualityDefinition';
-
-const mapDispatchToProps = {
- setQualityDefinitionValue,
- clearPendingChanges
-};
-
-class QualityDefinitionConnector extends Component {
-
- componentWillUnmount() {
- this.props.clearPendingChanges({ section: 'settings.qualityDefinitions' });
- }
-
- //
- // Listeners
-
- onTitleChange = ({ value }) => {
- this.props.setQualityDefinitionValue({ id: this.props.id, name: 'title', value });
- };
-
- onSizeChange = ({ minSize, maxSize, preferredSize }) => {
- const {
- id,
- minSize: currentMinSize,
- maxSize: currentMaxSize,
- preferredSize: currentPreferredSize
- } = this.props;
-
- if (minSize !== currentMinSize) {
- this.props.setQualityDefinitionValue({ id, name: 'minSize', value: minSize });
- }
-
- if (maxSize !== currentMaxSize) {
- this.props.setQualityDefinitionValue({ id, name: 'maxSize', value: maxSize });
- }
-
- if (preferredSize !== currentPreferredSize) {
- this.props.setQualityDefinitionValue({ id, name: 'preferredSize', value: preferredSize });
- }
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-QualityDefinitionConnector.propTypes = {
- id: PropTypes.number.isRequired,
- minSize: PropTypes.number,
- maxSize: PropTypes.number,
- preferredSize: PropTypes.number,
- setQualityDefinitionValue: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(null, mapDispatchToProps)(QualityDefinitionConnector);
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitionLimits.js b/frontend/src/Settings/Quality/Definition/QualityDefinitionLimits.js
deleted file mode 100644
index b124ca70c..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitionLimits.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import formatBytes from 'Utilities/Number/formatBytes';
-import translate from 'Utilities/String/translate';
-
-function QualityDefinitionLimits(props) {
- const {
- bytes,
- message
- } = props;
-
- if (!bytes) {
- return {message}
;
- }
-
- const twenty = formatBytes(bytes * 20 * 60);
- const fourtyFive = formatBytes(bytes * 45 * 60);
- const sixty = formatBytes(bytes * 60 * 60);
-
- return (
-
-
- {translate('20MinutesTwenty', [twenty])}
-
-
- {translate('45MinutesFourtyFive', [fourtyFive])}
-
-
- {translate('60MinutesSixty', [sixty])}
-
-
- );
-}
-
-QualityDefinitionLimits.propTypes = {
- bytes: PropTypes.number,
- message: PropTypes.string.isRequired
-};
-
-export default QualityDefinitionLimits;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitions.css b/frontend/src/Settings/Quality/Definition/QualityDefinitions.css
deleted file mode 100644
index 3da40c624..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitions.css
+++ /dev/null
@@ -1,41 +0,0 @@
-.header {
- display: flex;
- font-weight: bold;
-}
-
-.quality,
-.title {
- flex: 0 1 250px;
-}
-
-.sizeLimit {
- flex: 0 1 500px;
-}
-
-.kilobitsPerSecond {
- flex: 0 0 250px;
-}
-
-.sizeLimitHelpTextContainer {
- display: flex;
- justify-content: flex-end;
- margin-top: 20px;
- max-width: 1000px;
-}
-
-.sizeLimitHelpText {
- max-width: 500px;
- color: var(--helpTextColor);
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .header {
- display: none;
- }
-
- .definitions {
- &:first-child {
- border-top: none;
- }
- }
-}
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitions.css.d.ts b/frontend/src/Settings/Quality/Definition/QualityDefinitions.css.d.ts
deleted file mode 100644
index 2284fb200..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitions.css.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'definitions': string;
- 'header': string;
- 'kilobitsPerSecond': string;
- 'quality': string;
- 'sizeLimit': string;
- 'sizeLimitHelpText': string;
- 'sizeLimitHelpTextContainer': string;
- 'title': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitions.js b/frontend/src/Settings/Quality/Definition/QualityDefinitions.js
deleted file mode 100644
index 392b9e1a7..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitions.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FieldSet from 'Components/FieldSet';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import translate from 'Utilities/String/translate';
-import QualityDefinitionConnector from './QualityDefinitionConnector';
-import styles from './QualityDefinitions.css';
-
-class QualityDefinitions extends Component {
-
- //
- // Render
-
- render() {
- const {
- items,
- advancedSettings,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
-
- {translate('Quality')}
-
-
- {translate('Title')}
-
-
- {translate('SizeLimit')}
-
-
- {
- advancedSettings ?
-
- Kilobits Per Second
-
:
- null
- }
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
- {translate('QualityLimitsHelpText')}
-
-
-
-
- );
- }
-}
-
-QualityDefinitions.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- defaultProfile: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- advancedSettings: PropTypes.bool.isRequired
-};
-
-export default QualityDefinitions;
diff --git a/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js b/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js
deleted file mode 100644
index 4b1fc72a6..000000000
--- a/frontend/src/Settings/Quality/Definition/QualityDefinitionsConnector.js
+++ /dev/null
@@ -1,90 +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 { fetchQualityDefinitions, saveQualityDefinitions } from 'Store/Actions/settingsActions';
-import QualityDefinitions from './QualityDefinitions';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.qualityDefinitions,
- (state) => state.settings.advancedSettings,
- (qualityDefinitions, advancedSettings) => {
- const items = qualityDefinitions.items.map((item) => {
- const pendingChanges = qualityDefinitions.pendingChanges[item.id] || {};
-
- return Object.assign({}, item, pendingChanges);
- });
-
- return {
- ...qualityDefinitions,
- items,
- hasPendingChanges: !_.isEmpty(qualityDefinitions.pendingChanges),
- advancedSettings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchQualityDefinitions: fetchQualityDefinitions,
- dispatchSaveQualityDefinitions: saveQualityDefinitions
-};
-
-class QualityDefinitionsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- dispatchFetchQualityDefinitions,
- dispatchSaveQualityDefinitions,
- onChildMounted
- } = this.props;
-
- dispatchFetchQualityDefinitions();
- onChildMounted(dispatchSaveQualityDefinitions);
- }
-
- componentDidUpdate(prevProps) {
- const {
- hasPendingChanges,
- isSaving,
- onChildStateChange
- } = this.props;
-
- if (
- prevProps.isSaving !== isSaving ||
- prevProps.hasPendingChanges !== hasPendingChanges
- ) {
- onChildStateChange({
- isSaving,
- hasPendingChanges
- });
- }
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-QualityDefinitionsConnector.propTypes = {
- isSaving: PropTypes.bool.isRequired,
- hasPendingChanges: PropTypes.bool.isRequired,
- dispatchFetchQualityDefinitions: PropTypes.func.isRequired,
- dispatchSaveQualityDefinitions: PropTypes.func.isRequired,
- onChildMounted: PropTypes.func.isRequired,
- onChildStateChange: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps, null)(QualityDefinitionsConnector);
diff --git a/frontend/src/Settings/Quality/Quality.js b/frontend/src/Settings/Quality/Quality.js
deleted file mode 100644
index 49c9df5d0..000000000
--- a/frontend/src/Settings/Quality/Quality.js
+++ /dev/null
@@ -1,105 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component, Fragment } from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
-import { icons } from 'Helpers/Props';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import QualityDefinitionsConnector from './Definition/QualityDefinitionsConnector';
-import ResetQualityDefinitionsModal from './Reset/ResetQualityDefinitionsModal';
-
-class Quality extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this._saveCallback = null;
-
- this.state = {
- isSaving: false,
- hasPendingChanges: false,
- isConfirmQualityDefinitionResetModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onChildMounted = (saveCallback) => {
- this._saveCallback = saveCallback;
- };
-
- onChildStateChange = (payload) => {
- this.setState(payload);
- };
-
- onResetQualityDefinitionsPress = () => {
- this.setState({ isConfirmQualityDefinitionResetModalOpen: true });
- };
-
- onCloseResetQualityDefinitionsModal = () => {
- this.setState({ isConfirmQualityDefinitionResetModalOpen: false });
- };
-
- onSavePress = () => {
- if (this._saveCallback) {
- this._saveCallback();
- }
- };
-
- //
- // Render
-
- render() {
- const {
- isSaving,
- isResettingQualityDefinitions,
- hasPendingChanges
- } = this.state;
-
- return (
-
-
-
-
-
-
- }
- onSavePress={this.onSavePress}
- />
-
-
-
-
-
-
-
- );
- }
-}
-
-Quality.propTypes = {
- isResettingQualityDefinitions: PropTypes.bool.isRequired
-};
-
-export default Quality;
diff --git a/frontend/src/Settings/Quality/QualityConnector.js b/frontend/src/Settings/Quality/QualityConnector.js
deleted file mode 100644
index 8cc9219cb..000000000
--- a/frontend/src/Settings/Quality/QualityConnector.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import Quality from './Quality';
-
-function createMapStateToProps() {
- return createSelector(
- createCommandExecutingSelector(commandNames.RESET_QUALITY_DEFINITIONS),
- (isResettingQualityDefinitions) => {
- return {
- isResettingQualityDefinitions
- };
- }
- );
-}
-
-class QualityConnector extends Component {
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-QualityConnector.propTypes = {
- isResettingQualityDefinitions: PropTypes.bool.isRequired
-};
-
-export default connect(createMapStateToProps)(QualityConnector);
diff --git a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModal.js b/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModal.js
deleted file mode 100644
index ee9caa260..000000000
--- a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModal.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import ResetQualityDefinitionsModalContentConnector from './ResetQualityDefinitionsModalContentConnector';
-
-function ResetQualityDefinitionsModal(props) {
- const {
- isOpen,
- onModalClose,
- ...otherProps
- } = props;
-
- return (
-
-
-
- );
-}
-
-ResetQualityDefinitionsModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default ResetQualityDefinitionsModal;
diff --git a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css b/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css
deleted file mode 100644
index 99c50adbe..000000000
--- a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.messageContainer {
- margin-bottom: 20px;
-}
diff --git a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css.d.ts b/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css.d.ts
deleted file mode 100644
index 651320174..000000000
--- a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'messageContainer': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.js b/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.js
deleted file mode 100644
index 11f9dfa2f..000000000
--- a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContent.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './ResetQualityDefinitionsModalContent.css';
-
-class ResetQualityDefinitionsModalContent extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- resetDefinitionTitles: false
- };
- }
-
- //
- // Listeners
-
- onResetDefinitionTitlesChange = ({ value }) => {
- this.setState({ resetDefinitionTitles: value });
- };
-
- onResetQualityDefinitionsConfirmed = () => {
- const resetDefinitionTitles = this.state.resetDefinitionTitles;
-
- this.setState({ resetDefinitionTitles: false });
- this.props.onResetQualityDefinitions(resetDefinitionTitles);
- };
-
- //
- // Render
-
- render() {
- const {
- onModalClose,
- isResettingQualityDefinitions
- } = this.props;
-
- const resetDefinitionTitles = this.state.resetDefinitionTitles;
-
- return (
-
-
- {translate('ResetQualityDefinitions')}
-
-
-
-
- {translate('ResetQualityDefinitionsMessageText')}
-
-
-
-
- {translate('ResetTitles')}
-
-
-
-
-
-
-
-
-
- {translate('Cancel')}
-
-
-
- {translate('Reset')}
-
-
-
- );
- }
-}
-
-ResetQualityDefinitionsModalContent.propTypes = {
- onResetQualityDefinitions: PropTypes.func.isRequired,
- isResettingQualityDefinitions: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default ResetQualityDefinitionsModalContent;
diff --git a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContentConnector.js b/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContentConnector.js
deleted file mode 100644
index 645cac1e1..000000000
--- a/frontend/src/Settings/Quality/Reset/ResetQualityDefinitionsModalContentConnector.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import { executeCommand } from 'Store/Actions/commandActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import ResetQualityDefinitionsModalContent from './ResetQualityDefinitionsModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- createCommandExecutingSelector(commandNames.RESET_QUALITY_DEFINITIONS),
- (isResettingQualityDefinitions) => {
- return {
- isResettingQualityDefinitions
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- executeCommand
-};
-
-class ResetQualityDefinitionsModalContentConnector extends Component {
-
- //
- // Listeners
-
- onResetQualityDefinitions = (resetTitles) => {
- this.props.executeCommand({ name: commandNames.RESET_QUALITY_DEFINITIONS, resetTitles });
- this.props.onModalClose(true);
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-ResetQualityDefinitionsModalContentConnector.propTypes = {
- onModalClose: PropTypes.func.isRequired,
- isResettingQualityDefinitions: PropTypes.bool.isRequired,
- executeCommand: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(ResetQualityDefinitionsModalContentConnector);
diff --git a/frontend/src/Settings/Settings.css b/frontend/src/Settings/Settings.css
deleted file mode 100644
index ef69e9674..000000000
--- a/frontend/src/Settings/Settings.css
+++ /dev/null
@@ -1,18 +0,0 @@
-.link {
- composes: link from '~Components/Link/Link.css';
-
- border-bottom: 1px solid #e5e5e5;
- color: var(--textColor);
- font-size: 21px;
-
- &:hover {
- color: #616573;
- text-decoration: none;
- }
-}
-
-.summary {
- margin-top: 10px;
- margin-bottom: 30px;
- color: var(--helpTextColor);
-}
diff --git a/frontend/src/Settings/Settings.css.d.ts b/frontend/src/Settings/Settings.css.d.ts
deleted file mode 100644
index ad1605615..000000000
--- a/frontend/src/Settings/Settings.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'link': string;
- 'summary': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Settings.js b/frontend/src/Settings/Settings.js
deleted file mode 100644
index d2a86adc6..000000000
--- a/frontend/src/Settings/Settings.js
+++ /dev/null
@@ -1,156 +0,0 @@
-import React from 'react';
-import Link from 'Components/Link/Link';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import translate from 'Utilities/String/translate';
-import SettingsToolbarConnector from './SettingsToolbarConnector';
-import styles from './Settings.css';
-
-function Settings() {
- return (
-
-
-
-
-
- {translate('MediaManagement')}
-
-
-
- {translate('MediaManagementSettingsSummary')}
-
-
-
- {translate('Profiles')}
-
-
-
- {translate('ProfilesSettingsArtistSummary')}
-
-
-
- {translate('Quality')}
-
-
-
- {translate('QualitySettingsSummary')}
-
-
-
- {translate('CustomFormats')}
-
-
-
- {translate('CustomFormatsSettingsSummary')}
-
-
-
- {translate('Indexers')}
-
-
-
- {translate('IndexersSettingsSummary')}
-
-
-
- {translate('DownloadClients')}
-
-
-
- {translate('DownloadClientsSettingsSummary')}
-
-
-
- {translate('ImportLists')}
-
-
-
- {translate('ImportListsSettingsSummary')}
-
-
-
- {translate('Connect')}
-
-
-
- {translate('ConnectSettingsSummary')}
-
-
-
- {translate('Metadata')}
-
-
-
- {translate('MetadataSettingsArtistSummary')}
-
-
-
- {translate('Tags')}
-
-
-
- {translate('TagsSettingsSummary')}
-
-
-
- {translate('General')}
-
-
-
- {translate('GeneralSettingsSummary')}
-
-
-
- {translate('Ui')}
-
-
-
- {translate('UiSettingsSummary')}
-
-
-
- );
-}
-
-Settings.propTypes = {
-};
-
-export default Settings;
diff --git a/frontend/src/Settings/SettingsToolbar.js b/frontend/src/Settings/SettingsToolbar.js
deleted file mode 100644
index b36cdcaca..000000000
--- a/frontend/src/Settings/SettingsToolbar.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import keyboardShortcuts, { shortcuts } from 'Components/keyboardShortcuts';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import AdvancedSettingsButton from './AdvancedSettingsButton';
-import PendingChangesModal from './PendingChangesModal';
-
-class SettingsToolbar extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.bindShortcut(shortcuts.SAVE_SETTINGS.key, this.saveSettings, { isGlobal: true });
- }
-
- //
- // Control
-
- saveSettings = (event) => {
- event.preventDefault();
-
- const {
- hasPendingChanges,
- onSavePress
- } = this.props;
-
- if (hasPendingChanges) {
- onSavePress();
- }
- };
-
- //
- // Render
-
- render() {
- const {
- advancedSettings,
- showSave,
- isSaving,
- hasPendingChanges,
- additionalButtons,
- hasPendingLocation,
- onSavePress,
- onConfirmNavigation,
- onCancelNavigation,
- onAdvancedSettingsPress
- } = this.props;
-
- return (
-
-
-
-
- {
- showSave &&
-
- }
-
- {
- additionalButtons
- }
-
-
-
-
- );
- }
-}
-
-SettingsToolbar.propTypes = {
- advancedSettings: PropTypes.bool.isRequired,
- showSave: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool,
- hasPendingLocation: PropTypes.bool.isRequired,
- hasPendingChanges: PropTypes.bool,
- additionalButtons: PropTypes.node,
- onSavePress: PropTypes.func,
- onAdvancedSettingsPress: PropTypes.func.isRequired,
- onConfirmNavigation: PropTypes.func.isRequired,
- onCancelNavigation: PropTypes.func.isRequired,
- bindShortcut: PropTypes.func.isRequired
-};
-
-SettingsToolbar.defaultProps = {
- showSave: true
-};
-
-export default keyboardShortcuts(SettingsToolbar);
diff --git a/frontend/src/Settings/SettingsToolbarConnector.js b/frontend/src/Settings/SettingsToolbarConnector.js
deleted file mode 100644
index 65d937ab8..000000000
--- a/frontend/src/Settings/SettingsToolbarConnector.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { withRouter } from 'react-router-dom';
-import { toggleAdvancedSettings } from 'Store/Actions/settingsActions';
-import SettingsToolbar from './SettingsToolbar';
-
-function mapStateToProps(state) {
- return {
- advancedSettings: state.settings.advancedSettings
- };
-}
-
-const mapDispatchToProps = {
- toggleAdvancedSettings
-};
-
-class SettingsToolbarConnector extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- nextLocation: null,
- nextLocationAction: null,
- confirmed: false
- };
-
- this._unblock = null;
- }
-
- componentDidMount() {
- this._unblock = this.props.history.block(this.routerWillLeave);
- }
-
- componentWillUnmount() {
- if (this._unblock) {
- this._unblock();
- }
- }
-
- //
- // Control
-
- routerWillLeave = (nextLocation, nextLocationAction) => {
- if (this.state.confirmed) {
- this.setState({
- nextLocation: null,
- nextLocationAction: null,
- confirmed: false
- });
-
- return true;
- }
-
- if (this.props.hasPendingChanges ) {
- this.setState({
- nextLocation,
- nextLocationAction
- });
-
- return false;
- }
-
- return true;
- };
-
- //
- // Listeners
-
- onAdvancedSettingsPress = () => {
- this.props.toggleAdvancedSettings();
- };
-
- onConfirmNavigation = () => {
- const {
- nextLocation,
- nextLocationAction
- } = this.state;
-
- const history = this.props.history;
-
- const path = `${nextLocation.pathname}${nextLocation.search}`;
-
- this.setState({
- confirmed: true
- }, () => {
- if (nextLocationAction === 'PUSH') {
- history.push(path);
- } else {
- // Unfortunately back and forward both use POP,
- // which means we don't actually know which direction
- // the user wanted to go, assuming back.
-
- history.goBack();
- }
- });
- };
-
- onCancelNavigation = () => {
- this.setState({
- nextLocation: null,
- nextLocationAction: null,
- confirmed: false
- });
- };
-
- //
- // Render
-
- render() {
- const hasPendingLocation = this.state.nextLocation !== null;
-
- return (
-
- );
- }
-}
-
-const historyShape = {
- block: PropTypes.func.isRequired,
- goBack: PropTypes.func.isRequired,
- push: PropTypes.func.isRequired
-};
-
-SettingsToolbarConnector.propTypes = {
- showSave: PropTypes.bool,
- hasPendingChanges: PropTypes.bool.isRequired,
- history: PropTypes.shape(historyShape).isRequired,
- onSavePress: PropTypes.func,
- toggleAdvancedSettings: PropTypes.func.isRequired
-};
-
-SettingsToolbarConnector.defaultProps = {
- hasPendingChanges: false
-};
-
-export default withRouter(connect(mapStateToProps, mapDispatchToProps)(SettingsToolbarConnector));
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css b/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css
deleted file mode 100644
index b1e2de95b..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.autoTagging {
- composes: card from '~Components/Card.css';
-
- width: 300px;
-}
-
-.nameContainer {
- display: flex;
- justify-content: space-between;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.cloneButton {
- composes: button from '~Components/Link/IconButton.css';
-
- height: 36px;
-}
-
-.formats {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
- pointer-events: all;
-}
-
-.tooltipLabel {
- composes: label from '~Components/Label.css';
-
- margin: 0;
- border: none;
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css.d.ts
deleted file mode 100644
index b6b665429..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'autoTagging': string;
- 'cloneButton': string;
- 'formats': string;
- 'name': string;
- 'nameContainer': string;
- 'tooltipLabel': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.js b/frontend/src/Settings/Tags/AutoTagging/AutoTagging.js
deleted file mode 100644
index 760273cb3..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTagging.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback, useState } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import TagList from 'Components/TagList';
-import { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditAutoTaggingModal from './EditAutoTaggingModal';
-import styles from './AutoTagging.css';
-
-export default function AutoTagging(props) {
- const {
- id,
- name,
- tags,
- tagList,
- specifications,
- isDeleting,
- onConfirmDeleteAutoTagging,
- onCloneAutoTaggingPress
- } = props;
-
- const [isEditModalOpen, setIsEditModalOpen] = useState(false);
- const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
-
- const onEditPress = useCallback(() => {
- setIsEditModalOpen(true);
- }, [setIsEditModalOpen]);
-
- const onEditModalClose = useCallback(() => {
- setIsEditModalOpen(false);
- }, [setIsEditModalOpen]);
-
- const onDeletePress = useCallback(() => {
- setIsEditModalOpen(false);
- setIsDeleteModalOpen(true);
- }, [setIsEditModalOpen, setIsDeleteModalOpen]);
-
- const onDeleteModalClose = useCallback(() => {
- setIsDeleteModalOpen(false);
- }, [setIsDeleteModalOpen]);
-
- const onConfirmDelete = useCallback(() => {
- onConfirmDeleteAutoTagging(id);
- }, [id, onConfirmDeleteAutoTagging]);
-
- const onClonePress = useCallback(() => {
- onCloneAutoTaggingPress(id);
- }, [id, onCloneAutoTaggingPress]);
-
- return (
-
-
-
-
-
-
- {
- specifications.map((item, index) => {
- if (!item) {
- return null;
- }
-
- let kind = kinds.DEFAULT;
- if (item.required) {
- kind = kinds.SUCCESS;
- }
- if (item.negate) {
- kind = kinds.DANGER;
- }
-
- return (
-
- {item.name}
-
- );
- })
- }
-
-
-
-
-
-
- );
-}
-
-AutoTagging.propTypes = {
- id: PropTypes.number.isRequired,
- name: PropTypes.string.isRequired,
- specifications: PropTypes.arrayOf(PropTypes.object).isRequired,
- tags: PropTypes.arrayOf(PropTypes.number).isRequired,
- tagList: PropTypes.arrayOf(PropTypes.object).isRequired,
- isDeleting: PropTypes.bool.isRequired,
- onConfirmDeleteAutoTagging: PropTypes.func.isRequired,
- onCloneAutoTaggingPress: PropTypes.func.isRequired
-};
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css b/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css
deleted file mode 100644
index 40950bd5f..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css
+++ /dev/null
@@ -1,21 +0,0 @@
-.autoTaggings {
- display: flex;
- flex-wrap: wrap;
-}
-
-.addAutoTagging {
- composes: autoTagging from '~./AutoTagging.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
- font-size: 45px;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css.d.ts
deleted file mode 100644
index ef3094d3b..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.css.d.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addAutoTagging': string;
- 'autoTaggings': string;
- 'center': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.js b/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.js
deleted file mode 100644
index 005547bb7..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/AutoTaggings.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import React, { useCallback, useEffect, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { icons } from 'Helpers/Props';
-import {
- cloneAutoTagging,
- deleteAutoTagging,
- fetchAutoTaggings,
- fetchRootFolders
-} from 'Store/Actions/settingsActions';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import createTagsSelector from 'Store/Selectors/createTagsSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import translate from 'Utilities/String/translate';
-import AutoTagging from './AutoTagging';
-import EditAutoTaggingModal from './EditAutoTaggingModal';
-import styles from './AutoTaggings.css';
-
-export default function AutoTaggings() {
- const {
- error,
- items,
- isDeleting,
- isFetching,
- isPopulated
- } = useSelector(
- createSortedSectionSelector('settings.autoTaggings', sortByProp('name'))
- );
-
- const tagList = useSelector(createTagsSelector());
- const dispatch = useDispatch();
- const [isEditModalOpen, setIsEditModalOpen] = useState(false);
- const [tagsFromId, setTagsFromId] = useState(undefined);
-
- const onClonePress = useCallback((id) => {
- dispatch(cloneAutoTagging({ id }));
-
- setTagsFromId(id);
- setIsEditModalOpen(true);
- }, [dispatch, setIsEditModalOpen]);
-
- const onEditPress = useCallback(() => {
- setIsEditModalOpen(true);
- }, [setIsEditModalOpen]);
-
- const onEditModalClose = useCallback(() => {
- setIsEditModalOpen(false);
- }, [setIsEditModalOpen]);
-
- const onConfirmDelete = useCallback((id) => {
- dispatch(deleteAutoTagging({ id }));
- }, [dispatch]);
-
- useEffect(() => {
- dispatch(fetchAutoTaggings());
- dispatch(fetchRootFolders());
- }, [dispatch]);
-
- return (
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModal.js b/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModal.js
deleted file mode 100644
index c6f810785..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModal.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback, useState } from 'react';
-import { useDispatch } from 'react-redux';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditAutoTaggingModalContent from './EditAutoTaggingModalContent';
-
-export default function EditAutoTaggingModal(props) {
- const {
- isOpen,
- onModalClose: onOriginalModalClose,
- ...otherProps
- } = props;
-
- const dispatch = useDispatch();
- const [height, setHeight] = useState('auto');
-
- const onContentHeightChange = useCallback((h) => {
- if (height === 'auto' || h > height) {
- setHeight(h);
- }
- }, [height, setHeight]);
-
- const onModalClose = useCallback(() => {
- dispatch(clearPendingChanges({ section: 'settings.autoTaggings' }));
- onOriginalModalClose();
- }, [dispatch, onOriginalModalClose]);
-
- return (
-
-
-
- );
-}
-
-EditAutoTaggingModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
diff --git a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css b/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css
deleted file mode 100644
index d503b0af3..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css
+++ /dev/null
@@ -1,32 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
-
-.rightButtons {
- justify-content: flex-end;
- margin-right: auto;
-}
-
-.addSpecification {
- composes: autoTagging from '~./AutoTagging.css';
-
- background-color: var(--cardAlternateBackgroundColor);
- color: var(--gray);
- text-align: center;
- font-size: 45px;
-}
-
-.center {
- display: inline-block;
- padding: 5px 20px 0;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardCenterBackgroundColor);
-}
-
-.autoTaggings {
- display: flex;
- flex-wrap: wrap;
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css.d.ts
deleted file mode 100644
index 2a7f6b41e..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'addSpecification': string;
- 'autoTaggings': string;
- 'center': string;
- 'deleteButton': string;
- 'rightButtons': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.js b/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.js
deleted file mode 100644
index 01a5e846b..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/EditAutoTaggingModalContent.js
+++ /dev/null
@@ -1,269 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback, useEffect, useRef, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import Card from 'Components/Card';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import Icon from 'Components/Icon';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 { icons, inputTypes, kinds } from 'Helpers/Props';
-import {
- cloneAutoTaggingSpecification,
- deleteAutoTaggingSpecification,
- fetchAutoTaggingSpecifications,
- saveAutoTagging,
- setAutoTaggingValue
-} from 'Store/Actions/settingsActions';
-import { createProviderSettingsSelectorHook } from 'Store/Selectors/createProviderSettingsSelector';
-import translate from 'Utilities/String/translate';
-import AddSpecificationModal from './Specifications/AddSpecificationModal';
-import EditSpecificationModal from './Specifications/EditSpecificationModal';
-import Specification from './Specifications/Specification';
-import styles from './EditAutoTaggingModalContent.css';
-
-export default function EditAutoTaggingModalContent(props) {
- const {
- id,
- tagsFromId,
- onModalClose,
- onDeleteAutoTaggingPress
- } = props;
-
- const {
- error,
- item,
- isFetching,
- isSaving,
- saveError,
- validationErrors,
- validationWarnings
- } = useSelector(createProviderSettingsSelectorHook('autoTaggings', id));
-
- const {
- isPopulated: specificationsPopulated,
- items: specifications
- } = useSelector((state) => state.settings.autoTaggingSpecifications);
-
- const dispatch = useDispatch();
- const [isAddSpecificationModalOpen, setIsAddSpecificationModalOpen] = useState(false);
- const [isEditSpecificationModalOpen, setIsEditSpecificationModalOpen] = useState(false);
- // const [isImportAutoTaggingModalOpen, setIsImportAutoTaggingModalOpen] = useState(false);
-
- const onAddSpecificationPress = useCallback(() => {
- setIsAddSpecificationModalOpen(true);
- }, [setIsAddSpecificationModalOpen]);
-
- const onAddSpecificationModalClose = useCallback(({ specificationSelected = false } = {}) => {
- setIsAddSpecificationModalOpen(false);
- setIsEditSpecificationModalOpen(specificationSelected);
- }, [setIsAddSpecificationModalOpen]);
-
- const onEditSpecificationModalClose = useCallback(() => {
- setIsEditSpecificationModalOpen(false);
- }, [setIsEditSpecificationModalOpen]);
-
- const onInputChange = useCallback(({ name, value }) => {
- dispatch(setAutoTaggingValue({ name, value }));
- }, [dispatch]);
-
- const onSavePress = useCallback(() => {
- dispatch(saveAutoTagging({ id }));
- }, [dispatch, id]);
-
- const onCloneSpecificationPress = useCallback((specId) => {
- dispatch(cloneAutoTaggingSpecification({ id: specId }));
- }, [dispatch]);
-
- const onConfirmDeleteSpecification = useCallback((specId) => {
- dispatch(deleteAutoTaggingSpecification({ id: specId }));
- }, [dispatch]);
-
- useEffect(() => {
- dispatch(fetchAutoTaggingSpecifications({ id: tagsFromId || id }));
- }, [id, tagsFromId, dispatch]);
-
- const isSavingRef = useRef();
-
- useEffect(() => {
- if (isSavingRef.current && !isSaving && !saveError) {
- onModalClose();
- }
-
- isSavingRef.current = isSaving;
- }, [isSaving, saveError, onModalClose]);
-
- const {
- name,
- removeTagsAutomatically,
- tags
- } = item;
-
- return (
-
-
-
- {id ? translate('EditAutoTag') : translate('AddAutoTag')}
-
-
-
-
- {
- isFetching ?
: null
- }
-
- {
- !isFetching && !!error ?
-
- {translate('AddAutoTagError')}
-
:
- null
- }
-
- {
- !isFetching && !error && specificationsPopulated ?
-
-
-
-
-
- {
- specifications.map((tag) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
- {/*
*/}
-
-
:
- null
- }
-
-
-
-
- {
- id ?
-
- {translate('Delete')}
- :
- null
- }
-
- {/*
- Import
- */}
-
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditAutoTaggingModalContent.propTypes = {
- id: PropTypes.number,
- tagsFromId: PropTypes.number,
- onModalClose: PropTypes.func.isRequired,
- onDeleteAutoTaggingPress: PropTypes.func
-};
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css
deleted file mode 100644
index eabcae750..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css
+++ /dev/null
@@ -1,44 +0,0 @@
-.specification {
- composes: card from '~Components/Card.css';
-
- position: relative;
- width: 300px;
- height: 100px;
-}
-
-.underlay {
- @add-mixin cover;
-}
-
-.overlay {
- @add-mixin linkOverlay;
-
- padding: 10px;
-}
-
-.name {
- text-align: center;
- font-weight: lighter;
- font-size: 24px;
-}
-
-.actions {
- margin-top: 20px;
- text-align: right;
-}
-
-.presetsMenu {
- composes: menu from '~Components/Menu/Menu.css';
-
- display: inline-block;
- margin: 0 5px;
-}
-
-.presetsMenuButton {
- composes: button from '~Components/Link/Button.css';
-
- &::after {
- margin-left: 5px;
- content: '\25BE';
- }
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css.d.ts
deleted file mode 100644
index 7f8a93de9..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'name': string;
- 'overlay': string;
- 'presetsMenu': string;
- 'presetsMenuButton': string;
- 'specification': string;
- 'underlay': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.js
deleted file mode 100644
index f6f2b134e..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationItem.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback } from 'react';
-import Button from 'Components/Link/Button';
-import Link from 'Components/Link/Link';
-import Menu from 'Components/Menu/Menu';
-import MenuContent from 'Components/Menu/MenuContent';
-import { sizes } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import AddSpecificationPresetMenuItem from './AddSpecificationPresetMenuItem';
-import styles from './AddSpecificationItem.css';
-
-export default function AddSpecificationItem(props) {
- const {
- implementation,
- implementationName,
- infoLink,
- presets,
- onSpecificationSelect
- } = props;
-
- const onWrappedSpecificationSelect = useCallback(() => {
- onSpecificationSelect({ implementation });
- }, [implementation, onSpecificationSelect]);
-
- const hasPresets = !!presets && !!presets.length;
-
- return (
-
-
-
-
-
- {implementationName}
-
-
-
- {
- hasPresets ?
-
-
- {translate('Custom')}
-
-
-
-
- {translate('Presets')}
-
-
-
- {
- presets.map((preset, index) => {
- return (
-
- );
- })
- }
-
-
- :
- null
- }
-
- {
- infoLink ?
-
- {translate('MoreInfo')}
- :
- null
- }
-
-
-
- );
-}
-
-AddSpecificationItem.propTypes = {
- implementation: PropTypes.string.isRequired,
- implementationName: PropTypes.string.isRequired,
- infoLink: PropTypes.string,
- presets: PropTypes.arrayOf(PropTypes.object),
- onSpecificationSelect: PropTypes.func.isRequired
-};
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModal.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModal.js
deleted file mode 100644
index 1a8c115f0..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModal.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import AddSpecificationModalContent from './AddSpecificationModalContent';
-
-function AddSpecificationModal({ isOpen, onModalClose, ...otherProps }) {
- return (
-
-
-
- );
-}
-
-AddSpecificationModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default AddSpecificationModal;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css
deleted file mode 100644
index d51349ea9..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.specifications {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css.d.ts
deleted file mode 100644
index 83fbf5804..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'specifications': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.js
deleted file mode 100644
index 454a2591a..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationModalContent.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback, useEffect } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import Alert from 'Components/Alert';
-import Button from 'Components/Link/Button';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-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 { kinds } from 'Helpers/Props';
-import {
- fetchAutoTaggingSpecificationSchema,
- selectAutoTaggingSpecificationSchema
-} from 'Store/Actions/settingsActions';
-import translate from 'Utilities/String/translate';
-import AddSpecificationItem from './AddSpecificationItem';
-import styles from './AddSpecificationModalContent.css';
-
-export default function AddSpecificationModalContent(props) {
- const {
- onModalClose
- } = props;
-
- const {
- isSchemaFetching,
- isSchemaPopulated,
- schemaError,
- schema
- } = useSelector(
- (state) => state.settings.autoTaggingSpecifications
- );
-
- const dispatch = useDispatch();
-
- const onSpecificationSelect = useCallback(({ implementation, name }) => {
- dispatch(selectAutoTaggingSpecificationSchema({ implementation, presetName: name }));
- onModalClose({ specificationSelected: true });
- }, [dispatch, onModalClose]);
-
- useEffect(() => {
- dispatch(fetchAutoTaggingSpecificationSchema());
- }, [dispatch]);
-
- return (
-
-
- {translate('AddCondition')}
-
-
-
- {
- isSchemaFetching ? : null
- }
-
- {
- !isSchemaFetching && !!schemaError ?
-
- {translate('AddConditionError')}
-
:
- null
- }
-
- {
- isSchemaPopulated && !schemaError ?
-
-
-
-
- {translate('SupportedAutoTaggingProperties')}
-
-
-
-
- {
- schema.map((specification) => {
- return (
-
- );
- })
- }
-
-
-
:
- null
- }
-
-
-
-
- {translate('Close')}
-
-
-
- );
-}
-
-AddSpecificationModalContent.propTypes = {
- onModalClose: PropTypes.func.isRequired
-};
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationPresetMenuItem.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationPresetMenuItem.js
deleted file mode 100644
index b043ddf06..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/AddSpecificationPresetMenuItem.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback } from 'react';
-import MenuItem from 'Components/Menu/MenuItem';
-
-export default function AddSpecificationPresetMenuItem(props) {
- const {
- name,
- implementation,
- onPress,
- ...otherProps
- } = props;
-
- const onWrappedPress = useCallback(() => {
- onPress({
- name,
- implementation
- });
- }, [name, implementation, onPress]);
-
- return (
-
- {name}
-
- );
-}
-
-AddSpecificationPresetMenuItem.propTypes = {
- name: PropTypes.string.isRequired,
- implementation: PropTypes.string.isRequired,
- onPress: PropTypes.func.isRequired
-};
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModal.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModal.js
deleted file mode 100644
index 16ed4daec..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModal.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback } from 'react';
-import { useDispatch } from 'react-redux';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import EditSpecificationModalContent from './EditSpecificationModalContent';
-
-function EditSpecificationModal({ isOpen, onModalClose, ...otherProps }) {
- const dispatch = useDispatch();
-
- const onWrappedModalClose = useCallback(() => {
- dispatch(clearPendingChanges({ section: 'settings.autoTaggingSpecifications' }));
- onModalClose();
- }, [onModalClose, dispatch]);
-
- return (
-
-
-
- );
-}
-
-EditSpecificationModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditSpecificationModal;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css
deleted file mode 100644
index a2b6014df..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css.d.ts
deleted file mode 100644
index c5f0ef8a7..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js
deleted file mode 100644
index 04302729b..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContent.js
+++ /dev/null
@@ -1,190 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import Alert from 'Components/Alert';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
-import Button from 'Components/Link/Button';
-import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-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 { inputTypes, kinds } from 'Helpers/Props';
-import {
- clearAutoTaggingSpecificationPending,
- saveAutoTaggingSpecification,
- setAutoTaggingSpecificationFieldValue,
- setAutoTaggingSpecificationValue
-} from 'Store/Actions/settingsActions';
-import { createProviderSettingsSelectorHook } from 'Store/Selectors/createProviderSettingsSelector';
-import translate from 'Utilities/String/translate';
-import styles from './EditSpecificationModalContent.css';
-
-function EditSpecificationModalContent(props) {
- const {
- id,
- onDeleteSpecificationPress,
- onModalClose
- } = props;
-
- const advancedSettings = useSelector((state) => state.settings.advancedSettings);
-
- const {
- item,
- ...otherFormProps
- } = useSelector(
- createProviderSettingsSelectorHook('autoTaggingSpecifications', id)
- );
-
- const dispatch = useDispatch();
-
- const onInputChange = useCallback(({ name, value }) => {
- dispatch(setAutoTaggingSpecificationValue({ name, value }));
- }, [dispatch]);
-
- const onFieldChange = useCallback(({ name, value }) => {
- dispatch(setAutoTaggingSpecificationFieldValue({ name, value }));
- }, [dispatch]);
-
- const onCancelPress = useCallback(({ name, value }) => {
- dispatch(clearAutoTaggingSpecificationPending());
- onModalClose();
- }, [dispatch, onModalClose]);
-
- const onSavePress = useCallback(({ name, value }) => {
- dispatch(saveAutoTaggingSpecification({ id }));
- onModalClose();
- }, [dispatch, id, onModalClose]);
-
- const {
- implementationName,
- name,
- negate,
- required,
- fields
- } = item;
-
- return (
-
-
- {id ? translate('EditConditionImplementation', { implementationName }) : translate('AddConditionImplementation', { implementationName })}
-
-
-
-
-
-
- {
- id ?
-
- {translate('Delete')}
- :
- null
- }
-
-
- {translate('Cancel')}
-
-
-
- {translate('Save')}
-
-
-
- );
-}
-
-EditSpecificationModalContent.propTypes = {
- id: PropTypes.number,
- onDeleteSpecificationPress: PropTypes.func,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default EditSpecificationModalContent;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContentConnector.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContentConnector.js
deleted file mode 100644
index 8f27b74e0..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/EditSpecificationModalContentConnector.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearAutoTaggingSpecificationPending, saveAutoTaggingSpecification, setAutoTaggingSpecificationFieldValue, setAutoTaggingSpecificationValue } from 'Store/Actions/settingsActions';
-import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
-import EditSpecificationModalContent from './EditSpecificationModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- createProviderSettingsSelector('autoTaggingSpecifications'),
- (advancedSettings, specification) => {
- return {
- advancedSettings,
- ...specification
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setAutoTaggingSpecificationValue,
- setAutoTaggingSpecificationFieldValue,
- saveAutoTaggingSpecification,
- clearAutoTaggingSpecificationPending
-};
-
-class EditSpecificationModalContentConnector extends Component {
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setAutoTaggingSpecificationValue({ name, value });
- };
-
- onFieldChange = ({ name, value }) => {
- this.props.setAutoTaggingSpecificationFieldValue({ name, value });
- };
-
- onCancelPress = () => {
- this.props.clearAutoTaggingSpecificationPending();
- this.props.onModalClose();
- };
-
- onSavePress = () => {
- this.props.saveAutoTaggingSpecification({ id: this.props.id });
- this.props.onModalClose();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-EditSpecificationModalContentConnector.propTypes = {
- id: PropTypes.number,
- item: PropTypes.object.isRequired,
- setAutoTaggingSpecificationValue: PropTypes.func.isRequired,
- setAutoTaggingSpecificationFieldValue: PropTypes.func.isRequired,
- clearAutoTaggingSpecificationPending: PropTypes.func.isRequired,
- saveAutoTaggingSpecification: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(EditSpecificationModalContentConnector);
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css b/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css
deleted file mode 100644
index e329fc313..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css
+++ /dev/null
@@ -1,38 +0,0 @@
-.autoTagging {
- composes: card from '~Components/Card.css';
-
- width: 300px;
-}
-
-.nameContainer {
- display: flex;
- justify-content: space-between;
-}
-
-.name {
- @add-mixin truncate;
-
- margin-bottom: 20px;
- font-weight: 300;
- font-size: 24px;
-}
-
-.cloneButton {
- composes: button from '~Components/Link/IconButton.css';
-
- height: 36px;
-}
-
-.labels {
- display: flex;
- flex-wrap: wrap;
- margin-top: 5px;
- pointer-events: all;
-}
-
-.tooltipLabel {
- composes: label from '~Components/Label.css';
-
- margin: 0;
- border: none;
-}
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css.d.ts b/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css.d.ts
deleted file mode 100644
index b3229d715..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'autoTagging': string;
- 'cloneButton': string;
- 'labels': string;
- 'name': string;
- 'nameContainer': string;
- 'tooltipLabel': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.js b/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.js
deleted file mode 100644
index 21977e160..000000000
--- a/frontend/src/Settings/Tags/AutoTagging/Specifications/Specification.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { useCallback, useState } from 'react';
-import Card from 'Components/Card';
-import Label from 'Components/Label';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import EditSpecificationModal from './EditSpecificationModal';
-import styles from './Specification.css';
-
-export default function Specification(props) {
- const {
- id,
- implementationName,
- name,
- required,
- negate,
- onConfirmDeleteSpecification,
- onCloneSpecificationPress
- } = props;
-
- const [isEditModalOpen, setIsEditModalOpen] = useState(false);
- const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
-
- const onEditPress = useCallback(() => {
- setIsEditModalOpen(true);
- }, [setIsEditModalOpen]);
-
- const onEditModalClose = useCallback(() => {
- setIsEditModalOpen(false);
- }, [setIsEditModalOpen]);
-
- const onDeletePress = useCallback(() => {
- setIsEditModalOpen(false);
- setIsDeleteModalOpen(true);
- }, [setIsEditModalOpen, setIsDeleteModalOpen]);
-
- const onDeleteModalClose = useCallback(() => {
- setIsDeleteModalOpen(false);
- }, [setIsDeleteModalOpen]);
-
- const onConfirmDelete = useCallback(() => {
- onConfirmDeleteSpecification(id);
- }, [id, onConfirmDeleteSpecification]);
-
- const onClonePress = useCallback(() => {
- onCloneSpecificationPress(id);
- }, [id, onCloneSpecificationPress]);
-
- return (
-
-
-
-
-
- {implementationName}
-
-
- {
- negate ?
-
- {translate('Negated')}
- :
- null
- }
-
- {
- required ?
-
- {translate('Required')}
- :
- null
- }
-
-
-
-
-
-
- );
-}
-
-Specification.propTypes = {
- id: PropTypes.number.isRequired,
- implementation: PropTypes.string.isRequired,
- implementationName: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- negate: PropTypes.bool.isRequired,
- required: PropTypes.bool.isRequired,
- fields: PropTypes.arrayOf(PropTypes.object).isRequired,
- onConfirmDeleteSpecification: PropTypes.func.isRequired,
- onCloneSpecificationPress: PropTypes.func.isRequired
-};
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsDelayProfile.js b/frontend/src/Settings/Tags/Details/TagDetailsDelayProfile.js
deleted file mode 100644
index ab670359b..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsDelayProfile.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import titleCase from 'Utilities/String/titleCase';
-
-function TagDetailsDelayProfile(props) {
- const {
- preferredProtocol,
- enableUsenet,
- enableTorrent,
- usenetDelay,
- torrentDelay
- } = props;
-
- return (
-
-
- Protocol: {titleCase(preferredProtocol)}
-
-
-
- {
- enableUsenet ?
- `Usenet Delay: ${usenetDelay}` :
- 'Usenet disabled'
- }
-
-
-
- {
- enableTorrent ?
- `Torrent Delay: ${torrentDelay}` :
- 'Torrents disabled'
- }
-
-
- );
-}
-
-TagDetailsDelayProfile.propTypes = {
- preferredProtocol: PropTypes.string.isRequired,
- enableUsenet: PropTypes.bool.isRequired,
- enableTorrent: PropTypes.bool.isRequired,
- usenetDelay: PropTypes.number.isRequired,
- torrentDelay: PropTypes.number.isRequired
-};
-
-export default TagDetailsDelayProfile;
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModal.js b/frontend/src/Settings/Tags/Details/TagDetailsModal.js
deleted file mode 100644
index 4195c64db..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsModal.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import { sizes } from 'Helpers/Props';
-import TagDetailsModalContentConnector from './TagDetailsModalContentConnector';
-
-function TagDetailsModal(props) {
- const {
- isOpen,
- onModalClose,
- ...otherProps
- } = props;
-
- return (
-
-
-
- );
-}
-
-TagDetailsModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default TagDetailsModal;
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css b/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css
deleted file mode 100644
index 75b157063..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css
+++ /dev/null
@@ -1,26 +0,0 @@
-.items {
- display: flex;
- flex-wrap: wrap;
-}
-
-.item {
- flex: 0 0 100%;
-}
-
-.restriction {
- margin-bottom: 5px;
- padding-bottom: 5px;
- border-bottom: 1px solid var(--borderColor);
-
- &:last-child {
- margin: 0;
- padding: 0;
- border-bottom: none;
- }
-}
-
-.deleteButton {
- composes: button from '~Components/Link/Button.css';
-
- margin-right: auto;
-}
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css.d.ts b/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css.d.ts
deleted file mode 100644
index 81112f53f..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'deleteButton': string;
- 'item': string;
- 'items': string;
- 'restriction': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.js b/frontend/src/Settings/Tags/Details/TagDetailsModalContent.js
deleted file mode 100644
index 78372d5a3..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsModalContent.js
+++ /dev/null
@@ -1,257 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import FieldSet from 'Components/FieldSet';
-import Label from 'Components/Label';
-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 { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import TagDetailsDelayProfile from './TagDetailsDelayProfile';
-import styles from './TagDetailsModalContent.css';
-
-function TagDetailsModalContent(props) {
- const {
- label,
- isTagUsed,
- artist,
- delayProfiles,
- importLists,
- notifications,
- releaseProfiles,
- indexers,
- downloadClients,
- autoTags,
- onModalClose,
- onDeleteTagPress
- } = props;
-
- return (
-
-
- Tag Details - {label}
-
-
-
- {
- !isTagUsed &&
-
- {translate('TagIsNotUsedAndCanBeDeleted')}
-
- }
-
- {
- artist.length ?
-
- {
- artist.map((item) => {
- return (
-
- {item.artistName}
-
- );
- })
- }
- :
- null
- }
-
- {
- delayProfiles.length ?
-
- {
- delayProfiles.map((item) => {
- const {
- id,
- preferredProtocol,
- enableUsenet,
- enableTorrent,
- usenetDelay,
- torrentDelay
- } = item;
-
- return (
-
- );
- })
- }
- :
- null
- }
-
- {
- notifications.length ?
-
- {
- notifications.map((item) => {
- return (
-
- {item.name}
-
- );
- })
- }
- :
- null
- }
-
- {
- importLists.length ?
-
- {
- importLists.map((item) => {
- return (
-
- {item.name}
-
- );
- })
- }
- :
- null
- }
-
- {
- releaseProfiles.length ?
-
- {
- releaseProfiles.map((item) => {
- return (
-
-
- {
- item.required.map((r) => {
- return (
-
- {r}
-
- );
- })
- }
-
-
-
- {
- item.ignored.map((i) => {
- return (
-
- {i}
-
- );
- })
- }
-
-
- );
- })
- }
- :
- null
- }
-
- {
- indexers.length ?
-
- {
- indexers.map((item) => {
- return (
-
- {item.name}
-
- );
- })
- }
- :
- null
- }
-
- {
- downloadClients.length ?
-
- {
- downloadClients.map((item) => {
- return (
-
- {item.name}
-
- );
- })
- }
- :
- null
- }
-
- {
- autoTags.length ?
-
- {
- autoTags.map((item) => {
- return (
-
- {item.name}
-
- );
- })
- }
- :
- null
- }
-
-
-
- {
-
- Delete
-
- }
-
-
- Close
-
-
-
- );
-}
-
-TagDetailsModalContent.propTypes = {
- label: PropTypes.string.isRequired,
- isTagUsed: PropTypes.bool.isRequired,
- artist: PropTypes.arrayOf(PropTypes.object).isRequired,
- delayProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
- importLists: PropTypes.arrayOf(PropTypes.object).isRequired,
- notifications: PropTypes.arrayOf(PropTypes.object).isRequired,
- releaseProfiles: PropTypes.arrayOf(PropTypes.object).isRequired,
- indexers: PropTypes.arrayOf(PropTypes.object).isRequired,
- downloadClients: PropTypes.arrayOf(PropTypes.object).isRequired,
- autoTags: PropTypes.arrayOf(PropTypes.object).isRequired,
- onModalClose: PropTypes.func.isRequired,
- onDeleteTagPress: PropTypes.func.isRequired
-};
-
-export default TagDetailsModalContent;
diff --git a/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js b/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js
deleted file mode 100644
index ddd70b253..000000000
--- a/frontend/src/Settings/Tags/Details/TagDetailsModalContentConnector.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import createAllArtistSelector from 'Store/Selectors/createAllArtistSelector';
-import TagDetailsModalContent from './TagDetailsModalContent';
-
-function findMatchingItems(ids, items) {
- return items.filter((s) => {
- return ids.includes(s.id);
- });
-}
-
-function createUnorderedMatchingArtistSelector() {
- return createSelector(
- (state, { artistIds }) => artistIds,
- createAllArtistSelector(),
- findMatchingItems
- );
-}
-
-function createMatchingArtistSelector() {
- return createSelector(
- createUnorderedMatchingArtistSelector(),
- (artists) => {
- return artists.sort((artistA, artistB) => {
- const sortNameA = artistA.sortName;
- const sortNameB = artistB.sortName;
-
- if (sortNameA > sortNameB) {
- return 1;
- } else if (sortNameA < sortNameB) {
- return -1;
- }
-
- return 0;
- });
- }
- );
-}
-
-function createMatchingDelayProfilesSelector() {
- return createSelector(
- (state, { delayProfileIds }) => delayProfileIds,
- (state) => state.settings.delayProfiles.items,
- findMatchingItems
- );
-}
-
-function createMatchingImportListsSelector() {
- return createSelector(
- (state, { importListIds }) => importListIds,
- (state) => state.settings.importLists.items,
- findMatchingItems
- );
-}
-
-function createMatchingNotificationsSelector() {
- return createSelector(
- (state, { notificationIds }) => notificationIds,
- (state) => state.settings.notifications.items,
- findMatchingItems
- );
-}
-
-function createMatchingReleaseProfilesSelector() {
- return createSelector(
- (state, { restrictionIds }) => restrictionIds,
- (state) => state.settings.releaseProfiles.items,
- findMatchingItems
- );
-}
-
-function createMatchingIndexersSelector() {
- return createSelector(
- (state, { indexerIds }) => indexerIds,
- (state) => state.settings.indexers.items,
- findMatchingItems
- );
-}
-
-function createMatchingDownloadClientsSelector() {
- return createSelector(
- (state, { downloadClientIds }) => downloadClientIds,
- (state) => state.settings.downloadClients.items,
- findMatchingItems
- );
-}
-
-function createMatchingAutoTagsSelector() {
- return createSelector(
- (state, { autoTagIds }) => autoTagIds,
- (state) => state.settings.autoTaggings.items,
- findMatchingItems
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- createMatchingArtistSelector(),
- createMatchingDelayProfilesSelector(),
- createMatchingImportListsSelector(),
- createMatchingNotificationsSelector(),
- createMatchingReleaseProfilesSelector(),
- createMatchingIndexersSelector(),
- createMatchingDownloadClientsSelector(),
- createMatchingAutoTagsSelector(),
- (artist, delayProfiles, importLists, notifications, releaseProfiles, indexers, downloadClients, autoTags) => {
- return {
- artist,
- delayProfiles,
- importLists,
- notifications,
- releaseProfiles,
- indexers,
- downloadClients,
- autoTags
- };
- }
- );
-}
-
-export default connect(createMapStateToProps)(TagDetailsModalContent);
diff --git a/frontend/src/Settings/Tags/Tag.css b/frontend/src/Settings/Tags/Tag.css
deleted file mode 100644
index ebf61e539..000000000
--- a/frontend/src/Settings/Tags/Tag.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.tag {
- composes: card from '~Components/Card.css';
-
- flex: 150px 0 1;
-}
-
-.label {
- margin-bottom: 20px;
- white-space: nowrap;
- font-weight: 300;
- font-size: 24px;
-}
diff --git a/frontend/src/Settings/Tags/Tag.css.d.ts b/frontend/src/Settings/Tags/Tag.css.d.ts
deleted file mode 100644
index 51d18383e..000000000
--- a/frontend/src/Settings/Tags/Tag.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'label': string;
- 'tag': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/Tag.js b/frontend/src/Settings/Tags/Tag.js
deleted file mode 100644
index 525bf5844..000000000
--- a/frontend/src/Settings/Tags/Tag.js
+++ /dev/null
@@ -1,208 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Card from 'Components/Card';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import TagDetailsModal from './Details/TagDetailsModal';
-import TagInUse from './TagInUse';
-import styles from './Tag.css';
-
-class Tag extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isDetailsModalOpen: false,
- isDeleteTagModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onShowDetailsPress = () => {
- this.setState({ isDetailsModalOpen: true });
- };
-
- onDetailsModalClose = () => {
- this.setState({ isDetailsModalOpen: false });
- };
-
- onDeleteTagPress = () => {
- this.setState({
- isDetailsModalOpen: false,
- isDeleteTagModalOpen: true
- });
- };
-
- onDeleteTagModalClose= () => {
- this.setState({ isDeleteTagModalOpen: false });
- };
-
- onConfirmDeleteTag = () => {
- this.props.onConfirmDeleteTag({ id: this.props.id });
- };
-
- //
- // Render
-
- render() {
- const {
- label,
- delayProfileIds,
- importListIds,
- notificationIds,
- restrictionIds,
- indexerIds,
- downloadClientIds,
- autoTagIds,
- artistIds
- } = this.props;
-
- const {
- isDetailsModalOpen,
- isDeleteTagModalOpen
- } = this.state;
-
- const isTagUsed = !!(
- delayProfileIds.length ||
- importListIds.length ||
- notificationIds.length ||
- restrictionIds.length ||
- indexerIds.length ||
- downloadClientIds.length ||
- autoTagIds.length ||
- artistIds.length
- );
-
- return (
-
-
- {label}
-
-
- {
- isTagUsed ?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
:
- null
- }
-
- {
- !isTagUsed &&
-
- No links
-
- }
-
-
-
-
-
- );
- }
-}
-
-Tag.propTypes = {
- id: PropTypes.number.isRequired,
- label: PropTypes.string.isRequired,
- delayProfileIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- importListIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- notificationIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- restrictionIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- indexerIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- downloadClientIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- autoTagIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- artistIds: PropTypes.arrayOf(PropTypes.number).isRequired,
- onConfirmDeleteTag: PropTypes.func.isRequired
-};
-
-Tag.defaultProps = {
- delayProfileIds: [],
- importListIds: [],
- notificationIds: [],
- restrictionIds: [],
- indexerIds: [],
- downloadClientIds: [],
- autoTagIds: [],
- artistIds: []
-};
-
-export default Tag;
diff --git a/frontend/src/Settings/Tags/TagConnector.js b/frontend/src/Settings/Tags/TagConnector.js
deleted file mode 100644
index 986acc8e8..000000000
--- a/frontend/src/Settings/Tags/TagConnector.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { deleteTag } from 'Store/Actions/tagActions';
-import createTagDetailsSelector from 'Store/Selectors/createTagDetailsSelector';
-import Tag from './Tag';
-
-function createMapStateToProps() {
- return createSelector(
- createTagDetailsSelector(),
- (tagDetails) => {
- return {
- ...tagDetails
- };
- }
- );
-}
-
-const mapStateToProps = {
- onConfirmDeleteTag: deleteTag
-};
-
-export default connect(createMapStateToProps, mapStateToProps)(Tag);
diff --git a/frontend/src/Settings/Tags/TagInUse.js b/frontend/src/Settings/Tags/TagInUse.js
deleted file mode 100644
index 27228fa2e..000000000
--- a/frontend/src/Settings/Tags/TagInUse.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-
-export default function TagInUse(props) {
- const {
- label,
- labelPlural,
- count
- } = props;
-
- if (count === 0) {
- return null;
- }
-
- if (count > 1 && labelPlural) {
- return (
-
- {count} {labelPlural.toLowerCase()}
-
- );
- }
-
- return (
-
- {count} {label.toLowerCase()}
-
- );
-}
-
-TagInUse.propTypes = {
- label: PropTypes.string.isRequired,
- labelPlural: PropTypes.string,
- count: PropTypes.number.isRequired
-};
diff --git a/frontend/src/Settings/Tags/TagSettings.js b/frontend/src/Settings/Tags/TagSettings.js
deleted file mode 100644
index ca8672603..000000000
--- a/frontend/src/Settings/Tags/TagSettings.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import translate from 'Utilities/String/translate';
-import AutoTaggings from './AutoTagging/AutoTaggings';
-import TagsConnector from './TagsConnector';
-
-function TagSettings() {
- return (
-
-
-
-
-
-
-
-
- );
-}
-
-export default TagSettings;
diff --git a/frontend/src/Settings/Tags/Tags.css b/frontend/src/Settings/Tags/Tags.css
deleted file mode 100644
index 5a44f8331..000000000
--- a/frontend/src/Settings/Tags/Tags.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.tags {
- display: flex;
- flex-wrap: wrap;
-}
diff --git a/frontend/src/Settings/Tags/Tags.css.d.ts b/frontend/src/Settings/Tags/Tags.css.d.ts
deleted file mode 100644
index bf5da21eb..000000000
--- a/frontend/src/Settings/Tags/Tags.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'tags': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/Tags/Tags.js b/frontend/src/Settings/Tags/Tags.js
deleted file mode 100644
index c5f3d8706..000000000
--- a/frontend/src/Settings/Tags/Tags.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import PageSectionContent from 'Components/Page/PageSectionContent';
-import { kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import TagConnector from './TagConnector';
-import styles from './Tags.css';
-
-function Tags(props) {
- const {
- items,
- ...otherProps
- } = props;
-
- if (!items.length) {
- return (
-
- {translate('NoTagsHaveBeenAddedYet')}
-
- );
- }
-
- return (
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
- );
-}
-
-Tags.propTypes = {
- items: PropTypes.arrayOf(PropTypes.object).isRequired
-};
-
-export default Tags;
diff --git a/frontend/src/Settings/Tags/TagsConnector.js b/frontend/src/Settings/Tags/TagsConnector.js
deleted file mode 100644
index 15f31d3c5..000000000
--- a/frontend/src/Settings/Tags/TagsConnector.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchDelayProfiles, fetchDownloadClients, fetchImportLists, fetchIndexers, fetchNotifications, fetchReleaseProfiles } from 'Store/Actions/settingsActions';
-import { fetchTagDetails, fetchTags } from 'Store/Actions/tagActions';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import Tags from './Tags';
-
-function createMapStateToProps() {
- return createSelector(
- createSortedSectionSelector('tags', sortByProp('label')),
- (tags) => {
- const isFetching = tags.isFetching || tags.details.isFetching;
- const error = tags.error || tags.details.error;
- const isPopulated = tags.isPopulated && tags.details.isPopulated;
-
- return {
- ...tags,
- isFetching,
- error,
- isPopulated
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchTags: fetchTags,
- dispatchFetchTagDetails: fetchTagDetails,
- dispatchFetchDelayProfiles: fetchDelayProfiles,
- dispatchFetchImportLists: fetchImportLists,
- dispatchFetchNotifications: fetchNotifications,
- dispatchFetchReleaseProfiles: fetchReleaseProfiles,
- dispatchFetchIndexers: fetchIndexers,
- dispatchFetchDownloadClients: fetchDownloadClients
-};
-
-class MetadatasConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- dispatchFetchTags,
- dispatchFetchTagDetails,
- dispatchFetchDelayProfiles,
- dispatchFetchImportLists,
- dispatchFetchNotifications,
- dispatchFetchReleaseProfiles,
- dispatchFetchIndexers,
- dispatchFetchDownloadClients
- } = this.props;
-
- dispatchFetchTags();
- dispatchFetchTagDetails();
- dispatchFetchDelayProfiles();
- dispatchFetchImportLists();
- dispatchFetchNotifications();
- dispatchFetchReleaseProfiles();
- dispatchFetchIndexers();
- dispatchFetchDownloadClients();
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MetadatasConnector.propTypes = {
- dispatchFetchTags: PropTypes.func.isRequired,
- dispatchFetchTagDetails: PropTypes.func.isRequired,
- dispatchFetchDelayProfiles: PropTypes.func.isRequired,
- dispatchFetchImportLists: PropTypes.func.isRequired,
- dispatchFetchNotifications: PropTypes.func.isRequired,
- dispatchFetchReleaseProfiles: PropTypes.func.isRequired,
- dispatchFetchIndexers: PropTypes.func.isRequired,
- dispatchFetchDownloadClients: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(MetadatasConnector);
diff --git a/frontend/src/Settings/UI/UISettings.css b/frontend/src/Settings/UI/UISettings.css
deleted file mode 100644
index 2e6213823..000000000
--- a/frontend/src/Settings/UI/UISettings.css
+++ /dev/null
@@ -1,3 +0,0 @@
-.columnGroup {
- flex-direction: column;
-}
diff --git a/frontend/src/Settings/UI/UISettings.css.d.ts b/frontend/src/Settings/UI/UISettings.css.d.ts
deleted file mode 100644
index ef0f392ed..000000000
--- a/frontend/src/Settings/UI/UISettings.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'columnGroup': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Settings/UI/UISettings.js b/frontend/src/Settings/UI/UISettings.js
deleted file mode 100644
index cc27829df..000000000
--- a/frontend/src/Settings/UI/UISettings.js
+++ /dev/null
@@ -1,300 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Form from 'Components/Form/Form';
-import FormGroup from 'Components/Form/FormGroup';
-import FormInputGroup from 'Components/Form/FormInputGroup';
-import FormLabel from 'Components/Form/FormLabel';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import { inputTypes, kinds } from 'Helpers/Props';
-import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
-import themes from 'Styles/Themes';
-import titleCase from 'Utilities/String/titleCase';
-import translate from 'Utilities/String/translate';
-import styles from './UISettings.css';
-
-export const firstDayOfWeekOptions = [
- { key: 0, value: 'Sunday' },
- { key: 1, value: 'Monday' }
-];
-
-export const weekColumnOptions = [
- { key: 'ddd M/D', value: 'Tue 3/25', hint: 'ddd M/D' },
- { key: 'ddd MM/DD', value: 'Tue 03/25', hint: 'ddd MM/DD' },
- { key: 'ddd D/M', value: 'Tue 25/3', hint: 'ddd D/M' },
- { key: 'ddd DD/MM', value: 'Tue 25/03', hint: 'ddd DD/MM' }
-];
-
-const shortDateFormatOptions = [
- { key: 'MMM D YYYY', value: 'Mar 25 2014', hint: 'MMM D YYYY' },
- { key: 'DD MMM YYYY', value: '25 Mar 2014', hint: 'DD MMM YYYY' },
- { key: 'MM/D/YYYY', value: '03/25/2014', hint: 'MM/D/YYYY' },
- { key: 'MM/DD/YYYY', value: '03/25/2014', hint: 'MM/DD/YYYY' },
- { key: 'DD/MM/YYYY', value: '25/03/2014', hint: 'DD/MM/YYYY' },
- { key: 'YYYY-MM-DD', value: '2014-03-25', hint: 'YYYY-MM-DD' }
-];
-
-const longDateFormatOptions = [
- { key: 'dddd, MMMM D YYYY', value: 'Tuesday, March 25, 2014' },
- { key: 'dddd, D MMMM YYYY', value: 'Tuesday, 25 March, 2014' }
-];
-
-export const timeFormatOptions = [
- { key: 'h(:mm)a', value: '5pm/5:30pm' },
- { key: 'HH:mm', value: '17:00/17:30' }
-];
-
-class UISettings extends Component {
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- error,
- settings,
- hasSettings,
- onInputChange,
- onSavePress,
- languages,
- ...otherProps
- } = this.props;
-
- const uiLanguages = languages.filter((item) => item.value !== 'Original');
- const themeOptions = Object.keys(themes)
- .map((theme) => ({ key: theme, value: titleCase(theme) }));
-
- return (
-
-
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && error &&
-
- {translate('UnableToLoadUISettings')}
-
- }
-
- {
- hasSettings && !isFetching && !error &&
-
- }
-
-
- );
- }
-
-}
-
-UISettings.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object,
- settings: PropTypes.object.isRequired,
- hasSettings: PropTypes.bool.isRequired,
- onSavePress: PropTypes.func.isRequired,
- languages: PropTypes.arrayOf(PropTypes.object).isRequired,
- onInputChange: PropTypes.func.isRequired
-};
-
-export default UISettings;
diff --git a/frontend/src/Settings/UI/UISettingsConnector.js b/frontend/src/Settings/UI/UISettingsConnector.js
deleted file mode 100644
index ea9194f8c..000000000
--- a/frontend/src/Settings/UI/UISettingsConnector.js
+++ /dev/null
@@ -1,102 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { clearPendingChanges } from 'Store/Actions/baseActions';
-import { fetchUISettings, saveUISettings, setUISettingsValue } from 'Store/Actions/settingsActions';
-import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
-import UISettings from './UISettings';
-
-const SECTION = 'ui';
-
-function createLanguagesSelector() {
- return createSelector(
- (state) => state.settings.languages,
- (languages) => {
- const items = languages.items;
- const filterItems = ['Any', 'Unknown'];
-
- if (!items) {
- return [];
- }
-
- const newItems = items.filter((lang) => !filterItems.includes(lang.name)).map((item) => {
- return {
- key: item.id,
- value: item.name
- };
- });
-
- return newItems;
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.settings.advancedSettings,
- createSettingsSectionSelector(SECTION),
- createLanguagesSelector(),
- (advancedSettings, sectionSettings, languages) => {
- return {
- advancedSettings,
- languages,
- ...sectionSettings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- setUISettingsValue,
- saveUISettings,
- fetchUISettings,
- clearPendingChanges
-};
-
-class UISettingsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchUISettings();
- }
-
- componentWillUnmount() {
- this.props.clearPendingChanges({ section: `settings.${SECTION}` });
- }
-
- //
- // Listeners
-
- onInputChange = ({ name, value }) => {
- this.props.setUISettingsValue({ name, value });
- };
-
- onSavePress = () => {
- this.props.saveUISettings();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-UISettingsConnector.propTypes = {
- setUISettingsValue: PropTypes.func.isRequired,
- saveUISettings: PropTypes.func.isRequired,
- fetchUISettings: PropTypes.func.isRequired,
- clearPendingChanges: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(UISettingsConnector);
diff --git a/frontend/src/Shared/piwikCheck.js b/frontend/src/Shared/piwikCheck.js
deleted file mode 100644
index 9fcc84361..000000000
--- a/frontend/src/Shared/piwikCheck.js
+++ /dev/null
@@ -1,10 +0,0 @@
-if (window.Lidarr.analytics) {
- const d = document;
- const g = d.createElement('script');
- const s = d.getElementsByTagName('script')[0];
- g.type = 'text/javascript';
- g.async = true;
- g.defer = true;
- g.src = '//piwik.sonarr.tv/piwik.js';
- s.parentNode.insertBefore(g, s);
-}
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createClearReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createClearReducer.js
deleted file mode 100644
index 2952973a9..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createClearReducer.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function createClearReducer(section, defaultState) {
- return (state) => {
- const newState = Object.assign(getSectionState(state, section), defaultState);
-
- return updateSectionState(state, section, newState);
- };
-}
-
-export default createClearReducer;
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionFilterReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionFilterReducer.js
deleted file mode 100644
index d58bb1cd4..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionFilterReducer.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function createSetClientSideCollectionFilterReducer(section) {
- return (state, { payload }) => {
- const newState = getSectionState(state, section);
-
- newState.selectedFilterKey = payload.selectedFilterKey;
-
- return updateSectionState(state, section, newState);
- };
-}
-
-export default createSetClientSideCollectionFilterReducer;
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer.js
deleted file mode 100644
index 1bc048a80..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { sortDirections } from 'Helpers/Props';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function createSetClientSideCollectionSortReducer(section) {
- return (state, { payload }) => {
- const newState = getSectionState(state, section);
-
- const sortKey = payload.sortKey || newState.sortKey;
- let sortDirection = payload.sortDirection;
-
- if (!sortDirection) {
- if (payload.sortKey === newState.sortKey) {
- sortDirection = newState.sortDirection === sortDirections.ASCENDING ?
- sortDirections.DESCENDING :
- sortDirections.ASCENDING;
- } else {
- sortDirection = newState.sortDirection;
- }
- }
-
- newState.sortKey = sortKey;
- newState.sortDirection = sortDirection;
-
- return updateSectionState(state, section, newState);
- };
-}
-
-export default createSetClientSideCollectionSortReducer;
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer.js
deleted file mode 100644
index 3af58dd3b..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function createSetProviderFieldValueReducer(section) {
- return (state, { payload }) => {
- if (section === payload.section) {
- const { name, value } = payload;
- const newState = getSectionState(state, section);
- newState.pendingChanges = Object.assign({}, newState.pendingChanges);
- const fields = Object.assign({}, newState.pendingChanges.fields || {});
-
- fields[name] = value;
-
- newState.pendingChanges.fields = fields;
-
- return updateSectionState(state, section, newState);
- }
-
- return state;
- };
-}
-
-export default createSetProviderFieldValueReducer;
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createSetSettingValueReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createSetSettingValueReducer.js
deleted file mode 100644
index 474eb7bb2..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createSetSettingValueReducer.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import _ from 'lodash';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function createSetSettingValueReducer(section) {
- return (state, { payload }) => {
- if (section === payload.section) {
- const { name, value } = payload;
- const newState = getSectionState(state, section);
- newState.pendingChanges = Object.assign({}, newState.pendingChanges);
-
- const currentValue = newState.item ? newState.item[name] : null;
- const pendingState = newState.pendingChanges;
-
- let parsedValue = null;
-
- if (_.isNumber(currentValue) && value != null) {
- parsedValue = parseInt(value);
- } else {
- parsedValue = value;
- }
-
- if (currentValue === parsedValue) {
- delete pendingState[name];
- } else {
- pendingState[name] = parsedValue;
- }
-
- return updateSectionState(state, section, newState);
- }
-
- return state;
- };
-}
-
-export default createSetSettingValueReducer;
diff --git a/frontend/src/Store/Actions/Creators/Reducers/createSetTableOptionReducer.js b/frontend/src/Store/Actions/Creators/Reducers/createSetTableOptionReducer.js
deleted file mode 100644
index 70b57446d..000000000
--- a/frontend/src/Store/Actions/Creators/Reducers/createSetTableOptionReducer.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import _ from 'lodash';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-const whitelistedProperties = [
- 'pageSize',
- 'columns',
- 'tableOptions'
-];
-
-function createSetTableOptionReducer(section) {
- return (state, { payload }) => {
- const newState = Object.assign(
- getSectionState(state, section),
- _.pick(payload, whitelistedProperties));
-
- return updateSectionState(state, section, newState);
- };
-}
-
-export default createSetTableOptionReducer;
diff --git a/frontend/src/Store/Actions/Creators/createBatchToggleAlbumMonitoredHandler.js b/frontend/src/Store/Actions/Creators/createBatchToggleAlbumMonitoredHandler.js
deleted file mode 100644
index 1dab0ab0f..000000000
--- a/frontend/src/Store/Actions/Creators/createBatchToggleAlbumMonitoredHandler.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import updateAlbums from 'Utilities/Album/updateAlbums';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getSectionState from 'Utilities/State/getSectionState';
-
-function createBatchToggleAlbumMonitoredHandler(section, fetchHandler) {
- return function(getState, payload, dispatch) {
- const {
- albumIds,
- monitored
- } = payload;
-
- const state = getSectionState(getState(), section, true);
-
- dispatch(updateAlbums(section, state.items, albumIds, {
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- url: '/album/monitor',
- method: 'PUT',
- data: JSON.stringify({ albumIds, monitored }),
- dataType: 'json'
- }).request;
-
- promise.done(() => {
- dispatch(updateAlbums(section, state.items, albumIds, {
- isSaving: false,
- monitored
- }));
-
- dispatch(fetchHandler());
- });
-
- promise.fail(() => {
- dispatch(updateAlbums(section, state.items, albumIds, {
- isSaving: false
- }));
- });
- };
-}
-
-export default createBatchToggleAlbumMonitoredHandler;
diff --git a/frontend/src/Store/Actions/Creators/createBulkEditItemHandler.js b/frontend/src/Store/Actions/Creators/createBulkEditItemHandler.js
deleted file mode 100644
index f174dae54..000000000
--- a/frontend/src/Store/Actions/Creators/createBulkEditItemHandler.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set, updateItem } from '../baseActions';
-
-function createBulkEditItemHandler(section, url) {
- return function(getState, payload, dispatch) {
-
- dispatch(set({ section, isSaving: true }));
-
- const ajaxOptions = {
- url: `${url}`,
- method: 'PUT',
- data: JSON.stringify(payload),
- dataType: 'json'
- };
-
- const promise = createAjaxRequest(ajaxOptions).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- set({
- section,
- isSaving: false,
- saveError: null
- }),
-
- ...data.map((provider) => {
-
- const {
- ...propsToUpdate
- } = provider;
-
- return updateItem({
- id: provider.id,
- section,
- ...propsToUpdate
- });
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
-
- return promise;
- };
-}
-
-export default createBulkEditItemHandler;
diff --git a/frontend/src/Store/Actions/Creators/createBulkRemoveItemHandler.js b/frontend/src/Store/Actions/Creators/createBulkRemoveItemHandler.js
deleted file mode 100644
index 3293ff1b5..000000000
--- a/frontend/src/Store/Actions/Creators/createBulkRemoveItemHandler.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { removeItem, set } from '../baseActions';
-
-function createBulkRemoveItemHandler(section, url) {
- return function(getState, payload, dispatch) {
- const {
- ids
- } = payload;
-
- dispatch(set({ section, isDeleting: true }));
-
- const ajaxOptions = {
- url: `${url}`,
- method: 'DELETE',
- data: JSON.stringify(payload),
- dataType: 'json'
- };
-
- const promise = createAjaxRequest(ajaxOptions).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- set({
- section,
- isDeleting: false,
- deleteError: null
- }),
-
- ...ids.map((id) => {
- return removeItem({ section, id });
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: xhr
- }));
- });
-
- return promise;
- };
-}
-
-export default createBulkRemoveItemHandler;
diff --git a/frontend/src/Store/Actions/Creators/createFetchHandler.js b/frontend/src/Store/Actions/Creators/createFetchHandler.js
deleted file mode 100644
index c9cd058bd..000000000
--- a/frontend/src/Store/Actions/Creators/createFetchHandler.js
+++ /dev/null
@@ -1,44 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set, update, updateItem } from '../baseActions';
-
-export default function createFetchHandler(section, url) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const {
- id,
- ...otherPayload
- } = payload;
-
- const { request, abortRequest } = createAjaxRequest({
- url: id == null ? url : `${url}/${id}`,
- data: otherPayload,
- traditional: true
- });
-
- request.done((data) => {
- dispatch(batchActions([
- id == null ? update({ section, data }) : updateItem({ section, ...data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- request.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr.aborted ? null : xhr
- }));
- });
-
- return abortRequest;
- };
-}
diff --git a/frontend/src/Store/Actions/Creators/createFetchSchemaHandler.js b/frontend/src/Store/Actions/Creators/createFetchSchemaHandler.js
deleted file mode 100644
index a1f24bbbd..000000000
--- a/frontend/src/Store/Actions/Creators/createFetchSchemaHandler.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set } from '../baseActions';
-
-function createFetchSchemaHandler(section, url) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isSchemaFetching: true }));
-
- const promise = createAjaxRequest({
- url
- }).request;
-
- promise.done((data) => {
- dispatch(set({
- section,
- isSchemaFetching: false,
- isSchemaPopulated: true,
- schemaError: null,
- schema: data
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSchemaFetching: false,
- isSchemaPopulated: true,
- schemaError: xhr
- }));
- });
- };
-}
-
-export default createFetchSchemaHandler;
diff --git a/frontend/src/Store/Actions/Creators/createFetchServerSideCollectionHandler.js b/frontend/src/Store/Actions/Creators/createFetchServerSideCollectionHandler.js
deleted file mode 100644
index f5ef10a4d..000000000
--- a/frontend/src/Store/Actions/Creators/createFetchServerSideCollectionHandler.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import _ from 'lodash';
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import findSelectedFilters from 'Utilities/Filter/findSelectedFilters';
-import getSectionState from 'Utilities/State/getSectionState';
-import { set, updateServerSideCollection } from '../baseActions';
-
-function createFetchServerSideCollectionHandler(section, url, fetchDataAugmenter) {
- const [baseSection] = section.split('.');
-
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const sectionState = getSectionState(getState(), section, true);
- const page = payload.page || sectionState.page || 1;
-
- const data = Object.assign({ page },
- _.pick(sectionState, [
- 'pageSize',
- 'sortDirection',
- 'sortKey'
- ]));
-
- if (fetchDataAugmenter) {
- fetchDataAugmenter(getState, payload, data);
- }
-
- const {
- selectedFilterKey,
- filters
- } = sectionState;
-
- const customFilters = getState().customFilters.items.filter((customFilter) => {
- return customFilter.type === section || customFilter.type === baseSection;
- });
-
- const selectedFilters = findSelectedFilters(selectedFilterKey, filters, customFilters);
-
- selectedFilters.forEach((filter) => {
- data[filter.key] = filter.value;
- });
-
- const promise = createAjaxRequest({
- url,
- data,
- traditional: true
- }).request;
-
- promise.done((response) => {
- dispatch(batchActions([
- updateServerSideCollection({ section, data: response }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- };
-}
-
-export default createFetchServerSideCollectionHandler;
diff --git a/frontend/src/Store/Actions/Creators/createHandleActions.js b/frontend/src/Store/Actions/Creators/createHandleActions.js
deleted file mode 100644
index 817cfda24..000000000
--- a/frontend/src/Store/Actions/Creators/createHandleActions.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import _ from 'lodash';
-import { handleActions } from 'redux-actions';
-import {
- CLEAR_PENDING_CHANGES,
- REMOVE_ITEM,
- SET,
- UPDATE,
- UPDATE_ITEM,
- UPDATE_SERVER_SIDE_COLLECTION } from 'Store/Actions/baseActions';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-const omittedProperties = [
- 'section',
- 'id'
-];
-
-function createItemMap(data) {
- return data.reduce((acc, d, index) => {
- acc[d.id] = index;
- return acc;
- }, {});
-}
-
-export default function createHandleActions(handlers, defaultState, section) {
- return handleActions({
-
- [SET]: function(state, { payload }) {
- const payloadSection = payload.section;
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const newState = Object.assign(getSectionState(state, payloadSection),
- _.omit(payload, omittedProperties));
-
- return updateSectionState(state, payloadSection, newState);
- }
-
- return state;
- },
-
- [UPDATE]: function(state, { payload }) {
- const payloadSection = payload.section;
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const newState = getSectionState(state, payloadSection);
-
- if (_.isArray(payload.data)) {
- newState.items = payload.data;
- newState.itemMap = createItemMap(payload.data);
- } else {
- newState.item = payload.data;
- }
-
- return updateSectionState(state, payloadSection, newState);
- }
-
- return state;
- },
-
- [UPDATE_ITEM]: function(state, { payload }) {
- const {
- section: payloadSection,
- updateOnly = false,
- ...otherProps
- } = payload;
-
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const newState = getSectionState(state, payloadSection);
- const items = newState.items;
-
- // Client side collections that are created by adding items to an
- // existing array may not have an itemMap, the array is probably empty,
- // but on the offchance it's not create a new item map based on the
- // items in the array.
- const itemMap = newState.itemMap ?? createItemMap(items);
- const index = payload.id in itemMap ? itemMap[payload.id] : -1;
-
- newState.items = [...items];
-
- // TODO: Move adding to it's own reducer
- if (index >= 0) {
- const item = items[index];
- const newItem = { ...item, ...otherProps };
-
- // if the item to update is equal to existing, then don't actually update
- // to prevent costly reselections
- if (_.isEqual(item, newItem)) {
- return state;
- }
-
- newState.items.splice(index, 1, newItem);
- } else if (!updateOnly) {
- const newIndex = newState.items.push({ ...otherProps }) - 1;
-
- newState.itemMap = { ...itemMap };
- newState.itemMap[payload.id] = newIndex;
- }
-
- return updateSectionState(state, payloadSection, newState);
- }
-
- return state;
- },
-
- [CLEAR_PENDING_CHANGES]: function(state, { payload }) {
- const payloadSection = payload.section;
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const newState = getSectionState(state, payloadSection);
- newState.pendingChanges = {};
-
- if (newState.hasOwnProperty('saveError')) {
- newState.saveError = null;
- }
-
- return updateSectionState(state, payloadSection, newState);
- }
-
- return state;
- },
-
- [REMOVE_ITEM]: function(state, { payload }) {
- const payloadSection = payload.section;
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const newState = getSectionState(state, payloadSection);
-
- newState.items = [...newState.items];
- _.remove(newState.items, { id: payload.id });
-
- newState.itemMap = createItemMap(newState.items);
-
- return updateSectionState(state, payloadSection, newState);
- }
-
- return state;
- },
-
- [UPDATE_SERVER_SIDE_COLLECTION]: function(state, { payload }) {
- const payloadSection = payload.section;
- const [baseSection] = payloadSection.split('.');
-
- if (section === baseSection) {
- const data = payload.data;
- const newState = getSectionState(state, payloadSection);
-
- const serverState = _.omit(data, ['records']);
- const calculatedState = {
- totalPages: Math.max(Math.ceil(data.totalRecords / data.pageSize), 1),
- items: data.records,
- itemMap: createItemMap(data.records)
- };
-
- return updateSectionState(state, payloadSection, Object.assign(newState, serverState, calculatedState));
- }
-
- return state;
- },
-
- ...handlers
-
- }, defaultState);
-}
diff --git a/frontend/src/Store/Actions/Creators/createRemoveItemHandler.js b/frontend/src/Store/Actions/Creators/createRemoveItemHandler.js
deleted file mode 100644
index 3de794bdf..000000000
--- a/frontend/src/Store/Actions/Creators/createRemoveItemHandler.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import $ from 'jquery';
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { removeItem, set } from '../baseActions';
-
-function createRemoveItemHandler(section, url) {
- return function(getState, payload, dispatch) {
- const {
- id,
- queryParams
- } = payload;
-
- dispatch(set({ section, isDeleting: true }));
-
- const ajaxOptions = {
- url: `${url}/${id}?${$.param(queryParams, true)}`,
- method: 'DELETE'
- };
-
- const promise = createAjaxRequest(ajaxOptions).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- set({
- section,
- isDeleting: false,
- deleteError: null
- }),
-
- removeItem({ section, id })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: xhr
- }));
- });
-
- return promise;
- };
-}
-
-export default createRemoveItemHandler;
diff --git a/frontend/src/Store/Actions/Creators/createSaveHandler.js b/frontend/src/Store/Actions/Creators/createSaveHandler.js
deleted file mode 100644
index e064b7e5a..000000000
--- a/frontend/src/Store/Actions/Creators/createSaveHandler.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getSectionState from 'Utilities/State/getSectionState';
-import { set, update } from '../baseActions';
-
-function createSaveHandler(section, url) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isSaving: true }));
-
- const state = getSectionState(getState(), section, true);
- const saveData = Object.assign({}, state.item, state.pendingChanges, payload);
-
- const promise = createAjaxRequest({
- url,
- method: 'PUT',
- dataType: 'json',
- data: JSON.stringify(saveData)
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- };
-}
-
-export default createSaveHandler;
diff --git a/frontend/src/Store/Actions/Creators/createSaveProviderHandler.js b/frontend/src/Store/Actions/Creators/createSaveProviderHandler.js
deleted file mode 100644
index 800895d77..000000000
--- a/frontend/src/Store/Actions/Creators/createSaveProviderHandler.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import $ from 'jquery';
-import _ from 'lodash';
-import { batchActions } from 'redux-batched-actions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getProviderState from 'Utilities/State/getProviderState';
-import { removeItem, set, updateItem } from '../baseActions';
-
-const abortCurrentRequests = {};
-let lastSaveData = null;
-
-export function createCancelSaveProviderHandler(section) {
- return function(getState, payload, dispatch) {
- if (abortCurrentRequests[section]) {
- abortCurrentRequests[section]();
- abortCurrentRequests[section] = null;
- }
- };
-}
-
-function createSaveProviderHandler(section, url, options = {}, removeStale = false) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isSaving: true }));
-
- const {
- id,
- queryParams = {},
- ...otherPayload
- } = payload;
-
- const saveData = Array.isArray(id) ? id.map((x) => getProviderState({ id: x, ...otherPayload }, getState, section)) : getProviderState({ id, ...otherPayload }, getState, section);
- const requestUrl = id ? `${url}/${id}` : url;
- const params = { ...queryParams };
-
- // If the user is re-saving the same provider without changes
- // force it to be saved.
-
- if (_.isEqual(saveData, lastSaveData)) {
- params.forceSave = true;
- }
-
- lastSaveData = saveData;
-
- const ajaxOptions = {
- url: `${requestUrl}?${$.param(params, true)}`,
- method: id ? 'PUT' : 'POST',
- contentType: 'application/json',
- dataType: 'json',
- data: JSON.stringify(saveData)
- };
-
- const { request, abortRequest } = createAjaxRequest(ajaxOptions);
-
- abortCurrentRequests[section] = abortRequest;
-
- request.done((data) => {
- lastSaveData = null;
-
- if (!Array.isArray(data)) {
- data = [data];
- }
-
- const toRemove = removeStale && Array.isArray(id) ? _.difference(id, _.map(data, 'id')) : [];
-
- dispatch(batchActions(
- data.map((item) => updateItem({ section, ...item })).concat(
- toRemove.map((item) => removeItem({ section, id: item }))
- ).concat(
- set({
- section,
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- })
- )));
- });
-
- request.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr.aborted ? null : xhr
- }));
- });
- };
-}
-
-export default createSaveProviderHandler;
diff --git a/frontend/src/Store/Actions/Creators/createServerSideCollectionHandlers.js b/frontend/src/Store/Actions/Creators/createServerSideCollectionHandlers.js
deleted file mode 100644
index 8b4697377..000000000
--- a/frontend/src/Store/Actions/Creators/createServerSideCollectionHandlers.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import pages from 'Utilities/pages';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import createFetchServerSideCollectionHandler from './createFetchServerSideCollectionHandler';
-import createSetServerSideCollectionFilterHandler from './createSetServerSideCollectionFilterHandler';
-import createSetServerSideCollectionPageHandler from './createSetServerSideCollectionPageHandler';
-import createSetServerSideCollectionSortHandler from './createSetServerSideCollectionSortHandler';
-
-function createServerSideCollectionHandlers(section, url, fetchThunk, handlers, fetchDataAugmenter) {
- const actionHandlers = {};
- const fetchHandlerType = handlers[serverSideCollectionHandlers.FETCH];
- const fetchHandler = createFetchServerSideCollectionHandler(section, url, fetchDataAugmenter);
- actionHandlers[fetchHandlerType] = fetchHandler;
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.FIRST_PAGE)) {
- const handlerType = handlers[serverSideCollectionHandlers.FIRST_PAGE];
- actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.FIRST, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.PREVIOUS_PAGE)) {
- const handlerType = handlers[serverSideCollectionHandlers.PREVIOUS_PAGE];
- actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.PREVIOUS, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.NEXT_PAGE)) {
- const handlerType = handlers[serverSideCollectionHandlers.NEXT_PAGE];
- actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.NEXT, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.LAST_PAGE)) {
- const handlerType = handlers[serverSideCollectionHandlers.LAST_PAGE];
- actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.LAST, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.EXACT_PAGE)) {
- const handlerType = handlers[serverSideCollectionHandlers.EXACT_PAGE];
- actionHandlers[handlerType] = createSetServerSideCollectionPageHandler(section, pages.EXACT, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.SORT)) {
- const handlerType = handlers[serverSideCollectionHandlers.SORT];
- actionHandlers[handlerType] = createSetServerSideCollectionSortHandler(section, fetchThunk);
- }
-
- if (handlers.hasOwnProperty(serverSideCollectionHandlers.FILTER)) {
- const handlerType = handlers[serverSideCollectionHandlers.FILTER];
- actionHandlers[handlerType] = createSetServerSideCollectionFilterHandler(section, fetchThunk);
- }
-
- return actionHandlers;
-}
-
-export default createServerSideCollectionHandlers;
diff --git a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionFilterHandler.js b/frontend/src/Store/Actions/Creators/createSetServerSideCollectionFilterHandler.js
deleted file mode 100644
index d7e476444..000000000
--- a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionFilterHandler.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { set } from '../baseActions';
-
-function createSetServerSideCollectionFilterHandler(section, fetchHandler) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, ...payload }));
- dispatch(fetchHandler({ page: 1 }));
- };
-}
-
-export default createSetServerSideCollectionFilterHandler;
diff --git a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionPageHandler.js b/frontend/src/Store/Actions/Creators/createSetServerSideCollectionPageHandler.js
deleted file mode 100644
index 12b21bb0d..000000000
--- a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionPageHandler.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import pages from 'Utilities/pages';
-import getSectionState from 'Utilities/State/getSectionState';
-
-function createSetServerSideCollectionPageHandler(section, page, fetchHandler) {
- return function(getState, payload, dispatch) {
- const sectionState = getSectionState(getState(), section, true);
- const currentPage = sectionState.page || 1;
- let nextPage = 0;
-
- switch (page) {
- case pages.FIRST:
- nextPage = 1;
- break;
- case pages.PREVIOUS:
- nextPage = currentPage - 1;
- break;
- case pages.NEXT:
- nextPage = currentPage + 1;
- break;
- case pages.LAST:
- nextPage = sectionState.totalPages;
- break;
- default:
- nextPage = payload.page;
- }
-
- // If we prefer to update the page immediately we should
- // set the page and not pass a page to the fetch handler.
-
- // dispatch(set({ section, page: nextPage }));
- dispatch(fetchHandler({ page: nextPage }));
- };
-}
-
-export default createSetServerSideCollectionPageHandler;
diff --git a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionSortHandler.js b/frontend/src/Store/Actions/Creators/createSetServerSideCollectionSortHandler.js
deleted file mode 100644
index 9bddfc2b7..000000000
--- a/frontend/src/Store/Actions/Creators/createSetServerSideCollectionSortHandler.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import { sortDirections } from 'Helpers/Props';
-import getSectionState from 'Utilities/State/getSectionState';
-import { set } from '../baseActions';
-
-function createSetServerSideCollectionSortHandler(section, fetchHandler) {
- return function(getState, payload, dispatch) {
- const sectionState = getSectionState(getState(), section, true);
- const sortKey = payload.sortKey || sectionState.sortKey;
- let sortDirection = payload.sortDirection;
-
- if (!sortDirection) {
- if (payload.sortKey === sectionState.sortKey) {
- sortDirection = sectionState.sortDirection === sortDirections.ASCENDING ?
- sortDirections.DESCENDING :
- sortDirections.ASCENDING;
- } else {
- sortDirection = sectionState.sortDirection;
- }
- }
-
- dispatch(set({ section, sortKey, sortDirection }));
- dispatch(fetchHandler());
- };
-}
-
-export default createSetServerSideCollectionSortHandler;
diff --git a/frontend/src/Store/Actions/Creators/createTestAllProvidersHandler.js b/frontend/src/Store/Actions/Creators/createTestAllProvidersHandler.js
deleted file mode 100644
index 77deaec64..000000000
--- a/frontend/src/Store/Actions/Creators/createTestAllProvidersHandler.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set } from '../baseActions';
-
-function createTestAllProvidersHandler(section, url) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isTestingAll: true }));
-
- const ajaxOptions = {
- url: `${url}/testall`,
- method: 'POST',
- contentType: 'application/json',
- dataType: 'json'
- };
-
- const { request } = createAjaxRequest(ajaxOptions);
-
- request.done((data) => {
- dispatch(set({
- section,
- isTestingAll: false,
- saveError: null
- }));
- });
-
- request.fail((xhr) => {
- dispatch(set({
- section,
- isTestingAll: false
- }));
- });
- };
-}
-
-export default createTestAllProvidersHandler;
diff --git a/frontend/src/Store/Actions/Creators/createTestProviderHandler.js b/frontend/src/Store/Actions/Creators/createTestProviderHandler.js
deleted file mode 100644
index e35157dbd..000000000
--- a/frontend/src/Store/Actions/Creators/createTestProviderHandler.js
+++ /dev/null
@@ -1,72 +0,0 @@
-import $ from 'jquery';
-import _ from 'lodash';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getProviderState from 'Utilities/State/getProviderState';
-import { set } from '../baseActions';
-
-const abortCurrentRequests = {};
-let lastTestData = null;
-
-export function createCancelTestProviderHandler(section) {
- return function(getState, payload, dispatch) {
- if (abortCurrentRequests[section]) {
- abortCurrentRequests[section]();
- abortCurrentRequests[section] = null;
- }
- };
-}
-
-function createTestProviderHandler(section, url) {
- return function(getState, payload, dispatch) {
- dispatch(set({ section, isTesting: true }));
-
- const {
- queryParams = {},
- ...otherPayload
- } = payload;
-
- const testData = getProviderState({ ...otherPayload }, getState, section);
- const params = { ...queryParams };
-
- // If the user is re-testing the same provider without changes
- // force it to be tested.
-
- if (_.isEqual(testData, lastTestData)) {
- params.forceTest = true;
- }
-
- lastTestData = testData;
-
- const ajaxOptions = {
- url: `${url}/test?${$.param(params, true)}`,
- method: 'POST',
- contentType: 'application/json',
- dataType: 'json',
- data: JSON.stringify(testData)
- };
-
- const { request, abortRequest } = createAjaxRequest(ajaxOptions);
-
- abortCurrentRequests[section] = abortRequest;
-
- request.done((data) => {
- lastTestData = null;
-
- dispatch(set({
- section,
- isTesting: false,
- saveError: null
- }));
- });
-
- request.fail((xhr) => {
- dispatch(set({
- section,
- isTesting: false,
- saveError: xhr.aborted ? null : xhr
- }));
- });
- };
-}
-
-export default createTestProviderHandler;
diff --git a/frontend/src/Store/Actions/Settings/autoTaggingSpecifications.js b/frontend/src/Store/Actions/Settings/autoTaggingSpecifications.js
deleted file mode 100644
index cfc919c7d..000000000
--- a/frontend/src/Store/Actions/Settings/autoTaggingSpecifications.js
+++ /dev/null
@@ -1,193 +0,0 @@
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createClearReducer from 'Store/Actions/Creators/Reducers/createClearReducer';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getNextId from 'Utilities/State/getNextId';
-import getProviderState from 'Utilities/State/getProviderState';
-import getSectionState from 'Utilities/State/getSectionState';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { removeItem, set, update, updateItem } from '../baseActions';
-
-//
-// Variables
-
-const section = 'settings.autoTaggingSpecifications';
-
-//
-// Actions Types
-
-export const FETCH_AUTO_TAGGING_SPECIFICATIONS = 'settings/autoTaggingSpecifications/fetchAutoTaggingSpecifications';
-export const FETCH_AUTO_TAGGING_SPECIFICATION_SCHEMA = 'settings/autoTaggingSpecifications/fetchAutoTaggingSpecificationSchema';
-export const SELECT_AUTO_TAGGING_SPECIFICATION_SCHEMA = 'settings/autoTaggingSpecifications/selectAutoTaggingSpecificationSchema';
-export const SET_AUTO_TAGGING_SPECIFICATION_VALUE = 'settings/autoTaggingSpecifications/setAutoTaggingSpecificationValue';
-export const SET_AUTO_TAGGING_SPECIFICATION_FIELD_VALUE = 'settings/autoTaggingSpecifications/setAutoTaggingSpecificationFieldValue';
-export const SAVE_AUTO_TAGGING_SPECIFICATION = 'settings/autoTaggingSpecifications/saveAutoTaggingSpecification';
-export const DELETE_AUTO_TAGGING_SPECIFICATION = 'settings/autoTaggingSpecifications/deleteAutoTaggingSpecification';
-export const DELETE_ALL_AUTO_TAGGING_SPECIFICATION = 'settings/autoTaggingSpecifications/deleteAllAutoTaggingSpecification';
-export const CLONE_AUTO_TAGGING_SPECIFICATION = 'settings/autoTaggingSpecifications/cloneAutoTaggingSpecification';
-export const CLEAR_AUTO_TAGGING_SPECIFICATIONS = 'settings/autoTaggingSpecifications/clearAutoTaggingSpecifications';
-export const CLEAR_AUTO_TAGGING_SPECIFICATION_PENDING = 'settings/autoTaggingSpecifications/clearAutoTaggingSpecificationPending';
-//
-// Action Creators
-
-export const fetchAutoTaggingSpecifications = createThunk(FETCH_AUTO_TAGGING_SPECIFICATIONS);
-export const fetchAutoTaggingSpecificationSchema = createThunk(FETCH_AUTO_TAGGING_SPECIFICATION_SCHEMA);
-export const selectAutoTaggingSpecificationSchema = createAction(SELECT_AUTO_TAGGING_SPECIFICATION_SCHEMA);
-
-export const saveAutoTaggingSpecification = createThunk(SAVE_AUTO_TAGGING_SPECIFICATION);
-export const deleteAutoTaggingSpecification = createThunk(DELETE_AUTO_TAGGING_SPECIFICATION);
-export const deleteAllAutoTaggingSpecification = createThunk(DELETE_ALL_AUTO_TAGGING_SPECIFICATION);
-
-export const setAutoTaggingSpecificationValue = createAction(SET_AUTO_TAGGING_SPECIFICATION_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setAutoTaggingSpecificationFieldValue = createAction(SET_AUTO_TAGGING_SPECIFICATION_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneAutoTaggingSpecification = createAction(CLONE_AUTO_TAGGING_SPECIFICATION);
-
-export const clearAutoTaggingSpecification = createAction(CLEAR_AUTO_TAGGING_SPECIFICATIONS);
-
-export const clearAutoTaggingSpecificationPending = createThunk(CLEAR_AUTO_TAGGING_SPECIFICATION_PENDING);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_AUTO_TAGGING_SPECIFICATION_SCHEMA]: createFetchSchemaHandler(section, '/autoTagging/schema'),
-
- [FETCH_AUTO_TAGGING_SPECIFICATIONS]: (getState, payload, dispatch) => {
- let tags = [];
- if (payload.id) {
- const cfState = getSectionState(getState(), 'settings.autoTaggings', true);
- const cf = cfState.items[cfState.itemMap[payload.id]];
- tags = cf.specifications.map((tag, i) => {
- return {
- id: i + 1,
- ...tag
- };
- });
- }
-
- dispatch(batchActions([
- update({ section, data: tags }),
- set({
- section,
- isPopulated: true
- })
- ]));
- },
-
- [SAVE_AUTO_TAGGING_SPECIFICATION]: (getState, payload, dispatch) => {
- const {
- id,
- ...otherPayload
- } = payload;
-
- const saveData = getProviderState({ id, ...otherPayload }, getState, section, false);
-
- // we have to set id since not actually posting to server yet
- if (!saveData.id) {
- saveData.id = getNextId(getState().settings.autoTaggingSpecifications.items);
- }
-
- dispatch(batchActions([
- updateItem({ section, ...saveData }),
- set({
- section,
- pendingChanges: {}
- })
- ]));
- },
-
- [DELETE_AUTO_TAGGING_SPECIFICATION]: (getState, payload, dispatch) => {
- const id = payload.id;
- return dispatch(removeItem({ section, id }));
- },
-
- [DELETE_ALL_AUTO_TAGGING_SPECIFICATION]: (getState, payload, dispatch) => {
- return dispatch(set({
- section,
- items: []
- }));
- },
-
- [CLEAR_AUTO_TAGGING_SPECIFICATION_PENDING]: (getState, payload, dispatch) => {
- return dispatch(set({
- section,
- pendingChanges: {}
- }));
- }
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_AUTO_TAGGING_SPECIFICATION_VALUE]: createSetSettingValueReducer(section),
- [SET_AUTO_TAGGING_SPECIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_AUTO_TAGGING_SPECIFICATION_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- return selectedSchema;
- });
- },
-
- [CLONE_AUTO_TAGGING_SPECIFICATION]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const items = newState.items;
- const item = items.find((i) => i.id === id);
- const newId = getNextId(newState.items);
- const newItem = {
- ...item,
- id: newId,
- name: `${item.name} - Copy`
- };
- newState.items = [...items, newItem];
- newState.itemMap[newId] = newState.items.length - 1;
-
- return updateSectionState(state, section, newState);
- },
-
- [CLEAR_AUTO_TAGGING_SPECIFICATIONS]: createClearReducer(section, {
- isPopulated: false,
- error: null,
- items: []
- })
- }
-};
diff --git a/frontend/src/Store/Actions/Settings/autoTaggings.js b/frontend/src/Store/Actions/Settings/autoTaggings.js
deleted file mode 100644
index 35b3d4149..000000000
--- a/frontend/src/Store/Actions/Settings/autoTaggings.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import { createAction } from 'redux-actions';
-import { set } from 'Store/Actions/baseActions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-//
-// Variables
-
-const section = 'settings.autoTaggings';
-
-//
-// Actions Types
-
-export const FETCH_AUTO_TAGGINGS = 'settings/autoTaggings/fetchAutoTaggings';
-export const SAVE_AUTO_TAGGING = 'settings/autoTaggings/saveAutoTagging';
-export const DELETE_AUTO_TAGGING = 'settings/autoTaggings/deleteAutoTagging';
-export const SET_AUTO_TAGGING_VALUE = 'settings/autoTaggings/setAutoTaggingValue';
-export const CLONE_AUTO_TAGGING = 'settings/autoTaggings/cloneAutoTagging';
-
-//
-// Action Creators
-
-export const fetchAutoTaggings = createThunk(FETCH_AUTO_TAGGINGS);
-export const saveAutoTagging = createThunk(SAVE_AUTO_TAGGING);
-export const deleteAutoTagging = createThunk(DELETE_AUTO_TAGGING);
-
-export const setAutoTaggingValue = createAction(SET_AUTO_TAGGING_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneAutoTagging = createAction(CLONE_AUTO_TAGGING);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isSchemaFetching: false,
- isSchemaPopulated: false,
- isFetching: false,
- isPopulated: false,
- schema: {
- removeTagsAutomatically: false,
- tags: []
- },
- error: null,
- isDeleting: false,
- deleteError: null,
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_AUTO_TAGGINGS]: createFetchHandler(section, '/autoTagging'),
-
- [DELETE_AUTO_TAGGING]: createRemoveItemHandler(section, '/autoTagging'),
-
- [SAVE_AUTO_TAGGING]: (getState, payload, dispatch) => {
- // move the format tags in as a pending change
- const state = getState();
- const pendingChanges = state.settings.autoTaggings.pendingChanges;
- pendingChanges.specifications = state.settings.autoTaggingSpecifications.items;
- dispatch(set({
- section,
- pendingChanges
- }));
-
- createSaveProviderHandler(section, '/autoTagging')(getState, payload, dispatch);
- }
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_AUTO_TAGGING_VALUE]: createSetSettingValueReducer(section),
-
- [CLONE_AUTO_TAGGING]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const item = newState.items.find((i) => i.id === id);
- const pendingChanges = { ...item, id: 0 };
- delete pendingChanges.id;
-
- pendingChanges.name = `${pendingChanges.name} - Copy`;
- newState.pendingChanges = pendingChanges;
-
- return updateSectionState(state, section, newState);
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/customFormatSpecifications.js b/frontend/src/Store/Actions/Settings/customFormatSpecifications.js
deleted file mode 100644
index d74898d3e..000000000
--- a/frontend/src/Store/Actions/Settings/customFormatSpecifications.js
+++ /dev/null
@@ -1,193 +0,0 @@
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createClearReducer from 'Store/Actions/Creators/Reducers/createClearReducer';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getNextId from 'Utilities/State/getNextId';
-import getProviderState from 'Utilities/State/getProviderState';
-import getSectionState from 'Utilities/State/getSectionState';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { removeItem, set, update, updateItem } from '../baseActions';
-
-//
-// Variables
-
-const section = 'settings.customFormatSpecifications';
-
-//
-// Actions Types
-
-export const FETCH_CUSTOM_FORMAT_SPECIFICATIONS = 'settings/customFormatSpecifications/fetchCustomFormatSpecifications';
-export const FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA = 'settings/customFormatSpecifications/fetchCustomFormatSpecificationSchema';
-export const SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA = 'settings/customFormatSpecifications/selectCustomFormatSpecificationSchema';
-export const SET_CUSTOM_FORMAT_SPECIFICATION_VALUE = 'settings/customFormatSpecifications/setCustomFormatSpecificationValue';
-export const SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE = 'settings/customFormatSpecifications/setCustomFormatSpecificationFieldValue';
-export const SAVE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/saveCustomFormatSpecification';
-export const DELETE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/deleteCustomFormatSpecification';
-export const DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/deleteAllCustomFormatSpecification';
-export const CLONE_CUSTOM_FORMAT_SPECIFICATION = 'settings/customFormatSpecifications/cloneCustomFormatSpecification';
-export const CLEAR_CUSTOM_FORMAT_SPECIFICATIONS = 'settings/customFormatSpecifications/clearCustomFormatSpecifications';
-export const CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING = 'settings/customFormatSpecifications/clearCustomFormatSpecificationPending';
-//
-// Action Creators
-
-export const fetchCustomFormatSpecifications = createThunk(FETCH_CUSTOM_FORMAT_SPECIFICATIONS);
-export const fetchCustomFormatSpecificationSchema = createThunk(FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA);
-export const selectCustomFormatSpecificationSchema = createAction(SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA);
-
-export const saveCustomFormatSpecification = createThunk(SAVE_CUSTOM_FORMAT_SPECIFICATION);
-export const deleteCustomFormatSpecification = createThunk(DELETE_CUSTOM_FORMAT_SPECIFICATION);
-export const deleteAllCustomFormatSpecification = createThunk(DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION);
-
-export const setCustomFormatSpecificationValue = createAction(SET_CUSTOM_FORMAT_SPECIFICATION_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setCustomFormatSpecificationFieldValue = createAction(SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneCustomFormatSpecification = createAction(CLONE_CUSTOM_FORMAT_SPECIFICATION);
-
-export const clearCustomFormatSpecification = createAction(CLEAR_CUSTOM_FORMAT_SPECIFICATIONS);
-
-export const clearCustomFormatSpecificationPending = createThunk(CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_CUSTOM_FORMAT_SPECIFICATION_SCHEMA]: createFetchSchemaHandler(section, '/customformat/schema'),
-
- [FETCH_CUSTOM_FORMAT_SPECIFICATIONS]: (getState, payload, dispatch) => {
- let tags = [];
- if (payload.id) {
- const cfState = getSectionState(getState(), 'settings.customFormats', true);
- const cf = cfState.items[cfState.itemMap[payload.id]];
- tags = cf.specifications.map((tag, i) => {
- return {
- id: i + 1,
- ...tag
- };
- });
- }
-
- dispatch(batchActions([
- update({ section, data: tags }),
- set({
- section,
- isPopulated: true
- })
- ]));
- },
-
- [SAVE_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => {
- const {
- id,
- ...otherPayload
- } = payload;
-
- const saveData = getProviderState({ id, ...otherPayload }, getState, section, false);
-
- // we have to set id since not actually posting to server yet
- if (!saveData.id) {
- saveData.id = getNextId(getState().settings.customFormatSpecifications.items);
- }
-
- dispatch(batchActions([
- updateItem({ section, ...saveData }),
- set({
- section,
- pendingChanges: {}
- })
- ]));
- },
-
- [DELETE_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => {
- const id = payload.id;
- return dispatch(removeItem({ section, id }));
- },
-
- [DELETE_ALL_CUSTOM_FORMAT_SPECIFICATION]: (getState, payload, dispatch) => {
- return dispatch(set({
- section,
- items: []
- }));
- },
-
- [CLEAR_CUSTOM_FORMAT_SPECIFICATION_PENDING]: (getState, payload, dispatch) => {
- return dispatch(set({
- section,
- pendingChanges: {}
- }));
- }
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_CUSTOM_FORMAT_SPECIFICATION_VALUE]: createSetSettingValueReducer(section),
- [SET_CUSTOM_FORMAT_SPECIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_CUSTOM_FORMAT_SPECIFICATION_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- return selectedSchema;
- });
- },
-
- [CLONE_CUSTOM_FORMAT_SPECIFICATION]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const items = newState.items;
- const item = items.find((i) => i.id === id);
- const newId = getNextId(newState.items);
- const newItem = {
- ...item,
- id: newId,
- name: `${item.name} - Copy`
- };
- newState.items = [...items, newItem];
- newState.itemMap[newId] = newState.items.length - 1;
-
- return updateSectionState(state, section, newState);
- },
-
- [CLEAR_CUSTOM_FORMAT_SPECIFICATIONS]: createClearReducer(section, {
- isPopulated: false,
- error: null,
- items: []
- })
- }
-};
diff --git a/frontend/src/Store/Actions/Settings/customFormats.js b/frontend/src/Store/Actions/Settings/customFormats.js
deleted file mode 100644
index 3b8a209f9..000000000
--- a/frontend/src/Store/Actions/Settings/customFormats.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { createAction } from 'redux-actions';
-import { sortDirections } from 'Helpers/Props';
-import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler';
-import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetClientSideCollectionSortReducer
- from 'Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { set } from '../baseActions';
-
-//
-// Variables
-
-const section = 'settings.customFormats';
-
-//
-// Actions Types
-
-export const FETCH_CUSTOM_FORMATS = 'settings/customFormats/fetchCustomFormats';
-export const SAVE_CUSTOM_FORMAT = 'settings/customFormats/saveCustomFormat';
-export const DELETE_CUSTOM_FORMAT = 'settings/customFormats/deleteCustomFormat';
-export const SET_CUSTOM_FORMAT_VALUE = 'settings/customFormats/setCustomFormatValue';
-export const CLONE_CUSTOM_FORMAT = 'settings/customFormats/cloneCustomFormat';
-export const BULK_EDIT_CUSTOM_FORMATS = 'settings/downloadClients/bulkEditCustomFormats';
-export const BULK_DELETE_CUSTOM_FORMATS = 'settings/downloadClients/bulkDeleteCustomFormats';
-export const SET_MANAGE_CUSTOM_FORMATS_SORT = 'settings/downloadClients/setManageCustomFormatsSort';
-
-//
-// Action Creators
-
-export const fetchCustomFormats = createThunk(FETCH_CUSTOM_FORMATS);
-export const saveCustomFormat = createThunk(SAVE_CUSTOM_FORMAT);
-export const deleteCustomFormat = createThunk(DELETE_CUSTOM_FORMAT);
-export const bulkEditCustomFormats = createThunk(BULK_EDIT_CUSTOM_FORMATS);
-export const bulkDeleteCustomFormats = createThunk(BULK_DELETE_CUSTOM_FORMATS);
-export const setManageCustomFormatsSort = createAction(SET_MANAGE_CUSTOM_FORMATS_SORT);
-
-export const setCustomFormatValue = createAction(SET_CUSTOM_FORMAT_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneCustomFormat = createAction(CLONE_CUSTOM_FORMAT);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- items: [],
- pendingChanges: {},
-
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: {
- includeCustomFormatWhenRenaming: false
- },
-
- sortKey: 'name',
- sortDirection: sortDirections.ASCENDING,
- sortPredicates: {
- name: ({ name }) => {
- return name.toLocaleLowerCase();
- }
- }
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_CUSTOM_FORMATS]: createFetchHandler(section, '/customformat'),
-
- [DELETE_CUSTOM_FORMAT]: createRemoveItemHandler(section, '/customformat'),
-
- [SAVE_CUSTOM_FORMAT]: (getState, payload, dispatch) => {
- // move the format tags in as a pending change
- const state = getState();
- const pendingChanges = state.settings.customFormats.pendingChanges;
- pendingChanges.specifications = state.settings.customFormatSpecifications.items;
- dispatch(set({
- section,
- pendingChanges
- }));
-
- createSaveProviderHandler(section, '/customformat')(getState, payload, dispatch);
- },
-
- [BULK_EDIT_CUSTOM_FORMATS]: createBulkEditItemHandler(section, '/customformat/bulk'),
- [BULK_DELETE_CUSTOM_FORMATS]: createBulkRemoveItemHandler(section, '/customformat/bulk')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_CUSTOM_FORMAT_VALUE]: createSetSettingValueReducer(section),
-
- [CLONE_CUSTOM_FORMAT]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const item = newState.items.find((i) => i.id === id);
- const pendingChanges = { ...item, id: 0 };
- delete pendingChanges.id;
-
- pendingChanges.name = `${pendingChanges.name} - Copy`;
- newState.pendingChanges = pendingChanges;
-
- return updateSectionState(state, section, newState);
- },
-
- [SET_MANAGE_CUSTOM_FORMATS_SORT]: createSetClientSideCollectionSortReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/delayProfiles.js b/frontend/src/Store/Actions/Settings/delayProfiles.js
deleted file mode 100644
index 38abc5841..000000000
--- a/frontend/src/Store/Actions/Settings/delayProfiles.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { update } from 'Store/Actions/baseActions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-
-//
-// Variables
-
-const section = 'settings.delayProfiles';
-
-//
-// Actions Types
-
-export const FETCH_DELAY_PROFILES = 'settings/delayProfiles/fetchDelayProfiles';
-export const FETCH_DELAY_PROFILE_SCHEMA = 'settings/delayProfiles/fetchDelayProfileSchema';
-export const SAVE_DELAY_PROFILE = 'settings/delayProfiles/saveDelayProfile';
-export const DELETE_DELAY_PROFILE = 'settings/delayProfiles/deleteDelayProfile';
-export const REORDER_DELAY_PROFILE = 'settings/delayProfiles/reorderDelayProfile';
-export const SET_DELAY_PROFILE_VALUE = 'settings/delayProfiles/setDelayProfileValue';
-
-//
-// Action Creators
-
-export const fetchDelayProfiles = createThunk(FETCH_DELAY_PROFILES);
-export const fetchDelayProfileSchema = createThunk(FETCH_DELAY_PROFILE_SCHEMA);
-export const saveDelayProfile = createThunk(SAVE_DELAY_PROFILE);
-export const deleteDelayProfile = createThunk(DELETE_DELAY_PROFILE);
-export const reorderDelayProfile = createThunk(REORDER_DELAY_PROFILE);
-
-export const setDelayProfileValue = createAction(SET_DELAY_PROFILE_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_DELAY_PROFILES]: createFetchHandler(section, '/delayprofile'),
- [FETCH_DELAY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/delayprofile/schema'),
-
- [SAVE_DELAY_PROFILE]: createSaveProviderHandler(section, '/delayprofile'),
- [DELETE_DELAY_PROFILE]: createRemoveItemHandler(section, '/delayprofile'),
-
- [REORDER_DELAY_PROFILE]: (getState, payload, dispatch) => {
- const { id, moveIndex } = payload;
- const moveOrder = moveIndex + 1;
- const delayProfiles = getState().settings.delayProfiles.items;
- const moving = _.find(delayProfiles, { id });
-
- // Don't move if the order hasn't changed
- if (moving.order === moveOrder) {
- return;
- }
-
- const after = moveIndex > 0 ? _.find(delayProfiles, { order: moveIndex }) : null;
- const afterQueryParam = after ? `after=${after.id}` : '';
-
- const promise = createAjaxRequest({
- method: 'PUT',
- url: `/delayprofile/reorder/${id}?${afterQueryParam}`
- }).request;
-
- promise.done((data) => {
- dispatch(update({ section, data }));
- });
- }
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_DELAY_PROFILE_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/downloadClientOptions.js b/frontend/src/Store/Actions/Settings/downloadClientOptions.js
deleted file mode 100644
index 0cd7b285e..000000000
--- a/frontend/src/Store/Actions/Settings/downloadClientOptions.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.downloadClientOptions';
-
-//
-// Actions Types
-
-export const FETCH_DOWNLOAD_CLIENT_OPTIONS = 'FETCH_DOWNLOAD_CLIENT_OPTIONS';
-export const SET_DOWNLOAD_CLIENT_OPTIONS_VALUE = 'SET_DOWNLOAD_CLIENT_OPTIONS_VALUE';
-export const SAVE_DOWNLOAD_CLIENT_OPTIONS = 'SAVE_DOWNLOAD_CLIENT_OPTIONS';
-
-//
-// Action Creators
-
-export const fetchDownloadClientOptions = createThunk(FETCH_DOWNLOAD_CLIENT_OPTIONS);
-export const saveDownloadClientOptions = createThunk(SAVE_DOWNLOAD_CLIENT_OPTIONS);
-export const setDownloadClientOptionsValue = createAction(SET_DOWNLOAD_CLIENT_OPTIONS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_DOWNLOAD_CLIENT_OPTIONS]: createFetchHandler(section, '/config/downloadclient'),
- [SAVE_DOWNLOAD_CLIENT_OPTIONS]: createSaveHandler(section, '/config/downloadclient')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_DOWNLOAD_CLIENT_OPTIONS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/downloadClients.js b/frontend/src/Store/Actions/Settings/downloadClients.js
deleted file mode 100644
index 1113e7daf..000000000
--- a/frontend/src/Store/Actions/Settings/downloadClients.js
+++ /dev/null
@@ -1,142 +0,0 @@
-import { createAction } from 'redux-actions';
-import { sortDirections } from 'Helpers/Props';
-import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler';
-import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
-import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
-import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
-import createSetClientSideCollectionSortReducer from 'Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-
-//
-// Variables
-
-const section = 'settings.downloadClients';
-
-//
-// Actions Types
-
-export const FETCH_DOWNLOAD_CLIENTS = 'settings/downloadClients/fetchDownloadClients';
-export const FETCH_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/fetchDownloadClientSchema';
-export const SELECT_DOWNLOAD_CLIENT_SCHEMA = 'settings/downloadClients/selectDownloadClientSchema';
-export const SET_DOWNLOAD_CLIENT_VALUE = 'settings/downloadClients/setDownloadClientValue';
-export const SET_DOWNLOAD_CLIENT_FIELD_VALUE = 'settings/downloadClients/setDownloadClientFieldValue';
-export const SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/saveDownloadClient';
-export const CANCEL_SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelSaveDownloadClient';
-export const DELETE_DOWNLOAD_CLIENT = 'settings/downloadClients/deleteDownloadClient';
-export const TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/testDownloadClient';
-export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestDownloadClient';
-export const TEST_ALL_DOWNLOAD_CLIENTS = 'settings/downloadClients/testAllDownloadClients';
-export const BULK_EDIT_DOWNLOAD_CLIENTS = 'settings/downloadClients/bulkEditDownloadClients';
-export const BULK_DELETE_DOWNLOAD_CLIENTS = 'settings/downloadClients/bulkDeleteDownloadClients';
-export const SET_MANAGE_DOWNLOAD_CLIENTS_SORT = 'settings/downloadClients/setManageDownloadClientsSort';
-
-//
-// Action Creators
-
-export const fetchDownloadClients = createThunk(FETCH_DOWNLOAD_CLIENTS);
-export const fetchDownloadClientSchema = createThunk(FETCH_DOWNLOAD_CLIENT_SCHEMA);
-export const selectDownloadClientSchema = createAction(SELECT_DOWNLOAD_CLIENT_SCHEMA);
-
-export const saveDownloadClient = createThunk(SAVE_DOWNLOAD_CLIENT);
-export const cancelSaveDownloadClient = createThunk(CANCEL_SAVE_DOWNLOAD_CLIENT);
-export const deleteDownloadClient = createThunk(DELETE_DOWNLOAD_CLIENT);
-export const testDownloadClient = createThunk(TEST_DOWNLOAD_CLIENT);
-export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT);
-export const testAllDownloadClients = createThunk(TEST_ALL_DOWNLOAD_CLIENTS);
-export const bulkEditDownloadClients = createThunk(BULK_EDIT_DOWNLOAD_CLIENTS);
-export const bulkDeleteDownloadClients = createThunk(BULK_DELETE_DOWNLOAD_CLIENTS);
-export const setManageDownloadClientsSort = createAction(SET_MANAGE_DOWNLOAD_CLIENTS_SORT);
-
-export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setDownloadClientFieldValue = createAction(SET_DOWNLOAD_CLIENT_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- isTesting: false,
- isTestingAll: false,
- items: [],
- pendingChanges: {},
- sortKey: 'name',
- sortDirection: sortDirections.ASCENDING,
- sortPredicates: {
- name: ({ name }) => {
- return name.toLocaleLowerCase();
- }
- }
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_DOWNLOAD_CLIENTS]: createFetchHandler(section, '/downloadclient'),
- [FETCH_DOWNLOAD_CLIENT_SCHEMA]: createFetchSchemaHandler(section, '/downloadclient/schema'),
-
- [SAVE_DOWNLOAD_CLIENT]: createSaveProviderHandler(section, '/downloadclient'),
- [CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section),
- [DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'),
- [TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'),
- [CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section),
- [TEST_ALL_DOWNLOAD_CLIENTS]: createTestAllProvidersHandler(section, '/downloadclient'),
- [BULK_EDIT_DOWNLOAD_CLIENTS]: createBulkEditItemHandler(section, '/downloadclient/bulk'),
- [BULK_DELETE_DOWNLOAD_CLIENTS]: createBulkRemoveItemHandler(section, '/downloadclient/bulk')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_DOWNLOAD_CLIENT_VALUE]: createSetSettingValueReducer(section),
- [SET_DOWNLOAD_CLIENT_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_DOWNLOAD_CLIENT_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- selectedSchema.name = selectedSchema.implementationName;
- selectedSchema.enable = true;
-
- return selectedSchema;
- });
- },
-
- [SET_MANAGE_DOWNLOAD_CLIENTS_SORT]: createSetClientSideCollectionSortReducer(section)
-
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/general.js b/frontend/src/Store/Actions/Settings/general.js
deleted file mode 100644
index 98bb2703d..000000000
--- a/frontend/src/Store/Actions/Settings/general.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.general';
-
-//
-// Actions Types
-
-export const FETCH_GENERAL_SETTINGS = 'settings/general/fetchGeneralSettings';
-export const SET_GENERAL_SETTINGS_VALUE = 'settings/general/setGeneralSettingsValue';
-export const SAVE_GENERAL_SETTINGS = 'settings/general/saveGeneralSettings';
-
-//
-// Action Creators
-
-export const fetchGeneralSettings = createThunk(FETCH_GENERAL_SETTINGS);
-export const saveGeneralSettings = createThunk(SAVE_GENERAL_SETTINGS);
-export const setGeneralSettingsValue = createAction(SET_GENERAL_SETTINGS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_GENERAL_SETTINGS]: createFetchHandler(section, '/config/host'),
- [SAVE_GENERAL_SETTINGS]: createSaveHandler(section, '/config/host')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_GENERAL_SETTINGS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/importListExclusions.js b/frontend/src/Store/Actions/Settings/importListExclusions.js
deleted file mode 100644
index b9b38a0ef..000000000
--- a/frontend/src/Store/Actions/Settings/importListExclusions.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.importListExclusions';
-
-//
-// Actions Types
-
-export const FETCH_IMPORT_LIST_EXCLUSIONS = 'settings/importListExclusions/fetchImportListExclusions';
-export const SAVE_IMPORT_LIST_EXCLUSION = 'settings/importListExclusions/saveImportListExclusion';
-export const DELETE_IMPORT_LIST_EXCLUSION = 'settings/importListExclusions/deleteImportListExclusion';
-export const SET_IMPORT_LIST_EXCLUSION_VALUE = 'settings/importListExclusions/setImportListExclusionValue';
-
-//
-// Action Creators
-
-export const fetchImportListExclusions = createThunk(FETCH_IMPORT_LIST_EXCLUSIONS);
-export const saveImportListExclusion = createThunk(SAVE_IMPORT_LIST_EXCLUSION);
-export const deleteImportListExclusion = createThunk(DELETE_IMPORT_LIST_EXCLUSION);
-
-export const setImportListExclusionValue = createAction(SET_IMPORT_LIST_EXCLUSION_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_IMPORT_LIST_EXCLUSIONS]: createFetchHandler(section, '/importlistexclusion'),
- [SAVE_IMPORT_LIST_EXCLUSION]: createSaveProviderHandler(section, '/importlistexclusion'),
- [DELETE_IMPORT_LIST_EXCLUSION]: createRemoveItemHandler(section, '/importlistexclusion')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_IMPORT_LIST_EXCLUSION_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/importLists.js b/frontend/src/Store/Actions/Settings/importLists.js
deleted file mode 100644
index fcd6877c4..000000000
--- a/frontend/src/Store/Actions/Settings/importLists.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import { createAction } from 'redux-actions';
-import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler';
-import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
-import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
-import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-
-//
-// Variables
-
-const section = 'settings.importLists';
-
-//
-// Actions Types
-
-export const FETCH_IMPORT_LISTS = 'settings/importlists/fetchImportLists';
-export const FETCH_IMPORT_LIST_SCHEMA = 'settings/importlists/fetchImportListSchema';
-export const SELECT_IMPORT_LIST_SCHEMA = 'settings/importlists/selectImportListSchema';
-export const SET_IMPORT_LIST_VALUE = 'settings/importlists/setImportListValue';
-export const SET_IMPORT_LIST_FIELD_VALUE = 'settings/importlists/setImportListFieldValue';
-export const SAVE_IMPORT_LIST = 'settings/importlists/saveImportList';
-export const CANCEL_SAVE_IMPORT_LIST = 'settings/importlists/cancelSaveImportList';
-export const DELETE_IMPORT_LIST = 'settings/importlists/deleteImportList';
-export const TEST_IMPORT_LIST = 'settings/importlists/testImportList';
-export const CANCEL_TEST_IMPORT_LIST = 'settings/importlists/cancelTestImportList';
-export const TEST_ALL_IMPORT_LISTS = 'settings/importlists/testAllImportLists';
-export const BULK_EDIT_IMPORT_LISTS = 'settings/importlists/bulkEditImportLists';
-export const BULK_DELETE_IMPORT_LISTS = 'settings/importlists/bulkDeleteImportLists';
-
-//
-// Action Creators
-
-export const fetchImportLists = createThunk(FETCH_IMPORT_LISTS);
-export const fetchImportListSchema = createThunk(FETCH_IMPORT_LIST_SCHEMA);
-export const selectImportListSchema = createAction(SELECT_IMPORT_LIST_SCHEMA);
-
-export const saveImportList = createThunk(SAVE_IMPORT_LIST);
-export const cancelSaveImportList = createThunk(CANCEL_SAVE_IMPORT_LIST);
-export const deleteImportList = createThunk(DELETE_IMPORT_LIST);
-export const testImportList = createThunk(TEST_IMPORT_LIST);
-export const cancelTestImportList = createThunk(CANCEL_TEST_IMPORT_LIST);
-export const testAllImportLists = createThunk(TEST_ALL_IMPORT_LISTS);
-export const bulkEditImportLists = createThunk(BULK_EDIT_IMPORT_LISTS);
-export const bulkDeleteImportLists = createThunk(BULK_DELETE_IMPORT_LISTS);
-
-export const setImportListValue = createAction(SET_IMPORT_LIST_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setImportListFieldValue = createAction(SET_IMPORT_LIST_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- isTesting: false,
- isTestingAll: false,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_IMPORT_LISTS]: createFetchHandler(section, '/importlist'),
- [FETCH_IMPORT_LIST_SCHEMA]: createFetchSchemaHandler(section, '/importlist/schema'),
-
- [SAVE_IMPORT_LIST]: createSaveProviderHandler(section, '/importlist'),
- [CANCEL_SAVE_IMPORT_LIST]: createCancelSaveProviderHandler(section),
- [DELETE_IMPORT_LIST]: createRemoveItemHandler(section, '/importlist'),
- [TEST_IMPORT_LIST]: createTestProviderHandler(section, '/importlist'),
- [CANCEL_TEST_IMPORT_LIST]: createCancelTestProviderHandler(section),
- [TEST_ALL_IMPORT_LISTS]: createTestAllProvidersHandler(section, '/importlist'),
- [BULK_EDIT_IMPORT_LISTS]: createBulkEditItemHandler(section, '/importlist/bulk'),
- [BULK_DELETE_IMPORT_LISTS]: createBulkRemoveItemHandler(section, '/importlist/bulk')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_IMPORT_LIST_VALUE]: createSetSettingValueReducer(section),
- [SET_IMPORT_LIST_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_IMPORT_LIST_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- selectedSchema.name = payload.presetName ?? payload.implementationName;
- selectedSchema.implementationName = payload.implementationName;
- selectedSchema.minRefreshInterval = payload.minRefreshInterval;
- selectedSchema.enableAutomaticAdd = true;
- selectedSchema.shouldMonitor = 'entireArtist';
- selectedSchema.rootFolderPath = '';
-
- return selectedSchema;
- });
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/indexerFlags.js b/frontend/src/Store/Actions/Settings/indexerFlags.js
deleted file mode 100644
index a53fe1c61..000000000
--- a/frontend/src/Store/Actions/Settings/indexerFlags.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.indexerFlags';
-
-//
-// Actions Types
-
-export const FETCH_INDEXER_FLAGS = 'settings/indexerFlags/fetchIndexerFlags';
-
-//
-// Action Creators
-
-export const fetchIndexerFlags = createThunk(FETCH_INDEXER_FLAGS);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_INDEXER_FLAGS]: createFetchHandler(section, '/indexerFlag')
- },
-
- //
- // Reducers
-
- reducers: {
-
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/indexerOptions.js b/frontend/src/Store/Actions/Settings/indexerOptions.js
deleted file mode 100644
index bafc2735d..000000000
--- a/frontend/src/Store/Actions/Settings/indexerOptions.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.indexerOptions';
-
-//
-// Actions Types
-
-export const FETCH_INDEXER_OPTIONS = 'settings/indexerOptions/fetchIndexerOptions';
-export const SAVE_INDEXER_OPTIONS = 'settings/indexerOptions/saveIndexerOptions';
-export const SET_INDEXER_OPTIONS_VALUE = 'settings/indexerOptions/setIndexerOptionsValue';
-
-//
-// Action Creators
-
-export const fetchIndexerOptions = createThunk(FETCH_INDEXER_OPTIONS);
-export const saveIndexerOptions = createThunk(SAVE_INDEXER_OPTIONS);
-export const setIndexerOptionsValue = createAction(SET_INDEXER_OPTIONS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_INDEXER_OPTIONS]: createFetchHandler(section, '/config/indexer'),
- [SAVE_INDEXER_OPTIONS]: createSaveHandler(section, '/config/indexer')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_INDEXER_OPTIONS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/indexers.js b/frontend/src/Store/Actions/Settings/indexers.js
deleted file mode 100644
index 511a2e475..000000000
--- a/frontend/src/Store/Actions/Settings/indexers.js
+++ /dev/null
@@ -1,179 +0,0 @@
-import { createAction } from 'redux-actions';
-import { sortDirections } from 'Helpers/Props';
-import createBulkEditItemHandler from 'Store/Actions/Creators/createBulkEditItemHandler';
-import createBulkRemoveItemHandler from 'Store/Actions/Creators/createBulkRemoveItemHandler';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
-import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
-import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
-import createSetClientSideCollectionSortReducer from 'Store/Actions/Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getSectionState from 'Utilities/State/getSectionState';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-//
-// Variables
-
-const section = 'settings.indexers';
-
-//
-// Actions Types
-
-export const FETCH_INDEXERS = 'settings/indexers/fetchIndexers';
-export const FETCH_INDEXER_SCHEMA = 'settings/indexers/fetchIndexerSchema';
-export const SELECT_INDEXER_SCHEMA = 'settings/indexers/selectIndexerSchema';
-export const CLONE_INDEXER = 'settings/indexers/cloneIndexer';
-export const SET_INDEXER_VALUE = 'settings/indexers/setIndexerValue';
-export const SET_INDEXER_FIELD_VALUE = 'settings/indexers/setIndexerFieldValue';
-export const SAVE_INDEXER = 'settings/indexers/saveIndexer';
-export const CANCEL_SAVE_INDEXER = 'settings/indexers/cancelSaveIndexer';
-export const DELETE_INDEXER = 'settings/indexers/deleteIndexer';
-export const TEST_INDEXER = 'settings/indexers/testIndexer';
-export const CANCEL_TEST_INDEXER = 'settings/indexers/cancelTestIndexer';
-export const TEST_ALL_INDEXERS = 'settings/indexers/testAllIndexers';
-export const BULK_EDIT_INDEXERS = 'settings/indexers/bulkEditIndexers';
-export const BULK_DELETE_INDEXERS = 'settings/indexers/bulkDeleteIndexers';
-export const SET_MANAGE_INDEXERS_SORT = 'settings/indexers/setManageIndexersSort';
-
-//
-// Action Creators
-
-export const fetchIndexers = createThunk(FETCH_INDEXERS);
-export const fetchIndexerSchema = createThunk(FETCH_INDEXER_SCHEMA);
-export const selectIndexerSchema = createAction(SELECT_INDEXER_SCHEMA);
-export const cloneIndexer = createAction(CLONE_INDEXER);
-
-export const saveIndexer = createThunk(SAVE_INDEXER);
-export const cancelSaveIndexer = createThunk(CANCEL_SAVE_INDEXER);
-export const deleteIndexer = createThunk(DELETE_INDEXER);
-export const testIndexer = createThunk(TEST_INDEXER);
-export const cancelTestIndexer = createThunk(CANCEL_TEST_INDEXER);
-export const testAllIndexers = createThunk(TEST_ALL_INDEXERS);
-export const bulkEditIndexers = createThunk(BULK_EDIT_INDEXERS);
-export const bulkDeleteIndexers = createThunk(BULK_DELETE_INDEXERS);
-export const setManageIndexersSort = createAction(SET_MANAGE_INDEXERS_SORT);
-
-export const setIndexerValue = createAction(SET_INDEXER_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setIndexerFieldValue = createAction(SET_INDEXER_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- isTesting: false,
- isTestingAll: false,
- items: [],
- pendingChanges: {},
- sortKey: 'name',
- sortDirection: sortDirections.ASCENDING,
- sortPredicates: {
- name: ({ name }) => {
- return name.toLocaleLowerCase();
- }
- }
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_INDEXERS]: createFetchHandler(section, '/indexer'),
- [FETCH_INDEXER_SCHEMA]: createFetchSchemaHandler(section, '/indexer/schema'),
-
- [SAVE_INDEXER]: createSaveProviderHandler(section, '/indexer'),
- [CANCEL_SAVE_INDEXER]: createCancelSaveProviderHandler(section),
- [DELETE_INDEXER]: createRemoveItemHandler(section, '/indexer'),
- [TEST_INDEXER]: createTestProviderHandler(section, '/indexer'),
- [CANCEL_TEST_INDEXER]: createCancelTestProviderHandler(section),
- [TEST_ALL_INDEXERS]: createTestAllProvidersHandler(section, '/indexer'),
- [BULK_EDIT_INDEXERS]: createBulkEditItemHandler(section, '/indexer/bulk'),
- [BULK_DELETE_INDEXERS]: createBulkRemoveItemHandler(section, '/indexer/bulk')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_INDEXER_VALUE]: createSetSettingValueReducer(section),
- [SET_INDEXER_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_INDEXER_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- selectedSchema.name = payload.presetName ?? payload.implementationName;
- selectedSchema.implementationName = payload.implementationName;
- selectedSchema.enableRss = selectedSchema.supportsRss;
- selectedSchema.enableAutomaticSearch = selectedSchema.supportsSearch;
- selectedSchema.enableInteractiveSearch = selectedSchema.supportsSearch;
-
- return selectedSchema;
- });
- },
-
- [CLONE_INDEXER]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const item = newState.items.find((i) => i.id === id);
-
- // Use selectedSchema so `createProviderSettingsSelector` works properly
- const selectedSchema = { ...item };
- delete selectedSchema.id;
- delete selectedSchema.name;
-
- selectedSchema.fields = selectedSchema.fields.map((field) => {
- const newField = { ...field };
-
- if (newField.privacy === 'apiKey' || newField.privacy === 'password') {
- newField.value = '';
- }
-
- return newField;
- });
-
- newState.selectedSchema = selectedSchema;
-
- // Set the name in pendingChanges
- newState.pendingChanges = {
- name: `${item.name} - Copy`
- };
-
- return updateSectionState(state, section, newState);
- },
-
- [SET_MANAGE_INDEXERS_SORT]: createSetClientSideCollectionSortReducer(section)
-
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/languages.js b/frontend/src/Store/Actions/Settings/languages.js
deleted file mode 100644
index a0b62fc49..000000000
--- a/frontend/src/Store/Actions/Settings/languages.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.languages';
-
-//
-// Actions Types
-
-export const FETCH_LANGUAGES = 'settings/languages/fetchLanguages';
-
-//
-// Action Creators
-
-export const fetchLanguages = createThunk(FETCH_LANGUAGES);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_LANGUAGES]: createFetchHandler(section, '/language')
- },
-
- //
- // Reducers
-
- reducers: {
-
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/mediaManagement.js b/frontend/src/Store/Actions/Settings/mediaManagement.js
deleted file mode 100644
index b1ace08b0..000000000
--- a/frontend/src/Store/Actions/Settings/mediaManagement.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.mediaManagement';
-
-//
-// Actions Types
-
-export const FETCH_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/fetchMediaManagementSettings';
-export const SAVE_MEDIA_MANAGEMENT_SETTINGS = 'settings/mediaManagement/saveMediaManagementSettings';
-export const SET_MEDIA_MANAGEMENT_SETTINGS_VALUE = 'settings/mediaManagement/setMediaManagementSettingsValue';
-
-//
-// Action Creators
-
-export const fetchMediaManagementSettings = createThunk(FETCH_MEDIA_MANAGEMENT_SETTINGS);
-export const saveMediaManagementSettings = createThunk(SAVE_MEDIA_MANAGEMENT_SETTINGS);
-export const setMediaManagementSettingsValue = createAction(SET_MEDIA_MANAGEMENT_SETTINGS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_MEDIA_MANAGEMENT_SETTINGS]: createFetchHandler(section, '/config/mediamanagement'),
- [SAVE_MEDIA_MANAGEMENT_SETTINGS]: createSaveHandler(section, '/config/mediamanagement')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_MEDIA_MANAGEMENT_SETTINGS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/metadata.js b/frontend/src/Store/Actions/Settings/metadata.js
deleted file mode 100644
index e3a661f6d..000000000
--- a/frontend/src/Store/Actions/Settings/metadata.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.metadata';
-
-//
-// Actions Types
-
-export const FETCH_METADATA = 'settings/metadata/fetchMetadata';
-export const SET_METADATA_VALUE = 'settings/metadata/setMetadataValue';
-export const SET_METADATA_FIELD_VALUE = 'settings/metadata/setMetadataFieldValue';
-export const SAVE_METADATA = 'settings/metadata/saveMetadata';
-
-//
-// Action Creators
-
-export const fetchMetadata = createThunk(FETCH_METADATA);
-export const saveMetadata = createThunk(SAVE_METADATA);
-
-export const setMetadataValue = createAction(SET_METADATA_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setMetadataFieldValue = createAction(SET_METADATA_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_METADATA]: createFetchHandler(section, '/metadata'),
- [SAVE_METADATA]: createSaveProviderHandler(section, '/metadata')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_METADATA_VALUE]: createSetSettingValueReducer(section),
- [SET_METADATA_FIELD_VALUE]: createSetProviderFieldValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/metadataProfiles.js b/frontend/src/Store/Actions/Settings/metadataProfiles.js
deleted file mode 100644
index 2d80cfe91..000000000
--- a/frontend/src/Store/Actions/Settings/metadataProfiles.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-//
-// Variables
-
-const section = 'settings.metadataProfiles';
-
-//
-// Actions Types
-
-export const FETCH_METADATA_PROFILES = 'settings/metadataProfiles/fetchMetadataProfiles';
-export const FETCH_METADATA_PROFILE_SCHEMA = 'settings/metadataProfiles/fetchMetadataProfileSchema';
-export const SAVE_METADATA_PROFILE = 'settings/metadataProfiles/saveMetadataProfile';
-export const DELETE_METADATA_PROFILE = 'settings/metadataProfiles/deleteMetadataProfile';
-export const SET_METADATA_PROFILE_VALUE = 'settings/metadataProfiles/setMetadataProfileValue';
-export const CLONE_METADATA_PROFILE = 'settings/metadataProfiles/cloneMetadataProfile';
-
-//
-// Action Creators
-
-export const fetchMetadataProfiles = createThunk(FETCH_METADATA_PROFILES);
-export const fetchMetadataProfileSchema = createThunk(FETCH_METADATA_PROFILE_SCHEMA);
-export const saveMetadataProfile = createThunk(SAVE_METADATA_PROFILE);
-export const deleteMetadataProfile = createThunk(DELETE_METADATA_PROFILE);
-
-export const setMetadataProfileValue = createAction(SET_METADATA_PROFILE_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneMetadataProfile = createAction(CLONE_METADATA_PROFILE);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isDeleting: false,
- deleteError: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: {},
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_METADATA_PROFILES]: createFetchHandler(section, '/metadataprofile'),
- [FETCH_METADATA_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/metadataprofile/schema'),
- [SAVE_METADATA_PROFILE]: createSaveProviderHandler(section, '/metadataprofile'),
- [DELETE_METADATA_PROFILE]: createRemoveItemHandler(section, '/metadataprofile')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_METADATA_PROFILE_VALUE]: createSetSettingValueReducer(section),
-
- [CLONE_METADATA_PROFILE]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const item = newState.items.find((i) => i.id === id);
- const pendingChanges = { ...item, id: 0 };
- delete pendingChanges.id;
-
- pendingChanges.name = `${pendingChanges.name} - Copy`;
- newState.pendingChanges = pendingChanges;
-
- return updateSectionState(state, section, newState);
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/metadataProvider.js b/frontend/src/Store/Actions/Settings/metadataProvider.js
deleted file mode 100644
index ba30110ae..000000000
--- a/frontend/src/Store/Actions/Settings/metadataProvider.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.metadataProvider';
-
-//
-// Actions Types
-
-export const FETCH_METADATA_PROVIDER = 'settings/metadataProvider/fetchMetadataProvider';
-export const SET_METADATA_PROVIDER_VALUE = 'settings/metadataProvider/setMetadataProviderValue';
-export const SAVE_METADATA_PROVIDER = 'settings/metadataProvider/saveMetadataProvider';
-
-//
-// Action Creators
-
-export const fetchMetadataProvider = createThunk(FETCH_METADATA_PROVIDER);
-export const saveMetadataProvider = createThunk(SAVE_METADATA_PROVIDER);
-export const setMetadataProviderValue = createAction(SET_METADATA_PROVIDER_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_METADATA_PROVIDER]: createFetchHandler(section, '/config/metadataProvider'),
- [SAVE_METADATA_PROVIDER]: createSaveHandler(section, '/config/metadataProvider')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_METADATA_PROVIDER_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/naming.js b/frontend/src/Store/Actions/Settings/naming.js
deleted file mode 100644
index cf5a6818a..000000000
--- a/frontend/src/Store/Actions/Settings/naming.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.naming';
-
-//
-// Actions Types
-
-export const FETCH_NAMING_SETTINGS = 'settings/naming/fetchNamingSettings';
-export const SAVE_NAMING_SETTINGS = 'settings/naming/saveNamingSettings';
-export const SET_NAMING_SETTINGS_VALUE = 'settings/naming/setNamingSettingsValue';
-
-//
-// Action Creators
-
-export const fetchNamingSettings = createThunk(FETCH_NAMING_SETTINGS);
-export const saveNamingSettings = createThunk(SAVE_NAMING_SETTINGS);
-export const setNamingSettingsValue = createAction(SET_NAMING_SETTINGS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_NAMING_SETTINGS]: createFetchHandler(section, '/config/naming'),
- [SAVE_NAMING_SETTINGS]: createSaveHandler(section, '/config/naming')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_NAMING_SETTINGS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/namingExamples.js b/frontend/src/Store/Actions/Settings/namingExamples.js
deleted file mode 100644
index 0fef90ce2..000000000
--- a/frontend/src/Store/Actions/Settings/namingExamples.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import { set, update } from 'Store/Actions/baseActions';
-import { createThunk } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-
-//
-// Variables
-
-const section = 'settings.namingExamples';
-
-//
-// Actions Types
-
-export const FETCH_NAMING_EXAMPLES = 'settings/namingExamples/fetchNamingExamples';
-
-//
-// Action Creators
-
-export const fetchNamingExamples = createThunk(FETCH_NAMING_EXAMPLES);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_NAMING_EXAMPLES]: function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const naming = getState().settings.naming;
-
- const promise = createAjaxRequest({
- url: '/config/naming/examples',
- data: Object.assign({}, naming.item, naming.pendingChanges)
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- }
- },
-
- //
- // Reducers
-
- reducers: {}
-
-};
diff --git a/frontend/src/Store/Actions/Settings/notifications.js b/frontend/src/Store/Actions/Settings/notifications.js
deleted file mode 100644
index 4e557db87..000000000
--- a/frontend/src/Store/Actions/Settings/notifications.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
-import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
-import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import selectProviderSchema from 'Utilities/State/selectProviderSchema';
-
-//
-// Variables
-
-const section = 'settings.notifications';
-
-//
-// Actions Types
-
-export const FETCH_NOTIFICATIONS = 'settings/notifications/fetchNotifications';
-export const FETCH_NOTIFICATION_SCHEMA = 'settings/notifications/fetchNotificationSchema';
-export const SELECT_NOTIFICATION_SCHEMA = 'settings/notifications/selectNotificationSchema';
-export const SET_NOTIFICATION_VALUE = 'settings/notifications/setNotificationValue';
-export const SET_NOTIFICATION_FIELD_VALUE = 'settings/notifications/setNotificationFieldValue';
-export const SAVE_NOTIFICATION = 'settings/notifications/saveNotification';
-export const CANCEL_SAVE_NOTIFICATION = 'settings/notifications/cancelSaveNotification';
-export const DELETE_NOTIFICATION = 'settings/notifications/deleteNotification';
-export const TEST_NOTIFICATION = 'settings/notifications/testNotification';
-export const CANCEL_TEST_NOTIFICATION = 'settings/notifications/cancelTestNotification';
-
-//
-// Action Creators
-
-export const fetchNotifications = createThunk(FETCH_NOTIFICATIONS);
-export const fetchNotificationSchema = createThunk(FETCH_NOTIFICATION_SCHEMA);
-export const selectNotificationSchema = createAction(SELECT_NOTIFICATION_SCHEMA);
-
-export const saveNotification = createThunk(SAVE_NOTIFICATION);
-export const cancelSaveNotification = createThunk(CANCEL_SAVE_NOTIFICATION);
-export const deleteNotification = createThunk(DELETE_NOTIFICATION);
-export const testNotification = createThunk(TEST_NOTIFICATION);
-export const cancelTestNotification = createThunk(CANCEL_TEST_NOTIFICATION);
-
-export const setNotificationValue = createAction(SET_NOTIFICATION_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setNotificationFieldValue = createAction(SET_NOTIFICATION_FIELD_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: [],
- selectedSchema: {},
- isSaving: false,
- saveError: null,
- isTesting: false,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_NOTIFICATIONS]: createFetchHandler(section, '/notification'),
- [FETCH_NOTIFICATION_SCHEMA]: createFetchSchemaHandler(section, '/notification/schema'),
-
- [SAVE_NOTIFICATION]: createSaveProviderHandler(section, '/notification'),
- [CANCEL_SAVE_NOTIFICATION]: createCancelSaveProviderHandler(section),
- [DELETE_NOTIFICATION]: createRemoveItemHandler(section, '/notification'),
- [TEST_NOTIFICATION]: createTestProviderHandler(section, '/notification'),
- [CANCEL_TEST_NOTIFICATION]: createCancelTestProviderHandler(section)
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_NOTIFICATION_VALUE]: createSetSettingValueReducer(section),
- [SET_NOTIFICATION_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
-
- [SELECT_NOTIFICATION_SCHEMA]: (state, { payload }) => {
- return selectProviderSchema(state, section, payload, (selectedSchema) => {
- selectedSchema.name = selectedSchema.implementationName;
- selectedSchema.onGrab = selectedSchema.supportsOnGrab;
- selectedSchema.onReleaseImport = selectedSchema.supportsOnReleaseImport;
- selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
- selectedSchema.onRename = selectedSchema.supportsOnRename;
- selectedSchema.onArtistAdd = selectedSchema.supportsOnArtistAdd;
- selectedSchema.onArtistDelete = selectedSchema.supportsOnArtistDelete;
- selectedSchema.onHealthIssue = selectedSchema.supportsOnHealthIssue;
- selectedSchema.onDownloadFailure = selectedSchema.supportsOnDownloadFailure;
- selectedSchema.onImportFailure = selectedSchema.supportsOnImportFailure;
- selectedSchema.onTrackRetag = selectedSchema.supportsOnTrackRetag;
- selectedSchema.onApplicationUpdate = selectedSchema.supportsOnApplicationUpdate;
-
- return selectedSchema;
- });
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/qualityDefinitions.js b/frontend/src/Store/Actions/Settings/qualityDefinitions.js
deleted file mode 100644
index 09317ca07..000000000
--- a/frontend/src/Store/Actions/Settings/qualityDefinitions.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { clearPendingChanges, set, update } from 'Store/Actions/baseActions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import { createThunk } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-//
-// Variables
-
-const section = 'settings.qualityDefinitions';
-
-//
-// Actions Types
-
-export const FETCH_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/fetchQualityDefinitions';
-export const SAVE_QUALITY_DEFINITIONS = 'settings/qualityDefinitions/saveQualityDefinitions';
-export const SET_QUALITY_DEFINITION_VALUE = 'settings/qualityDefinitions/setQualityDefinitionValue';
-
-//
-// Action Creators
-
-export const fetchQualityDefinitions = createThunk(FETCH_QUALITY_DEFINITIONS);
-export const saveQualityDefinitions = createThunk(SAVE_QUALITY_DEFINITIONS);
-
-export const setQualityDefinitionValue = createAction(SET_QUALITY_DEFINITION_VALUE);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_QUALITY_DEFINITIONS]: createFetchHandler(section, '/qualitydefinition'),
- [SAVE_QUALITY_DEFINITIONS]: createSaveHandler(section, '/qualitydefinition'),
-
- [SAVE_QUALITY_DEFINITIONS]: function(getState, payload, dispatch) {
- const qualityDefinitions = getState().settings.qualityDefinitions;
-
- const upatedDefinitions = Object.keys(qualityDefinitions.pendingChanges).map((key) => {
- const id = parseInt(key);
- const pendingChanges = qualityDefinitions.pendingChanges[id] || {};
- const item = _.find(qualityDefinitions.items, { id });
-
- return Object.assign({}, item, pendingChanges);
- });
-
- // If there is nothing to save don't bother isSaving
- if (!upatedDefinitions || !upatedDefinitions.length) {
- return;
- }
-
- dispatch(set({
- section,
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- method: 'PUT',
- url: '/qualityDefinition/update',
- data: JSON.stringify(upatedDefinitions),
- contentType: 'application/json',
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- set({
- section,
- isSaving: false,
- saveError: null
- }),
-
- update({ section, data }),
- clearPendingChanges({ section })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- }
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_QUALITY_DEFINITION_VALUE]: function(state, { payload }) {
- const { id, name, value } = payload;
- const newState = getSectionState(state, section);
- newState.pendingChanges = _.cloneDeep(newState.pendingChanges);
-
- const pendingState = newState.pendingChanges[id] || {};
- const currentValue = _.find(newState.items, { id })[name];
-
- if (currentValue === value) {
- delete pendingState[name];
- } else {
- pendingState[name] = value;
- }
-
- if (_.isEmpty(pendingState)) {
- delete newState.pendingChanges[id];
- } else {
- newState.pendingChanges[id] = pendingState;
- }
-
- return updateSectionState(state, section, newState);
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/qualityProfiles.js b/frontend/src/Store/Actions/Settings/qualityProfiles.js
deleted file mode 100644
index 8e6036073..000000000
--- a/frontend/src/Store/Actions/Settings/qualityProfiles.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-//
-// Variables
-
-const section = 'settings.qualityProfiles';
-
-//
-// Actions Types
-
-export const FETCH_QUALITY_PROFILES = 'settings/qualityProfiles/fetchQualityProfiles';
-export const FETCH_QUALITY_PROFILE_SCHEMA = 'settings/qualityProfiles/fetchQualityProfileSchema';
-export const SAVE_QUALITY_PROFILE = 'settings/qualityProfiles/saveQualityProfile';
-export const DELETE_QUALITY_PROFILE = 'settings/qualityProfiles/deleteQualityProfile';
-export const SET_QUALITY_PROFILE_VALUE = 'settings/qualityProfiles/setQualityProfileValue';
-export const CLONE_QUALITY_PROFILE = 'settings/qualityProfiles/cloneQualityProfile';
-
-//
-// Action Creators
-
-export const fetchQualityProfiles = createThunk(FETCH_QUALITY_PROFILES);
-export const fetchQualityProfileSchema = createThunk(FETCH_QUALITY_PROFILE_SCHEMA);
-export const saveQualityProfile = createThunk(SAVE_QUALITY_PROFILE);
-export const deleteQualityProfile = createThunk(DELETE_QUALITY_PROFILE);
-
-export const setQualityProfileValue = createAction(SET_QUALITY_PROFILE_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const cloneQualityProfile = createAction(CLONE_QUALITY_PROFILE);
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isDeleting: false,
- deleteError: null,
- isSchemaFetching: false,
- isSchemaPopulated: false,
- schemaError: null,
- schema: {},
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_QUALITY_PROFILES]: createFetchHandler(section, '/qualityprofile'),
- [FETCH_QUALITY_PROFILE_SCHEMA]: createFetchSchemaHandler(section, '/qualityprofile/schema'),
- [SAVE_QUALITY_PROFILE]: createSaveProviderHandler(section, '/qualityprofile'),
- [DELETE_QUALITY_PROFILE]: createRemoveItemHandler(section, '/qualityprofile')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_QUALITY_PROFILE_VALUE]: createSetSettingValueReducer(section),
-
- [CLONE_QUALITY_PROFILE]: function(state, { payload }) {
- const id = payload.id;
- const newState = getSectionState(state, section);
- const item = newState.items.find((i) => i.id === id);
- const pendingChanges = { ...item, id: 0 };
- delete pendingChanges.id;
-
- pendingChanges.name = `${pendingChanges.name} - Copy`;
- newState.pendingChanges = pendingChanges;
-
- return updateSectionState(state, section, newState);
- }
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/releaseProfiles.js b/frontend/src/Store/Actions/Settings/releaseProfiles.js
deleted file mode 100644
index 37fd16c85..000000000
--- a/frontend/src/Store/Actions/Settings/releaseProfiles.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.releaseProfiles';
-
-//
-// Actions Types
-
-export const FETCH_RELEASE_PROFILES = 'settings/releaseProfiles/fetchReleaseProfiles';
-export const SAVE_RELEASE_PROFILE = 'settings/releaseProfiles/saveReleaseProfile';
-export const DELETE_RELEASE_PROFILE = 'settings/releaseProfiles/deleteReleaseProfile';
-export const SET_RELEASE_PROFILE_VALUE = 'settings/releaseProfiles/setReleaseProfileValue';
-
-//
-// Action Creators
-
-export const fetchReleaseProfiles = createThunk(FETCH_RELEASE_PROFILES);
-export const saveReleaseProfile = createThunk(SAVE_RELEASE_PROFILE);
-export const deleteReleaseProfile = createThunk(DELETE_RELEASE_PROFILE);
-
-export const setReleaseProfileValue = createAction(SET_RELEASE_PROFILE_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_RELEASE_PROFILES]: createFetchHandler(section, '/releaseprofile'),
-
- [SAVE_RELEASE_PROFILE]: createSaveProviderHandler(section, '/releaseprofile'),
-
- [DELETE_RELEASE_PROFILE]: createRemoveItemHandler(section, '/releaseprofile')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_RELEASE_PROFILE_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/remotePathMappings.js b/frontend/src/Store/Actions/Settings/remotePathMappings.js
deleted file mode 100644
index ca7955754..000000000
--- a/frontend/src/Store/Actions/Settings/remotePathMappings.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.remotePathMappings';
-
-//
-// Actions Types
-
-export const FETCH_REMOTE_PATH_MAPPINGS = 'settings/remotePathMappings/fetchRemotePathMappings';
-export const SAVE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/saveRemotePathMapping';
-export const DELETE_REMOTE_PATH_MAPPING = 'settings/remotePathMappings/deleteRemotePathMapping';
-export const SET_REMOTE_PATH_MAPPING_VALUE = 'settings/remotePathMappings/setRemotePathMappingValue';
-
-//
-// Action Creators
-
-export const fetchRemotePathMappings = createThunk(FETCH_REMOTE_PATH_MAPPINGS);
-export const saveRemotePathMapping = createThunk(SAVE_REMOTE_PATH_MAPPING);
-export const deleteRemotePathMapping = createThunk(DELETE_REMOTE_PATH_MAPPING);
-
-export const setRemotePathMappingValue = createAction(SET_REMOTE_PATH_MAPPING_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- isSaving: false,
- saveError: null,
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_REMOTE_PATH_MAPPINGS]: createFetchHandler(section, '/remotepathmapping'),
- [SAVE_REMOTE_PATH_MAPPING]: createSaveProviderHandler(section, '/remotepathmapping'),
- [DELETE_REMOTE_PATH_MAPPING]: createRemoveItemHandler(section, '/remotepathmapping')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_REMOTE_PATH_MAPPING_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/Settings/rootFolders.js b/frontend/src/Store/Actions/Settings/rootFolders.js
deleted file mode 100644
index 42d4b0fce..000000000
--- a/frontend/src/Store/Actions/Settings/rootFolders.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
-import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-import monitorNewItemsOptions from 'Utilities/Artist/monitorNewItemsOptions';
-import monitorOptions from 'Utilities/Artist/monitorOptions';
-
-//
-// Variables
-
-export const section = 'settings.rootFolders';
-
-//
-// Actions Types
-
-export const FETCH_ROOT_FOLDERS = 'settings/rootFolders/fetchRootFolders';
-export const SET_ROOT_FOLDER_VALUE = 'settings/rootFolders/setRootFolderValue';
-export const SAVE_ROOT_FOLDER = 'settings/rootFolders/saveRootFolder';
-export const CANCEL_SAVE_ROOT_FOLDER = 'settings/rootFolders/cancelSaveRootFolder';
-export const DELETE_ROOT_FOLDER = 'settings/rootFolders/deleteRootFolder';
-
-//
-// Action Creators
-
-export const fetchRootFolders = createThunk(FETCH_ROOT_FOLDERS);
-export const saveRootFolder = createThunk(SAVE_ROOT_FOLDER);
-export const cancelSaveRootFolder = createThunk(CANCEL_SAVE_ROOT_FOLDER);
-export const deleteRootFolder = createThunk(DELETE_ROOT_FOLDER);
-
-export const setRootFolderValue = createAction(SET_ROOT_FOLDER_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- schema: {
- defaultQualityProfileId: 0,
- defaultMetadataProfileId: 0,
- defaultMonitorOption: monitorOptions[0].key,
- defaultNewItemMonitorOption: monitorNewItemsOptions[0].key,
- defaultTags: []
- },
- isSaving: false,
- saveError: null,
- items: [],
- pendingChanges: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
-
- [FETCH_ROOT_FOLDERS]: createFetchHandler(section, '/rootFolder'),
-
- [SAVE_ROOT_FOLDER]: createSaveProviderHandler(section, '/rootFolder'),
- [CANCEL_SAVE_ROOT_FOLDER]: createCancelSaveProviderHandler(section),
- [DELETE_ROOT_FOLDER]: createRemoveItemHandler(section, '/rootFolder')
-
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_ROOT_FOLDER_VALUE]: createSetSettingValueReducer(section)
- }
-};
diff --git a/frontend/src/Store/Actions/Settings/ui.js b/frontend/src/Store/Actions/Settings/ui.js
deleted file mode 100644
index 7a57add6d..000000000
--- a/frontend/src/Store/Actions/Settings/ui.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { createAction } from 'redux-actions';
-import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
-import createSaveHandler from 'Store/Actions/Creators/createSaveHandler';
-import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
-import { createThunk } from 'Store/thunks';
-
-//
-// Variables
-
-const section = 'settings.ui';
-
-//
-// Actions Types
-
-export const FETCH_UI_SETTINGS = 'settings/ui/fetchUiSettings';
-export const SET_UI_SETTINGS_VALUE = 'SET_UI_SETTINGS_VALUE';
-export const SAVE_UI_SETTINGS = 'SAVE_UI_SETTINGS';
-
-//
-// Action Creators
-
-export const fetchUISettings = createThunk(FETCH_UI_SETTINGS);
-export const saveUISettings = createThunk(SAVE_UI_SETTINGS);
-export const setUISettingsValue = createAction(SET_UI_SETTINGS_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-//
-// Details
-
-export default {
-
- //
- // State
-
- defaultState: {
- isFetching: false,
- isPopulated: false,
- error: null,
- pendingChanges: {},
- isSaving: false,
- saveError: null,
- item: {}
- },
-
- //
- // Action Handlers
-
- actionHandlers: {
- [FETCH_UI_SETTINGS]: createFetchHandler(section, '/config/ui'),
- [SAVE_UI_SETTINGS]: createSaveHandler(section, '/config/ui')
- },
-
- //
- // Reducers
-
- reducers: {
- [SET_UI_SETTINGS_VALUE]: createSetSettingValueReducer(section)
- }
-
-};
diff --git a/frontend/src/Store/Actions/actionTypes.js b/frontend/src/Store/Actions/actionTypes.js
deleted file mode 100644
index dcb13d86d..000000000
--- a/frontend/src/Store/Actions/actionTypes.js
+++ /dev/null
@@ -1,16 +0,0 @@
-//
-// App
-
-export const SHOW_MESSAGE = 'SHOW_MESSAGE';
-export const HIDE_MESSAGE = 'HIDE_MESSAGE';
-export const SAVE_DIMENSIONS = 'SAVE_DIMENSIONS';
-export const SET_VERSION = 'SET_VERSION';
-export const SET_APP_VALUE = 'SET_APP_VALUE';
-export const SET_IS_SIDEBAR_VISIBLE = 'SET_IS_SIDEBAR_VISIBLE';
-
-//
-// Settings
-
-export const FETCH_GENERAL_SETTINGS = 'settings/general/fetchGeneralSettings';
-export const SET_GENERAL_SETTINGS_VALUE = 'settings/general/setGeneralSettingsValue';
-export const SAVE_GENERAL_SETTINGS = 'settings/general/saveGeneralSettings';
diff --git a/frontend/src/Store/Actions/albumActions.js b/frontend/src/Store/Actions/albumActions.js
deleted file mode 100644
index 4ac39a0aa..000000000
--- a/frontend/src/Store/Actions/albumActions.js
+++ /dev/null
@@ -1,282 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import albumEntities from 'Album/albumEntities';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import translate from 'Utilities/String/translate';
-import { updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createSaveProviderHandler from './Creators/createSaveProviderHandler';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'albums';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- sortKey: 'releaseDate',
- sortDirection: sortDirections.DESCENDING,
- items: [],
- pendingChanges: {},
- sortPredicates: {
- rating: function(item) {
- return item.ratings.value;
- },
- size: function(item) {
- const { statistics = {} } = item;
-
- return statistics.sizeOnDisk || 0;
- }
- },
-
- columns: [
- {
- name: 'monitored',
- columnLabel: () => translate('Monitored'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'title',
- label: () => translate('Title'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'releaseDate',
- label: () => translate('ReleaseDate'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'secondaryTypes',
- label: () => translate('SecondaryTypes'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'mediumCount',
- label: () => translate('MediaCount'),
- isVisible: false
- },
- {
- name: 'trackCount',
- label: () => translate('TrackCount'),
- isVisible: false
- },
- {
- name: 'duration',
- label: () => translate('Duration'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'size',
- label: () => translate('Size'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'rating',
- label: () => translate('Rating'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'status',
- label: () => translate('Status'),
- isVisible: true
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ]
-};
-
-export const persistState = [
- 'albums.sortKey',
- 'albums.sortDirection',
- 'albums.columns'
-];
-
-//
-// Actions Types
-
-export const FETCH_ALBUMS = 'albums/fetchAlbums';
-export const SET_ALBUMS_SORT = 'albums/setAlbumsSort';
-export const SET_ALBUMS_TABLE_OPTION = 'albums/setAlbumsTableOption';
-export const CLEAR_ALBUMS = 'albums/clearAlbums';
-export const SET_ALBUM_VALUE = 'albums/setAlbumValue';
-export const SAVE_ALBUM = 'albums/saveAlbum';
-export const DELETE_ALBUM = 'albums/deleteAlbum';
-export const TOGGLE_ALBUM_MONITORED = 'albums/toggleAlbumMonitored';
-export const TOGGLE_ALBUMS_MONITORED = 'albums/toggleAlbumsMonitored';
-
-//
-// Action Creators
-
-export const fetchAlbums = createThunk(FETCH_ALBUMS);
-export const setAlbumsSort = createAction(SET_ALBUMS_SORT);
-export const setAlbumsTableOption = createAction(SET_ALBUMS_TABLE_OPTION);
-export const clearAlbums = createAction(CLEAR_ALBUMS);
-export const toggleAlbumMonitored = createThunk(TOGGLE_ALBUM_MONITORED);
-export const toggleAlbumsMonitored = createThunk(TOGGLE_ALBUMS_MONITORED);
-
-export const saveAlbum = createThunk(SAVE_ALBUM);
-
-export const deleteAlbum = createThunk(DELETE_ALBUM, (payload) => {
- return {
- ...payload,
- queryParams: {
- deleteFiles: payload.deleteFiles,
- addImportListExclusion: payload.addImportListExclusion
- }
- };
-});
-
-export const setAlbumValue = createAction(SET_ALBUM_VALUE, (payload) => {
- return {
- section: 'albums',
- ...payload
- };
-});
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_ALBUMS]: createFetchHandler(section, '/album'),
- [SAVE_ALBUM]: createSaveProviderHandler(section, '/album'),
- [DELETE_ALBUM]: createRemoveItemHandler(section, '/album'),
-
- [TOGGLE_ALBUM_MONITORED]: function(getState, payload, dispatch) {
- const {
- albumId,
- albumEntity = albumEntities.ALBUMS,
- monitored
- } = payload;
-
- const albumSection = _.last(albumEntity.split('.'));
-
- dispatch(updateItem({
- id: albumId,
- section: albumSection,
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- url: `/album/${albumId}`,
- method: 'PUT',
- data: JSON.stringify({ monitored }),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(updateItem({
- id: albumId,
- section: albumSection,
- isSaving: false,
- monitored
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({
- id: albumId,
- section: albumSection,
- isSaving: false
- }));
- });
- },
-
- [TOGGLE_ALBUMS_MONITORED]: function(getState, payload, dispatch) {
- const {
- albumIds,
- albumEntity = albumEntities.ALBUMS,
- monitored
- } = payload;
-
- dispatch(batchActions(
- albumIds.map((albumId) => {
- return updateItem({
- id: albumId,
- section: albumEntity,
- isSaving: true
- });
- })
- ));
-
- const promise = createAjaxRequest({
- url: '/album/monitor',
- method: 'PUT',
- data: JSON.stringify({ albumIds, monitored }),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions(
- albumIds.map((albumId) => {
- return updateItem({
- id: albumId,
- section: albumEntity,
- isSaving: false,
- monitored
- });
- })
- ));
- });
-
- promise.fail((xhr) => {
- dispatch(batchActions(
- albumIds.map((albumId) => {
- return updateItem({
- id: albumId,
- section: albumEntity,
- isSaving: false
- });
- })
- ));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ALBUMS_SORT]: createSetClientSideCollectionSortReducer(section),
-
- [SET_ALBUMS_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [SET_ALBUM_VALUE]: createSetSettingValueReducer(section),
-
- [CLEAR_ALBUMS]: (state) => {
- return Object.assign({}, state, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- });
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/albumHistoryActions.js b/frontend/src/Store/Actions/albumHistoryActions.js
deleted file mode 100644
index 12cb1e4c0..000000000
--- a/frontend/src/Store/Actions/albumHistoryActions.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set, update } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'albumHistory';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
-};
-
-//
-// Actions Types
-
-export const FETCH_ALBUM_HISTORY = 'albumHistory/fetchAlbumHistory';
-export const CLEAR_ALBUM_HISTORY = 'albumHistory/clearAlbumHistory';
-export const ALBUM_HISTORY_MARK_AS_FAILED = 'albumHistory/albumHistoryMarkAsFailed';
-
-//
-// Action Creators
-
-export const fetchAlbumHistory = createThunk(FETCH_ALBUM_HISTORY);
-export const clearAlbumHistory = createAction(CLEAR_ALBUM_HISTORY);
-export const albumHistoryMarkAsFailed = createThunk(ALBUM_HISTORY_MARK_AS_FAILED);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_ALBUM_HISTORY]: function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const queryParams = {
- pageSize: 1000,
- page: 1,
- sortKey: 'date',
- sortDirection: sortDirections.DESCENDING,
- albumId: payload.albumId
- };
-
- const promise = createAjaxRequest({
- url: '/history',
- data: queryParams
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- update({ section, data: data.records }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- },
-
- [ALBUM_HISTORY_MARK_AS_FAILED]: function(getState, payload, dispatch) {
- const {
- historyId,
- albumId
- } = payload;
-
- const promise = createAjaxRequest({
- url: '/history/failed',
- method: 'POST',
- dataType: 'json',
- data: {
- id: historyId
- }
- }).request;
-
- promise.done(() => {
- dispatch(fetchAlbumHistory({ albumId }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_ALBUM_HISTORY]: (state) => {
- return Object.assign({}, state, defaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/albumSelectionActions.js b/frontend/src/Store/Actions/albumSelectionActions.js
deleted file mode 100644
index f19f5b691..000000000
--- a/frontend/src/Store/Actions/albumSelectionActions.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import moment from 'moment';
-import { createAction } from 'redux-actions';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-
-//
-// Variables
-
-export const section = 'albumSelection';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isReprocessing: false,
- isPopulated: false,
- error: null,
- sortKey: 'title',
- sortDirection: sortDirections.ASCENDING,
- items: [],
- sortPredicates: {
- title: ({ title }) => {
- return title.toLocaleLowerCase();
- },
-
- releaseDate: function({ releaseDate }, direction) {
- if (releaseDate) {
- return moment(releaseDate).unix();
- }
-
- if (direction === sortDirections.DESCENDING) {
- return 0;
- }
-
- return Number.MAX_VALUE;
- }
- }
-};
-
-export const persistState = [
- 'albumSelection.sortKey',
- 'albumSelection.sortDirection'
-];
-
-//
-// Actions Types
-
-export const FETCH_ALBUMS = 'albumSelection/fetchAlbums';
-export const SET_ALBUMS_SORT = 'albumSelection/setAlbumsSort';
-export const CLEAR_ALBUMS = 'albumSelection/clearAlbums';
-
-//
-// Action Creators
-
-export const fetchAlbums = createThunk(FETCH_ALBUMS);
-export const setAlbumsSort = createAction(SET_ALBUMS_SORT);
-export const clearAlbums = createAction(CLEAR_ALBUMS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_ALBUMS]: createFetchHandler(section, '/album')
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ALBUMS_SORT]: createSetClientSideCollectionSortReducer(section),
-
- [CLEAR_ALBUMS]: (state) => {
- return updateSectionState(state, section, {
- ...defaultState,
- sortKey: state.sortKey,
- sortDirection: state.sortDirection
- });
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/appActions.js b/frontend/src/Store/Actions/appActions.js
deleted file mode 100644
index 972fd1be2..000000000
--- a/frontend/src/Store/Actions/appActions.js
+++ /dev/null
@@ -1,226 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { fetchTranslations as fetchAppTranslations } from 'Utilities/String/translate';
-import createHandleActions from './Creators/createHandleActions';
-
-function getDimensions(width, height) {
- const dimensions = {
- width,
- height,
- isExtraSmallScreen: width <= 480,
- isSmallScreen: width <= 768,
- isMediumScreen: width <= 992,
- isLargeScreen: width <= 1200
- };
-
- return dimensions;
-}
-
-//
-// Variables
-
-export const section = 'app';
-const messagesSection = 'app.messages';
-let abortPingServer = null;
-let pingTimeout = null;
-
-//
-// State
-
-export const defaultState = {
- dimensions: getDimensions(window.innerWidth, window.innerHeight),
- messages: {
- items: []
- },
- version: window.Lidarr.version,
- isUpdated: false,
- isConnected: true,
- isReconnecting: false,
- isDisconnected: false,
- isRestarting: false,
- isSidebarVisible: !getDimensions(window.innerWidth, window.innerHeight).isSmallScreen,
- translations: {
- isFetching: true,
- isPopulated: false,
- error: null
- }
-};
-
-//
-// Action Types
-
-export const SHOW_MESSAGE = 'app/showMessage';
-export const HIDE_MESSAGE = 'app/hideMessage';
-export const SAVE_DIMENSIONS = 'app/saveDimensions';
-export const SET_VERSION = 'app/setVersion';
-export const SET_APP_VALUE = 'app/setAppValue';
-export const SET_IS_SIDEBAR_VISIBLE = 'app/setIsSidebarVisible';
-export const FETCH_TRANSLATIONS = 'app/fetchTranslations';
-
-export const PING_SERVER = 'app/pingServer';
-
-//
-// Action Creators
-
-export const saveDimensions = createAction(SAVE_DIMENSIONS);
-export const setVersion = createAction(SET_VERSION);
-export const setIsSidebarVisible = createAction(SET_IS_SIDEBAR_VISIBLE);
-export const setAppValue = createAction(SET_APP_VALUE);
-export const showMessage = createAction(SHOW_MESSAGE);
-export const hideMessage = createAction(HIDE_MESSAGE);
-export const pingServer = createThunk(PING_SERVER);
-export const fetchTranslations = createThunk(FETCH_TRANSLATIONS);
-
-//
-// Helpers
-
-function pingServerAfterTimeout(getState, dispatch) {
- if (abortPingServer) {
- abortPingServer();
- abortPingServer = null;
- }
-
- if (pingTimeout) {
- clearTimeout(pingTimeout);
- pingTimeout = null;
- }
-
- pingTimeout = setTimeout(() => {
- if (!getState().isRestarting && getState().isConnected) {
- return;
- }
-
- const ajaxOptions = {
- url: '/system/status',
- method: 'GET',
- contentType: 'application/json'
- };
-
- const { request, abortRequest } = createAjaxRequest(ajaxOptions);
-
- abortPingServer = abortRequest;
-
- request.done(() => {
- abortPingServer = null;
- pingTimeout = null;
-
- dispatch(setAppValue({
- isRestarting: false
- }));
- });
-
- request.fail((xhr) => {
- abortPingServer = null;
- pingTimeout = null;
-
- // Unauthorized, but back online
- if (xhr.status === 401) {
- dispatch(setAppValue({
- isRestarting: false
- }));
- } else {
- pingServerAfterTimeout(getState, dispatch);
- }
- });
- }, 5000);
-}
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [PING_SERVER]: function(getState, payload, dispatch) {
- pingServerAfterTimeout(getState, dispatch);
- },
- [FETCH_TRANSLATIONS]: async function(getState, payload, dispatch) {
- const isFetchingComplete = await fetchAppTranslations();
-
- dispatch(setAppValue({
- translations: {
- isFetching: false,
- isPopulated: isFetchingComplete,
- error: isFetchingComplete ? null : 'Failed to load translations from API'
- }
- }));
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SAVE_DIMENSIONS]: function(state, { payload }) {
- const {
- width,
- height
- } = payload;
-
- const dimensions = getDimensions(width, height);
-
- return Object.assign({}, state, { dimensions });
- },
-
- [SHOW_MESSAGE]: function(state, { payload }) {
- const newState = getSectionState(state, messagesSection);
- const items = newState.items;
- const index = _.findIndex(items, { id: payload.id });
-
- newState.items = [...items];
-
- if (index >= 0) {
- const item = items[index];
-
- newState.items.splice(index, 1, { ...item, ...payload });
- } else {
- newState.items.push({ ...payload });
- }
-
- return updateSectionState(state, messagesSection, newState);
- },
-
- [HIDE_MESSAGE]: function(state, { payload }) {
- const newState = getSectionState(state, messagesSection);
-
- newState.items = [...newState.items];
- _.remove(newState.items, { id: payload.id });
-
- return updateSectionState(state, messagesSection, newState);
- },
-
- [SET_APP_VALUE]: function(state, { payload }) {
- const newState = Object.assign(getSectionState(state, section), payload);
-
- return updateSectionState(state, section, newState);
- },
-
- [SET_VERSION]: function(state, { payload }) {
- const version = payload.version;
-
- const newState = {
- version
- };
-
- if (state.version !== version) {
- if (!state.prevVersion) {
- newState.prevVersion = state.version;
- }
- newState.isUpdated = true;
- }
-
- return Object.assign({}, state, newState);
- },
-
- [SET_IS_SIDEBAR_VISIBLE]: function(state, { payload }) {
- const newState = {
- isSidebarVisible: payload.isSidebarVisible
- };
-
- return Object.assign({}, state, newState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/artistActions.js b/frontend/src/Store/Actions/artistActions.js
deleted file mode 100644
index 89384bcc4..000000000
--- a/frontend/src/Store/Actions/artistActions.js
+++ /dev/null
@@ -1,511 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { filterTypePredicates, filterTypes, sortDirections } from 'Helpers/Props';
-import { fetchAlbums } from 'Store/Actions/albumActions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import dateFilterPredicate from 'Utilities/Date/dateFilterPredicate';
-import translate from 'Utilities/String/translate';
-import { set, updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createSaveProviderHandler from './Creators/createSaveProviderHandler';
-import createSetSettingValueReducer from './Creators/Reducers/createSetSettingValueReducer';
-
-//
-// Variables
-
-export const section = 'artist';
-
-export const filters = [
- {
- key: 'all',
- label: () => translate('All'),
- filters: []
- },
- {
- key: 'monitored',
- label: () => translate('MonitoredOnly'),
- filters: [
- {
- key: 'monitored',
- value: true,
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'unmonitored',
- label: () => translate('UnmonitoredOnly'),
- filters: [
- {
- key: 'monitored',
- value: false,
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'continuing',
- label: () => translate('ContinuingOnly'),
- filters: [
- {
- key: 'status',
- value: 'continuing',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'ended',
- label: () => translate('EndedOnly'),
- filters: [
- {
- key: 'status',
- value: 'ended',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'missing',
- label: () => translate('MissingTracks'),
- filters: [
- {
- key: 'missing',
- value: true,
- type: filterTypes.EQUAL
- }
- ]
- }
-];
-
-export const filterPredicates = {
- missing: function(item) {
- const { statistics = {} } = item;
-
- return statistics.trackCount - statistics.trackFileCount > 0;
- },
-
- nextAlbum: function(item, filterValue, type) {
- return dateFilterPredicate(item.nextAlbum?.releaseDate, filterValue, type);
- },
-
- lastAlbum: function(item, filterValue, type) {
- return dateFilterPredicate(item.lastAlbum?.releaseDate, filterValue, type);
- },
-
- added: function(item, filterValue, type) {
- return dateFilterPredicate(item.added, filterValue, type);
- },
-
- ratings: function(item, filterValue, type) {
- const predicate = filterTypePredicates[type];
-
- return predicate(item.ratings.value * 10, filterValue);
- },
-
- albumCount: function(item, filterValue, type) {
- const predicate = filterTypePredicates[type];
- const albumCount = item.statistics ? item.statistics.albumCount : 0;
-
- return predicate(albumCount, filterValue);
- },
-
- sizeOnDisk: function(item, filterValue, type) {
- const predicate = filterTypePredicates[type];
- const sizeOnDisk = item.statistics && item.statistics.sizeOnDisk ?
- item.statistics.sizeOnDisk :
- 0;
-
- return predicate(sizeOnDisk, filterValue);
- }
-};
-
-export const sortPredicates = {
- status: function(item) {
- let result = 0;
-
- if (item.monitored) {
- result += 2;
- }
-
- if (item.status === 'continuing') {
- result++;
- }
-
- return result;
- },
-
- sizeOnDisk: function(item) {
- const { statistics = {} } = item;
-
- return statistics.sizeOnDisk || 0;
- }
-};
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- items: [],
- sortKey: 'sortName',
- sortDirection: sortDirections.ASCENDING,
- pendingChanges: {},
- deleteOptions: {
- addImportListExclusion: false
- }
-};
-
-export const persistState = [
- 'artist.deleteOptions'
-];
-
-//
-// Actions Types
-
-export const FETCH_ARTIST = 'artist/fetchArtist';
-export const SET_ARTIST_VALUE = 'artist/setArtistValue';
-export const SAVE_ARTIST = 'artist/saveArtist';
-export const DELETE_ARTIST = 'artist/deleteArtist';
-
-export const TOGGLE_ARTIST_MONITORED = 'artist/toggleArtistMonitored';
-export const TOGGLE_ALBUM_MONITORED = 'artist/toggleAlbumMonitored';
-export const UPDATE_ARTISTS_MONITOR = 'artist/updateArtistsMonitor';
-export const SAVE_ARTIST_EDITOR = 'artist/saveArtistEditor';
-export const BULK_DELETE_ARTIST = 'artist/bulkDeleteArtist';
-
-export const SET_DELETE_OPTION = 'artist/setDeleteOption';
-
-//
-// Action Creators
-
-export const fetchArtist = createThunk(FETCH_ARTIST);
-export const saveArtist = createThunk(SAVE_ARTIST, (payload) => {
- const newPayload = {
- ...payload
- };
-
- if (payload.moveFiles) {
- newPayload.queryParams = {
- moveFiles: true
- };
- }
-
- delete newPayload.moveFiles;
-
- return newPayload;
-});
-
-export const deleteArtist = createThunk(DELETE_ARTIST, (payload) => {
- return {
- ...payload,
- queryParams: {
- deleteFiles: payload.deleteFiles,
- addImportListExclusion: payload.addImportListExclusion
- }
- };
-});
-
-export const toggleArtistMonitored = createThunk(TOGGLE_ARTIST_MONITORED);
-export const toggleAlbumMonitored = createThunk(TOGGLE_ALBUM_MONITORED);
-export const updateArtistsMonitor = createThunk(UPDATE_ARTISTS_MONITOR);
-export const saveArtistEditor = createThunk(SAVE_ARTIST_EDITOR);
-export const bulkDeleteArtist = createThunk(BULK_DELETE_ARTIST);
-
-export const setArtistValue = createAction(SET_ARTIST_VALUE, (payload) => {
- return {
- section,
- ...payload
- };
-});
-
-export const setDeleteOption = createAction(SET_DELETE_OPTION);
-
-//
-// Helpers
-
-function getSaveAjaxOptions({ ajaxOptions, payload }) {
- if (payload.moveFolder) {
- ajaxOptions.url = `${ajaxOptions.url}?moveFolder=true`;
- }
-
- return ajaxOptions;
-}
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_ARTIST]: createFetchHandler(section, '/artist'),
- [SAVE_ARTIST]: createSaveProviderHandler(section, '/artist', { getAjaxOptions: getSaveAjaxOptions }),
- [DELETE_ARTIST]: createRemoveItemHandler(section, '/artist'),
-
- [TOGGLE_ARTIST_MONITORED]: (getState, payload, dispatch) => {
- const {
- artistId: id,
- monitored
- } = payload;
-
- const artist = _.find(getState().artist.items, { id });
-
- dispatch(updateItem({
- id,
- section,
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- url: `/artist/${id}`,
- method: 'PUT',
- data: JSON.stringify({
- ...artist,
- monitored
- }),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(updateItem({
- id,
- section,
- isSaving: false,
- monitored
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({
- id,
- section,
- isSaving: false
- }));
- });
- },
-
- [TOGGLE_ALBUM_MONITORED]: function(getState, payload, dispatch) {
- const {
- artistId: id,
- seasonNumber,
- monitored
- } = payload;
-
- const artist = _.find(getState().artist.items, { id });
- const seasons = _.cloneDeep(artist.seasons);
- const season = _.find(seasons, { seasonNumber });
-
- season.isSaving = true;
-
- dispatch(updateItem({
- id,
- section,
- seasons
- }));
-
- season.monitored = monitored;
-
- const promise = createAjaxRequest({
- url: `/artist/${id}`,
- method: 'PUT',
- data: JSON.stringify({
- ...artist,
- seasons
- }),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- const albums = _.filter(getState().albums.items, { artistId: id, seasonNumber });
-
- dispatch(batchActions([
- updateItem({
- id,
- section,
- ...data
- }),
-
- ...albums.map((album) => {
- return updateItem({
- id: album.id,
- section: 'albums',
- monitored
- });
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({
- id,
- section,
- seasons: artist.seasons
- }));
- });
- },
-
- [UPDATE_ARTISTS_MONITOR]: function(getState, payload, dispatch) {
- const {
- artistIds,
- monitor,
- monitored,
- monitorNewItems,
- shouldFetchAlbumsAfterUpdate = false
- } = payload;
-
- const artists = [];
-
- artistIds.forEach((id) => {
- const artistsToUpdate = { id };
-
- if (monitored != null) {
- 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) => {
- if (shouldFetchAlbumsAfterUpdate) {
- dispatch(fetchAlbums({ artistId: artistIds[0] }));
- }
-
- dispatch(set({
- section,
- isSaving: false,
- saveError: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- },
-
- [SAVE_ARTIST_EDITOR]: function(getState, payload, dispatch) {
- dispatch(set({
- section,
- isSaving: true
- }));
-
- const promise = createAjaxRequest({
- url: '/artist/editor',
- method: 'PUT',
- data: JSON.stringify(payload),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- ...data.map((artist) => {
-
- const {
- images,
- rootFolderPath,
- statistics,
- ...propsToUpdate
- } = artist;
-
- return updateItem({
- id: artist.id,
- section: 'artist',
- ...propsToUpdate
- });
- }),
-
- set({
- section,
- isSaving: false,
- saveError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- },
-
- [BULK_DELETE_ARTIST]: function(getState, payload, dispatch) {
- dispatch(set({
- section,
- isDeleting: true
- }));
-
- const promise = createAjaxRequest({
- url: '/artist/editor',
- method: 'DELETE',
- data: JSON.stringify(payload),
- dataType: 'json'
- }).request;
-
- promise.done(() => {
- // SignaR will take care of removing the artist from the collection
-
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: xhr
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ARTIST_VALUE]: createSetSettingValueReducer(section),
-
- [SET_DELETE_OPTION]: (state, { payload }) => {
- return {
- ...state,
- deleteOptions: {
- ...payload
- }
- };
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/artistHistoryActions.js b/frontend/src/Store/Actions/artistHistoryActions.js
deleted file mode 100644
index 59ce098d0..000000000
--- a/frontend/src/Store/Actions/artistHistoryActions.js
+++ /dev/null
@@ -1,101 +0,0 @@
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set, update } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'artistHistory';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
-};
-
-//
-// Actions Types
-
-export const FETCH_ARTIST_HISTORY = 'artistHistory/fetchArtistHistory';
-export const CLEAR_ARTIST_HISTORY = 'artistHistory/clearArtistHistory';
-export const ARTIST_HISTORY_MARK_AS_FAILED = 'artistHistory/artistHistoryMarkAsFailed';
-
-//
-// Action Creators
-
-export const fetchArtistHistory = createThunk(FETCH_ARTIST_HISTORY);
-export const clearArtistHistory = createAction(CLEAR_ARTIST_HISTORY);
-export const artistHistoryMarkAsFailed = createThunk(ARTIST_HISTORY_MARK_AS_FAILED);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_ARTIST_HISTORY]: function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const promise = createAjaxRequest({
- url: '/history/artist',
- data: payload
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- },
-
- [ARTIST_HISTORY_MARK_AS_FAILED]: function(getState, payload, dispatch) {
- const {
- historyId,
- artistId,
- albumId
- } = payload;
-
- const promise = createAjaxRequest({
- url: `/history/failed/${historyId}`,
- method: 'POST',
- dataType: 'json'
- }).request;
-
- promise.done(() => {
- dispatch(fetchArtistHistory({ artistId, albumId }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_ARTIST_HISTORY]: (state) => {
- return Object.assign({}, state, defaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/artistIndexActions.js b/frontend/src/Store/Actions/artistIndexActions.js
deleted file mode 100644
index 736502460..000000000
--- a/frontend/src/Store/Actions/artistIndexActions.js
+++ /dev/null
@@ -1,439 +0,0 @@
-import { createAction } from 'redux-actions';
-import { filterBuilderTypes, filterBuilderValueTypes, filterTypePredicates, sortDirections } from 'Helpers/Props';
-import sortByProp from 'Utilities/Array/sortByProp';
-import translate from 'Utilities/String/translate';
-import { filterPredicates, filters, sortPredicates } from './artistActions';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'artistIndex';
-
-//
-// State
-
-export const defaultState = {
- sortKey: 'sortName',
- sortDirection: sortDirections.ASCENDING,
- secondarySortKey: 'sortName',
- secondarySortDirection: sortDirections.ASCENDING,
- view: 'posters',
-
- posterOptions: {
- detailedProgressBar: false,
- size: 'large',
- showTitle: true,
- showMonitored: true,
- showQualityProfile: true,
- showNextAlbum: true,
- showSearchAction: false
- },
-
- bannerOptions: {
- detailedProgressBar: false,
- size: 'large',
- showTitle: false,
- showMonitored: true,
- showQualityProfile: true,
- showNextAlbum: true,
- showSearchAction: false
- },
-
- overviewOptions: {
- detailedProgressBar: false,
- size: 'medium',
- showMonitored: true,
- showQualityProfile: true,
- showLastAlbum: false,
- showAdded: false,
- showAlbumCount: true,
- showPath: false,
- showSizeOnDisk: false,
- showSearchAction: false
- },
-
- tableOptions: {
- showBanners: false,
- showSearchAction: false
- },
-
- columns: [
- {
- name: 'status',
- columnLabel: () => translate('Status'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'sortName',
- label: () => translate('ArtistName'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'artistType',
- label: () => translate('Type'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'qualityProfileId',
- label: () => translate('QualityProfile'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'metadataProfileId',
- label: () => translate('MetadataProfile'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'monitorNewItems',
- label: () => translate('MonitorNewItems'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'nextAlbum',
- label: () => translate('NextAlbum'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'lastAlbum',
- label: () => translate('LastAlbum'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'added',
- label: () => translate('Added'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'albumCount',
- label: () => translate('Albums'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'trackProgress',
- label: () => translate('Tracks'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'trackCount',
- label: () => translate('TrackCount'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'path',
- label: () => translate('Path'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'sizeOnDisk',
- label: () => translate('SizeOnDisk'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'genres',
- label: () => translate('Genres'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'ratings',
- label: () => translate('Rating'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'tags',
- label: () => translate('Tags'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ],
-
- sortPredicates: {
- ...sortPredicates,
-
- trackProgress: function(item) {
- const { statistics = {} } = item;
-
- const {
- trackCount = 0,
- trackFileCount = 0
- } = statistics;
-
- const progress = trackCount ? trackFileCount / trackCount * 100 : 100;
-
- return progress + trackCount / 1000000;
- },
-
- nextAlbum: function(item) {
- if (item.nextAlbum) {
- return item.nextAlbum.releaseDate;
- }
- return '1/1/1000';
- },
-
- lastAlbum: function(item) {
- if (item.lastAlbum) {
- return item.lastAlbum.releaseDate;
- }
- return '1/1/1000';
- },
-
- albumCount: function(item) {
- const { statistics = {} } = item;
-
- return statistics.albumCount || 0;
- },
-
- trackCount: function(item) {
- const { statistics = {} } = item;
-
- return statistics.totalTrackCount || 0;
- },
-
- ratings: function(item) {
- const { ratings = {} } = item;
-
- return ratings.value;
- }
- },
-
- selectedFilterKey: 'all',
-
- filters,
-
- filterPredicates: {
- ...filterPredicates,
-
- trackProgress: function(item, filterValue, type) {
- const { statistics = {} } = item;
-
- const {
- trackCount = 0,
- trackFileCount = 0
- } = statistics;
-
- const progress = trackCount ?
- trackFileCount / trackCount * 100 :
- 100;
-
- const predicate = filterTypePredicates[type];
-
- return predicate(progress, filterValue);
- }
- },
-
- 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: 'qualityProfileId',
- label: () => translate('QualityProfile'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.QUALITY_PROFILE
- },
- {
- name: 'metadataProfileId',
- label: () => translate('MetadataProfile'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.METADATA_PROFILE
- },
- {
- name: 'monitorNewItems',
- label: () => translate('MonitorNewItems'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.MONITOR_NEW_ITEMS
- },
- {
- name: 'nextAlbum',
- label: () => translate('NextAlbum'),
- type: filterBuilderTypes.DATE,
- valueType: filterBuilderValueTypes.DATE
- },
- {
- name: 'lastAlbum',
- label: () => translate('LastAlbum'),
- type: filterBuilderTypes.DATE,
- valueType: filterBuilderValueTypes.DATE
- },
- {
- name: 'added',
- label: () => translate('Added'),
- type: filterBuilderTypes.DATE,
- valueType: filterBuilderValueTypes.DATE
- },
- {
- name: 'albumCount',
- label: () => translate('AlbumCount'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'trackProgress',
- label: () => translate('TrackProgress'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'path',
- label: () => translate('Path'),
- type: filterBuilderTypes.STRING
- },
- {
- name: 'sizeOnDisk',
- label: () => translate('SizeOnDisk'),
- type: filterBuilderTypes.NUMBER,
- valueType: filterBuilderValueTypes.BYTES
- },
- {
- name: 'genres',
- label: () => translate('Genres'),
- type: filterBuilderTypes.ARRAY,
- optionsSelector: function(items) {
- const tagList = items.reduce((acc, artist) => {
- artist.genres.forEach((genre) => {
- acc.push({
- id: genre,
- name: genre
- });
- });
-
- return acc;
- }, []);
-
- return tagList.sort(sortByProp('name'));
- }
- },
- {
- name: 'ratings',
- label: () => translate('Rating'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'tags',
- label: () => translate('Tags'),
- type: filterBuilderTypes.ARRAY,
- valueType: filterBuilderValueTypes.TAG
- }
- ]
-};
-
-export const persistState = [
- 'artistIndex.sortKey',
- 'artistIndex.sortDirection',
- 'artistIndex.selectedFilterKey',
- 'artistIndex.customFilters',
- 'artistIndex.view',
- 'artistIndex.columns',
- 'artistIndex.posterOptions',
- 'artistIndex.bannerOptions',
- 'artistIndex.overviewOptions',
- 'artistIndex.tableOptions'
-];
-
-//
-// Actions Types
-
-export const SET_ARTIST_SORT = 'artistIndex/setArtistSort';
-export const SET_ARTIST_FILTER = 'artistIndex/setArtistFilter';
-export const SET_ARTIST_VIEW = 'artistIndex/setArtistView';
-export const SET_ARTIST_TABLE_OPTION = 'artistIndex/setArtistTableOption';
-export const SET_ARTIST_POSTER_OPTION = 'artistIndex/setArtistPosterOption';
-export const SET_ARTIST_BANNER_OPTION = 'artistIndex/setArtistBannerOption';
-export const SET_ARTIST_OVERVIEW_OPTION = 'artistIndex/setArtistOverviewOption';
-
-//
-// Action Creators
-
-export const setArtistSort = createAction(SET_ARTIST_SORT);
-export const setArtistFilter = createAction(SET_ARTIST_FILTER);
-export const setArtistView = createAction(SET_ARTIST_VIEW);
-export const setArtistTableOption = createAction(SET_ARTIST_TABLE_OPTION);
-export const setArtistPosterOption = createAction(SET_ARTIST_POSTER_OPTION);
-export const setArtistBannerOption = createAction(SET_ARTIST_BANNER_OPTION);
-export const setArtistOverviewOption = createAction(SET_ARTIST_OVERVIEW_OPTION);
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ARTIST_SORT]: createSetClientSideCollectionSortReducer(section),
- [SET_ARTIST_FILTER]: createSetClientSideCollectionFilterReducer(section),
-
- [SET_ARTIST_VIEW]: function(state, { payload }) {
- return Object.assign({}, state, { view: payload.view });
- },
-
- [SET_ARTIST_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [SET_ARTIST_POSTER_OPTION]: function(state, { payload }) {
- const posterOptions = state.posterOptions;
-
- return {
- ...state,
- posterOptions: {
- ...posterOptions,
- ...payload
- }
- };
- },
-
- [SET_ARTIST_BANNER_OPTION]: function(state, { payload }) {
- const bannerOptions = state.bannerOptions;
-
- return {
- ...state,
- bannerOptions: {
- ...bannerOptions,
- ...payload
- }
- };
- },
-
- [SET_ARTIST_OVERVIEW_OPTION]: function(state, { payload }) {
- const overviewOptions = state.overviewOptions;
-
- return {
- ...state,
- overviewOptions: {
- ...overviewOptions,
- ...payload
- }
- };
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/baseActions.js b/frontend/src/Store/Actions/baseActions.js
deleted file mode 100644
index 37be3e0d2..000000000
--- a/frontend/src/Store/Actions/baseActions.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { createAction } from 'redux-actions';
-
-//
-// Action Types
-
-export const SET = 'base/set';
-
-export const UPDATE = 'base/update';
-export const UPDATE_ITEM = 'base/updateItem';
-export const UPDATE_SERVER_SIDE_COLLECTION = 'base/updateServerSideCollection';
-
-export const SET_SETTING_VALUE = 'base/setSettingValue';
-export const CLEAR_PENDING_CHANGES = 'base/clearPendingChanges';
-
-export const REMOVE_ITEM = 'base/removeItem';
-
-//
-// Action Creators
-
-export const set = createAction(SET);
-
-export const update = createAction(UPDATE);
-export const updateItem = createAction(UPDATE_ITEM);
-export const updateServerSideCollection = createAction(UPDATE_SERVER_SIDE_COLLECTION);
-
-export const setSettingValue = createAction(SET_SETTING_VALUE);
-export const clearPendingChanges = createAction(CLEAR_PENDING_CHANGES);
-
-export const removeItem = createAction(REMOVE_ITEM);
diff --git a/frontend/src/Store/Actions/blocklistActions.js b/frontend/src/Store/Actions/blocklistActions.js
deleted file mode 100644
index 217ee7f64..000000000
--- a/frontend/src/Store/Actions/blocklistActions.js
+++ /dev/null
@@ -1,199 +0,0 @@
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import translate from 'Utilities/String/translate';
-import { set, updateItem } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'blocklist';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- pageSize: 20,
- sortKey: 'date',
- sortDirection: sortDirections.DESCENDING,
- error: null,
- items: [],
- isRemoving: false,
-
- columns: [
- {
- name: 'artists.sortName',
- label: () => translate('ArtistName'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'sourceTitle',
- label: () => translate('SourceTitle'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- isVisible: true
- },
- {
- name: 'customFormats',
- label: 'Formats',
- isSortable: false,
- isVisible: true
- },
- {
- name: 'date',
- label: () => translate('Date'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'indexer',
- label: () => translate('Indexer'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ]
-};
-
-export const persistState = [
- 'blocklist.pageSize',
- 'blocklist.sortKey',
- 'blocklist.sortDirection',
- 'blocklist.columns'
-];
-
-//
-// Action Types
-
-export const FETCH_BLOCKLIST = 'blocklist/fetchBlocklist';
-export const GOTO_FIRST_BLOCKLIST_PAGE = 'blocklist/gotoBlocklistFirstPage';
-export const GOTO_PREVIOUS_BLOCKLIST_PAGE = 'blocklist/gotoBlocklistPreviousPage';
-export const GOTO_NEXT_BLOCKLIST_PAGE = 'blocklist/gotoBlocklistNextPage';
-export const GOTO_LAST_BLOCKLIST_PAGE = 'blocklist/gotoBlocklistLastPage';
-export const GOTO_BLOCKLIST_PAGE = 'blocklist/gotoBlocklistPage';
-export const SET_BLOCKLIST_SORT = 'blocklist/setBlocklistSort';
-export const SET_BLOCKLIST_TABLE_OPTION = 'blocklist/setBlocklistTableOption';
-export const REMOVE_BLOCKLIST_ITEM = 'blocklist/removeBlocklistItem';
-export const REMOVE_BLOCKLIST_ITEMS = 'blocklist/removeBlocklistItems';
-export const CLEAR_BLOCKLIST = 'blocklist/clearBlocklist';
-
-//
-// Action Creators
-
-export const fetchBlocklist = createThunk(FETCH_BLOCKLIST);
-export const gotoBlocklistFirstPage = createThunk(GOTO_FIRST_BLOCKLIST_PAGE);
-export const gotoBlocklistPreviousPage = createThunk(GOTO_PREVIOUS_BLOCKLIST_PAGE);
-export const gotoBlocklistNextPage = createThunk(GOTO_NEXT_BLOCKLIST_PAGE);
-export const gotoBlocklistLastPage = createThunk(GOTO_LAST_BLOCKLIST_PAGE);
-export const gotoBlocklistPage = createThunk(GOTO_BLOCKLIST_PAGE);
-export const setBlocklistSort = createThunk(SET_BLOCKLIST_SORT);
-export const setBlocklistTableOption = createAction(SET_BLOCKLIST_TABLE_OPTION);
-export const removeBlocklistItem = createThunk(REMOVE_BLOCKLIST_ITEM);
-export const removeBlocklistItems = createThunk(REMOVE_BLOCKLIST_ITEMS);
-export const clearBlocklist = createAction(CLEAR_BLOCKLIST);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- ...createServerSideCollectionHandlers(
- section,
- '/blocklist',
- fetchBlocklist,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_BLOCKLIST,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_BLOCKLIST_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_BLOCKLIST_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_BLOCKLIST_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_BLOCKLIST_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_BLOCKLIST_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_BLOCKLIST_SORT
- }),
-
- [REMOVE_BLOCKLIST_ITEM]: createRemoveItemHandler(section, '/blocklist'),
-
- [REMOVE_BLOCKLIST_ITEMS]: function(getState, payload, dispatch) {
- const {
- ids
- } = payload;
-
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section,
- id,
- isRemoving: true
- });
- }),
-
- set({ section, isRemoving: true })
- ]));
-
- const promise = createAjaxRequest({
- url: '/blocklist/bulk',
- method: 'DELETE',
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify({ ids })
- }).request;
-
- promise.done((data) => {
- // Don't use batchActions with thunks
- dispatch(fetchBlocklist());
-
- dispatch(set({ section, isRemoving: false }));
- });
-
- promise.fail((xhr) => {
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section,
- id,
- isRemoving: false
- });
- }),
-
- set({ section, isRemoving: false })
- ]));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_BLOCKLIST_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [CLEAR_BLOCKLIST]: createClearReducer(section, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- })
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/calendarActions.js b/frontend/src/Store/Actions/calendarActions.js
deleted file mode 100644
index e13ff4672..000000000
--- a/frontend/src/Store/Actions/calendarActions.js
+++ /dev/null
@@ -1,424 +0,0 @@
-import _ from 'lodash';
-import moment from 'moment';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import * as calendarViews from 'Calendar/calendarViews';
-import * as commandNames from 'Commands/commandNames';
-import { filterBuilderTypes, filterBuilderValueTypes, filterTypes } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import findSelectedFilters from 'Utilities/Filter/findSelectedFilters';
-import translate from 'Utilities/String/translate';
-import { set, update } from './baseActions';
-import { executeCommandHelper } from './commandActions';
-import createHandleActions from './Creators/createHandleActions';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-
-//
-// Variables
-
-export const section = 'calendar';
-
-const viewRanges = {
- [calendarViews.DAY]: 'day',
- [calendarViews.WEEK]: 'week',
- [calendarViews.MONTH]: 'month',
- [calendarViews.FORECAST]: 'day'
-};
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- start: null,
- end: null,
- dates: [],
- dayCount: 7,
- view: window.innerWidth > 768 ? 'week' : 'day',
- showUpcoming: true,
- error: null,
- items: [],
- searchMissingCommandId: null,
-
- options: {
- collapseMultipleAlbums: false,
- showCutoffUnmetIcon: false
- },
-
- selectedFilterKey: 'monitored',
-
- filters: [
- {
- key: 'all',
- label: () => translate('All'),
- filters: [
- {
- key: 'unmonitored',
- value: [true],
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'monitored',
- label: () => translate('MonitoredOnly'),
- filters: [
- {
- key: 'unmonitored',
- value: [false],
- type: filterTypes.EQUAL
- }
- ]
- }
- ],
-
- filterBuilderProps: [
- {
- name: 'unmonitored',
- label: () => translate('IncludeUnmonitored'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.BOOL
- },
- {
- name: 'tags',
- label: () => translate('Tags'),
- type: filterBuilderTypes.CONTAINS,
- valueType: filterBuilderValueTypes.TAG
- }
- ]
-};
-
-export const persistState = [
- 'calendar.view',
- 'calendar.selectedFilterKey',
- 'calendar.options',
- 'calendar.customFilters'
-];
-
-//
-// Actions Types
-
-export const FETCH_CALENDAR = 'calendar/fetchCalendar';
-export const SET_CALENDAR_DAYS_COUNT = 'calendar/setCalendarDaysCount';
-export const SET_CALENDAR_FILTER = 'calendar/setCalendarFilter';
-export const SET_CALENDAR_VIEW = 'calendar/setCalendarView';
-export const GOTO_CALENDAR_TODAY = 'calendar/gotoCalendarToday';
-export const GOTO_CALENDAR_NEXT_RANGE = 'calendar/gotoCalendarNextRange';
-export const CLEAR_CALENDAR = 'calendar/clearCalendar';
-export const SET_CALENDAR_OPTION = 'calendar/setCalendarOption';
-export const SEARCH_MISSING = 'calendar/searchMissing';
-export const GOTO_CALENDAR_PREVIOUS_RANGE = 'calendar/gotoCalendarPreviousRange';
-
-//
-// Helpers
-
-function getDays(start, end) {
- const startTime = moment(start);
- const endTime = moment(end);
- const difference = endTime.diff(startTime, 'days');
-
- // Difference is one less than the number of days we need to account for.
- return _.times(difference + 1, (i) => {
- return startTime.clone().add(i, 'days').toISOString();
- });
-}
-
-function getDates(time, view, firstDayOfWeek, dayCount) {
- const weekName = firstDayOfWeek === 0 ? 'week' : 'isoWeek';
-
- let start = time.clone().startOf('day');
- let end = time.clone().endOf('day');
-
- if (view === calendarViews.WEEK) {
- start = time.clone().startOf(weekName);
- end = time.clone().endOf(weekName);
- }
-
- if (view === calendarViews.FORECAST) {
- start = time.clone().subtract(1, 'day').startOf('day');
- end = time.clone().add(dayCount - 2, 'days').endOf('day');
- }
-
- if (view === calendarViews.MONTH) {
- start = time.clone().startOf('month').startOf(weekName);
- end = time.clone().endOf('month').endOf(weekName);
- }
-
- if (view === calendarViews.AGENDA) {
- start = time.clone().subtract(1, 'day').startOf('day');
- end = time.clone().add(1, 'month').endOf('day');
- }
-
- return {
- start: start.toISOString(),
- end: end.toISOString(),
- time: time.toISOString(),
- dates: getDays(start, end)
- };
-}
-
-function getPopulatableRange(startDate, endDate, view) {
- switch (view) {
- case calendarViews.DAY:
- return {
- start: moment(startDate).subtract(1, 'day').toISOString(),
- end: moment(endDate).add(1, 'day').toISOString()
- };
- case calendarViews.WEEK:
- case calendarViews.FORECAST:
- return {
- start: moment(startDate).subtract(1, 'week').toISOString(),
- end: moment(endDate).add(1, 'week').toISOString()
- };
- default:
- return {
- start: startDate,
- end: endDate
- };
- }
-}
-
-function isRangePopulated(start, end, state) {
- const {
- start: currentStart,
- end: currentEnd,
- view: currentView
- } = state;
-
- if (!currentStart || !currentEnd) {
- return false;
- }
-
- const {
- start: currentPopulatedStart,
- end: currentPopulatedEnd
- } = getPopulatableRange(currentStart, currentEnd, currentView);
-
- if (
- moment(start).isAfter(currentPopulatedStart) &&
- moment(start).isBefore(currentPopulatedEnd)
- ) {
- return true;
- }
-
- return false;
-}
-
-function getCustomFilters(state, type) {
- return state.customFilters.items.filter((customFilter) => customFilter.type === type);
-}
-
-//
-// Action Creators
-
-export const fetchCalendar = createThunk(FETCH_CALENDAR);
-export const setCalendarDaysCount = createThunk(SET_CALENDAR_DAYS_COUNT);
-export const setCalendarFilter = createThunk(SET_CALENDAR_FILTER);
-export const setCalendarView = createThunk(SET_CALENDAR_VIEW);
-export const gotoCalendarToday = createThunk(GOTO_CALENDAR_TODAY);
-export const gotoCalendarPreviousRange = createThunk(GOTO_CALENDAR_PREVIOUS_RANGE);
-export const gotoCalendarNextRange = createThunk(GOTO_CALENDAR_NEXT_RANGE);
-export const clearCalendar = createAction(CLEAR_CALENDAR);
-export const setCalendarOption = createAction(SET_CALENDAR_OPTION);
-export const searchMissing = createThunk(SEARCH_MISSING);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_CALENDAR]: function(getState, payload, dispatch) {
- const state = getState();
- const calendar = state.calendar;
- const customFilters = getCustomFilters(state, section);
- const selectedFilters = findSelectedFilters(calendar.selectedFilterKey, calendar.filters, customFilters);
-
- const {
- time = calendar.time,
- view = calendar.view
- } = payload;
-
- const dayCount = state.calendar.dayCount;
- const dates = getDates(moment(time), view, state.settings.ui.item.firstDayOfWeek, dayCount);
- const { start, end } = getPopulatableRange(dates.start, dates.end, view);
- const isPrePopulated = isRangePopulated(start, end, state.calendar);
-
- const basesAttrs = {
- section,
- isFetching: true
- };
-
- const attrs = isPrePopulated ?
- {
- view,
- ...basesAttrs,
- ...dates
- } :
- basesAttrs;
-
- dispatch(set(attrs));
-
- const requestParams = {
- start,
- end
- };
-
- selectedFilters.forEach((selectedFilter) => {
- if (selectedFilter.key === 'unmonitored') {
- requestParams.unmonitored = selectedFilter.value.includes(true);
- }
-
- if (selectedFilter.key === 'tags') {
- requestParams.tags = selectedFilter.value.join(',');
- }
- });
-
- requestParams.unmonitored = requestParams.unmonitored ?? false;
-
- const promise = createAjaxRequest({
- url: '/calendar',
- data: requestParams
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- view,
- ...dates,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- },
-
- [SET_CALENDAR_DAYS_COUNT]: function(getState, payload, dispatch) {
- if (payload.dayCount === getState().calendar.dayCount) {
- return;
- }
-
- dispatch(set({
- section,
- dayCount: payload.dayCount
- }));
-
- const state = getState();
- const { time, view } = state.calendar;
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [SET_CALENDAR_FILTER]: function(getState, payload, dispatch) {
- dispatch(set({
- section,
- selectedFilterKey: payload.selectedFilterKey
- }));
-
- const state = getState();
- const { time, view } = state.calendar;
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [SET_CALENDAR_VIEW]: function(getState, payload, dispatch) {
- const state = getState();
- const view = payload.view;
- const time = view === calendarViews.FORECAST || calendarViews.AGENDA ?
- moment() :
- state.calendar.time;
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [GOTO_CALENDAR_TODAY]: function(getState, payload, dispatch) {
- const state = getState();
- const view = state.calendar.view;
- const time = moment();
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [GOTO_CALENDAR_PREVIOUS_RANGE]: function(getState, payload, dispatch) {
- const state = getState();
-
- const {
- view,
- dayCount
- } = state.calendar;
-
- const amount = view === calendarViews.FORECAST ? dayCount : 1;
- const time = moment(state.calendar.time).subtract(amount, viewRanges[view]);
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [GOTO_CALENDAR_NEXT_RANGE]: function(getState, payload, dispatch) {
- const state = getState();
-
- const {
- view,
- dayCount
- } = state.calendar;
-
- const amount = view === calendarViews.FORECAST ? dayCount : 1;
- const time = moment(state.calendar.time).add(amount, viewRanges[view]);
-
- dispatch(fetchCalendar({ time, view }));
- },
-
- [SEARCH_MISSING]: function(getState, payload, dispatch) {
- const { albumIds } = payload;
-
- const commandPayload = {
- name: commandNames.ALBUM_SEARCH,
- albumIds
- };
-
- executeCommandHelper(commandPayload, dispatch).then((data) => {
- dispatch(set({
- section,
- searchMissingCommandId: data.id
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_CALENDAR]: createClearReducer(section, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- }),
-
- [SET_CALENDAR_OPTION]: function(state, { payload }) {
- const options = state.options;
-
- return {
- ...state,
- options: {
- ...options,
- ...payload
- }
- };
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/captchaActions.js b/frontend/src/Store/Actions/captchaActions.js
deleted file mode 100644
index c83d231b7..000000000
--- a/frontend/src/Store/Actions/captchaActions.js
+++ /dev/null
@@ -1,119 +0,0 @@
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import requestAction from 'Utilities/requestAction';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'captcha';
-
-//
-// State
-
-export const defaultState = {
- refreshing: false,
- token: null,
- siteKey: null,
- secretToken: null,
- ray: null,
- stoken: null,
- responseUrl: null
-};
-
-//
-// Actions Types
-
-export const REFRESH_CAPTCHA = 'captcha/refreshCaptcha';
-export const GET_CAPTCHA_COOKIE = 'captcha/getCaptchaCookie';
-export const SET_CAPTCHA_VALUE = 'captcha/setCaptchaValue';
-export const RESET_CAPTCHA = 'captcha/resetCaptcha';
-
-//
-// Action Creators
-
-export const refreshCaptcha = createThunk(REFRESH_CAPTCHA);
-export const getCaptchaCookie = createThunk(GET_CAPTCHA_COOKIE);
-export const setCaptchaValue = createAction(SET_CAPTCHA_VALUE);
-export const resetCaptcha = createAction(RESET_CAPTCHA);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [REFRESH_CAPTCHA]: function(getState, payload, dispatch) {
- const actionPayload = {
- action: 'checkCaptcha',
- ...payload
- };
-
- dispatch(setCaptchaValue({
- refreshing: true
- }));
-
- const promise = requestAction(actionPayload);
-
- promise.done((data) => {
- if (!data.captchaRequest) {
- dispatch(setCaptchaValue({
- refreshing: false
- }));
- }
-
- dispatch(setCaptchaValue({
- refreshing: false,
- ...data.captchaRequest
- }));
- });
-
- promise.fail(() => {
- dispatch(setCaptchaValue({
- refreshing: false
- }));
- });
- },
-
- [GET_CAPTCHA_COOKIE]: function(getState, payload, dispatch) {
- const state = getState().captcha;
-
- const queryParams = {
- responseUrl: state.responseUrl,
- ray: state.ray,
- captchaResponse: payload.captchaResponse
- };
-
- const actionPayload = {
- action: 'getCaptchaCookie',
- queryParams,
- ...payload
- };
-
- const promise = requestAction(actionPayload);
-
- promise.done((data) => {
- dispatch(setCaptchaValue({
- token: data.captchaToken
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_CAPTCHA_VALUE]: function(state, { payload }) {
- const newState = Object.assign(getSectionState(state, section), payload);
-
- return updateSectionState(state, section, newState);
- },
-
- [RESET_CAPTCHA]: function(state) {
- return updateSectionState(state, section, defaultState);
- }
-
-}, defaultState);
diff --git a/frontend/src/Store/Actions/commandActions.js b/frontend/src/Store/Actions/commandActions.js
deleted file mode 100644
index 083bdd61f..000000000
--- a/frontend/src/Store/Actions/commandActions.js
+++ /dev/null
@@ -1,218 +0,0 @@
-import { batchActions } from 'redux-batched-actions';
-import { messageTypes } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import { isSameCommand } from 'Utilities/Command';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { hideMessage, showMessage } from './appActions';
-import { removeItem, updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-
-//
-// Variables
-
-export const section = 'commands';
-
-let lastCommand = null;
-let lastCommandTimeout = null;
-const removeCommandTimeoutIds = {};
-const commandFinishedCallbacks = {};
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- handlers: {}
-};
-
-//
-// Actions Types
-
-export const FETCH_COMMANDS = 'commands/fetchCommands';
-export const EXECUTE_COMMAND = 'commands/executeCommand';
-export const CANCEL_COMMAND = 'commands/cancelCommand';
-export const ADD_COMMAND = 'commands/addCommand';
-export const UPDATE_COMMAND = 'commands/updateCommand';
-export const FINISH_COMMAND = 'commands/finishCommand';
-export const REMOVE_COMMAND = 'commands/removeCommand';
-
-//
-// Action Creators
-
-export const fetchCommands = createThunk(FETCH_COMMANDS);
-export const executeCommand = createThunk(EXECUTE_COMMAND);
-export const cancelCommand = createThunk(CANCEL_COMMAND);
-export const addCommand = createThunk(ADD_COMMAND);
-export const updateCommand = createThunk(UPDATE_COMMAND);
-export const finishCommand = createThunk(FINISH_COMMAND);
-export const removeCommand = createThunk(REMOVE_COMMAND);
-
-//
-// Helpers
-
-function showCommandMessage(payload, dispatch) {
- const {
- id,
- name,
- trigger,
- message,
- body = {},
- status
- } = payload;
-
- const {
- sendUpdatesToClient,
- suppressMessages
- } = body;
-
- if (!message || !body || !sendUpdatesToClient || suppressMessages) {
- return;
- }
-
- let type = messageTypes.INFO;
- let hideAfter = 0;
-
- if (status === 'completed') {
- type = messageTypes.SUCCESS;
- hideAfter = 4;
- } else if (status === 'failed') {
- type = messageTypes.ERROR;
- hideAfter = trigger === 'manual' ? 10 : 4;
- }
-
- dispatch(showMessage({
- id,
- name,
- message,
- type,
- hideAfter
- }));
-}
-
-function scheduleRemoveCommand(command, dispatch) {
- const {
- id,
- status
- } = command;
-
- if (status === 'queued') {
- return;
- }
-
- const timeoutId = removeCommandTimeoutIds[id];
-
- if (timeoutId) {
- clearTimeout(timeoutId);
- }
-
- removeCommandTimeoutIds[id] = setTimeout(() => {
- dispatch(batchActions([
- removeCommand({ section: 'commands', id }),
- hideMessage({ id })
- ]));
-
- delete removeCommandTimeoutIds[id];
- }, 60000 * 5);
-}
-
-export function executeCommandHelper(payload, dispatch) {
- // TODO: show a message for the user
- if (lastCommand && isSameCommand(lastCommand, payload)) {
- console.warn('Please wait at least 5 seconds before running this command again');
- }
-
- lastCommand = payload;
-
- // clear last command after 5 seconds.
- if (lastCommandTimeout) {
- clearTimeout(lastCommandTimeout);
- }
-
- lastCommandTimeout = setTimeout(() => {
- lastCommand = null;
- }, 5000);
-
- const {
- commandFinished,
- ...requestPayload
- } = payload;
-
- const promise = createAjaxRequest({
- url: '/command',
- method: 'POST',
- data: JSON.stringify(requestPayload),
- dataType: 'json'
- }).request;
-
- return promise.then((data) => {
- if (commandFinished) {
- commandFinishedCallbacks[data.id] = commandFinished;
- }
-
- dispatch(addCommand(data));
- });
-}
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_COMMANDS]: createFetchHandler('commands', '/command'),
-
- [EXECUTE_COMMAND]: function(getState, payload, dispatch) {
- executeCommandHelper(payload, dispatch);
- },
-
- [CANCEL_COMMAND]: createRemoveItemHandler(section, '/command'),
-
- [ADD_COMMAND]: function(getState, payload, dispatch) {
- dispatch(updateItem({ section: 'commands', ...payload }));
- },
-
- [UPDATE_COMMAND]: function(getState, payload, dispatch) {
- dispatch(updateItem({ section: 'commands', ...payload }));
-
- showCommandMessage(payload, dispatch);
- scheduleRemoveCommand(payload, dispatch);
- },
-
- [FINISH_COMMAND]: function(getState, payload, dispatch) {
- const state = getState();
- const handlers = state.commands.handlers;
-
- Object.keys(handlers).forEach((key) => {
- const handler = handlers[key];
-
- if (handler.name === payload.name) {
- dispatch(handler.handler(payload));
- }
- });
-
- const commandFinished = commandFinishedCallbacks[payload.id];
-
- if (commandFinished) {
- commandFinished(payload);
- }
-
- delete commandFinishedCallbacks[payload.id];
-
- dispatch(updateItem({ section: 'commands', ...payload }));
- scheduleRemoveCommand(payload, dispatch);
- showCommandMessage(payload, dispatch);
- },
-
- [REMOVE_COMMAND]: function(getState, payload, dispatch) {
- dispatch(removeItem({ section: 'commands', ...payload }));
- }
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({}, defaultState, section);
diff --git a/frontend/src/Store/Actions/createReducers.js b/frontend/src/Store/Actions/createReducers.js
deleted file mode 100644
index 28c06b9c3..000000000
--- a/frontend/src/Store/Actions/createReducers.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import { connectRouter } from 'connected-react-router';
-import { combineReducers } from 'redux';
-import { enableBatching } from 'redux-batched-actions';
-import actions from 'Store/Actions';
-
-const defaultState = {};
-const reducers = {};
-
-actions.forEach((action) => {
- const section = action.section;
-
- defaultState[section] = action.defaultState;
- reducers[section] = action.reducers;
-});
-
-export { defaultState };
-
-export default function(history) {
- return enableBatching(combineReducers({
- ...reducers,
- router: connectRouter(history)
- }));
-}
diff --git a/frontend/src/Store/Actions/customFilterActions.js b/frontend/src/Store/Actions/customFilterActions.js
deleted file mode 100644
index d644afbf9..000000000
--- a/frontend/src/Store/Actions/customFilterActions.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { createThunk, handleThunks } from 'Store/thunks';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createSaveProviderHandler from './Creators/createSaveProviderHandler';
-
-//
-// Variables
-
-export const section = 'customFilters';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- isSaving: false,
- saveError: null,
- isDeleting: false,
- deleteError: null,
- items: [],
- pendingChanges: {}
-};
-
-//
-// Actions Types
-
-export const FETCH_CUSTOM_FILTERS = 'customFilters/fetchCustomFilters';
-export const SAVE_CUSTOM_FILTER = 'customFilters/saveCustomFilter';
-export const DELETE_CUSTOM_FILTER = 'customFilters/deleteCustomFilter';
-
-//
-// Action Creators
-
-export const fetchCustomFilters = createThunk(FETCH_CUSTOM_FILTERS);
-export const saveCustomFilter = createThunk(SAVE_CUSTOM_FILTER);
-export const deleteCustomFilter = createThunk(DELETE_CUSTOM_FILTER);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_CUSTOM_FILTERS]: createFetchHandler(section, '/customFilter'),
-
- [SAVE_CUSTOM_FILTER]: createSaveProviderHandler(section, '/customFilter'),
-
- [DELETE_CUSTOM_FILTER]: createRemoveItemHandler(section, '/customFilter')
-
-});
-
-//
-// Reducers
-export const reducers = createHandleActions({}, defaultState, section);
diff --git a/frontend/src/Store/Actions/historyActions.js b/frontend/src/Store/Actions/historyActions.js
deleted file mode 100644
index 9d16d29c4..000000000
--- a/frontend/src/Store/Actions/historyActions.js
+++ /dev/null
@@ -1,350 +0,0 @@
-import React from 'react';
-import { createAction } from 'redux-actions';
-import Icon from 'Components/Icon';
-import { filterBuilderTypes, filterBuilderValueTypes, filterTypes, icons, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import translate from 'Utilities/String/translate';
-import { updateItem } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'history';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- pageSize: 20,
- sortKey: 'date',
- sortDirection: sortDirections.DESCENDING,
- items: [],
-
- columns: [
- {
- name: 'eventType',
- columnLabel: () => translate('EventType'),
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'artists.sortName',
- label: () => translate('Artist'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.title',
- label: () => translate('AlbumTitle'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'trackTitle',
- label: () => translate('TrackTitle'),
- isVisible: true
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- isVisible: true
- },
- {
- name: 'customFormats',
- label: () => translate('Formats'),
- isSortable: false,
- isVisible: true
- },
- {
- name: 'date',
- label: () => translate('Date'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'downloadClient',
- label: () => translate('DownloadClient'),
- isVisible: false
- },
- {
- name: 'indexer',
- label: () => translate('Indexer'),
- isVisible: false
- },
- {
- name: 'releaseGroup',
- label: () => translate('ReleaseGroup'),
- isVisible: false
- },
- {
- name: 'sourceTitle',
- label: () => translate('SourceTitle'),
- isVisible: false
- },
- {
- name: 'customFormatScore',
- columnLabel: () => translate('CustomFormatScore'),
- label: React.createElement(Icon, {
- name: icons.SCORE,
- title: () => translate('CustomFormatScore')
- }),
- isVisible: false
- },
- {
- name: 'details',
- columnLabel: () => translate('Details'),
- isVisible: true,
- isModifiable: false
- }
- ],
-
- selectedFilterKey: 'all',
-
- filters: [
- {
- key: 'all',
- label: () => translate('All'),
- filters: []
- },
- {
- key: 'grabbed',
- label: () => translate('Grabbed'),
- filters: [
- {
- key: 'eventType',
- value: '1',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'trackFileImported',
- label: () => translate('TrackImported'),
- filters: [
- {
- key: 'eventType',
- value: '3',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'failed',
- label: () => translate('DownloadFailed'),
- filters: [
- {
- key: 'eventType',
- value: '4',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'importFailed',
- label: () => translate('ImportCompleteFailed'),
- filters: [
- {
- key: 'eventType',
- value: '7',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'downloadImported',
- label: () => translate('DownloadImported'),
- filters: [
- {
- key: 'eventType',
- value: '8',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'deleted',
- label: () => translate('Deleted'),
- filters: [
- {
- key: 'eventType',
- value: '5',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'renamed',
- label: () => translate('Renamed'),
- filters: [
- {
- key: 'eventType',
- value: '6',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'retagged',
- label: () => translate('Retagged'),
- filters: [
- {
- key: 'eventType',
- value: '9',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'ignored',
- label: () => translate('Ignored'),
- filters: [
- {
- key: 'eventType',
- value: '7',
- type: filterTypes.EQUAL
- }
- ]
- }
- ],
-
- filterBuilderProps: [
- {
- name: 'eventType',
- label: () => translate('EventType'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.HISTORY_EVENT_TYPE
- },
- {
- name: 'artistIds',
- label: () => translate('Artist'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.ARTIST
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.QUALITY
- }
- ]
-
-};
-
-export const persistState = [
- 'history.pageSize',
- 'history.sortKey',
- 'history.sortDirection',
- 'history.selectedFilterKey',
- 'history.columns'
-];
-
-//
-// Actions Types
-
-export const FETCH_HISTORY = 'history/fetchHistory';
-export const GOTO_FIRST_HISTORY_PAGE = 'history/gotoHistoryFirstPage';
-export const GOTO_PREVIOUS_HISTORY_PAGE = 'history/gotoHistoryPreviousPage';
-export const GOTO_NEXT_HISTORY_PAGE = 'history/gotoHistoryNextPage';
-export const GOTO_LAST_HISTORY_PAGE = 'history/gotoHistoryLastPage';
-export const GOTO_HISTORY_PAGE = 'history/gotoHistoryPage';
-export const SET_HISTORY_SORT = 'history/setHistorySort';
-export const SET_HISTORY_FILTER = 'history/setHistoryFilter';
-export const SET_HISTORY_TABLE_OPTION = 'history/setHistoryTableOption';
-export const CLEAR_HISTORY = 'history/clearHistory';
-export const MARK_AS_FAILED = 'history/markAsFailed';
-
-//
-// Action Creators
-
-export const fetchHistory = createThunk(FETCH_HISTORY);
-export const gotoHistoryFirstPage = createThunk(GOTO_FIRST_HISTORY_PAGE);
-export const gotoHistoryPreviousPage = createThunk(GOTO_PREVIOUS_HISTORY_PAGE);
-export const gotoHistoryNextPage = createThunk(GOTO_NEXT_HISTORY_PAGE);
-export const gotoHistoryLastPage = createThunk(GOTO_LAST_HISTORY_PAGE);
-export const gotoHistoryPage = createThunk(GOTO_HISTORY_PAGE);
-export const setHistorySort = createThunk(SET_HISTORY_SORT);
-export const setHistoryFilter = createThunk(SET_HISTORY_FILTER);
-export const setHistoryTableOption = createAction(SET_HISTORY_TABLE_OPTION);
-export const clearHistory = createAction(CLEAR_HISTORY);
-export const markAsFailed = createThunk(MARK_AS_FAILED);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- ...createServerSideCollectionHandlers(
- section,
- '/history',
- fetchHistory,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_HISTORY,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_HISTORY_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_HISTORY_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_HISTORY_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_HISTORY_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_HISTORY_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_HISTORY_SORT,
- [serverSideCollectionHandlers.FILTER]: SET_HISTORY_FILTER
- }),
-
- [MARK_AS_FAILED]: function(getState, payload, dispatch) {
- const id = payload.id;
-
- dispatch(updateItem({
- section,
- id,
- isMarkingAsFailed: true
- }));
-
- const promise = createAjaxRequest({
- url: `/history/failed/${id}`,
- method: 'POST',
- dataType: 'json'
- }).request;
-
- promise.done(() => {
- dispatch(updateItem({
- section,
- id,
- isMarkingAsFailed: false,
- markAsFailedError: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({
- section,
- id,
- isMarkingAsFailed: false,
- markAsFailedError: xhr
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_HISTORY_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [CLEAR_HISTORY]: createClearReducer(section, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- })
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/index.js b/frontend/src/Store/Actions/index.js
deleted file mode 100644
index 85fda482b..000000000
--- a/frontend/src/Store/Actions/index.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import * as albums from './albumActions';
-import * as albumHistory from './albumHistoryActions';
-import * as albumSelection from './albumSelectionActions';
-import * as app from './appActions';
-import * as artist from './artistActions';
-import * as artistHistory from './artistHistoryActions';
-import * as artistIndex from './artistIndexActions';
-import * as blocklist from './blocklistActions';
-import * as calendar from './calendarActions';
-import * as captcha from './captchaActions';
-import * as commands from './commandActions';
-import * as customFilters from './customFilterActions';
-import * as history from './historyActions';
-import * as interactiveImportActions from './interactiveImportActions';
-import * as oAuth from './oAuthActions';
-import * as organizePreview from './organizePreviewActions';
-import * as parse from './parseActions';
-import * as paths from './pathActions';
-import * as providerOptions from './providerOptionActions';
-import * as queue from './queueActions';
-import * as releases from './releaseActions';
-import * as retagPreview from './retagPreviewActions';
-import * as search from './searchActions';
-import * as settings from './settingsActions';
-import * as system from './systemActions';
-import * as tags from './tagActions';
-import * as tracks from './trackActions';
-import * as trackFiles from './trackFileActions';
-import * as wanted from './wantedActions';
-
-export default [
- app,
- albums,
- albumHistory,
- albumSelection,
- artist,
- artistHistory,
- artistIndex,
- blocklist,
- captcha,
- calendar,
- commands,
- customFilters,
- trackFiles,
- history,
- interactiveImportActions,
- oAuth,
- organizePreview,
- retagPreview,
- parse,
- paths,
- providerOptions,
- queue,
- releases,
- search,
- settings,
- system,
- tags,
- tracks,
- wanted
-];
diff --git a/frontend/src/Store/Actions/interactiveImportActions.js b/frontend/src/Store/Actions/interactiveImportActions.js
deleted file mode 100644
index a250292c5..000000000
--- a/frontend/src/Store/Actions/interactiveImportActions.js
+++ /dev/null
@@ -1,325 +0,0 @@
-import moment from 'moment';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import naturalExpansion from 'Utilities/String/naturalExpansion';
-import { set, update, updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-
-//
-// Variables
-
-export const section = 'interactiveImport';
-
-const trackFilesSection = `${section}.trackFiles`;
-let abortCurrentFetchRequest = null;
-let abortCurrentRequest = null;
-let currentIds = [];
-
-const MAXIMUM_RECENT_FOLDERS = 10;
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- isSaving: false,
- error: null,
- items: [],
- pendingChanges: {},
- sortKey: 'path',
- sortDirection: sortDirections.ASCENDING,
- secondarySortKey: 'path',
- secondarySortDirection: sortDirections.ASCENDING,
- recentFolders: [],
- importMode: 'chooseImportMode',
- sortPredicates: {
- path: function(item, direction) {
- const path = item.path;
-
- return naturalExpansion(path.toLowerCase());
- },
-
- artist: function(item, direction) {
- const artist = item.artist;
-
- return artist ? artist.sortName : '';
- },
-
- quality: function(item, direction) {
- return item.qualityWeight || 0;
- }
- },
-
- trackFiles: {
- isFetching: false,
- isPopulated: false,
- error: null,
- sortKey: 'relativePath',
- sortDirection: sortDirections.ASCENDING,
- items: []
- }
-};
-
-export const persistState = [
- 'interactiveImport.sortKey',
- 'interactiveImport.sortDirection',
- 'interactiveImport.recentFolders',
- 'interactiveImport.importMode'
-];
-
-//
-// Actions Types
-
-export const FETCH_INTERACTIVE_IMPORT_ITEMS = 'interactiveImport/fetchInteractiveImportItems';
-export const SAVE_INTERACTIVE_IMPORT_ITEM = 'interactiveImport/saveInteractiveImportItem';
-export const SET_INTERACTIVE_IMPORT_SORT = 'interactiveImport/setInteractiveImportSort';
-export const UPDATE_INTERACTIVE_IMPORT_ITEM = 'interactiveImport/updateInteractiveImportItem';
-export const UPDATE_INTERACTIVE_IMPORT_ITEMS = 'interactiveImport/updateInteractiveImportItems';
-export const CLEAR_INTERACTIVE_IMPORT = 'interactiveImport/clearInteractiveImport';
-export const ADD_RECENT_FOLDER = 'interactiveImport/addRecentFolder';
-export const REMOVE_RECENT_FOLDER = 'interactiveImport/removeRecentFolder';
-export const SET_INTERACTIVE_IMPORT_MODE = 'interactiveImport/setInteractiveImportMode';
-
-export const FETCH_INTERACTIVE_IMPORT_TRACKFILES = 'interactiveImport/fetchInteractiveImportTrackFiles';
-export const CLEAR_INTERACTIVE_IMPORT_TRACKFILES = 'interactiveImport/clearInteractiveImportTrackFiles';
-
-//
-// Action Creators
-
-export const fetchInteractiveImportItems = createThunk(FETCH_INTERACTIVE_IMPORT_ITEMS);
-export const setInteractiveImportSort = createAction(SET_INTERACTIVE_IMPORT_SORT);
-export const updateInteractiveImportItem = createAction(UPDATE_INTERACTIVE_IMPORT_ITEM);
-export const updateInteractiveImportItems = createAction(UPDATE_INTERACTIVE_IMPORT_ITEMS);
-export const saveInteractiveImportItem = createThunk(SAVE_INTERACTIVE_IMPORT_ITEM);
-export const clearInteractiveImport = createAction(CLEAR_INTERACTIVE_IMPORT);
-export const addRecentFolder = createAction(ADD_RECENT_FOLDER);
-export const removeRecentFolder = createAction(REMOVE_RECENT_FOLDER);
-export const setInteractiveImportMode = createAction(SET_INTERACTIVE_IMPORT_MODE);
-
-export const fetchInteractiveImportTrackFiles = createThunk(FETCH_INTERACTIVE_IMPORT_TRACKFILES);
-export const clearInteractiveImportTrackFiles = createAction(CLEAR_INTERACTIVE_IMPORT_TRACKFILES);
-
-//
-// Action Handlers
-export const actionHandlers = handleThunks({
- [FETCH_INTERACTIVE_IMPORT_ITEMS]: function(getState, payload, dispatch) {
- if (abortCurrentFetchRequest) {
- abortCurrentFetchRequest();
- abortCurrentFetchRequest = null;
- }
-
- if (!payload.downloadId && !payload.folder) {
- dispatch(set({ section, error: { message: '`downloadId` or `folder` is required.' } }));
- return;
- }
-
- dispatch(set({ section, isFetching: true }));
-
- const { request, abortRequest } = createAjaxRequest({
- url: '/manualimport',
- data: payload
- });
-
- abortCurrentFetchRequest = abortRequest;
-
- request.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- request.fail((xhr) => {
- if (xhr.aborted) {
- return;
- }
-
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- },
-
- [SAVE_INTERACTIVE_IMPORT_ITEM]: function(getState, payload, dispatch) {
- if (abortCurrentRequest) {
- abortCurrentRequest();
- }
-
- dispatch(batchActions([
- ...currentIds.map((id) => updateItem({
- section,
- id,
- isReprocessing: false,
- updateOnly: true
- })),
- ...payload.ids.map((id) => updateItem({
- section,
- id,
- isReprocessing: true,
- updateOnly: true
- }))
- ]));
-
- const items = getState()[section].items;
-
- const requestPayload = payload.ids.map((id) => {
- const item = items.find((i) => i.id === id);
-
- return {
- id,
- path: item.path,
- artistId: item.artist ? item.artist.id : undefined,
- albumId: item.album ? item.album.id : undefined,
- albumReleaseId: item.albumReleaseId ? item.albumReleaseId : undefined,
- trackIds: (item.tracks || []).map((e) => e.id),
- quality: item.quality,
- releaseGroup: item.releaseGroup,
- indexerFlags: item.indexerFlags,
- downloadId: item.downloadId,
- additionalFile: item.additionalFile,
- replaceExistingFiles: item.replaceExistingFiles,
- disableReleaseSwitching: item.disableReleaseSwitching
- };
- });
-
- const { request, abortRequest } = createAjaxRequest({
- method: 'POST',
- url: '/manualimport',
- contentType: 'application/json',
- data: JSON.stringify(requestPayload)
- });
-
- abortCurrentRequest = abortRequest;
- currentIds = payload.ids;
-
- request.done((data) => {
- dispatch(batchActions(
- data.map((item) => updateItem({
- section,
- ...item,
- isReprocessing: false,
- updateOnly: true
- }))
- ));
- });
-
- request.fail((xhr) => {
- if (xhr.aborted) {
- return;
- }
-
- dispatch(batchActions(
- payload.ids.map((id) => updateItem({
- section,
- id,
- isReprocessing: false,
- updateOnly: true
- }))
- ));
- });
- },
-
- [FETCH_INTERACTIVE_IMPORT_TRACKFILES]: createFetchHandler(trackFilesSection, '/trackFile')
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [UPDATE_INTERACTIVE_IMPORT_ITEM]: (state, { payload }) => {
- const id = payload.id;
- const newState = Object.assign({}, state);
- const items = newState.items;
- const index = items.findIndex((item) => item.id === id);
- const item = Object.assign({}, items[index], payload);
-
- newState.items = [...items];
- newState.items.splice(index, 1, item);
-
- return newState;
- },
-
- [UPDATE_INTERACTIVE_IMPORT_ITEMS]: (state, { payload }) => {
- const ids = payload.ids;
- const newState = Object.assign({}, state);
- const items = [...newState.items];
-
- ids.forEach((id) => {
- const index = items.findIndex((item) => item.id === id);
- const item = Object.assign({}, items[index], payload);
-
- items.splice(index, 1, item);
- });
-
- newState.items = items;
-
- return newState;
- },
-
- [ADD_RECENT_FOLDER]: function(state, { payload }) {
- const folder = payload.folder;
- const recentFolder = { folder, lastUsed: moment().toISOString() };
- const recentFolders = [...state.recentFolders];
- const index = recentFolders.findIndex((r) => r.folder === folder);
-
- if (index > -1) {
- recentFolders.splice(index, 1);
- }
-
- recentFolders.push(recentFolder);
-
- const sliceIndex = Math.max(recentFolders.length - MAXIMUM_RECENT_FOLDERS, 0);
-
- return Object.assign({}, state, { recentFolders: recentFolders.slice(sliceIndex) });
- },
-
- [REMOVE_RECENT_FOLDER]: function(state, { payload }) {
- const folder = payload.folder;
- const recentFolders = [...state.recentFolders];
- const index = recentFolders.findIndex((r) => r.folder === folder);
-
- recentFolders.splice(index, 1);
-
- return Object.assign({}, state, { recentFolders });
- },
-
- [CLEAR_INTERACTIVE_IMPORT]: function(state) {
- const newState = {
- ...defaultState,
- recentFolders: state.recentFolders,
- importMode: state.importMode
- };
-
- return newState;
- },
-
- [SET_INTERACTIVE_IMPORT_SORT]: createSetClientSideCollectionSortReducer(section),
-
- [SET_INTERACTIVE_IMPORT_MODE]: function(state, { payload }) {
- return Object.assign({}, state, { importMode: payload.importMode });
- },
-
- [CLEAR_INTERACTIVE_IMPORT_TRACKFILES]: (state) => {
- return updateSectionState(state, trackFilesSection, {
- ...defaultState.trackFiles
- });
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/oAuthActions.js b/frontend/src/Store/Actions/oAuthActions.js
deleted file mode 100644
index 8e3ad3636..000000000
--- a/frontend/src/Store/Actions/oAuthActions.js
+++ /dev/null
@@ -1,206 +0,0 @@
-import $ from 'jquery';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { set } from 'Store/Actions/baseActions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import requestAction from 'Utilities/requestAction';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'oAuth';
-const callbackUrl = `${window.location.origin}${window.Lidarr.urlBase}/oauth.html`;
-
-//
-// State
-
-export const defaultState = {
- authorizing: false,
- result: null,
- error: null
-};
-
-//
-// Actions Types
-
-export const START_OAUTH = 'oAuth/startOAuth';
-export const SET_OAUTH_VALUE = 'oAuth/setOAuthValue';
-export const RESET_OAUTH = 'oAuth/resetOAuth';
-
-//
-// Action Creators
-
-export const startOAuth = createThunk(START_OAUTH);
-export const setOAuthValue = createAction(SET_OAUTH_VALUE);
-export const resetOAuth = createAction(RESET_OAUTH);
-
-//
-// Helpers
-
-function showOAuthWindow(url, payload) {
- const deferred = $.Deferred();
- const selfWindow = window;
-
- const newWindow = window.open(url);
-
- if (
- !newWindow ||
- newWindow.closed ||
- typeof newWindow.closed == 'undefined'
- ) {
-
- // A fake validation error to mimic a 400 response from the API.
- const error = {
- status: 400,
- responseJSON: [
- {
- propertyName: payload.name,
- errorMessage: 'Pop-ups are being blocked by your browser'
- }
- ]
- };
-
- return deferred.reject(error).promise();
- }
-
- selfWindow.onCompleteOauth = function(query, onComplete) {
- delete selfWindow.onCompleteOauth;
-
- const queryParams = {};
- const splitQuery = query.substring(1).split('&');
-
- splitQuery.forEach((param) => {
- if (param) {
- const paramSplit = param.split('=');
-
- queryParams[paramSplit[0]] = paramSplit[1];
- }
- });
-
- onComplete();
- deferred.resolve(queryParams);
- };
-
- return deferred.promise();
-}
-
-function executeIntermediateRequest(payload, ajaxOptions) {
- return createAjaxRequest(ajaxOptions).request.then((data) => {
- return requestAction({
- action: 'continueOAuth',
- queryParams: {
- ...data,
- callbackUrl
- },
- ...payload
- });
- });
-}
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [START_OAUTH]: function(getState, payload, dispatch) {
- const {
- name,
- section: actionSection,
- ...otherPayload
- } = payload;
-
- const actionPayload = {
- action: 'startOAuth',
- queryParams: { callbackUrl },
- ...otherPayload
- };
-
- dispatch(setOAuthValue({
- authorizing: true
- }));
-
- let startResponse = {};
-
- const promise = requestAction(actionPayload)
- .then((response) => {
- startResponse = response;
-
- if (response.oauthUrl) {
- return showOAuthWindow(response.oauthUrl, payload);
- }
-
- return executeIntermediateRequest(otherPayload, response).then((intermediateResponse) => {
- startResponse = intermediateResponse;
-
- return showOAuthWindow(intermediateResponse.oauthUrl, payload);
- });
- })
- .then((queryParams) => {
- return requestAction({
- action: 'getOAuthToken',
- queryParams: {
- ...startResponse,
- ...queryParams
- },
- ...otherPayload
- });
- })
- .then((response) => {
- dispatch(setOAuthValue({
- authorizing: false,
- result: response,
- error: null
- }));
- });
-
- promise.done(() => {
- // Clear any previously set save error.
- dispatch(set({
- section: actionSection,
- saveError: null
- }));
- });
-
- promise.fail((xhr) => {
- const actions = [
- setOAuthValue({
- authorizing: false,
- result: null,
- error: xhr
- })
- ];
-
- if (xhr.status === 400) {
- // Set a save error so the UI can display validation errors to the user.
- actions.splice(0, 0, set({
- section: actionSection,
- saveError: xhr
- }));
- }
-
- dispatch(batchActions(actions));
- });
- }
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_OAUTH_VALUE]: function(state, { payload }) {
- const newState = Object.assign(getSectionState(state, section), payload);
-
- return updateSectionState(state, section, newState);
- },
-
- [RESET_OAUTH]: function(state) {
- return updateSectionState(state, section, defaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/organizePreviewActions.js b/frontend/src/Store/Actions/organizePreviewActions.js
deleted file mode 100644
index 78f943f32..000000000
--- a/frontend/src/Store/Actions/organizePreviewActions.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'organizePreview';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
-};
-
-//
-// Actions Types
-
-export const FETCH_ORGANIZE_PREVIEW = 'organizePreview/fetchOrganizePreview';
-export const CLEAR_ORGANIZE_PREVIEW = 'organizePreview/clearOrganizePreview';
-
-//
-// Action Creators
-
-export const fetchOrganizePreview = createThunk(FETCH_ORGANIZE_PREVIEW);
-export const clearOrganizePreview = createAction(CLEAR_ORGANIZE_PREVIEW);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_ORGANIZE_PREVIEW]: createFetchHandler('organizePreview', '/rename')
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_ORGANIZE_PREVIEW]: (state) => {
- return Object.assign({}, state, defaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/parseActions.ts b/frontend/src/Store/Actions/parseActions.ts
deleted file mode 100644
index d4b6e9bcb..000000000
--- a/frontend/src/Store/Actions/parseActions.ts
+++ /dev/null
@@ -1,111 +0,0 @@
-import { Dispatch } from 'redux';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import AppState from 'App/State/AppState';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set, update } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-
-interface FetchPayload {
- title: string;
-}
-
-//
-// Variables
-
-export const section = 'parse';
-let parseTimeout: number | null = null;
-let abortCurrentRequest: (() => void) | null = null;
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- item: {},
-};
-
-//
-// Actions Types
-
-export const FETCH = 'parse/fetch';
-export const CLEAR = 'parse/clear';
-
-//
-// Action Creators
-
-export const fetch = createThunk(FETCH);
-export const clear = createAction(CLEAR);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH]: function (
- _getState: () => AppState,
- payload: FetchPayload,
- dispatch: Dispatch
- ) {
- if (parseTimeout) {
- clearTimeout(parseTimeout);
- }
-
- parseTimeout = window.setTimeout(async () => {
- dispatch(set({ section, isFetching: true }));
-
- if (abortCurrentRequest) {
- abortCurrentRequest();
- }
-
- const { request, abortRequest } = createAjaxRequest({
- url: '/parse',
- data: {
- title: payload.title,
- },
- });
-
- try {
- const data = await request;
-
- dispatch(
- batchActions([
- update({ section, data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null,
- }),
- ])
- );
- } catch (error) {
- dispatch(
- set({
- section,
- isAdding: false,
- isAdded: false,
- addError: error,
- })
- );
- }
-
- abortCurrentRequest = abortRequest;
- }, 300);
- },
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions(
- {
- [CLEAR]: createClearReducer(section, defaultState),
- },
- defaultState,
- section
-);
diff --git a/frontend/src/Store/Actions/pathActions.js b/frontend/src/Store/Actions/pathActions.js
deleted file mode 100644
index 1cb7a15a2..000000000
--- a/frontend/src/Store/Actions/pathActions.js
+++ /dev/null
@@ -1,112 +0,0 @@
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { set } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'paths';
-
-//
-// State
-
-export const defaultState = {
- currentPath: '',
- isPopulated: false,
- isFetching: false,
- error: null,
- directories: [],
- files: [],
- parent: null
-};
-
-//
-// Actions Types
-
-export const FETCH_PATHS = 'paths/fetchPaths';
-export const UPDATE_PATHS = 'paths/updatePaths';
-export const CLEAR_PATHS = 'paths/clearPaths';
-
-//
-// Action Creators
-
-export const fetchPaths = createThunk(FETCH_PATHS);
-export const updatePaths = createAction(UPDATE_PATHS);
-export const clearPaths = createAction(CLEAR_PATHS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_PATHS]: function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- const {
- path,
- allowFoldersWithoutTrailingSlashes = false,
- includeFiles = false
- } = payload;
-
- const promise = createAjaxRequest({
- url: '/filesystem',
- data: {
- path,
- allowFoldersWithoutTrailingSlashes,
- includeFiles
- }
- }).request;
-
- promise.done((data) => {
- dispatch(updatePaths({ path, ...data }));
-
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- });
- }
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [UPDATE_PATHS]: (state, { payload }) => {
- const newState = Object.assign({}, state);
-
- newState.currentPath = payload.path;
- newState.directories = payload.directories;
- newState.files = payload.files;
- newState.parent = payload.parent;
-
- return newState;
- },
-
- [CLEAR_PATHS]: (state, { payload }) => {
- const newState = Object.assign({}, state);
-
- newState.path = '';
- newState.directories = [];
- newState.files = [];
- newState.parent = '';
-
- return newState;
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/providerOptionActions.js b/frontend/src/Store/Actions/providerOptionActions.js
deleted file mode 100644
index 4dc38a98f..000000000
--- a/frontend/src/Store/Actions/providerOptionActions.js
+++ /dev/null
@@ -1,111 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import requestAction from 'Utilities/requestAction';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { set } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'providerOptions';
-
-const lastActions = {};
-let lastActionId = 0;
-
-//
-// State
-
-export const defaultState = {
- items: [],
- isFetching: false,
- isPopulated: false,
- error: false
-};
-
-//
-// Actions Types
-
-export const FETCH_OPTIONS = 'providers/fetchOptions';
-export const CLEAR_OPTIONS = 'providers/clearOptions';
-
-//
-// Action Creators
-
-export const fetchOptions = createThunk(FETCH_OPTIONS);
-export const clearOptions = createAction(CLEAR_OPTIONS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_OPTIONS]: function(getState, payload, dispatch) {
- const subsection = `${section}.${payload.section}`;
-
- if (lastActions[payload.section] && _.isEqual(payload, lastActions[payload.section].payload)) {
- return;
- }
-
- const actionId = ++lastActionId;
-
- lastActions[payload.section] = {
- actionId,
- payload
- };
-
- dispatch(set({
- section: subsection,
- isFetching: true
- }));
-
- const promise = requestAction(payload);
-
- promise.done((data) => {
- if (lastActions[payload.section]) {
- if (lastActions[payload.section].actionId === actionId) {
- lastActions[payload.section] = null;
- }
-
- dispatch(set({
- section: subsection,
- isFetching: false,
- isPopulated: true,
- error: null,
- items: data.options || []
- }));
- }
- });
-
- promise.fail((xhr) => {
- if (lastActions[payload.section]) {
- if (lastActions[payload.section].actionId === actionId) {
- lastActions[payload.section] = null;
- }
-
- dispatch(set({
- section: subsection,
- isFetching: false,
- isPopulated: false,
- error: xhr
- }));
- }
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_OPTIONS]: function(state, { payload }) {
- const subsection = `${section}.${payload.section}`;
-
- lastActions[payload.section] = null;
-
- return updateSectionState(state, subsection, defaultState);
- }
-
-}, {}, section);
diff --git a/frontend/src/Store/Actions/queueActions.js b/frontend/src/Store/Actions/queueActions.js
deleted file mode 100644
index 4bf200a5c..000000000
--- a/frontend/src/Store/Actions/queueActions.js
+++ /dev/null
@@ -1,517 +0,0 @@
-import _ from 'lodash';
-import React from 'react';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import Icon from 'Components/Icon';
-import { filterBuilderTypes, filterBuilderValueTypes, icons, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import translate from 'Utilities/String/translate';
-import { set, updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'queue';
-const status = `${section}.status`;
-const details = `${section}.details`;
-const paged = `${section}.paged`;
-
-//
-// State
-
-export const defaultState = {
- options: {
- includeUnknownArtistItems: true
- },
-
- status: {
- isFetching: false,
- isPopulated: false,
- error: null,
- item: {}
- },
-
- details: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- params: {}
- },
-
- paged: {
- isFetching: false,
- isPopulated: false,
- pageSize: 20,
- sortKey: 'timeleft',
- sortDirection: sortDirections.ASCENDING,
- error: null,
- items: [],
- isGrabbing: false,
- isRemoving: false,
-
- columns: [
- {
- name: 'status',
- columnLabel: () => translate('Status'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'artists.sortName',
- label: () => translate('Artist'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.title',
- label: () => translate('AlbumTitle'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.releaseDate',
- label: () => translate('AlbumReleaseDate'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'customFormats',
- label: 'Formats',
- isSortable: false,
- isVisible: true
- },
- {
- name: 'customFormatScore',
- columnLabel: () => translate('CustomFormatScore'),
- label: React.createElement(Icon, {
- name: icons.SCORE,
- title: () => translate('CustomFormatScore')
- }),
- isVisible: false
- },
- {
- name: 'protocol',
- label: () => translate('Protocol'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'indexer',
- label: () => translate('Indexer'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'downloadClient',
- label: () => translate('DownloadClient'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'title',
- label: () => translate('ReleaseTitle'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'size',
- label: () => translate('Size'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'outputPath',
- label: () => translate('OutputPath'),
- isSortable: false,
- isVisible: false
- },
- {
- name: 'estimatedCompletionTime',
- label: () => translate('TimeLeft'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'added',
- label: () => translate('Added'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'progress',
- label: () => translate('Progress'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ],
-
- selectedFilterKey: 'all',
-
- filters: [
- {
- key: 'all',
- label: 'All',
- filters: []
- }
- ],
-
- filterBuilderProps: [
- {
- name: 'artistIds',
- label: () => translate('Artist'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.ARTIST
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.QUALITY
- },
- {
- name: 'protocol',
- label: () => translate('Protocol'),
- type: filterBuilderTypes.EQUAL,
- valueType: filterBuilderValueTypes.PROTOCOL
- }
- ]
- }
-};
-
-export const persistState = [
- 'queue.options',
- 'queue.paged.pageSize',
- 'queue.paged.sortKey',
- 'queue.paged.sortDirection',
- 'queue.paged.columns',
- 'queue.paged.selectedFilterKey'
-];
-
-//
-// Helpers
-
-function fetchDataAugmenter(getState, payload, data) {
- data.includeUnknownArtistItems = getState().queue.options.includeUnknownArtistItems;
-}
-
-//
-// Actions Types
-
-export const FETCH_QUEUE_STATUS = 'queue/fetchQueueStatus';
-
-export const FETCH_QUEUE_DETAILS = 'queue/fetchQueueDetails';
-export const CLEAR_QUEUE_DETAILS = 'queue/clearQueueDetails';
-
-export const FETCH_QUEUE = 'queue/fetchQueue';
-export const GOTO_FIRST_QUEUE_PAGE = 'queue/gotoQueueFirstPage';
-export const GOTO_PREVIOUS_QUEUE_PAGE = 'queue/gotoQueuePreviousPage';
-export const GOTO_NEXT_QUEUE_PAGE = 'queue/gotoQueueNextPage';
-export const GOTO_LAST_QUEUE_PAGE = 'queue/gotoQueueLastPage';
-export const GOTO_QUEUE_PAGE = 'queue/gotoQueuePage';
-export const SET_QUEUE_SORT = 'queue/setQueueSort';
-export const SET_QUEUE_FILTER = 'queue/setQueueFilter';
-export const SET_QUEUE_TABLE_OPTION = 'queue/setQueueTableOption';
-export const SET_QUEUE_OPTION = 'queue/setQueueOption';
-export const CLEAR_QUEUE = 'queue/clearQueue';
-
-export const GRAB_QUEUE_ITEM = 'queue/grabQueueItem';
-export const GRAB_QUEUE_ITEMS = 'queue/grabQueueItems';
-export const REMOVE_QUEUE_ITEM = 'queue/removeQueueItem';
-export const REMOVE_QUEUE_ITEMS = 'queue/removeQueueItems';
-
-//
-// Action Creators
-
-export const fetchQueueStatus = createThunk(FETCH_QUEUE_STATUS);
-
-export const fetchQueueDetails = createThunk(FETCH_QUEUE_DETAILS);
-export const clearQueueDetails = createAction(CLEAR_QUEUE_DETAILS);
-
-export const fetchQueue = createThunk(FETCH_QUEUE);
-export const gotoQueueFirstPage = createThunk(GOTO_FIRST_QUEUE_PAGE);
-export const gotoQueuePreviousPage = createThunk(GOTO_PREVIOUS_QUEUE_PAGE);
-export const gotoQueueNextPage = createThunk(GOTO_NEXT_QUEUE_PAGE);
-export const gotoQueueLastPage = createThunk(GOTO_LAST_QUEUE_PAGE);
-export const gotoQueuePage = createThunk(GOTO_QUEUE_PAGE);
-export const setQueueSort = createThunk(SET_QUEUE_SORT);
-export const setQueueFilter = createThunk(SET_QUEUE_FILTER);
-export const setQueueTableOption = createAction(SET_QUEUE_TABLE_OPTION);
-export const setQueueOption = createAction(SET_QUEUE_OPTION);
-export const clearQueue = createAction(CLEAR_QUEUE);
-
-export const grabQueueItem = createThunk(GRAB_QUEUE_ITEM);
-export const grabQueueItems = createThunk(GRAB_QUEUE_ITEMS);
-export const removeQueueItem = createThunk(REMOVE_QUEUE_ITEM);
-export const removeQueueItems = createThunk(REMOVE_QUEUE_ITEMS);
-
-//
-// Helpers
-
-const fetchQueueDetailsHelper = createFetchHandler(details, '/queue/details');
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_QUEUE_STATUS]: createFetchHandler(status, '/queue/status'),
-
- [FETCH_QUEUE_DETAILS]: function(getState, payload, dispatch) {
- let params = payload;
-
- // If the payload params are empty try to get params from state.
-
- if (params && !_.isEmpty(params)) {
- dispatch(set({ section: details, params }));
- } else {
- params = getState().queue.details.params;
- }
-
- // Ensure there are params before trying to fetch the queue
- // so we don't make a bad request to the server.
-
- if (params && !_.isEmpty(params)) {
- fetchQueueDetailsHelper(getState, params, dispatch);
- }
- },
-
- ...createServerSideCollectionHandlers(
- paged,
- '/queue',
- fetchQueue,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_QUEUE,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_QUEUE_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_QUEUE_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_QUEUE_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_QUEUE_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_QUEUE_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_QUEUE_SORT,
- [serverSideCollectionHandlers.FILTER]: SET_QUEUE_FILTER
- },
- fetchDataAugmenter
- ),
-
- [GRAB_QUEUE_ITEM]: function(getState, payload, dispatch) {
- const id = payload.id;
-
- dispatch(updateItem({ section: paged, id, isGrabbing: true }));
-
- const promise = createAjaxRequest({
- url: `/queue/grab/${id}`,
- method: 'POST'
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- fetchQueue(),
-
- set({
- section: paged,
- isGrabbing: false,
- grabError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({
- section: paged,
- id,
- isGrabbing: false,
- grabError: xhr
- }));
- });
- },
-
- [GRAB_QUEUE_ITEMS]: function(getState, payload, dispatch) {
- const ids = payload.ids;
-
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section: paged,
- id,
- isGrabbing: true
- });
- }),
-
- set({
- section: paged,
- isGrabbing: true
- })
- ]));
-
- const promise = createAjaxRequest({
- url: '/queue/grab/bulk',
- method: 'POST',
- dataType: 'json',
- data: JSON.stringify(payload)
- }).request;
-
- promise.done((data) => {
- dispatch(fetchQueue());
-
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section: paged,
- id,
- isGrabbing: false,
- grabError: null
- });
- }),
-
- set({
- section: paged,
- isGrabbing: false,
- grabError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section: paged,
- id,
- isGrabbing: false,
- grabError: null
- });
- }),
-
- set({ section: paged, isGrabbing: false })
- ]));
- });
- },
-
- [REMOVE_QUEUE_ITEM]: function(getState, payload, dispatch) {
- const {
- id,
- removeFromClient,
- blocklist,
- skipRedownload,
- changeCategory
- } = payload;
-
- dispatch(updateItem({ section: paged, id, isRemoving: true }));
-
- const promise = createAjaxRequest({
- url: `/queue/${id}?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}&changeCategory=${changeCategory}`,
- method: 'DELETE'
- }).request;
-
- promise.done((data) => {
- dispatch(fetchQueue());
- });
-
- promise.fail((xhr) => {
- dispatch(updateItem({ section: paged, id, isRemoving: false }));
- });
- },
-
- [REMOVE_QUEUE_ITEMS]: function(getState, payload, dispatch) {
- const {
- ids,
- removeFromClient,
- blocklist,
- skipRedownload,
- changeCategory
- } = payload;
-
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section: paged,
- id,
- isRemoving: true
- });
- }),
-
- set({ section: paged, isRemoving: true })
- ]));
-
- const promise = createAjaxRequest({
- url: `/queue/bulk?removeFromClient=${removeFromClient}&blocklist=${blocklist}&skipRedownload=${skipRedownload}&changeCategory=${changeCategory}`,
- method: 'DELETE',
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify({ ids })
- }).request;
-
- promise.done((data) => {
- // Don't use batchActions with thunks
- dispatch(fetchQueue());
-
- dispatch(set({ section: paged, isRemoving: false }));
- });
-
- promise.fail((xhr) => {
- dispatch(batchActions([
- ...ids.map((id) => {
- return updateItem({
- section: paged,
- id,
- isRemoving: false
- });
- }),
-
- set({ section: paged, isRemoving: false })
- ]));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_QUEUE_DETAILS]: createClearReducer(details, defaultState.details),
-
- [SET_QUEUE_TABLE_OPTION]: createSetTableOptionReducer(paged),
-
- [SET_QUEUE_OPTION]: function(state, { payload }) {
- const queueOptions = state.options;
-
- return {
- ...state,
- options: {
- ...queueOptions,
- ...payload
- }
- };
- },
-
- [CLEAR_QUEUE]: createClearReducer(paged, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- })
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/releaseActions.js b/frontend/src/Store/Actions/releaseActions.js
deleted file mode 100644
index c4955c915..000000000
--- a/frontend/src/Store/Actions/releaseActions.js
+++ /dev/null
@@ -1,346 +0,0 @@
-import { createAction } from 'redux-actions';
-import { filterBuilderTypes, filterBuilderValueTypes, filterTypes, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import translate from 'Utilities/String/translate';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionFilterReducer from './Creators/Reducers/createSetClientSideCollectionFilterReducer';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-
-//
-// Variables
-
-export const section = 'releases';
-export const albumSection = 'releases.album';
-export const artistSection = 'releases.artist';
-
-let abortCurrentRequest = null;
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- sortKey: 'releaseWeight',
- sortDirection: sortDirections.ASCENDING,
- sortPredicates: {
- age: function(item, direction) {
- return item.ageMinutes;
- },
- peers: function(item, direction) {
- const seeders = item.seeders || 0;
- const leechers = item.leechers || 0;
-
- return seeders * 1000000 + leechers;
- },
- rejections: function(item, direction) {
- const rejections = item.rejections;
- const releaseWeight = item.releaseWeight;
-
- if (rejections.length !== 0) {
- return releaseWeight + 1000000;
- }
-
- return releaseWeight;
- }
- },
-
- filters: [
- {
- key: 'all',
- label: () => translate('All'),
- filters: []
- },
- {
- key: 'discography-pack',
- label: () => translate('Discography'),
- filters: [
- {
- key: 'discography',
- value: true,
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'not-discography-pack',
- label: () => translate('NotDiscography'),
- filters: [
- {
- key: 'discography',
- value: false,
- type: filterTypes.EQUAL
- }
- ]
- }
- ],
-
- filterPredicates: {
- quality: function(item, value, type) {
- const qualityId = item.quality.quality.id;
-
- if (type === filterTypes.EQUAL) {
- return qualityId === value;
- }
-
- if (type === filterTypes.NOT_EQUAL) {
- return qualityId !== value;
- }
-
- // Default to false
- return false;
- },
-
- rejectionCount: function(item, value, type) {
- const rejectionCount = item.rejections.length;
-
- switch (type) {
- case filterTypes.EQUAL:
- return rejectionCount === value;
-
- case filterTypes.GREATER_THAN:
- return rejectionCount > value;
-
- case filterTypes.GREATER_THAN_OR_EQUAL:
- return rejectionCount >= value;
-
- case filterTypes.LESS_THAN:
- return rejectionCount < value;
-
- case filterTypes.LESS_THAN_OR_EQUAL:
- return rejectionCount <= value;
-
- case filterTypes.NOT_EQUAL:
- return rejectionCount !== value;
-
- default:
- return false;
- }
- },
-
- peers: function(item, value, type) {
- const seeders = item.seeders || 0;
- const leechers = item.leechers || 0;
- const peers = seeders + leechers;
-
- switch (type) {
- case filterTypes.EQUAL:
- return peers === value;
-
- case filterTypes.GREATER_THAN:
- return peers > value;
-
- case filterTypes.GREATER_THAN_OR_EQUAL:
- return peers >= value;
-
- case filterTypes.LESS_THAN:
- return peers < value;
-
- case filterTypes.LESS_THAN_OR_EQUAL:
- return peers <= value;
-
- case filterTypes.NOT_EQUAL:
- return peers !== value;
-
- default:
- return false;
- }
- }
- },
-
- filterBuilderProps: [
- {
- name: 'title',
- label: () => translate('Title'),
- type: filterBuilderTypes.STRING
- },
- {
- name: 'age',
- label: () => translate('Age'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'protocol',
- label: () => translate('Protocol'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.PROTOCOL
- },
- {
- name: 'indexerId',
- label: () => translate('Indexer'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.INDEXER
- },
- {
- name: 'size',
- label: () => translate('Size'),
- type: filterBuilderTypes.NUMBER,
- valueType: filterBuilderValueTypes.BYTES
- },
- {
- name: 'seeders',
- label: () => translate('Seeders'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'leechers',
- label: () => translate('Peers'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- type: filterBuilderTypes.EXACT,
- valueType: filterBuilderValueTypes.QUALITY
- },
- {
- name: 'customFormatScore',
- label: () => translate('CustomFormatScore'),
- type: filterBuilderTypes.NUMBER
- },
- {
- name: 'rejectionCount',
- label: () => translate('RejectionCount'),
- type: filterBuilderTypes.NUMBER
- }
- ],
-
- album: {
- selectedFilterKey: 'all'
- },
-
- artist: {
- selectedFilterKey: 'discography-pack'
- }
-};
-
-export const persistState = [
- 'releases.album.selectedFilterKey',
- 'releases.album.customFilters',
- 'releases.artist.selectedFilterKey',
- 'releases.artist.customFilters'
-];
-
-//
-// Actions Types
-
-export const FETCH_RELEASES = 'releases/fetchReleases';
-export const CANCEL_FETCH_RELEASES = 'releases/cancelFetchReleases';
-export const SET_RELEASES_SORT = 'releases/setReleasesSort';
-export const CLEAR_RELEASES = 'releases/clearReleases';
-export const GRAB_RELEASE = 'releases/grabRelease';
-export const UPDATE_RELEASE = 'releases/updateRelease';
-export const SET_ALBUM_RELEASES_FILTER = 'releases/setAlbumReleasesFilter';
-export const SET_ARTIST_RELEASES_FILTER = 'releases/setArtistReleasesFilter';
-
-//
-// Action Creators
-
-export const fetchReleases = createThunk(FETCH_RELEASES);
-export const cancelFetchReleases = createThunk(CANCEL_FETCH_RELEASES);
-export const setReleasesSort = createAction(SET_RELEASES_SORT);
-export const clearReleases = createAction(CLEAR_RELEASES);
-export const grabRelease = createThunk(GRAB_RELEASE);
-export const updateRelease = createAction(UPDATE_RELEASE);
-export const setAlbumReleasesFilter = createAction(SET_ALBUM_RELEASES_FILTER);
-export const setArtistReleasesFilter = createAction(SET_ARTIST_RELEASES_FILTER);
-
-//
-// Helpers
-
-const fetchReleasesHelper = createFetchHandler(section, '/release');
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_RELEASES]: function(getState, payload, dispatch) {
- const abortRequest = fetchReleasesHelper(getState, payload, dispatch);
-
- abortCurrentRequest = abortRequest;
- },
-
- [CANCEL_FETCH_RELEASES]: function(getState, payload, dispatch) {
- if (abortCurrentRequest) {
- abortCurrentRequest = abortCurrentRequest();
- }
- },
-
- [GRAB_RELEASE]: function(getState, payload, dispatch) {
- const guid = payload.guid;
-
- dispatch(updateRelease({ guid, isGrabbing: true }));
-
- const promise = createAjaxRequest({
- url: '/release',
- method: 'POST',
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(payload)
- }).request;
-
- promise.done((data) => {
- dispatch(updateRelease({
- guid,
- isGrabbing: false,
- isGrabbed: true,
- grabError: null
- }));
- });
-
- promise.fail((xhr) => {
- const grabError = xhr.responseJSON && xhr.responseJSON.message || 'Failed to add to download queue';
-
- dispatch(updateRelease({
- guid,
- isGrabbing: false,
- isGrabbed: false,
- grabError
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_RELEASES]: (state) => {
- const {
- album,
- artist,
- ...otherDefaultState
- } = defaultState;
-
- return Object.assign({}, state, otherDefaultState);
- },
-
- [UPDATE_RELEASE]: (state, { payload }) => {
- const guid = payload.guid;
- const newState = Object.assign({}, state);
- const items = newState.items;
- const index = items.findIndex((item) => item.guid === guid);
-
- // Don't try to update if there isnt a matching item (the user closed the modal)
-
- if (index >= 0) {
- const item = Object.assign({}, items[index], payload);
-
- newState.items = [...items];
- newState.items.splice(index, 1, item);
- }
-
- return newState;
- },
-
- [SET_RELEASES_SORT]: createSetClientSideCollectionSortReducer(section),
- [SET_ALBUM_RELEASES_FILTER]: createSetClientSideCollectionFilterReducer(albumSection),
- [SET_ARTIST_RELEASES_FILTER]: createSetClientSideCollectionFilterReducer(artistSection)
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/retagPreviewActions.js b/frontend/src/Store/Actions/retagPreviewActions.js
deleted file mode 100644
index 73632fcf8..000000000
--- a/frontend/src/Store/Actions/retagPreviewActions.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { createAction } from 'redux-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'retagPreview';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
-};
-
-//
-// Actions Types
-
-export const FETCH_RETAG_PREVIEW = 'retagPreview/fetchRetagPreview';
-export const CLEAR_RETAG_PREVIEW = 'retagPreview/clearRetagPreview';
-
-//
-// Action Creators
-
-export const fetchRetagPreview = createThunk(FETCH_RETAG_PREVIEW);
-export const clearRetagPreview = createAction(CLEAR_RETAG_PREVIEW);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [FETCH_RETAG_PREVIEW]: createFetchHandler('retagPreview', '/retag')
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_RETAG_PREVIEW]: (state) => {
- return Object.assign({}, state, defaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/searchActions.js b/frontend/src/Store/Actions/searchActions.js
deleted file mode 100644
index c2af6f47b..000000000
--- a/frontend/src/Store/Actions/searchActions.js
+++ /dev/null
@@ -1,217 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import getNewAlbum from 'Utilities/Album/getNewAlbum';
-import getNewArtist from 'Utilities/Artist/getNewArtist';
-import monitorNewItemsOptions from 'Utilities/Artist/monitorNewItemsOptions';
-import monitorOptions from 'Utilities/Artist/monitorOptions';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-import { set, update, updateItem } from './baseActions';
-import createHandleActions from './Creators/createHandleActions';
-
-//
-// Variables
-
-export const section = 'search';
-let abortCurrentRequest = null;
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- isAdding: false,
- isAdded: false,
- addError: null,
- items: [],
-
- defaults: {
- rootFolderPath: '',
- monitor: monitorOptions[0].key,
- monitorNewItems: monitorNewItemsOptions[0].key,
- qualityProfileId: 0,
- metadataProfileId: 0,
- searchForMissingAlbums: false,
- searchForNewAlbum: false,
- tags: []
- }
-};
-
-export const persistState = [
- 'search.defaults'
-];
-
-//
-// Actions Types
-
-export const GET_SEARCH_RESULTS = 'search/getSearchResults';
-export const ADD_ARTIST = 'search/addArtist';
-export const ADD_ALBUM = 'search/addAlbum';
-export const CLEAR_SEARCH_RESULTS = 'search/clearSearchResults';
-export const SET_ADD_DEFAULT = 'search/setAddDefault';
-
-//
-// Action Creators
-
-export const getSearchResults = createThunk(GET_SEARCH_RESULTS);
-export const addArtist = createThunk(ADD_ARTIST);
-export const addAlbum = createThunk(ADD_ALBUM);
-export const clearSearchResults = createAction(CLEAR_SEARCH_RESULTS);
-export const setAddDefault = createAction(SET_ADD_DEFAULT);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- [GET_SEARCH_RESULTS]: function(getState, payload, dispatch) {
- dispatch(set({ section, isFetching: true }));
-
- if (abortCurrentRequest) {
- abortCurrentRequest();
- }
-
- const { request, abortRequest } = createAjaxRequest({
- url: '/search',
- data: {
- term: payload.term
- }
- });
-
- abortCurrentRequest = abortRequest;
-
- request.done((data) => {
- dispatch(batchActions([
- update({ section, data }),
-
- set({
- section,
- isFetching: false,
- isPopulated: true,
- error: null
- })
- ]));
- });
-
- request.fail((xhr) => {
- dispatch(set({
- section,
- isFetching: false,
- isPopulated: false,
- error: xhr.aborted ? null : xhr
- }));
- });
- },
-
- [ADD_ARTIST]: function(getState, payload, dispatch) {
- dispatch(set({ section, isAdding: true }));
-
- const foreignArtistId = payload.foreignArtistId;
- const items = getState().search.items;
- const itemToAdd = _.find(items, { foreignId: foreignArtistId });
- const newArtist = getNewArtist(_.cloneDeep(itemToAdd.artist), payload);
-
- const promise = createAjaxRequest({
- url: '/artist',
- method: 'POST',
- dataType: 'json',
- contentType: 'application/json',
- data: JSON.stringify(newArtist)
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- updateItem({ section: 'artist', ...data }),
-
- set({
- section,
- isAdding: false,
- isAdded: true,
- addError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isAdding: false,
- isAdded: false,
- addError: xhr
- }));
- });
- },
-
- [ADD_ALBUM]: function(getState, payload, dispatch) {
- dispatch(set({ section, isAdding: true }));
-
- const foreignAlbumId = payload.foreignAlbumId;
- const items = getState().search.items;
- const itemToAdd = _.find(items, { foreignId: foreignAlbumId });
- const newAlbum = getNewAlbum(_.cloneDeep(itemToAdd.album), payload);
-
- const promise = createAjaxRequest({
- url: '/album',
- method: 'POST',
- contentType: 'application/json',
- data: JSON.stringify(newAlbum)
- }).request;
-
- promise.done((data) => {
- data.releases = itemToAdd.album.releases;
- itemToAdd.album = data;
- dispatch(batchActions([
- updateItem({ section: 'artist', ...data.artist }),
- updateItem({ section, ...itemToAdd }),
-
- set({
- section,
- isAdding: false,
- isAdded: true,
- addError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isAdding: false,
- isAdded: false,
- addError: xhr
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_ADD_DEFAULT]: function(state, { payload }) {
- const newState = getSectionState(state, section);
-
- newState.defaults = {
- ...newState.defaults,
- ...payload
- };
-
- return updateSectionState(state, section, newState);
- },
-
- [CLEAR_SEARCH_RESULTS]: function(state) {
- const {
- defaults,
- ...otherDefaultState
- } = defaultState;
-
- return Object.assign({}, state, otherDefaultState);
- }
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/settingsActions.js b/frontend/src/Store/Actions/settingsActions.js
deleted file mode 100644
index 54b059083..000000000
--- a/frontend/src/Store/Actions/settingsActions.js
+++ /dev/null
@@ -1,183 +0,0 @@
-import { createAction } from 'redux-actions';
-import { handleThunks } from 'Store/thunks';
-import createHandleActions from './Creators/createHandleActions';
-import autoTaggings from './Settings/autoTaggings';
-import autoTaggingSpecifications from './Settings/autoTaggingSpecifications';
-import customFormats from './Settings/customFormats';
-import customFormatSpecifications from './Settings/customFormatSpecifications';
-import delayProfiles from './Settings/delayProfiles';
-import downloadClientOptions from './Settings/downloadClientOptions';
-import downloadClients from './Settings/downloadClients';
-import general from './Settings/general';
-import importListExclusions from './Settings/importListExclusions';
-import importLists from './Settings/importLists';
-import indexerFlags from './Settings/indexerFlags';
-import indexerOptions from './Settings/indexerOptions';
-import indexers from './Settings/indexers';
-import languages from './Settings/languages';
-import mediaManagement from './Settings/mediaManagement';
-import metadata from './Settings/metadata';
-import metadataProfiles from './Settings/metadataProfiles';
-import metadataProvider from './Settings/metadataProvider';
-import naming from './Settings/naming';
-import namingExamples from './Settings/namingExamples';
-import notifications from './Settings/notifications';
-import qualityDefinitions from './Settings/qualityDefinitions';
-import qualityProfiles from './Settings/qualityProfiles';
-import releaseProfiles from './Settings/releaseProfiles';
-import remotePathMappings from './Settings/remotePathMappings';
-import rootFolders from './Settings/rootFolders';
-import ui from './Settings/ui';
-
-export * from './Settings/autoTaggingSpecifications';
-export * from './Settings/autoTaggings';
-export * from './Settings/customFormatSpecifications.js';
-export * from './Settings/customFormats';
-export * from './Settings/delayProfiles';
-export * from './Settings/downloadClients';
-export * from './Settings/downloadClientOptions';
-export * from './Settings/general';
-export * from './Settings/importLists';
-export * from './Settings/importListExclusions';
-export * from './Settings/indexerFlags';
-export * from './Settings/indexerOptions';
-export * from './Settings/indexers';
-export * from './Settings/languages';
-export * from './Settings/metadataProfiles';
-export * from './Settings/mediaManagement';
-export * from './Settings/metadata';
-export * from './Settings/metadataProvider';
-export * from './Settings/naming';
-export * from './Settings/namingExamples';
-export * from './Settings/notifications';
-export * from './Settings/qualityDefinitions';
-export * from './Settings/qualityProfiles';
-export * from './Settings/releaseProfiles';
-export * from './Settings/remotePathMappings';
-export * from './Settings/rootFolders';
-export * from './Settings/ui';
-
-//
-// Variables
-
-export const section = 'settings';
-
-//
-// State
-
-export const defaultState = {
- advancedSettings: false,
- autoTaggingSpecifications: autoTaggingSpecifications.defaultState,
- autoTaggings: autoTaggings.defaultState,
- customFormatSpecifications: customFormatSpecifications.defaultState,
- customFormats: customFormats.defaultState,
- delayProfiles: delayProfiles.defaultState,
- downloadClients: downloadClients.defaultState,
- downloadClientOptions: downloadClientOptions.defaultState,
- general: general.defaultState,
- indexerFlags: indexerFlags.defaultState,
- indexerOptions: indexerOptions.defaultState,
- indexers: indexers.defaultState,
- importLists: importLists.defaultState,
- importListExclusions: importListExclusions.defaultState,
- languages: languages.defaultState,
- metadataProfiles: metadataProfiles.defaultState,
- mediaManagement: mediaManagement.defaultState,
- metadata: metadata.defaultState,
- metadataProvider: metadataProvider.defaultState,
- naming: naming.defaultState,
- namingExamples: namingExamples.defaultState,
- notifications: notifications.defaultState,
- qualityDefinitions: qualityDefinitions.defaultState,
- qualityProfiles: qualityProfiles.defaultState,
- releaseProfiles: releaseProfiles.defaultState,
- remotePathMappings: remotePathMappings.defaultState,
- rootFolders: rootFolders.defaultState,
- ui: ui.defaultState
-};
-
-export const persistState = [
- 'settings.advancedSettings'
-];
-
-//
-// Actions Types
-
-export const TOGGLE_ADVANCED_SETTINGS = 'settings/toggleAdvancedSettings';
-
-//
-// Action Creators
-
-export const toggleAdvancedSettings = createAction(TOGGLE_ADVANCED_SETTINGS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- ...autoTaggingSpecifications.actionHandlers,
- ...autoTaggings.actionHandlers,
- ...customFormatSpecifications.actionHandlers,
- ...customFormats.actionHandlers,
- ...delayProfiles.actionHandlers,
- ...downloadClients.actionHandlers,
- ...downloadClientOptions.actionHandlers,
- ...general.actionHandlers,
- ...indexerFlags.actionHandlers,
- ...indexerOptions.actionHandlers,
- ...indexers.actionHandlers,
- ...importLists.actionHandlers,
- ...importListExclusions.actionHandlers,
- ...languages.actionHandlers,
- ...metadataProfiles.actionHandlers,
- ...mediaManagement.actionHandlers,
- ...metadata.actionHandlers,
- ...metadataProvider.actionHandlers,
- ...naming.actionHandlers,
- ...namingExamples.actionHandlers,
- ...notifications.actionHandlers,
- ...qualityDefinitions.actionHandlers,
- ...qualityProfiles.actionHandlers,
- ...releaseProfiles.actionHandlers,
- ...remotePathMappings.actionHandlers,
- ...rootFolders.actionHandlers,
- ...ui.actionHandlers
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [TOGGLE_ADVANCED_SETTINGS]: (state, { payload }) => {
- return Object.assign({}, state, { advancedSettings: !state.advancedSettings });
- },
-
- ...autoTaggingSpecifications.reducers,
- ...autoTaggings.reducers,
- ...customFormatSpecifications.reducers,
- ...customFormats.reducers,
- ...delayProfiles.reducers,
- ...downloadClients.reducers,
- ...downloadClientOptions.reducers,
- ...general.reducers,
- ...indexerFlags.reducers,
- ...indexerOptions.reducers,
- ...indexers.reducers,
- ...importLists.reducers,
- ...importListExclusions.reducers,
- ...languages.reducers,
- ...metadataProfiles.reducers,
- ...mediaManagement.reducers,
- ...metadata.reducers,
- ...metadataProvider.reducers,
- ...naming.reducers,
- ...namingExamples.reducers,
- ...notifications.reducers,
- ...qualityDefinitions.reducers,
- ...qualityProfiles.reducers,
- ...releaseProfiles.reducers,
- ...remotePathMappings.reducers,
- ...rootFolders.reducers,
- ...ui.reducers
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/systemActions.js b/frontend/src/Store/Actions/systemActions.js
deleted file mode 100644
index 92360b589..000000000
--- a/frontend/src/Store/Actions/systemActions.js
+++ /dev/null
@@ -1,395 +0,0 @@
-import { createAction } from 'redux-actions';
-import { filterTypes, sortDirections } from 'Helpers/Props';
-import { setAppValue } from 'Store/Actions/appActions';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import translate from 'Utilities/String/translate';
-import { pingServer } from './appActions';
-import { set } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'system';
-const backupsSection = 'system.backups';
-
-//
-// State
-
-export const defaultState = {
- status: {
- isFetching: false,
- isPopulated: false,
- error: null,
- item: {}
- },
-
- health: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- diskSpace: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- tasks: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- backups: {
- isFetching: false,
- isPopulated: false,
- error: null,
- isRestoring: false,
- restoreError: null,
- isDeleting: false,
- deleteError: null,
- items: []
- },
-
- updates: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- logs: {
- isFetching: false,
- isPopulated: false,
- pageSize: 50,
- sortKey: 'time',
- sortDirection: sortDirections.DESCENDING,
- error: null,
- items: [],
-
- columns: [
- {
- name: 'level',
- columnLabel: () => translate('Level'),
- isSortable: false,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'time',
- label: () => translate('Time'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'logger',
- label: () => translate('Component'),
- isSortable: false,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'message',
- label: () => translate('Message'),
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- }
- ],
-
- selectedFilterKey: 'all',
-
- filters: [
- {
- key: 'all',
- label: () => translate('All'),
- filters: []
- },
- {
- key: 'info',
- label: () => translate('Info'),
- filters: [
- {
- key: 'level',
- value: 'info',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'warn',
- label: () => translate('Warn'),
- filters: [
- {
- key: 'level',
- value: 'warn',
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'error',
- label: () => translate('Error'),
- filters: [
- {
- key: 'level',
- value: 'error',
- type: filterTypes.EQUAL
- }
- ]
- }
- ]
- },
-
- logFiles: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- },
-
- updateLogFiles: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- }
-};
-
-export const persistState = [
- 'system.logs.pageSize',
- 'system.logs.sortKey',
- 'system.logs.sortDirection',
- 'system.logs.selectedFilterKey'
-];
-
-//
-// Actions Types
-
-export const FETCH_STATUS = 'system/status/fetchStatus';
-export const FETCH_HEALTH = 'system/health/fetchHealth';
-export const FETCH_DISK_SPACE = 'system/diskSpace/fetchDiskSPace';
-
-export const FETCH_TASK = 'system/tasks/fetchTask';
-export const FETCH_TASKS = 'system/tasks/fetchTasks';
-
-export const FETCH_BACKUPS = 'system/backups/fetchBackups';
-export const RESTORE_BACKUP = 'system/backups/restoreBackup';
-export const CLEAR_RESTORE_BACKUP = 'system/backups/clearRestoreBackup';
-export const DELETE_BACKUP = 'system/backups/deleteBackup';
-
-export const FETCH_UPDATES = 'system/updates/fetchUpdates';
-
-export const FETCH_LOGS = 'system/logs/fetchLogs';
-export const GOTO_FIRST_LOGS_PAGE = 'system/logs/gotoLogsFirstPage';
-export const GOTO_PREVIOUS_LOGS_PAGE = 'system/logs/gotoLogsPreviousPage';
-export const GOTO_NEXT_LOGS_PAGE = 'system/logs/gotoLogsNextPage';
-export const GOTO_LAST_LOGS_PAGE = 'system/logs/gotoLogsLastPage';
-export const GOTO_LOGS_PAGE = 'system/logs/gotoLogsPage';
-export const SET_LOGS_SORT = 'system/logs/setLogsSort';
-export const SET_LOGS_FILTER = 'system/logs/setLogsFilter';
-export const SET_LOGS_TABLE_OPTION = 'system/logs/setLogsTableOption';
-export const CLEAR_LOGS_TABLE = 'system/logs/clearLogsTable';
-
-export const FETCH_LOG_FILES = 'system/logFiles/fetchLogFiles';
-export const FETCH_UPDATE_LOG_FILES = 'system/updateLogFiles/fetchUpdateLogFiles';
-
-export const RESTART = 'system/restart';
-export const SHUTDOWN = 'system/shutdown';
-
-//
-// Action Creators
-
-export const fetchStatus = createThunk(FETCH_STATUS);
-export const fetchHealth = createThunk(FETCH_HEALTH);
-export const fetchDiskSpace = createThunk(FETCH_DISK_SPACE);
-
-export const fetchTask = createThunk(FETCH_TASK);
-export const fetchTasks = createThunk(FETCH_TASKS);
-
-export const fetchBackups = createThunk(FETCH_BACKUPS);
-export const restoreBackup = createThunk(RESTORE_BACKUP);
-export const clearRestoreBackup = createAction(CLEAR_RESTORE_BACKUP);
-export const deleteBackup = createThunk(DELETE_BACKUP);
-
-export const fetchUpdates = createThunk(FETCH_UPDATES);
-
-export const fetchLogs = createThunk(FETCH_LOGS);
-export const gotoLogsFirstPage = createThunk(GOTO_FIRST_LOGS_PAGE);
-export const gotoLogsPreviousPage = createThunk(GOTO_PREVIOUS_LOGS_PAGE);
-export const gotoLogsNextPage = createThunk(GOTO_NEXT_LOGS_PAGE);
-export const gotoLogsLastPage = createThunk(GOTO_LAST_LOGS_PAGE);
-export const gotoLogsPage = createThunk(GOTO_LOGS_PAGE);
-export const setLogsSort = createThunk(SET_LOGS_SORT);
-export const setLogsFilter = createThunk(SET_LOGS_FILTER);
-export const setLogsTableOption = createAction(SET_LOGS_TABLE_OPTION);
-export const clearLogsTable = createAction(CLEAR_LOGS_TABLE);
-
-export const fetchLogFiles = createThunk(FETCH_LOG_FILES);
-export const fetchUpdateLogFiles = createThunk(FETCH_UPDATE_LOG_FILES);
-
-export const restart = createThunk(RESTART);
-export const shutdown = createThunk(SHUTDOWN);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_STATUS]: createFetchHandler('system.status', '/system/status'),
- [FETCH_HEALTH]: createFetchHandler('system.health', '/health'),
- [FETCH_DISK_SPACE]: createFetchHandler('system.diskSpace', '/diskspace'),
- [FETCH_TASK]: createFetchHandler('system.tasks', '/system/task'),
- [FETCH_TASKS]: createFetchHandler('system.tasks', '/system/task'),
-
- [FETCH_BACKUPS]: createFetchHandler(backupsSection, '/system/backup'),
-
- [RESTORE_BACKUP]: function(getState, payload, dispatch) {
- const {
- id,
- file
- } = payload;
-
- dispatch(set({
- section: backupsSection,
- isRestoring: true
- }));
-
- let ajaxOptions = null;
-
- if (id) {
- ajaxOptions = {
- url: `/system/backup/restore/${id}`,
- method: 'POST',
- contentType: 'application/json',
- dataType: 'json',
- data: JSON.stringify({
- id
- })
- };
- } else if (file) {
- const formData = new FormData();
- formData.append('restore', file);
-
- ajaxOptions = {
- url: '/system/backup/restore/upload',
- method: 'POST',
- processData: false,
- contentType: false,
- data: formData
- };
- } else {
- dispatch(set({
- section: backupsSection,
- isRestoring: false,
- restoreError: 'Error restoring backup'
- }));
- }
-
- const promise = createAjaxRequest(ajaxOptions).request;
-
- promise.done((data) => {
- dispatch(set({
- section: backupsSection,
- isRestoring: false,
- restoreError: null
- }));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section: backupsSection,
- isRestoring: false,
- restoreError: xhr
- }));
- });
- },
-
- [DELETE_BACKUP]: createRemoveItemHandler(backupsSection, '/system/backup'),
-
- [FETCH_UPDATES]: createFetchHandler('system.updates', '/update'),
- [FETCH_LOG_FILES]: createFetchHandler('system.logFiles', '/log/file'),
- [FETCH_UPDATE_LOG_FILES]: createFetchHandler('system.updateLogFiles', '/log/file/update'),
-
- ...createServerSideCollectionHandlers(
- 'system.logs',
- '/log',
- fetchLogs,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_LOGS,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_LOGS_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_LOGS_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_LOGS_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_LOGS_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_LOGS_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_LOGS_SORT,
- [serverSideCollectionHandlers.FILTER]: SET_LOGS_FILTER
- }
- ),
-
- [RESTART]: function(getState, payload, dispatch) {
- const promise = createAjaxRequest({
- url: '/system/restart',
- method: 'POST'
- }).request;
-
- promise.done(() => {
- dispatch(setAppValue({ isRestarting: true }));
- dispatch(pingServer());
- });
- },
-
- [SHUTDOWN]: function() {
- createAjaxRequest({
- url: '/system/shutdown',
- method: 'POST'
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [CLEAR_RESTORE_BACKUP]: function(state, { payload }) {
- return {
- ...state,
- backups: {
- ...state.backups,
- isRestoring: false,
- restoreError: null
- }
- };
- },
-
- [SET_LOGS_TABLE_OPTION]: createSetTableOptionReducer('logs'),
-
- [CLEAR_LOGS_TABLE]: createClearReducer(section, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- })
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/tagActions.js b/frontend/src/Store/Actions/tagActions.js
deleted file mode 100644
index 6800b1d58..000000000
--- a/frontend/src/Store/Actions/tagActions.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import { update } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-
-//
-// Variables
-
-export const section = 'tags';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
-
- details: {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- }
-};
-
-//
-// Actions Types
-
-export const FETCH_TAGS = 'tags/fetchTags';
-export const ADD_TAG = 'tags/addTag';
-export const DELETE_TAG = 'tags/deleteTag';
-export const FETCH_TAG_DETAILS = 'tags/fetchTagDetails';
-
-//
-// Action Creators
-
-export const fetchTags = createThunk(FETCH_TAGS);
-export const addTag = createThunk(ADD_TAG);
-export const deleteTag = createThunk(DELETE_TAG);
-export const fetchTagDetails = createThunk(FETCH_TAG_DETAILS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_TAGS]: createFetchHandler(section, '/tag'),
-
- [ADD_TAG]: function(getState, payload, dispatch) {
- const promise = createAjaxRequest({
- url: '/tag',
- method: 'POST',
- data: JSON.stringify(payload.tag),
- dataType: 'json'
- }).request;
-
- promise.done((data) => {
- const tags = getState().tags.items.slice();
- tags.push(data);
-
- dispatch(update({ section, data: tags }));
- payload.onTagCreated(data);
- });
- },
-
- [DELETE_TAG]: createRemoveItemHandler(section, '/tag'),
- [FETCH_TAG_DETAILS]: createFetchHandler('tags.details', '/tag/detail')
-
-});
-
-//
-// Reducers
-export const reducers = createHandleActions({}, defaultState, section);
diff --git a/frontend/src/Store/Actions/trackActions.js b/frontend/src/Store/Actions/trackActions.js
deleted file mode 100644
index a71388c88..000000000
--- a/frontend/src/Store/Actions/trackActions.js
+++ /dev/null
@@ -1,151 +0,0 @@
-import React from 'react';
-import { createAction } from 'redux-actions';
-import Icon from 'Components/Icon';
-import { icons, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import translate from 'Utilities/String/translate';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'tracks';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- error: null,
- sortKey: 'mediumNumber',
- sortDirection: sortDirections.ASCENDING,
- secondarySortKey: 'absoluteTrackNumber',
- secondarySortDirection: sortDirections.ASCENDING,
- items: [],
-
- columns: [
- {
- name: 'medium',
- label: () => translate('Medium'),
- isVisible: false
- },
- {
- name: 'absoluteTrackNumber',
- label: () => translate('Track'),
- isVisible: true
- },
- {
- name: 'title',
- label: () => translate('Title'),
- isVisible: true
- },
- {
- name: 'path',
- label: () => translate('Path'),
- isVisible: false
- },
- {
- name: 'duration',
- label: () => translate('Duration'),
- isVisible: true
- },
- {
- name: 'audioInfo',
- label: () => translate('AudioInfo'),
- isVisible: true
- },
- {
- name: 'size',
- label: () => translate('Size'),
- isVisible: false
- },
- {
- name: 'customFormats',
- label: 'Formats',
- isVisible: false
- },
- {
- name: 'customFormatScore',
- columnLabel: () => translate('CustomFormatScore'),
- label: React.createElement(Icon, {
- name: icons.SCORE,
- title: () => translate('CustomFormatScore')
- }),
- isVisible: false
- },
- {
- name: 'indexerFlags',
- columnLabel: () => translate('IndexerFlags'),
- label: React.createElement(Icon, {
- name: icons.FLAG,
- title: () => translate('IndexerFlags')
- }),
- isVisible: false
- },
- {
- name: 'status',
- label: () => translate('Status'),
- isVisible: true
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ]
-};
-
-export const persistState = [
- 'tracks.sortKey',
- 'tracks.sortDirection',
- 'tracks.columns'
-];
-
-//
-// Actions Types
-
-export const FETCH_TRACKS = 'tracks/fetchTracks';
-export const SET_TRACKS_SORT = 'tracks/setTracksSort';
-export const SET_TRACKS_TABLE_OPTION = 'tracks/setTracksTableOption';
-export const CLEAR_TRACKS = 'tracks/clearTracks';
-
-//
-// Action Creators
-
-export const fetchTracks = createThunk(FETCH_TRACKS);
-export const setTracksSort = createAction(SET_TRACKS_SORT);
-export const setTracksTableOption = createAction(SET_TRACKS_TABLE_OPTION);
-export const clearTracks = createAction(CLEAR_TRACKS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_TRACKS]: createFetchHandler(section, '/track')
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_TRACKS_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [FETCH_TRACKS]: (state) => {
- return Object.assign({}, state, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- });
- },
-
- [SET_TRACKS_SORT]: createSetClientSideCollectionSortReducer(section)
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/trackFileActions.js b/frontend/src/Store/Actions/trackFileActions.js
deleted file mode 100644
index f4af704ee..000000000
--- a/frontend/src/Store/Actions/trackFileActions.js
+++ /dev/null
@@ -1,275 +0,0 @@
-import _ from 'lodash';
-import { createAction } from 'redux-actions';
-import { batchActions } from 'redux-batched-actions';
-import albumEntities from 'Album/albumEntities';
-import { sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-import translate from 'Utilities/String/translate';
-import { removeItem, set, updateItem } from './baseActions';
-import createFetchHandler from './Creators/createFetchHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createRemoveItemHandler from './Creators/createRemoveItemHandler';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetClientSideCollectionSortReducer from './Creators/Reducers/createSetClientSideCollectionSortReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'trackFiles';
-
-//
-// State
-
-export const defaultState = {
- isFetching: false,
- isPopulated: false,
- sortKey: 'path',
- sortDirection: sortDirections.ASCENDING,
-
- error: null,
- isDeleting: false,
- deleteError: null,
- isSaving: false,
- saveError: null,
- items: [],
-
- sortPredicates: {
- quality: function(item, direction) {
- return item.quality ? item.qualityWeight : 0;
- }
- },
-
- columns: [
- {
- name: 'select',
- columnLabel: 'Select',
- isSortable: false,
- isVisible: true,
- isModifiable: false,
- isHidden: true
- },
- {
- name: 'path',
- label: () => translate('Path'),
- isSortable: true,
- isVisible: true,
- isModifiable: false
- },
- {
- name: 'size',
- label: () => translate('Size'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'dateAdded',
- label: () => translate('DateAdded'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ]
-};
-
-export const persistState = [
- 'trackFiles.sortKey',
- 'trackFiles.sortDirection'
-];
-
-//
-// Actions Types
-
-export const FETCH_TRACK_FILES = 'trackFiles/fetchTrackFiles';
-export const DELETE_TRACK_FILE = 'trackFiles/deleteTrackFile';
-export const DELETE_TRACK_FILES = 'trackFiles/deleteTrackFiles';
-export const UPDATE_TRACK_FILES = 'trackFiles/updateTrackFiles';
-export const SET_TRACK_FILES_SORT = 'trackFiles/setTrackFilesSort';
-export const SET_TRACK_FILES_TABLE_OPTION = 'trackFiles/setTrackFilesTableOption';
-export const CLEAR_TRACK_FILES = 'trackFiles/clearTrackFiles';
-
-//
-// Action Creators
-
-export const fetchTrackFiles = createThunk(FETCH_TRACK_FILES);
-export const deleteTrackFile = createThunk(DELETE_TRACK_FILE);
-export const deleteTrackFiles = createThunk(DELETE_TRACK_FILES);
-export const updateTrackFiles = createThunk(UPDATE_TRACK_FILES);
-export const setTrackFilesSort = createAction(SET_TRACK_FILES_SORT);
-export const setTrackFilesTableOption = createAction(SET_TRACK_FILES_TABLE_OPTION);
-export const clearTrackFiles = createAction(CLEAR_TRACK_FILES);
-
-//
-// Helpers
-
-const deleteTrackFileHelper = createRemoveItemHandler(section, '/trackFile');
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
- [FETCH_TRACK_FILES]: createFetchHandler(section, '/trackFile'),
-
- [DELETE_TRACK_FILE]: function(getState, payload, dispatch) {
- const {
- id: trackFileId,
- albumEntity = albumEntities.ALBUMS
- } = payload;
-
- const albumSection = _.last(albumEntity.split('.'));
- const deletePromise = deleteTrackFileHelper(getState, payload, dispatch);
-
- deletePromise.done(() => {
- const albums = getState().albums.items;
- const tracksWithRemovedFiles = _.filter(albums, { trackFileId });
-
- dispatch(batchActions([
- ...tracksWithRemovedFiles.map((track) => {
- return updateItem({
- section: albumSection,
- ...track,
- trackFileId: 0,
- hasFile: false
- });
- })
- ]));
- });
- },
-
- [DELETE_TRACK_FILES]: function(getState, payload, dispatch) {
- const {
- trackFileIds
- } = payload;
-
- dispatch(set({ section, isDeleting: true }));
-
- const promise = createAjaxRequest({
- url: '/trackFile/bulk',
- method: 'DELETE',
- dataType: 'json',
- data: JSON.stringify({ trackFileIds })
- }).request;
-
- promise.done(() => {
- const tracks = getState().tracks.items;
- const tracksWithRemovedFiles = trackFileIds.reduce((acc, trackFileId) => {
- acc.push(..._.filter(tracks, { trackFileId }));
-
- return acc;
- }, []);
-
- dispatch(batchActions([
- ...trackFileIds.map((id) => {
- return removeItem({ section, id });
- }),
-
- ...tracksWithRemovedFiles.map((track) => {
- return updateItem({
- section: 'tracks',
- ...track,
- trackFileId: 0,
- hasFile: false
- });
- }),
-
- set({
- section,
- isDeleting: false,
- deleteError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isDeleting: false,
- deleteError: xhr
- }));
- });
- },
-
- [UPDATE_TRACK_FILES]: function(getState, payload, dispatch) {
- const {
- trackFileIds,
- quality
- } = payload;
-
- dispatch(set({ section, isSaving: true }));
-
- const requestData = {
- trackFileIds
- };
-
- if (quality) {
- requestData.quality = quality;
- }
-
- const promise = createAjaxRequest({
- url: '/trackFile/editor',
- method: 'PUT',
- dataType: 'json',
- data: JSON.stringify(requestData)
- }).request;
-
- promise.done((data) => {
- dispatch(batchActions([
- ...trackFileIds.map((id) => {
- const props = {};
-
- const trackFile = data.find((file) => file.id === id);
-
- props.qualityCutoffNotMet = trackFile.qualityCutoffNotMet;
-
- if (quality) {
- props.quality = quality;
- }
-
- return updateItem({ section, id, ...props });
- }),
-
- set({
- section,
- isSaving: false,
- saveError: null
- })
- ]));
- });
-
- promise.fail((xhr) => {
- dispatch(set({
- section,
- isSaving: false,
- saveError: xhr
- }));
- });
- }
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
- [SET_TRACK_FILES_SORT]: createSetClientSideCollectionSortReducer(section),
- [SET_TRACK_FILES_TABLE_OPTION]: createSetTableOptionReducer(section),
-
- [CLEAR_TRACK_FILES]: createClearReducer(section, {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: []
- })
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Actions/wantedActions.js b/frontend/src/Store/Actions/wantedActions.js
deleted file mode 100644
index 61d6f7752..000000000
--- a/frontend/src/Store/Actions/wantedActions.js
+++ /dev/null
@@ -1,329 +0,0 @@
-import { createAction } from 'redux-actions';
-import { filterTypes, sortDirections } from 'Helpers/Props';
-import { createThunk, handleThunks } from 'Store/thunks';
-import serverSideCollectionHandlers from 'Utilities/serverSideCollectionHandlers';
-import translate from 'Utilities/String/translate';
-import createBatchToggleAlbumMonitoredHandler from './Creators/createBatchToggleAlbumMonitoredHandler';
-import createHandleActions from './Creators/createHandleActions';
-import createServerSideCollectionHandlers from './Creators/createServerSideCollectionHandlers';
-import createClearReducer from './Creators/Reducers/createClearReducer';
-import createSetTableOptionReducer from './Creators/Reducers/createSetTableOptionReducer';
-
-//
-// Variables
-
-export const section = 'wanted';
-
-//
-// State
-
-export const defaultState = {
- missing: {
- isFetching: false,
- isPopulated: false,
- pageSize: 20,
- sortKey: 'releaseDate',
- sortDirection: sortDirections.DESCENDING,
- error: null,
- items: [],
-
- columns: [
- {
- name: 'artists.sortName',
- label: () => translate('ArtistName'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.title',
- label: () => translate('AlbumTitle'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albumType',
- label: () => translate('AlbumType'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'releaseDate',
- label: () => translate('ReleaseDate'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.lastSearchTime',
- label: () => translate('LastSearched'),
- isSortable: true,
- isVisible: false
- },
- // {
- // name: 'status',
- // label: 'Status',
- // isVisible: true
- // },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ],
-
- selectedFilterKey: 'monitored',
-
- filters: [
- {
- key: 'monitored',
- label: () => translate('Monitored'),
- filters: [
- {
- key: 'monitored',
- value: true,
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'unmonitored',
- label: () => translate('Unmonitored'),
- filters: [
- {
- key: 'monitored',
- value: false,
- type: filterTypes.EQUAL
- }
- ]
- }
- ]
- },
-
- cutoffUnmet: {
- isFetching: false,
- isPopulated: false,
- pageSize: 20,
- sortKey: 'releaseDate',
- sortDirection: sortDirections.DESCENDING,
- items: [],
-
- columns: [
- {
- name: 'artists.sortName',
- label: () => translate('ArtistName'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albums.title',
- label: () => translate('AlbumTitle'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'albumType',
- label: () => translate('AlbumType'),
- isSortable: true,
- isVisible: true
- },
- {
- name: 'releaseDate',
- label: () => translate('ReleaseDate'),
- isSortable: true,
- isVisible: true
- },
- // {
- // name: 'status',
- // label: 'Status',
- // isVisible: true
- // },
- {
- name: 'albums.lastSearchTime',
- label: () => translate('LastSearched'),
- isSortable: true,
- isVisible: false
- },
- {
- name: 'actions',
- columnLabel: () => translate('Actions'),
- isVisible: true,
- isModifiable: false
- }
- ],
-
- selectedFilterKey: 'monitored',
-
- filters: [
- {
- key: 'monitored',
- label: () => translate('Monitored'),
- filters: [
- {
- key: 'monitored',
- value: true,
- type: filterTypes.EQUAL
- }
- ]
- },
- {
- key: 'unmonitored',
- label: () => translate('Unmonitored'),
- filters: [
- {
- key: 'monitored',
- value: false,
- type: filterTypes.EQUAL
- }
- ]
- }
- ]
- }
-};
-
-export const persistState = [
- 'wanted.missing.pageSize',
- 'wanted.missing.sortKey',
- 'wanted.missing.sortDirection',
- 'wanted.missing.selectedFilterKey',
- 'wanted.missing.columns',
- 'wanted.cutoffUnmet.pageSize',
- 'wanted.cutoffUnmet.sortKey',
- 'wanted.cutoffUnmet.sortDirection',
- 'wanted.cutoffUnmet.selectedFilterKey',
- 'wanted.cutoffUnmet.columns'
-];
-
-//
-// Actions Types
-
-export const FETCH_MISSING = 'wanted/missing/fetchMissing';
-export const GOTO_FIRST_MISSING_PAGE = 'wanted/missing/gotoMissingFirstPage';
-export const GOTO_PREVIOUS_MISSING_PAGE = 'wanted/missing/gotoMissingPreviousPage';
-export const GOTO_NEXT_MISSING_PAGE = 'wanted/missing/gotoMissingNextPage';
-export const GOTO_LAST_MISSING_PAGE = 'wanted/missing/gotoMissingLastPage';
-export const GOTO_MISSING_PAGE = 'wanted/missing/gotoMissingPage';
-export const SET_MISSING_SORT = 'wanted/missing/setMissingSort';
-export const SET_MISSING_FILTER = 'wanted/missing/setMissingFilter';
-export const SET_MISSING_TABLE_OPTION = 'wanted/missing/setMissingTableOption';
-export const CLEAR_MISSING = 'wanted/missing/clearMissing';
-
-export const BATCH_TOGGLE_MISSING_ALBUMS = 'wanted/missing/batchToggleMissingAlbums';
-
-export const FETCH_CUTOFF_UNMET = 'wanted/cutoffUnmet/fetchCutoffUnmet';
-export const GOTO_FIRST_CUTOFF_UNMET_PAGE = 'wanted/cutoffUnmet/gotoCutoffUnmetFirstPage';
-export const GOTO_PREVIOUS_CUTOFF_UNMET_PAGE = 'wanted/cutoffUnmet/gotoCutoffUnmetPreviousPage';
-export const GOTO_NEXT_CUTOFF_UNMET_PAGE = 'wanted/cutoffUnmet/gotoCutoffUnmetNextPage';
-export const GOTO_LAST_CUTOFF_UNMET_PAGE = 'wanted/cutoffUnmet/gotoCutoffUnmetFastPage';
-export const GOTO_CUTOFF_UNMET_PAGE = 'wanted/cutoffUnmet/gotoCutoffUnmetPage';
-export const SET_CUTOFF_UNMET_SORT = 'wanted/cutoffUnmet/setCutoffUnmetSort';
-export const SET_CUTOFF_UNMET_FILTER = 'wanted/cutoffUnmet/setCutoffUnmetFilter';
-export const SET_CUTOFF_UNMET_TABLE_OPTION = 'wanted/cutoffUnmet/setCutoffUnmetTableOption';
-export const CLEAR_CUTOFF_UNMET = 'wanted/cutoffUnmet/clearCutoffUnmet';
-
-export const BATCH_TOGGLE_CUTOFF_UNMET_ALBUMS = 'wanted/cutoffUnmet/batchToggleCutoffUnmetAlbums';
-
-//
-// Action Creators
-
-export const fetchMissing = createThunk(FETCH_MISSING);
-export const gotoMissingFirstPage = createThunk(GOTO_FIRST_MISSING_PAGE);
-export const gotoMissingPreviousPage = createThunk(GOTO_PREVIOUS_MISSING_PAGE);
-export const gotoMissingNextPage = createThunk(GOTO_NEXT_MISSING_PAGE);
-export const gotoMissingLastPage = createThunk(GOTO_LAST_MISSING_PAGE);
-export const gotoMissingPage = createThunk(GOTO_MISSING_PAGE);
-export const setMissingSort = createThunk(SET_MISSING_SORT);
-export const setMissingFilter = createThunk(SET_MISSING_FILTER);
-export const setMissingTableOption = createAction(SET_MISSING_TABLE_OPTION);
-export const clearMissing = createAction(CLEAR_MISSING);
-
-export const batchToggleMissingAlbums = createThunk(BATCH_TOGGLE_MISSING_ALBUMS);
-
-export const fetchCutoffUnmet = createThunk(FETCH_CUTOFF_UNMET);
-export const gotoCutoffUnmetFirstPage = createThunk(GOTO_FIRST_CUTOFF_UNMET_PAGE);
-export const gotoCutoffUnmetPreviousPage = createThunk(GOTO_PREVIOUS_CUTOFF_UNMET_PAGE);
-export const gotoCutoffUnmetNextPage = createThunk(GOTO_NEXT_CUTOFF_UNMET_PAGE);
-export const gotoCutoffUnmetLastPage = createThunk(GOTO_LAST_CUTOFF_UNMET_PAGE);
-export const gotoCutoffUnmetPage = createThunk(GOTO_CUTOFF_UNMET_PAGE);
-export const setCutoffUnmetSort = createThunk(SET_CUTOFF_UNMET_SORT);
-export const setCutoffUnmetFilter = createThunk(SET_CUTOFF_UNMET_FILTER);
-export const setCutoffUnmetTableOption = createAction(SET_CUTOFF_UNMET_TABLE_OPTION);
-export const clearCutoffUnmet = createAction(CLEAR_CUTOFF_UNMET);
-
-export const batchToggleCutoffUnmetAlbums = createThunk(BATCH_TOGGLE_CUTOFF_UNMET_ALBUMS);
-
-//
-// Action Handlers
-
-export const actionHandlers = handleThunks({
-
- ...createServerSideCollectionHandlers(
- 'wanted.missing',
- '/wanted/missing',
- fetchMissing,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_MISSING,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_MISSING_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_MISSING_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_MISSING_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_MISSING_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_MISSING_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_MISSING_SORT,
- [serverSideCollectionHandlers.FILTER]: SET_MISSING_FILTER
- }
- ),
-
- [BATCH_TOGGLE_MISSING_ALBUMS]: createBatchToggleAlbumMonitoredHandler('wanted.missing', fetchMissing),
-
- ...createServerSideCollectionHandlers(
- 'wanted.cutoffUnmet',
- '/wanted/cutoff',
- fetchCutoffUnmet,
- {
- [serverSideCollectionHandlers.FETCH]: FETCH_CUTOFF_UNMET,
- [serverSideCollectionHandlers.FIRST_PAGE]: GOTO_FIRST_CUTOFF_UNMET_PAGE,
- [serverSideCollectionHandlers.PREVIOUS_PAGE]: GOTO_PREVIOUS_CUTOFF_UNMET_PAGE,
- [serverSideCollectionHandlers.NEXT_PAGE]: GOTO_NEXT_CUTOFF_UNMET_PAGE,
- [serverSideCollectionHandlers.LAST_PAGE]: GOTO_LAST_CUTOFF_UNMET_PAGE,
- [serverSideCollectionHandlers.EXACT_PAGE]: GOTO_CUTOFF_UNMET_PAGE,
- [serverSideCollectionHandlers.SORT]: SET_CUTOFF_UNMET_SORT,
- [serverSideCollectionHandlers.FILTER]: SET_CUTOFF_UNMET_FILTER
- }
- ),
-
- [BATCH_TOGGLE_CUTOFF_UNMET_ALBUMS]: createBatchToggleAlbumMonitoredHandler('wanted.cutoffUnmet', fetchCutoffUnmet)
-
-});
-
-//
-// Reducers
-
-export const reducers = createHandleActions({
-
- [SET_MISSING_TABLE_OPTION]: createSetTableOptionReducer('wanted.missing'),
- [SET_CUTOFF_UNMET_TABLE_OPTION]: createSetTableOptionReducer('wanted.cutoffUnmet'),
-
- [CLEAR_MISSING]: createClearReducer(
- 'wanted.missing',
- {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- }
- ),
-
- [CLEAR_CUTOFF_UNMET]: createClearReducer(
- 'wanted.cutoffUnmet',
- {
- isFetching: false,
- isPopulated: false,
- error: null,
- items: [],
- totalPages: 0,
- totalRecords: 0
- }
- )
-
-}, defaultState, section);
diff --git a/frontend/src/Store/Middleware/createPersistState.js b/frontend/src/Store/Middleware/createPersistState.js
deleted file mode 100644
index 57452d6a3..000000000
--- a/frontend/src/Store/Middleware/createPersistState.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import _ from 'lodash';
-import persistState from 'redux-localstorage';
-import actions from 'Store/Actions';
-import migrate from 'Store/Migrators/migrate';
-
-const columnPaths = [];
-
-const paths = _.reduce([...actions], (acc, action) => {
- if (action.persistState) {
- action.persistState.forEach((path) => {
- if (path.match(/\.columns$/)) {
- columnPaths.push(path);
- }
-
- acc.push(path);
- });
- }
-
- return acc;
-}, []);
-
-function mergeColumns(path, initialState, persistedState, computedState) {
- const initialColumns = _.get(initialState, path);
- const persistedColumns = _.get(persistedState, path);
-
- if (!persistedColumns || !persistedColumns.length) {
- return;
- }
-
- const columns = [];
-
- // Add persisted columns in the same order they're currently in
- // as long as they haven't been removed.
-
- persistedColumns.forEach((persistedColumn) => {
- const column = initialColumns.find((i) => i.name === persistedColumn.name);
-
- if (column) {
- const newColumn = {};
-
- // We can't use a spread operator or Object.assign to clone the column
- // or any accessors are lost and can break translations.
- for (const prop of Object.keys(column)) {
- Object.defineProperty(newColumn, prop, Object.getOwnPropertyDescriptor(column, prop));
- }
-
- newColumn.isVisible = persistedColumn.isVisible;
-
- columns.push(newColumn);
- }
- });
-
- // Add any columns added to the app in the initial position.
- initialColumns.forEach((initialColumn, index) => {
- const persistedColumnIndex = persistedColumns.findIndex((i) => i.name === initialColumn.name);
- const column = Object.assign({}, initialColumn);
-
- if (persistedColumnIndex === -1) {
- columns.splice(index, 0, column);
- }
- });
-
- // Set the columns in the persisted state
- _.set(computedState, path, columns);
-}
-
-function slicer(paths_) {
- return (state) => {
- const subset = {};
-
- paths_.forEach((path) => {
- _.set(subset, path, _.get(state, path));
- });
-
- return subset;
- };
-}
-
-function serialize(obj) {
- return JSON.stringify(obj, null, 2);
-}
-
-function merge(initialState, persistedState) {
- if (!persistedState) {
- return initialState;
- }
-
- const computedState = {};
-
- _.merge(computedState, initialState, persistedState);
-
- columnPaths.forEach((columnPath) => {
- mergeColumns(columnPath, initialState, persistedState, computedState);
- });
-
- return computedState;
-}
-
-const config = {
- slicer,
- serialize,
- merge,
- key: 'lidarr'
-};
-
-export default function createPersistState() {
- // Migrate existing local storage before proceeding
- const persistedState = JSON.parse(localStorage.getItem(config.key));
- migrate(persistedState);
- localStorage.setItem(config.key, serialize(persistedState));
-
- return persistState(paths, config);
-}
diff --git a/frontend/src/Store/Middleware/createSentryMiddleware.js b/frontend/src/Store/Middleware/createSentryMiddleware.js
deleted file mode 100644
index 02706b8a1..000000000
--- a/frontend/src/Store/Middleware/createSentryMiddleware.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import * as sentry from '@sentry/browser';
-import * as Integrations from '@sentry/integrations';
-import _ from 'lodash';
-import parseUrl from 'Utilities/String/parseUrl';
-
-const IgnoreErrors = [
- // Innocuous browser errors
- /ResizeObserver loop limit exceeded/,
- /ResizeObserver loop completed with undelivered notifications/
-];
-
-function cleanseUrl(url) {
- const properties = parseUrl(url);
-
- return `${properties.pathname}${properties.search}`;
-}
-
-function shouldIgnoreException(s) {
- return s && IgnoreErrors.find((pattern) => pattern.test(s));
-}
-
-function cleanseData(event, hint) {
- const result = _.cloneDeep(event);
-
- const error = hint && hint.originalException;
-
- result.transaction = cleanseUrl(result.transaction);
-
- if (result.exception) {
- result.exception.values.forEach((exception) => {
- const stacktrace = exception.stacktrace;
-
- if (stacktrace) {
- stacktrace.frames.forEach((frame) => {
- frame.filename = cleanseUrl(frame.filename);
- });
- }
- });
- }
-
- if (
- error &&
- error.message &&
- shouldIgnoreException(error.message)
- ) {
- return null;
- }
-
- result.request.url = cleanseUrl(result.request.url);
-
- return result;
-}
-
-function identity(stuff) {
- return stuff;
-}
-
-function stripUrlBase(frame) {
- if (frame.filename && window.Lidarr.urlBase) {
- frame.filename = frame.filename.replace(window.Lidarr.urlBase, '');
- }
- return frame;
-}
-
-function createMiddleware() {
- return (store) => (next) => (action) => {
- try {
- // Adds a breadcrumb for reporting later (if necessary).
- sentry.addBreadcrumb({
- category: 'redux',
- message: action.type
- });
-
- return next(action);
- } catch (err) {
- console.error(`[sentry] Reporting error to Sentry: ${err}`);
-
- // Send the report including breadcrumbs.
- sentry.captureException(err, {
- extra: {
- action: identity(action),
- state: identity(store.getState())
- }
- });
- }
- };
-}
-
-export default function createSentryMiddleware() {
- const {
- analytics,
- branch,
- version,
- release,
- userHash,
- isProduction
- } = window.Lidarr;
-
- if (!analytics) {
- return;
- }
-
- const dsn = isProduction ? 'https://9df0cbe9eedf4b8698e8bc94ec03c4ff@sentry.servarr.com/18' :
- 'https://aaa261a8c3e542f0a52c07bed78e8d13@sentry.servarr.com/19';
-
- sentry.init({
- dsn,
- environment: branch,
- release,
- sendDefaultPii: true,
- beforeSend: cleanseData,
- integrations: [
- new Integrations.RewriteFrames({ iteratee: stripUrlBase }),
- new Integrations.Dedupe()
- ]
- });
-
- sentry.configureScope((scope) => {
- scope.setUser({ username: userHash });
- scope.setTag('version', version);
- scope.setTag('production', isProduction);
- });
-
- return createMiddleware();
-}
diff --git a/frontend/src/Store/Middleware/middlewares.js b/frontend/src/Store/Middleware/middlewares.js
deleted file mode 100644
index c4e4ce26f..000000000
--- a/frontend/src/Store/Middleware/middlewares.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import { routerMiddleware } from 'connected-react-router';
-import { applyMiddleware, compose } from 'redux';
-import thunk from 'redux-thunk';
-import createPersistState from './createPersistState';
-import createSentryMiddleware from './createSentryMiddleware';
-
-export default function(history) {
- const middlewares = [];
- const sentryMiddleware = createSentryMiddleware();
-
- if (sentryMiddleware) {
- middlewares.push(sentryMiddleware);
- }
-
- middlewares.push(routerMiddleware(history));
- middlewares.push(thunk);
-
- // eslint-disable-next-line no-underscore-dangle
- const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
-
- return composeEnhancers(
- applyMiddleware(...middlewares),
- createPersistState()
- );
-}
diff --git a/frontend/src/Store/Migrators/migrate.js b/frontend/src/Store/Migrators/migrate.js
deleted file mode 100644
index 793b6a209..000000000
--- a/frontend/src/Store/Migrators/migrate.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import migrateAddArtistDefaults from './migrateAddArtistDefaults';
-import migrateBlacklistToBlocklist from './migrateBlacklistToBlocklist';
-
-export default function migrate(persistedState) {
- migrateAddArtistDefaults(persistedState);
- migrateBlacklistToBlocklist(persistedState);
-}
diff --git a/frontend/src/Store/Migrators/migrateAddArtistDefaults.js b/frontend/src/Store/Migrators/migrateAddArtistDefaults.js
deleted file mode 100644
index 731bb00c6..000000000
--- a/frontend/src/Store/Migrators/migrateAddArtistDefaults.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { get } from 'lodash';
-import monitorOptions from 'Utilities/Artist/monitorOptions';
-
-export default function migrateAddArtistDefaults(persistedState) {
- const monitor = get(persistedState, 'addArtist.defaults.monitor');
-
- if (!monitor) {
- return;
- }
-
- if (!monitorOptions.find((option) => option.key === monitor)) {
- persistedState.addArtist.defaults.monitor = monitorOptions[0].key;
- }
-}
diff --git a/frontend/src/Store/Migrators/migrateBlacklistToBlocklist.js b/frontend/src/Store/Migrators/migrateBlacklistToBlocklist.js
deleted file mode 100644
index 3fc7a889e..000000000
--- a/frontend/src/Store/Migrators/migrateBlacklistToBlocklist.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import _, { get } from 'lodash';
-
-export default function migrateBlacklistToBlocklist(persistedState) {
- const blocklist = get(persistedState, 'blacklist');
-
- if (!blocklist) {
- return;
- }
-
- persistedState.blocklist = blocklist;
- _.remove(persistedState, 'blacklist');
-}
diff --git a/frontend/src/Store/Selectors/createAlbumSelector.js b/frontend/src/Store/Selectors/createAlbumSelector.js
deleted file mode 100644
index 13894a143..000000000
--- a/frontend/src/Store/Selectors/createAlbumSelector.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import _ from 'lodash';
-import { createSelector } from 'reselect';
-import albumEntities from 'Album/albumEntities';
-
-function createAlbumSelector() {
- return createSelector(
- (state, { albumId }) => albumId,
- (state, { albumEntity = albumEntities.ALBUMS }) => _.get(state, albumEntity, { items: [] }),
- (albumId, albums) => {
- return _.find(albums.items, { id: albumId });
- }
- );
-}
-
-export default createAlbumSelector;
diff --git a/frontend/src/Store/Selectors/createAllArtistSelector.ts b/frontend/src/Store/Selectors/createAllArtistSelector.ts
deleted file mode 100644
index 6b6010429..000000000
--- a/frontend/src/Store/Selectors/createAllArtistSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createAllArtistSelector() {
- return createSelector(
- (state: AppState) => state.artist,
- (artist) => {
- return artist.items;
- }
- );
-}
-
-export default createAllArtistSelector;
diff --git a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts b/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts
deleted file mode 100644
index 414a451f5..000000000
--- a/frontend/src/Store/Selectors/createArtistAlbumsSelector.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import { createSelector } from 'reselect';
-import AlbumAppState from 'App/State/AlbumAppState';
-import AppState from 'App/State/AppState';
-import Artist from 'Artist/Artist';
-import { createArtistSelectorForHook } from './createArtistSelector';
-
-function createArtistAlbumsSelector(artistId: number) {
- return createSelector(
- (state: AppState) => state.albums,
- createArtistSelectorForHook(artistId),
- (albums: AlbumAppState, artist = {} as Artist) => {
- const { isFetching, isPopulated, error, items } = albums;
-
- const filteredAlbums = items.filter(
- (album) => album.artistId === artist.id
- );
-
- return {
- isFetching,
- isPopulated,
- error,
- items: filteredAlbums,
- };
- }
- );
-}
-
-export default createArtistAlbumsSelector;
diff --git a/frontend/src/Store/Selectors/createArtistClientSideCollectionItemsSelector.js b/frontend/src/Store/Selectors/createArtistClientSideCollectionItemsSelector.js
deleted file mode 100644
index 3678c92dd..000000000
--- a/frontend/src/Store/Selectors/createArtistClientSideCollectionItemsSelector.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { createSelector, createSelectorCreator, defaultMemoize } from 'reselect';
-import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
-import createClientSideCollectionSelector from './createClientSideCollectionSelector';
-
-function createUnoptimizedSelector(uiSection) {
- return createSelector(
- createClientSideCollectionSelector('artist', uiSection),
- (artist) => {
- const items = artist.items.map((s) => {
- const {
- id,
- sortName
- } = s;
-
- return {
- id,
- sortName
- };
- });
-
- return {
- ...artist,
- items
- };
- }
- );
-}
-
-function artistListEqual(a, b) {
- return hasDifferentItemsOrOrder(a, b);
-}
-
-const createArtistEqualSelector = createSelectorCreator(
- defaultMemoize,
- artistListEqual
-);
-
-function createArtistClientSideCollectionItemsSelector(uiSection) {
- return createArtistEqualSelector(
- createUnoptimizedSelector(uiSection),
- (artist) => artist
- );
-}
-
-export default createArtistClientSideCollectionItemsSelector;
diff --git a/frontend/src/Store/Selectors/createArtistCountSelector.ts b/frontend/src/Store/Selectors/createArtistCountSelector.ts
deleted file mode 100644
index b432d64a7..000000000
--- a/frontend/src/Store/Selectors/createArtistCountSelector.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import createAllArtistSelector from './createAllArtistSelector';
-
-function createArtistCountSelector() {
- return createSelector(
- createAllArtistSelector(),
- (state: AppState) => state.artist.error,
- (state: AppState) => state.artist.isFetching,
- (state: AppState) => state.artist.isPopulated,
- (artists, error, isFetching, isPopulated) => {
- return {
- count: artists.length,
- error,
- isFetching,
- isPopulated,
- };
- }
- );
-}
-
-export default createArtistCountSelector;
diff --git a/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts b/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts
deleted file mode 100644
index fa60d936d..000000000
--- a/frontend/src/Store/Selectors/createArtistMetadataProfileSelector.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import Artist from 'Artist/Artist';
-import MetadataProfile from 'typings/MetadataProfile';
-import { createArtistSelectorForHook } from './createArtistSelector';
-
-function createArtistMetadataProfileSelector(artistId: number) {
- return createSelector(
- (state: AppState) => state.settings.metadataProfiles.items,
- createArtistSelectorForHook(artistId),
- (metadataProfiles: MetadataProfile[], artist = {} as Artist) => {
- return metadataProfiles.find((profile) => {
- return profile.id === artist.metadataProfileId;
- });
- }
- );
-}
-
-export default createArtistMetadataProfileSelector;
diff --git a/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts b/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts
deleted file mode 100644
index 67639919b..000000000
--- a/frontend/src/Store/Selectors/createArtistQualityProfileSelector.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import Artist from 'Artist/Artist';
-import QualityProfile from 'typings/QualityProfile';
-import { createArtistSelectorForHook } from './createArtistSelector';
-
-function createArtistQualityProfileSelector(artistId: number) {
- return createSelector(
- (state: AppState) => state.settings.qualityProfiles.items,
- createArtistSelectorForHook(artistId),
- (qualityProfiles: QualityProfile[], artist = {} as Artist) => {
- return qualityProfiles.find(
- (profile) => profile.id === artist.qualityProfileId
- );
- }
- );
-}
-
-export default createArtistQualityProfileSelector;
diff --git a/frontend/src/Store/Selectors/createArtistSelector.js b/frontend/src/Store/Selectors/createArtistSelector.js
deleted file mode 100644
index c335f37f5..000000000
--- a/frontend/src/Store/Selectors/createArtistSelector.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { createSelector } from 'reselect';
-
-export function createArtistSelectorForHook(artistId) {
- return createSelector(
- (state) => state.artist.itemMap,
- (state) => state.artist.items,
- (itemMap, allArtists) => {
- return artistId ? allArtists[itemMap[artistId]]: undefined;
- }
- );
-}
-
-function createArtistSelector() {
- return createSelector(
- (state, { artistId }) => artistId,
- (state) => state.artist.itemMap,
- (state) => state.artist.items,
- (artistId, itemMap, allArtists) => {
- return allArtists[itemMap[artistId]];
- }
- );
-}
-
-export default createArtistSelector;
diff --git a/frontend/src/Store/Selectors/createClientSideCollectionSelector.js b/frontend/src/Store/Selectors/createClientSideCollectionSelector.js
deleted file mode 100644
index 1bac14f08..000000000
--- a/frontend/src/Store/Selectors/createClientSideCollectionSelector.js
+++ /dev/null
@@ -1,144 +0,0 @@
-import _ from 'lodash';
-import { createSelector } from 'reselect';
-import { filterTypePredicates, filterTypes, sortDirections } from 'Helpers/Props';
-import findSelectedFilters from 'Utilities/Filter/findSelectedFilters';
-
-function getSortClause(sortKey, sortDirection, sortPredicates) {
- if (sortPredicates && sortPredicates.hasOwnProperty(sortKey)) {
- return function(item) {
- return sortPredicates[sortKey](item, sortDirection);
- };
- }
-
- return function(item) {
- return item[sortKey];
- };
-}
-
-function filter(items, state) {
- const {
- selectedFilterKey,
- filters,
- customFilters,
- filterPredicates
- } = state;
-
- if (!selectedFilterKey) {
- return items;
- }
-
- const selectedFilters = findSelectedFilters(selectedFilterKey, filters, customFilters);
-
- return _.filter(items, (item) => {
- let i = 0;
- let accepted = true;
-
- while (accepted && i < selectedFilters.length) {
- const {
- key,
- value,
- type = filterTypes.EQUAL
- } = selectedFilters[i];
-
- if (filterPredicates && filterPredicates.hasOwnProperty(key)) {
- const predicate = filterPredicates[key];
-
- if (Array.isArray(value)) {
- if (
- type === filterTypes.NOT_CONTAINS ||
- type === filterTypes.NOT_EQUAL
- ) {
- accepted = value.every((v) => predicate(item, v, type));
- } else {
- accepted = value.some((v) => predicate(item, v, type));
- }
- } else {
- accepted = predicate(item, value, type);
- }
- } else if (item.hasOwnProperty(key)) {
- const predicate = filterTypePredicates[type];
-
- if (Array.isArray(value)) {
- if (
- type === filterTypes.NOT_CONTAINS ||
- type === filterTypes.NOT_EQUAL
- ) {
- accepted = value.every((v) => predicate(item[key], v));
- } else {
- accepted = value.some((v) => predicate(item[key], v));
- }
- } else {
- accepted = predicate(item[key], value);
- }
- } else {
- // Default to false if the filter can't be tested
- accepted = false;
- }
-
- i++;
- }
-
- return accepted;
- });
-}
-
-function sort(items, state) {
- const {
- sortKey,
- sortDirection,
- sortPredicates,
- secondarySortKey,
- secondarySortDirection
- } = state;
-
- const clauses = [];
- const orders = [];
-
- clauses.push(getSortClause(sortKey, sortDirection, sortPredicates));
- orders.push(sortDirection === sortDirections.ASCENDING ? 'asc' : 'desc');
-
- if (secondarySortKey &&
- secondarySortDirection &&
- (sortKey !== secondarySortKey ||
- sortDirection !== secondarySortDirection)) {
- clauses.push(getSortClause(secondarySortKey, secondarySortDirection, sortPredicates));
- orders.push(secondarySortDirection === sortDirections.ASCENDING ? 'asc' : 'desc');
- }
-
- return _.orderBy(items, clauses, orders);
-}
-
-export function createCustomFiltersSelector(type, alternateType) {
- return createSelector(
- (state) => state.customFilters.items,
- (customFilters) => {
- return customFilters.filter((customFilter) => {
- return customFilter.type === type || customFilter.type === alternateType;
- });
- }
- );
-}
-
-function createClientSideCollectionSelector(section, uiSection) {
- return createSelector(
- (state) => _.get(state, section),
- (state) => _.get(state, uiSection),
- createCustomFiltersSelector(section, uiSection),
- (sectionState, uiSectionState = {}, customFilters) => {
- const state = Object.assign({}, sectionState, uiSectionState, { customFilters });
-
- const filtered = filter(state.items, state);
- const sorted = sort(filtered, state);
-
- return {
- ...sectionState,
- ...uiSectionState,
- customFilters,
- items: sorted,
- totalItems: state.items.length
- };
- }
- );
-}
-
-export default createClientSideCollectionSelector;
diff --git a/frontend/src/Store/Selectors/createCommandExecutingSelector.ts b/frontend/src/Store/Selectors/createCommandExecutingSelector.ts
deleted file mode 100644
index 6a80e172b..000000000
--- a/frontend/src/Store/Selectors/createCommandExecutingSelector.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { createSelector } from 'reselect';
-import { isCommandExecuting } from 'Utilities/Command';
-import createCommandSelector from './createCommandSelector';
-
-function createCommandExecutingSelector(name: string, contraints = {}) {
- return createSelector(createCommandSelector(name, contraints), (command) => {
- return isCommandExecuting(command);
- });
-}
-
-export default createCommandExecutingSelector;
diff --git a/frontend/src/Store/Selectors/createCommandSelector.ts b/frontend/src/Store/Selectors/createCommandSelector.ts
deleted file mode 100644
index cced7b186..000000000
--- a/frontend/src/Store/Selectors/createCommandSelector.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-import { createSelector } from 'reselect';
-import { findCommand } from 'Utilities/Command';
-import createCommandsSelector from './createCommandsSelector';
-
-function createCommandSelector(name: string, contraints = {}) {
- return createSelector(createCommandsSelector(), (commands) => {
- return findCommand(commands, { name, ...contraints });
- });
-}
-
-export default createCommandSelector;
diff --git a/frontend/src/Store/Selectors/createCommandsSelector.ts b/frontend/src/Store/Selectors/createCommandsSelector.ts
deleted file mode 100644
index 2dd5d24a2..000000000
--- a/frontend/src/Store/Selectors/createCommandsSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createCommandsSelector() {
- return createSelector(
- (state: AppState) => state.commands,
- (commands) => {
- return commands.items;
- }
- );
-}
-
-export default createCommandsSelector;
diff --git a/frontend/src/Store/Selectors/createDeepEqualSelector.ts b/frontend/src/Store/Selectors/createDeepEqualSelector.ts
deleted file mode 100644
index 9d4a63d2e..000000000
--- a/frontend/src/Store/Selectors/createDeepEqualSelector.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { isEqual } from 'lodash';
-import { createSelectorCreator, defaultMemoize } from 'reselect';
-
-const createDeepEqualSelector = createSelectorCreator(defaultMemoize, isEqual);
-
-export default createDeepEqualSelector;
diff --git a/frontend/src/Store/Selectors/createDimensionsSelector.ts b/frontend/src/Store/Selectors/createDimensionsSelector.ts
deleted file mode 100644
index b9602cb02..000000000
--- a/frontend/src/Store/Selectors/createDimensionsSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createDimensionsSelector() {
- return createSelector(
- (state: AppState) => state.app.dimensions,
- (dimensions) => {
- return dimensions;
- }
- );
-}
-
-export default createDimensionsSelector;
diff --git a/frontend/src/Store/Selectors/createExecutingCommandsSelector.ts b/frontend/src/Store/Selectors/createExecutingCommandsSelector.ts
deleted file mode 100644
index dd16571fc..000000000
--- a/frontend/src/Store/Selectors/createExecutingCommandsSelector.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import { isCommandExecuting } from 'Utilities/Command';
-
-function createExecutingCommandsSelector() {
- return createSelector(
- (state: AppState) => state.commands.items,
- (commands) => {
- return commands.filter((command) => isCommandExecuting(command));
- }
- );
-}
-
-export default createExecutingCommandsSelector;
diff --git a/frontend/src/Store/Selectors/createExistingArtistSelector.ts b/frontend/src/Store/Selectors/createExistingArtistSelector.ts
deleted file mode 100644
index 91b5bc4d6..000000000
--- a/frontend/src/Store/Selectors/createExistingArtistSelector.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { some } from 'lodash';
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import createAllArtistSelector from './createAllArtistSelector';
-
-function createExistingArtistSelector() {
- return createSelector(
- (_: AppState, { foreignArtistId }: { foreignArtistId: string }) =>
- foreignArtistId,
- createAllArtistSelector(),
- (foreignArtistId, artist) => {
- return some(artist, { foreignArtistId });
- }
- );
-}
-
-export default createExistingArtistSelector;
diff --git a/frontend/src/Store/Selectors/createHealthCheckSelector.js b/frontend/src/Store/Selectors/createHealthCheckSelector.js
deleted file mode 100644
index 86fca05b3..000000000
--- a/frontend/src/Store/Selectors/createHealthCheckSelector.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { createSelector } from 'reselect';
-
-function createHealthCheckSelector() {
- return createSelector(
- (state) => state.system.health,
- (state) => state.app,
- (health, app) => {
- const items = [...health.items];
-
- if (!app.isConnected) {
- items.push({
- source: 'UI',
- type: 'warning',
- message: 'Could not connect to SignalR, UI won\'t update',
- wikiUrl: 'https://wiki.servarr.com/lidarr/system#could-not-connect-to-signalr'
- });
- }
-
- return items;
- }
- );
-}
-
-export default createHealthCheckSelector;
diff --git a/frontend/src/Store/Selectors/createImportArtistItemSelector.js b/frontend/src/Store/Selectors/createImportArtistItemSelector.js
deleted file mode 100644
index 22406c853..000000000
--- a/frontend/src/Store/Selectors/createImportArtistItemSelector.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import _ from 'lodash';
-import { createSelector } from 'reselect';
-import createAllArtistSelector from './createAllArtistSelector';
-
-function createImportArtistItemSelector() {
- return createSelector(
- (state, { id }) => id,
- (state) => state.addArtist,
- (state) => state.importArtist,
- createAllArtistSelector(),
- (id, addArtist, importArtist, artist) => {
- const item = _.find(importArtist.items, { id }) || {};
- const selectedArtist = item && item.selectedArtist;
- const isExistingArtist = !!selectedArtist && _.some(artist, { foreignArtistId: selectedArtist.foreignArtistId });
-
- return {
- defaultMonitor: addArtist.defaults.monitor,
- defaultQualityProfileId: addArtist.defaults.qualityProfileId,
- ...item,
- isExistingArtist
- };
- }
- );
-}
-
-export default createImportArtistItemSelector;
diff --git a/frontend/src/Store/Selectors/createIndexerFlagsSelector.ts b/frontend/src/Store/Selectors/createIndexerFlagsSelector.ts
deleted file mode 100644
index 90587639c..000000000
--- a/frontend/src/Store/Selectors/createIndexerFlagsSelector.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-const createIndexerFlagsSelector = createSelector(
- (state: AppState) => state.settings.indexerFlags,
- (indexerFlags) => indexerFlags
-);
-
-export default createIndexerFlagsSelector;
diff --git a/frontend/src/Store/Selectors/createMetadataProfileSelector.ts b/frontend/src/Store/Selectors/createMetadataProfileSelector.ts
deleted file mode 100644
index ae4c061db..000000000
--- a/frontend/src/Store/Selectors/createMetadataProfileSelector.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createMetadataProfileSelector() {
- return createSelector(
- (_: AppState, { metadataProfileId }: { metadataProfileId: number }) =>
- metadataProfileId,
- (state: AppState) => state.settings.metadataProfiles.items,
- (metadataProfileId, metadataProfiles) => {
- return metadataProfiles.find(
- (profile) => profile.id === metadataProfileId
- );
- }
- );
-}
-
-export default createMetadataProfileSelector;
diff --git a/frontend/src/Store/Selectors/createMultiArtistsSelector.ts b/frontend/src/Store/Selectors/createMultiArtistsSelector.ts
deleted file mode 100644
index d8f7ea92b..000000000
--- a/frontend/src/Store/Selectors/createMultiArtistsSelector.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import Artist from 'Artist/Artist';
-
-function createMultiArtistsSelector(artistIds: number[]) {
- return createSelector(
- (state: AppState) => state.artist.itemMap,
- (state: AppState) => state.artist.items,
- (itemMap, allArtists) => {
- return artistIds.reduce((acc: Artist[], artistId) => {
- const artist = allArtists[itemMap[artistId]];
-
- if (artist) {
- acc.push(artist);
- }
-
- return acc;
- }, []);
- }
- );
-}
-
-export default createMultiArtistsSelector;
diff --git a/frontend/src/Store/Selectors/createProfileInUseSelector.ts b/frontend/src/Store/Selectors/createProfileInUseSelector.ts
deleted file mode 100644
index 85f0c3211..000000000
--- a/frontend/src/Store/Selectors/createProfileInUseSelector.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import Artist from 'Artist/Artist';
-import ImportList from 'typings/ImportList';
-import createAllArtistSelector from './createAllArtistSelector';
-
-function createProfileInUseSelector(profileProp: string) {
- return createSelector(
- (_: AppState, { id }: { id: number }) => id,
- createAllArtistSelector(),
- (state: AppState) => state.settings.importLists.items,
- (id, artists, lists) => {
- if (!id) {
- return false;
- }
-
- return (
- artists.some((a) => a[profileProp as keyof Artist] === id) ||
- lists.some((list) => list[profileProp as keyof ImportList] === id)
- );
- }
- );
-}
-
-export default createProfileInUseSelector;
diff --git a/frontend/src/Store/Selectors/createProviderSettingsSelector.js b/frontend/src/Store/Selectors/createProviderSettingsSelector.js
deleted file mode 100644
index f5ac9bad5..000000000
--- a/frontend/src/Store/Selectors/createProviderSettingsSelector.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import _ from 'lodash';
-import { createSelector } from 'reselect';
-import selectSettings from 'Store/Selectors/selectSettings';
-
-function selector(id, section) {
- if (!id) {
- const item = _.isArray(section.schema) ? section.selectedSchema : section.schema;
- const settings = selectSettings(Object.assign({ name: '' }, item), section.pendingChanges, section.saveError);
-
- const {
- isSchemaFetching: isFetching,
- isSchemaPopulated: isPopulated,
- schemaError: error,
- isSaving,
- saveError,
- isTesting,
- pendingChanges
- } = section;
-
- return {
- isFetching,
- isPopulated,
- error,
- isSaving,
- saveError,
- isTesting,
- pendingChanges,
- ...settings,
- item: settings.settings
- };
- }
-
- const {
- isFetching,
- isPopulated,
- error,
- isSaving,
- saveError,
- isTesting,
- pendingChanges
- } = section;
-
- const settings = selectSettings(_.find(section.items, { id }), pendingChanges, saveError);
-
- return {
- isFetching,
- isPopulated,
- error,
- isSaving,
- saveError,
- isTesting,
- ...settings,
- item: settings.settings
- };
-}
-
-export default function createProviderSettingsSelector(sectionName) {
- return createSelector(
- (state, { id }) => id,
- (state) => state.settings[sectionName],
- (id, section) => selector(id, section)
- );
-}
-
-export function createProviderSettingsSelectorHook(sectionName, id) {
- return createSelector(
- (state) => state.settings[sectionName],
- (section) => selector(id, section)
- );
-}
-
diff --git a/frontend/src/Store/Selectors/createQualityProfileSelector.ts b/frontend/src/Store/Selectors/createQualityProfileSelector.ts
deleted file mode 100644
index b913e0c46..000000000
--- a/frontend/src/Store/Selectors/createQualityProfileSelector.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-export function createQualityProfileSelectorForHook(qualityProfileId: number) {
- return createSelector(
- (state: AppState) => state.settings.qualityProfiles.items,
- (qualityProfiles) => {
- return qualityProfiles.find((profile) => profile.id === qualityProfileId);
- }
- );
-}
-
-function createQualityProfileSelector() {
- return createSelector(
- (_: AppState, { qualityProfileId }: { qualityProfileId: number }) =>
- qualityProfileId,
- (state: AppState) => state.settings.qualityProfiles.items,
- (qualityProfileId, qualityProfiles) => {
- return qualityProfiles.find((profile) => profile.id === qualityProfileId);
- }
- );
-}
-
-export default createQualityProfileSelector;
diff --git a/frontend/src/Store/Selectors/createQueueItemSelector.ts b/frontend/src/Store/Selectors/createQueueItemSelector.ts
deleted file mode 100644
index 54951a724..000000000
--- a/frontend/src/Store/Selectors/createQueueItemSelector.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createQueueItemSelector() {
- return createSelector(
- (_: AppState, { albumId }: { albumId: number }) => albumId,
- (state: AppState) => state.queue.details.items,
- (albumId, details) => {
- if (!albumId || !details) {
- return null;
- }
-
- return details.find((item) => item.albumId === albumId);
- }
- );
-}
-
-export default createQueueItemSelector;
diff --git a/frontend/src/Store/Selectors/createRootFoldersSelector.ts b/frontend/src/Store/Selectors/createRootFoldersSelector.ts
deleted file mode 100644
index 432f9056d..000000000
--- a/frontend/src/Store/Selectors/createRootFoldersSelector.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { createSelector } from 'reselect';
-import { RootFolderAppState } from 'App/State/SettingsAppState';
-import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
-import RootFolder from 'typings/RootFolder';
-import sortByProp from 'Utilities/Array/sortByProp';
-
-export default function createRootFoldersSelector() {
- return createSelector(
- createSortedSectionSelector(
- 'settings.rootFolders',
- sortByProp('name')
- ),
- (rootFolders: RootFolderAppState) => rootFolders
- );
-}
diff --git a/frontend/src/Store/Selectors/createSettingsSectionSelector.js b/frontend/src/Store/Selectors/createSettingsSectionSelector.js
deleted file mode 100644
index a9f6cbff6..000000000
--- a/frontend/src/Store/Selectors/createSettingsSectionSelector.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { createSelector } from 'reselect';
-import selectSettings from 'Store/Selectors/selectSettings';
-
-function createSettingsSectionSelector(section) {
- return createSelector(
- (state) => state.settings[section],
- (sectionSettings) => {
- const {
- isFetching,
- isPopulated,
- error,
- item,
- pendingChanges,
- isSaving,
- saveError
- } = sectionSettings;
-
- const settings = selectSettings(item, pendingChanges, saveError);
-
- return {
- isFetching,
- isPopulated,
- error,
- isSaving,
- saveError,
- ...settings
- };
- }
- );
-}
-
-export default createSettingsSectionSelector;
diff --git a/frontend/src/Store/Selectors/createSortedSectionSelector.ts b/frontend/src/Store/Selectors/createSortedSectionSelector.ts
deleted file mode 100644
index abee01f75..000000000
--- a/frontend/src/Store/Selectors/createSortedSectionSelector.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { createSelector } from 'reselect';
-import getSectionState from 'Utilities/State/getSectionState';
-
-function createSortedSectionSelector(
- section: string,
- comparer: (a: T, b: T) => number
-) {
- return createSelector(
- (state) => state,
- (state) => {
- const sectionState = getSectionState(state, section, true);
-
- return {
- ...sectionState,
- items: [...sectionState.items].sort(comparer),
- };
- }
- );
-}
-
-export default createSortedSectionSelector;
diff --git a/frontend/src/Store/Selectors/createSystemStatusSelector.ts b/frontend/src/Store/Selectors/createSystemStatusSelector.ts
deleted file mode 100644
index f5e276069..000000000
--- a/frontend/src/Store/Selectors/createSystemStatusSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createSystemStatusSelector() {
- return createSelector(
- (state: AppState) => state.system.status,
- (status) => {
- return status.item;
- }
- );
-}
-
-export default createSystemStatusSelector;
diff --git a/frontend/src/Store/Selectors/createTagDetailsSelector.ts b/frontend/src/Store/Selectors/createTagDetailsSelector.ts
deleted file mode 100644
index 2a271cafe..000000000
--- a/frontend/src/Store/Selectors/createTagDetailsSelector.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createTagDetailsSelector() {
- return createSelector(
- (_: AppState, { id }: { id: number }) => id,
- (state: AppState) => state.tags.details.items,
- (id, tagDetails) => {
- return tagDetails.find((t) => t.id === id);
- }
- );
-}
-
-export default createTagDetailsSelector;
diff --git a/frontend/src/Store/Selectors/createTagsSelector.ts b/frontend/src/Store/Selectors/createTagsSelector.ts
deleted file mode 100644
index f653ff6e3..000000000
--- a/frontend/src/Store/Selectors/createTagsSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createTagsSelector() {
- return createSelector(
- (state: AppState) => state.tags.items,
- (tags) => {
- return tags;
- }
- );
-}
-
-export default createTagsSelector;
diff --git a/frontend/src/Store/Selectors/createTrackFileSelector.ts b/frontend/src/Store/Selectors/createTrackFileSelector.ts
deleted file mode 100644
index a162df1fa..000000000
--- a/frontend/src/Store/Selectors/createTrackFileSelector.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createTrackFileSelector() {
- return createSelector(
- (_: AppState, { trackFileId }: { trackFileId: number }) => trackFileId,
- (state: AppState) => state.trackFiles,
- (trackFileId, trackFiles) => {
- if (!trackFileId) {
- return;
- }
-
- return trackFiles.items.find((trackFile) => trackFile.id === trackFileId);
- }
- );
-}
-
-export default createTrackFileSelector;
diff --git a/frontend/src/Store/Selectors/createTrackSelector.js b/frontend/src/Store/Selectors/createTrackSelector.js
deleted file mode 100644
index be57e6ca0..000000000
--- a/frontend/src/Store/Selectors/createTrackSelector.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import _ from 'lodash';
-import { createSelector } from 'reselect';
-
-function createTrackSelector() {
- return createSelector(
- (state, { trackId }) => trackId,
- (state) => state.tracks,
- (trackId, tracks) => {
- return _.find(tracks.items, { id: trackId });
- }
- );
-}
-
-export default createTrackSelector;
diff --git a/frontend/src/Store/Selectors/createUISettingsSelector.ts b/frontend/src/Store/Selectors/createUISettingsSelector.ts
deleted file mode 100644
index ff539679b..000000000
--- a/frontend/src/Store/Selectors/createUISettingsSelector.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-
-function createUISettingsSelector() {
- return createSelector(
- (state: AppState) => state.settings.ui,
- (ui) => {
- return ui.item;
- }
- );
-}
-
-export default createUISettingsSelector;
diff --git a/frontend/src/Store/Selectors/selectSettings.js b/frontend/src/Store/Selectors/selectSettings.js
deleted file mode 100644
index 3e30478b7..000000000
--- a/frontend/src/Store/Selectors/selectSettings.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import _ from 'lodash';
-
-function getValidationFailures(saveError) {
- if (!saveError || saveError.status !== 400) {
- return [];
- }
-
- return _.cloneDeep(saveError.responseJSON);
-}
-
-function mapFailure(failure) {
- return {
- message: failure.errorMessage,
- link: failure.infoLink,
- detailedMessage: failure.detailedDescription
- };
-}
-
-function selectSettings(item, pendingChanges, saveError) {
- const validationFailures = getValidationFailures(saveError);
-
- // Merge all settings from the item along with pending
- // changes to ensure any settings that were not included
- // with the item are included.
- const allSettings = Object.assign({}, item, pendingChanges);
-
- const settings = _.reduce(allSettings, (result, value, key) => {
- if (key === 'fields') {
- return result;
- }
-
- // Return a flattened value
- if (key === 'implementationName') {
- result.implementationName = item[key];
-
- return result;
- }
-
- const setting = {
- value: item[key],
- errors: _.map(_.remove(validationFailures, (failure) => {
- return failure.propertyName.toLowerCase() === key.toLowerCase() && !failure.isWarning;
- }), mapFailure),
-
- warnings: _.map(_.remove(validationFailures, (failure) => {
- return failure.propertyName.toLowerCase() === key.toLowerCase() && failure.isWarning;
- }), mapFailure)
- };
-
- if (pendingChanges.hasOwnProperty(key)) {
- setting.previousValue = setting.value;
- setting.value = pendingChanges[key];
- setting.pending = true;
- }
-
- result[key] = setting;
- return result;
- }, {});
-
- const fields = _.reduce(item.fields, (result, f) => {
- const field = Object.assign({ pending: false }, f);
- const hasPendingFieldChange = pendingChanges.fields && pendingChanges.fields.hasOwnProperty(field.name);
-
- if (hasPendingFieldChange) {
- field.previousValue = field.value;
- field.value = pendingChanges.fields[field.name];
- field.pending = true;
- }
-
- field.errors = _.map(_.remove(validationFailures, (failure) => {
- return failure.propertyName.toLowerCase() === field.name.toLowerCase() && !failure.isWarning;
- }), mapFailure);
-
- field.warnings = _.map(_.remove(validationFailures, (failure) => {
- return failure.propertyName.toLowerCase() === field.name.toLowerCase() && failure.isWarning;
- }), mapFailure);
-
- result.push(field);
- return result;
- }, []);
-
- if (fields.length) {
- settings.fields = fields;
- }
-
- const validationErrors = _.filter(validationFailures, (failure) => {
- return !failure.isWarning;
- });
-
- const validationWarnings = _.filter(validationFailures, (failure) => {
- return failure.isWarning;
- });
-
- return {
- settings,
- validationErrors,
- validationWarnings,
- hasPendingChanges: !_.isEmpty(pendingChanges),
- hasSettings: !_.isEmpty(settings),
- pendingChanges
- };
-}
-
-export default selectSettings;
diff --git a/frontend/src/Store/createAppStore.js b/frontend/src/Store/createAppStore.js
deleted file mode 100644
index 4fef265f1..000000000
--- a/frontend/src/Store/createAppStore.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { createStore } from 'redux';
-import createReducers, { defaultState } from 'Store/Actions/createReducers';
-import middlewares from 'Store/Middleware/middlewares';
-
-function createAppStore(history) {
- const appStore = createStore(
- createReducers(history),
- defaultState,
- middlewares(history)
- );
-
- return appStore;
-}
-
-export default createAppStore;
diff --git a/frontend/src/Store/scrollPositions.ts b/frontend/src/Store/scrollPositions.ts
deleted file mode 100644
index 199bfa84c..000000000
--- a/frontend/src/Store/scrollPositions.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-const scrollPositions: Record = {
- artistIndex: 0,
-};
-
-export default scrollPositions;
diff --git a/frontend/src/Store/thunks.ts b/frontend/src/Store/thunks.ts
deleted file mode 100644
index fd277211e..000000000
--- a/frontend/src/Store/thunks.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { Dispatch } from 'redux';
-import AppState from 'App/State/AppState';
-
-type GetState = () => AppState;
-type Thunk = (
- getState: GetState,
- identityFn: never,
- dispatch: Dispatch
-) => unknown;
-
-const thunks: Record = {};
-
-function identity(payload: T): TResult {
- return payload as unknown as TResult;
-}
-
-export function createThunk(type: string, identityFunction = identity) {
- return function (payload?: T) {
- return function (dispatch: Dispatch, getState: GetState) {
- const thunk = thunks[type];
-
- if (thunk) {
- const finalPayload = payload ?? {};
-
- return thunk(getState, identityFunction(finalPayload), dispatch);
- }
-
- throw Error(`Thunk handler has not been registered for ${type}`);
- };
- };
-}
-
-export function handleThunks(handlers: Record) {
- const types = Object.keys(handlers);
-
- types.forEach((type) => {
- thunks[type] = handlers[type];
- });
-}
diff --git a/frontend/src/Styles/Mixins/cover.css b/frontend/src/Styles/Mixins/cover.css
deleted file mode 100644
index e44c99be6..000000000
--- a/frontend/src/Styles/Mixins/cover.css
+++ /dev/null
@@ -1,8 +0,0 @@
-@define-mixin cover {
- position: absolute;
- top: 0;
- left: 0;
- display: block;
- width: 100%;
- height: 100%;
-}
diff --git a/frontend/src/Styles/Mixins/linkOverlay.css b/frontend/src/Styles/Mixins/linkOverlay.css
deleted file mode 100644
index 74c3fd753..000000000
--- a/frontend/src/Styles/Mixins/linkOverlay.css
+++ /dev/null
@@ -1,11 +0,0 @@
-@define-mixin linkOverlay {
- @add-mixin cover;
-
- pointer-events: none;
- user-select: none;
-
- a,
- button {
- pointer-events: all;
- }
-}
diff --git a/frontend/src/Styles/Mixins/scroller.css b/frontend/src/Styles/Mixins/scroller.css
deleted file mode 100644
index 29b2016b9..000000000
--- a/frontend/src/Styles/Mixins/scroller.css
+++ /dev/null
@@ -1,29 +0,0 @@
-@define-mixin scrollbar {
- scrollbar-color: var(--scrollbarBackgroundColor) transparent;
- scrollbar-width: thin;
-
- &::-webkit-scrollbar {
- width: 10px;
- height: 10px;
- }
-}
-
-@define-mixin scrollbarTrack {
- &::-webkit-scrollbar-track {
- background-color: transparent;
- }
-}
-
-@define-mixin scrollbarThumb {
- &::-webkit-scrollbar-thumb {
- min-height: 100px;
- border: 1px solid transparent;
- border-radius: 5px;
- background-color: var(--scrollbarBackgroundColor);
- background-clip: padding-box;
-
- &:hover {
- background-color: var(--scrollbarHoverBackgroundColor);
- }
- }
-}
diff --git a/frontend/src/Styles/Mixins/truncate.css b/frontend/src/Styles/Mixins/truncate.css
deleted file mode 100644
index 1941afc9b..000000000
--- a/frontend/src/Styles/Mixins/truncate.css
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * From: https://github.com/suitcss/utils-text/blob/master/lib/text.css
- *
- * Text truncation
- *
- * Prevent text from wrapping onto multiple lines, and truncate with an
- * ellipsis.
- *
- * 1. Ensure that the node has a maximum width after which truncation can
- * occur.
- */
-
-@define-mixin truncate {
- overflow: hidden !important;
- max-width: 100%; /* 1 */
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
-}
diff --git a/frontend/src/Styles/Themes/dark.js b/frontend/src/Styles/Themes/dark.js
deleted file mode 100644
index 7513139a4..000000000
--- a/frontend/src/Styles/Themes/dark.js
+++ /dev/null
@@ -1,241 +0,0 @@
-const lidarrGreen = '#00A65B';
-const darkGray = '#888';
-const gray = '#adadad';
-const black = '#000';
-const white = '#fff';
-const offWhite = '#f5f7fa';
-const purple = '#7a43b6';
-const pink = '#ff69b4';
-const lightGray = '#ddd';
-
-module.exports = {
- textColor: '#ccc',
- defaultColor: '#ccc',
- disabledColor: '#999',
- dimColor: '#555',
- black,
- white,
- offWhite,
- blue: '#06f',
- primaryColor: '#5d9cec',
- selectedColor: '#f9be03',
- successColor: '#00853d',
- dangerColor: '#f05050',
- warningColor: '#ffa500',
- infoColor: lidarrGreen,
- purple,
- pink,
- lidarrGreen,
- helpTextColor: '#909293',
- darkGray,
- gray,
- lightGray,
-
- // Theme Colors
-
- themeBlue: lidarrGreen,
- themeAlternateBlue: '#00a65b',
- themeRed: '#c4273c',
- themeDarkColor: '#494949',
- themeLightColor: '#595959',
- pageBackground: '#202020',
- pageFooterBackground: 'rgba(0, 0, 0, .25)',
-
- torrentColor: '#00853d',
- usenetColor: '#17b1d9',
-
- // Labels
- inverseLabelColor: '#ddd',
- inverseLabelTextColor: '#333',
- disabledLabelColor: '#838383',
- infoTextColor: white,
-
- // Links
- defaultLinkHoverColor: '#fff',
- linkColor: '#fff',
- linkHoverColor: '#0b8750',
-
- // Header
- pageHeaderBackgroundColor: '#2a2a2a',
-
- // Sidebar
-
- sidebarColor: '#e1e2e3',
- sidebarBackgroundColor: '#2a2a2a',
- sidebarActiveBackgroundColor: '#333333',
-
- // Toolbar
- toolbarColor: '#e1e2e3',
- toolbarBackgroundColor: '#262626',
- toolbarMenuItemBackgroundColor: '#333',
- toolbarMenuItemHoverBackgroundColor: '#414141',
- toolbarLabelColor: '#e1e2e3',
-
- // Accents
- borderColor: '#858585',
- inputBorderColor: '#dde6e9',
- inputBoxShadowColor: 'rgba(0, 0, 0, 0.075)',
- inputFocusBorderColor: '#66afe9',
- inputFocusBoxShadowColor: 'rgba(102, 175, 233, 0.6)',
- inputErrorBorderColor: '#f05050',
- inputErrorBoxShadowColor: 'rgba(240, 80, 80, 0.6)',
- inputWarningBorderColor: '#ffa500',
- inputWarningBoxShadowColor: 'rgba(255, 165, 0, 0.6)',
- colorImpairedGradient: '#707070',
- colorImpairedGradientDark: '#424242',
- colorImpairedDangerGradient: '#d84848',
- colorImpairedWarningGradient: '#e59400',
- colorImpairedPrimaryGradient: '#538cd4',
- colorImpairedGrayGradient: '#9b9b9b',
-
- //
- // Buttons
-
- defaultButtonTextColor: '#eee',
- defaultBackgroundColor: '#333',
- defaultBorderColor: '#393f45',
- defaultHoverBackgroundColor: '#444',
- defaultHoverBorderColor: '#5a6265',
-
- primaryBackgroundColor: '#0b8750',
- primaryBorderColor: '#1d563d',
- primaryHoverBackgroundColor: '#097948',
- primaryHoverBorderColor: '#1D563D',
-
- successBackgroundColor: '#27c24c',
- successBorderColor: '#26be4a',
- successHoverBackgroundColor: '#24b145',
- successHoverBorderColor: '#1f9c3d',
-
- warningBackgroundColor: '#ff902b',
- warningBorderColor: '#ff8d26',
- warningHoverBackgroundColor: '#ff8517',
- warningHoverBorderColor: '#fc7800',
-
- dangerBackgroundColor: '#f05050',
- dangerBorderColor: '#f04b4b',
- dangerHoverBackgroundColor: '#ee3d3d',
- dangerHoverBorderColor: '#ec2626',
-
- iconButtonDisabledColor: '#7a7a7a',
- iconButtonHoverColor: '#666',
- iconButtonHoverLightColor: '#ccc',
-
- //
- // Modal
-
- modalBackdropBackgroundColor: 'rgba(0, 0, 0, 0.6)',
- modalBackgroundColor: '#2a2a2a',
- modalCloseButtonHoverColor: '#888',
-
- //
- // Menu
- menuItemColor: '#e1e2e3',
- menuItemHoverColor: lidarrGreen,
- menuItemHoverBackgroundColor: '#606060',
-
- //
- // Toolbar
-
- toobarButtonHoverColor: lidarrGreen,
- toobarButtonSelectedColor: lidarrGreen,
-
- //
- // Scroller
-
- scrollbarBackgroundColor: '#707070',
- scrollbarHoverBackgroundColor: '#606060',
-
- //
- // Card
-
- cardBackgroundColor: '#333333',
- cardShadowColor: '#111',
- cardAlternateBackgroundColor: '#333333',
- cardCenterBackgroundColor: '#2a2a2a',
-
- //
- // Alert
-
- alertDangerBorderColor: '#a94442',
- alertDangerBackgroundColor: 'rgba(255,0,0,0.1)',
- alertDangerColor: '#ccc',
-
- alertInfoBorderColor: '#31708f',
- alertInfoBackgroundColor: 'rgba(0,0,255,0.1)',
- alertInfoColor: '#ccc',
-
- alertSuccessBorderColor: '#3c763d',
- alertSuccessBackgroundColor: 'rgba(0,255,0,0.1)',
- alertSuccessColor: '#ccc',
-
- alertWarningBorderColor: '#8a6d3b',
- alertWarningBackgroundColor: 'rgba(255,255,0,0.1)',
- alertWarningColor: '#ccc',
-
- //
- // Slider
-
- sliderAccentColor: '#0b8750',
-
- //
- // Form
-
- inputBackgroundColor: '#333',
- inputReadOnlyBackgroundColor: '#222',
- inputHoverBackgroundColor: 'rgba(255, 255, 255, 0.20)',
- inputSelectedBackgroundColor: 'rgba(255, 255, 255, 0.05)',
- advancedFormLabelColor: '#ff902b',
- disabledCheckInputColor: '#ddd',
- disabledInputColor: '#808080',
-
- //
- // Popover
-
- popoverTitleBackgroundColor: '#424242',
- popoverTitleBorderColor: '#2a2a2a',
- popoverBodyBackgroundColor: '#2a2a2a',
- popoverShadowColor: 'rgba(0, 0, 0, 0.2)',
- popoverArrowBorderColor: '#2a2a2a',
-
- popoverTitleBackgroundInverseColor: '#595959',
- popoverTitleBorderInverseColor: '#707070',
- popoverShadowInverseColor: 'rgba(0, 0, 0, 0.2)',
- popoverArrowBorderInverseColor: 'rgba(58, 63, 81, 0.75)',
-
- //
- // Calendar
-
- calendarTodayBackgroundColor: '#3e3e3e',
- calendarBackgroundColor: '#2a2a2a',
- calendarBorderColor: '#393f45',
- calendarTextDim: '#eee',
- calendarTextDimAlternate: '#fff',
-
- //
- // Table
-
- tableRowHoverBackgroundColor: 'rgba(255, 255, 255, 0.08)',
-
- //
- // Srtist
-
- addArtistBackgroundColor: '#2a2a2a',
- artistBackgroundColor: '#2a2a2a',
- searchIconContainerBackgroundColor: '#2b2b2b',
- collapseButtonBackgroundColor: '#2a2a2a',
-
- //
- // Album
-
- albumBackgroundColor: '#424242',
- trackBackgroundColor: '#2a2a2a',
-
- //
- // misc
-
- progressBarFrontTextColor: white,
- progressBarBackTextColor: white,
- progressBarBackgroundColor: '#727070',
- logEventsBackgroundColor: '#2a2a2a'
-};
diff --git a/frontend/src/Styles/Themes/index.js b/frontend/src/Styles/Themes/index.js
deleted file mode 100644
index 4dec39164..000000000
--- a/frontend/src/Styles/Themes/index.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import * as dark from './dark';
-import * as light from './light';
-
-const defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
-const auto = defaultDark ? dark : light;
-
-export default {
- auto,
- light,
- dark
-};
diff --git a/frontend/src/Styles/Themes/light.js b/frontend/src/Styles/Themes/light.js
deleted file mode 100644
index ccf5dcea6..000000000
--- a/frontend/src/Styles/Themes/light.js
+++ /dev/null
@@ -1,235 +0,0 @@
-const lidarrGreen = '#00A65B';
-const darkGray = '#888';
-const gray = '#adadad';
-const black = '#000';
-const white = '#fff';
-const offWhite = '#f5f7fa';
-const purple = '#7a43b6';
-const pink = '#ff69b4';
-const lightGray = '#ddd';
-
-module.exports = {
- textColor: '#515253',
- defaultColor: '#333',
- disabledColor: '#999',
- dimColor: '#555',
- black,
- white,
- offWhite,
- blue: '#06f',
- primaryColor: '#5d9cec',
- selectedColor: '#f9be03',
- successColor: '#00853d',
- dangerColor: '#f05050',
- warningColor: '#ffa500',
- infoColor: lidarrGreen,
- purple,
- pink,
- lidarrGreen,
- helpTextColor: '#909293',
- darkGray,
- gray,
- lightGray,
-
- // Theme Colors
-
- themeBlue: lidarrGreen,
- themeAlternateBlue: '#00a65b',
- themeRed: '#c4273c',
- themeDarkColor: '#353535',
- themeLightColor: '#1d563d',
- pageBackground: '#f5f7fa',
- pageFooterBackground: '#f1f1f1',
-
- torrentColor: '#00853d',
- usenetColor: '#17b1d9',
-
- // Labels
- inverseLabelColor: '#ddd',
- inverseLabelTextColor: '#333',
- disabledLabelColor: '#999',
- infoTextColor: white,
-
- // Links
- defaultLinkHoverColor: '#fff',
- linkColor: '#0b8750',
- linkHoverColor: '#1b72e2',
-
- // Header
- pageHeaderBackgroundColor: lidarrGreen,
-
- // Sidebar
-
- sidebarColor: '#e1e2e3',
- sidebarBackgroundColor: '#353535',
- sidebarActiveBackgroundColor: '#252525',
-
- // Toolbar
- toolbarColor: '#e1e2e3',
- toolbarBackgroundColor: '#1d563d',
- toolbarMenuItemBackgroundColor: '#4D8069',
- toolbarMenuItemHoverBackgroundColor: '#353535',
- toolbarLabelColor: '#8895aa',
-
- // Accents
- borderColor: '#e5e5e5',
- inputBorderColor: '#dde6e9',
- inputBoxShadowColor: 'rgba(0, 0, 0, 0.075)',
- inputFocusBorderColor: '#66afe9',
- inputFocusBoxShadowColor: 'rgba(102, 175, 233, 0.6)',
- inputErrorBorderColor: '#f05050',
- inputErrorBoxShadowColor: 'rgba(240, 80, 80, 0.6)',
- inputWarningBorderColor: '#ffa500',
- inputWarningBoxShadowColor: 'rgba(255, 165, 0, 0.6)',
- colorImpairedGradient: '#ffffff',
- colorImpairedGradientDark: '#f4f5f6',
-
- //
- // Buttons
-
- defaultButtonTextColor: '#eee',
- defaultBackgroundColor: '#fff',
- defaultBorderColor: '#eaeaea',
- defaultHoverBackgroundColor: '#f5f5f5',
- defaultHoverBorderColor: '#d6d6d6',
-
- primaryBackgroundColor: '#0b8750',
- primaryBorderColor: '#1d563d',
- primaryHoverBackgroundColor: '#097948',
- primaryHoverBorderColor: '#1D563D',
-
- successBackgroundColor: '#27c24c',
- successBorderColor: '#26be4a',
- successHoverBackgroundColor: '#24b145',
- successHoverBorderColor: '#1f9c3d',
-
- warningBackgroundColor: '#ff902b',
- warningBorderColor: '#ff8d26',
- warningHoverBackgroundColor: '#ff8517',
- warningHoverBorderColor: '#fc7800',
-
- dangerBackgroundColor: '#f05050',
- dangerBorderColor: '#f04b4b',
- dangerHoverBackgroundColor: '#ee3d3d',
- dangerHoverBorderColor: '#ec2626',
-
- iconButtonDisabledColor: '#7a7a7a',
- iconButtonHoverColor: '#666',
- iconButtonHoverLightColor: '#ccc',
-
- //
- // Modal
-
- modalBackdropBackgroundColor: 'rgba(0, 0, 0, 0.6)',
- modalBackgroundColor: '#fff',
- modalCloseButtonHoverColor: '#888',
-
- //
- // Menu
- menuItemColor: '#e1e2e3',
- menuItemHoverColor: '#fbfcfc',
- menuItemHoverBackgroundColor: '#f5f7fa',
-
- //
- // Toolbar
-
- toobarButtonHoverColor: '#00A65B',
- toobarButtonSelectedColor: '#00A65B',
-
- //
- // Scroller
-
- scrollbarBackgroundColor: '#9ea4b9',
- scrollbarHoverBackgroundColor: '#656d8c',
-
- //
- // Card
-
- cardBackgroundColor: '#fff',
- cardShadowColor: '#e1e1e1',
- cardAlternateBackgroundColor: '#f5f5f5',
- cardCenterBackgroundColor: '#fff',
-
- //
- // Alert
-
- alertDangerBorderColor: '#ebccd1',
- alertDangerBackgroundColor: '#f2dede',
- alertDangerColor: '#a94442',
-
- alertInfoBorderColor: '#bce8f1',
- alertInfoBackgroundColor: '#d9edf7',
- alertInfoColor: '#31708f',
-
- alertSuccessBorderColor: '#d6e9c6',
- alertSuccessBackgroundColor: '#dff0d8',
- alertSuccessColor: '#3c763d',
-
- alertWarningBorderColor: '#faebcc',
- alertWarningBackgroundColor: '#fcf8e3',
- alertWarningColor: '#8a6d3b',
-
- //
- // Slider
-
- sliderAccentColor: '#0b8750',
-
- //
- // Form
-
- inputBackgroundColor: '#fff',
- inputReadOnlyBackgroundColor: '#eee',
- inputHoverBackgroundColor: '#f8f8f8',
- inputSelectedBackgroundColor: '#e2e2e2',
- advancedFormLabelColor: '#ff902b',
- disabledCheckInputColor: '#ddd',
- disabledInputColor: '#808080',
-
- //
- // Popover
-
- popoverTitleBackgroundColor: '#f7f7f7',
- popoverTitleBorderColor: '#ebebeb',
- popoverBodyBackgroundColor: '#e9e9e9',
- popoverShadowColor: 'rgba(0, 0, 0, 0.2)',
- popoverArrowBorderColor: '#fff',
-
- popoverTitleBackgroundInverseColor: '#3a3f51',
- popoverTitleBorderInverseColor: '#353535',
- popoverShadowInverseColor: 'rgba(0, 0, 0, 0.2)',
- popoverArrowBorderInverseColor: 'rgba(58, 63, 81, 0.75)',
-
- //
- // Calendar
-
- calendarTodayBackgroundColor: '#c5c5c5',
- calendarBackgroundColor: '#e4eaec',
- calendarBorderColor: '#cecece',
-
- //
- // Table
-
- tableRowHoverBackgroundColor: '#fafbfc',
-
- //
- // Atist
-
- addArtistBackgroundColor: '#ededed',
- artistBackgroundColor: '#ededed',
- searchIconContainerBackgroundColor: offWhite,
- collapseButtonBackgroundColor: offWhite,
-
- //
- // Album
-
- albumBackgroundColor: white,
- trackBackgroundColor: offWhite,
-
- //
- // misc
-
- progressBarFrontTextColor: white,
- progressBarBackTextColor: darkGray,
- progressBarBackgroundColor: white,
- logEventsBackgroundColor: white
-};
diff --git a/frontend/src/Styles/Variables/animations.js b/frontend/src/Styles/Variables/animations.js
deleted file mode 100644
index 52d12827a..000000000
--- a/frontend/src/Styles/Variables/animations.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// Use CommonJS since this is consumed by PostCSS via webpack (node.js).
-
-module.exports = {
- // Durations
- defaultSpeed: '0.2s',
- slowSpeed: '0.6s',
- fastSpeed: '0.1s'
-};
diff --git a/frontend/src/Styles/Variables/dimensions.js b/frontend/src/Styles/Variables/dimensions.js
deleted file mode 100644
index a704270ff..000000000
--- a/frontend/src/Styles/Variables/dimensions.js
+++ /dev/null
@@ -1,53 +0,0 @@
-module.exports = {
- // Page
- pageContentBodyPadding: '20px',
- pageContentBodyPaddingSmallScreen: '10px',
-
- // Header
- headerHeight: '60px',
-
- // Sidebar
- sidebarWidth: '210px',
-
- // Toolbar
- toolbarHeight: '60px',
- toolbarButtonWidth: '60px',
- toolbarSeparatorMargin: '20px',
-
- // Break Points
- breakpointExtraSmall: '480px',
- breakpointSmall: '768px',
- breakpointMedium: '992px',
- breakpointLarge: '1310px',
- breakpointExtraLarge: '1450px',
-
- // Form
- formGroupExtraSmallWidth: '550px',
- formGroupSmallWidth: '650px',
- formGroupMediumWidth: '800px',
- formGroupLargeWidth: '1200px',
- formLabelSmallWidth: '150px',
- formLabelLargeWidth: '250px',
- formLabelRightMarginWidth: '20px',
-
- // Drag
- dragHandleWidth: '40px',
- qualityProfileItemHeight: '30px',
- qualityProfileItemDragSourcePadding: '4px',
-
- // Progress Bar
- progressBarSmallHeight: '5px',
- progressBarMediumHeight: '15px',
- progressBarLargeHeight: '20px',
-
- // Jump Bar
- jumpBarItemHeight: '25px',
-
- // Modal
- modalBodyPadding: '30px',
-
- // Artist
- artistIndexColumnPadding: '10px',
- artistIndexColumnPaddingSmallScreen: '5px',
- artistIndexOverviewInfoRowHeight: '21px'
-};
diff --git a/frontend/src/Styles/Variables/fonts.js b/frontend/src/Styles/Variables/fonts.js
deleted file mode 100644
index def48f28e..000000000
--- a/frontend/src/Styles/Variables/fonts.js
+++ /dev/null
@@ -1,14 +0,0 @@
-module.exports = {
- // Families
- defaultFontFamily: 'Roboto, "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif',
- monoSpaceFontFamily: '"Ubuntu Mono", Menlo, Monaco, Consolas, "Courier New", monospace;',
-
- // Sizes
- extraSmallFontSize: '11px',
- smallFontSize: '12px',
- defaultFontSize: '14px',
- intermediateFontSize: '15px',
- largeFontSize: '16px',
-
- lineHeight: '1.528571429'
-};
diff --git a/frontend/src/Styles/Variables/zIndexes.js b/frontend/src/Styles/Variables/zIndexes.js
deleted file mode 100644
index 4d10253a7..000000000
--- a/frontend/src/Styles/Variables/zIndexes.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- pageJumpBarZIndex: 10,
- modalZIndex: 1000,
- popperZIndex: 2000
-};
diff --git a/frontend/src/Styles/globals.css b/frontend/src/Styles/globals.css
deleted file mode 100644
index e630c77b9..000000000
--- a/frontend/src/Styles/globals.css
+++ /dev/null
@@ -1,6 +0,0 @@
-/* stylelint-disable */
-
-@import "~normalize.css/normalize.css";
-@import "scaffolding.css";
-
-/* stylelint-enable */
\ No newline at end of file
diff --git a/frontend/src/Styles/scaffolding.css b/frontend/src/Styles/scaffolding.css
deleted file mode 100644
index 3f5f0fa65..000000000
--- a/frontend/src/Styles/scaffolding.css
+++ /dev/null
@@ -1,54 +0,0 @@
-/* stylelint-disable */
-* {
- box-sizing: border-box;
-}
-
-*::before,
-*::after {
- box-sizing: border-box;
-}
-
-*:focus {
- outline: none;
-}
-/* stylelint-enable */
-
-html,
-body {
- color: var(--textColor);
- font-family: 'Roboto', 'open sans', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
-}
-
-body {
- font-size: 14px;
- line-height: 1.528571429; /* 20/14 */
-}
-
-/* Override normalize */
-
-button,
-input,
-optgroup,
-select,
-textarea {
- margin: 0;
- font-size: inherit;
- font-family: inherit;
- line-height: 1.528571429; /* 20/14 */
-}
-
-/* Better defaults for unordererd lists */
-
-ul {
- margin: 0;
- padding-left: 20px;
-}
-
-@media only screen and (min-device-width: 375px) and (max-device-width: 812px) {
- input,
- optgroup,
- select,
- textarea {
- font-size: 16px;
- }
-}
diff --git a/frontend/src/System/Backup/BackupRow.css b/frontend/src/System/Backup/BackupRow.css
deleted file mode 100644
index db805650e..000000000
--- a/frontend/src/System/Backup/BackupRow.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.type {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 20px;
- text-align: center;
-}
-
-.actions {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 70px;
-}
diff --git a/frontend/src/System/Backup/BackupRow.css.d.ts b/frontend/src/System/Backup/BackupRow.css.d.ts
deleted file mode 100644
index d758c14ca..000000000
--- a/frontend/src/System/Backup/BackupRow.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'type': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Backup/BackupRow.js b/frontend/src/System/Backup/BackupRow.js
deleted file mode 100644
index f053ef741..000000000
--- a/frontend/src/System/Backup/BackupRow.js
+++ /dev/null
@@ -1,161 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Icon from 'Components/Icon';
-import IconButton from 'Components/Link/IconButton';
-import Link from 'Components/Link/Link';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableRow from 'Components/Table/TableRow';
-import { icons, kinds } from 'Helpers/Props';
-import formatBytes from 'Utilities/Number/formatBytes';
-import translate from 'Utilities/String/translate';
-import RestoreBackupModalConnector from './RestoreBackupModalConnector';
-import styles from './BackupRow.css';
-
-class BackupRow extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isRestoreModalOpen: false,
- isConfirmDeleteModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onRestorePress = () => {
- this.setState({ isRestoreModalOpen: true });
- };
-
- onRestoreModalClose = () => {
- this.setState({ isRestoreModalOpen: false });
- };
-
- onDeletePress = () => {
- this.setState({ isConfirmDeleteModalOpen: true });
- };
-
- onConfirmDeleteModalClose = () => {
- this.setState({ isConfirmDeleteModalOpen: false });
- };
-
- onConfirmDeletePress = () => {
- const {
- id,
- onDeleteBackupPress
- } = this.props;
-
- this.setState({ isConfirmDeleteModalOpen: false }, () => {
- onDeleteBackupPress(id);
- });
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- type,
- name,
- path,
- size,
- time
- } = this.props;
-
- const {
- isRestoreModalOpen,
- isConfirmDeleteModalOpen
- } = this.state;
-
- let iconClassName = icons.SCHEDULED;
- let iconTooltip = translate('Scheduled');
-
- if (type === 'manual') {
- iconClassName = icons.INTERACTIVE;
- iconTooltip = translate('Manual');
- } else if (type === 'update') {
- iconClassName = icons.UPDATE;
- iconTooltip = translate('BeforeUpdate');
- }
-
- return (
-
-
- {
-
- }
-
-
-
-
- {name}
-
-
-
-
- {formatBytes(size)}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-BackupRow.propTypes = {
- id: PropTypes.number.isRequired,
- type: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- path: PropTypes.string.isRequired,
- size: PropTypes.number.isRequired,
- time: PropTypes.string.isRequired,
- onDeleteBackupPress: PropTypes.func.isRequired
-};
-
-export default BackupRow;
diff --git a/frontend/src/System/Backup/Backups.js b/frontend/src/System/Backup/Backups.js
deleted file mode 100644
index 8f7a5b0a5..000000000
--- a/frontend/src/System/Backup/Backups.js
+++ /dev/null
@@ -1,179 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import BackupRow from './BackupRow';
-import RestoreBackupModalConnector from './RestoreBackupModalConnector';
-
-const columns = [
- {
- name: 'type',
- isVisible: true
- },
- {
- name: 'name',
- label: () => translate('Name'),
- isVisible: true
- },
- {
- name: 'size',
- label: () => translate('Size'),
- isVisible: true
- },
- {
- name: 'time',
- label: () => translate('Time'),
- isVisible: true
- },
- {
- name: 'actions',
- isVisible: true
- }
-];
-
-class Backups extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isRestoreModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onRestorePress = () => {
- this.setState({ isRestoreModalOpen: true });
- };
-
- onRestoreModalClose = () => {
- this.setState({ isRestoreModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- isPopulated,
- error,
- items,
- backupExecuting,
- onBackupPress,
- onDeleteBackupPress
- } = this.props;
-
- const hasBackups = isPopulated && !!items.length;
- const noBackups = isPopulated && !items.length;
-
- return (
-
-
-
-
-
-
-
-
-
-
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- !isFetching && !!error &&
-
- {translate('UnableToLoadBackups')}
-
- }
-
- {
- noBackups &&
-
- {translate('NoBackupsAreAvailable')}
-
- }
-
- {
- hasBackups &&
-
-
- {
- items.map((item) => {
- const {
- id,
- type,
- name,
- path,
- size,
- time
- } = item;
-
- return (
-
- );
- })
- }
-
-
- }
-
-
-
-
- );
- }
-
-}
-
-Backups.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.array.isRequired,
- backupExecuting: PropTypes.bool.isRequired,
- onBackupPress: PropTypes.func.isRequired,
- onDeleteBackupPress: PropTypes.func.isRequired
-};
-
-export default Backups;
diff --git a/frontend/src/System/Backup/BackupsConnector.js b/frontend/src/System/Backup/BackupsConnector.js
deleted file mode 100644
index 1353b6196..000000000
--- a/frontend/src/System/Backup/BackupsConnector.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { deleteBackup, fetchBackups } from 'Store/Actions/systemActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import Backups from './Backups';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.backups,
- createCommandExecutingSelector(commandNames.BACKUP),
- (backups, backupExecuting) => {
- const {
- isFetching,
- isPopulated,
- error,
- items
- } = backups;
-
- return {
- isFetching,
- isPopulated,
- error,
- items,
- backupExecuting
- };
- }
- );
-}
-
-function createMapDispatchToProps(dispatch, props) {
- return {
- dispatchFetchBackups() {
- dispatch(fetchBackups());
- },
-
- onDeleteBackupPress(id) {
- dispatch(deleteBackup({ id }));
- },
-
- onBackupPress() {
- dispatch(executeCommand({
- name: commandNames.BACKUP
- }));
- }
- };
-}
-
-class BackupsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchBackups();
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.backupExecuting && !this.props.backupExecuting) {
- this.props.dispatchFetchBackups();
- }
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-BackupsConnector.propTypes = {
- backupExecuting: PropTypes.bool.isRequired,
- dispatchFetchBackups: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, createMapDispatchToProps)(BackupsConnector);
diff --git a/frontend/src/System/Backup/RestoreBackupModal.js b/frontend/src/System/Backup/RestoreBackupModal.js
deleted file mode 100644
index 48dad4d2a..000000000
--- a/frontend/src/System/Backup/RestoreBackupModal.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import RestoreBackupModalContentConnector from './RestoreBackupModalContentConnector';
-
-function RestoreBackupModal(props) {
- const {
- isOpen,
- onModalClose,
- ...otherProps
- } = props;
-
- return (
-
-
-
- );
-}
-
-RestoreBackupModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default RestoreBackupModal;
diff --git a/frontend/src/System/Backup/RestoreBackupModalConnector.js b/frontend/src/System/Backup/RestoreBackupModalConnector.js
deleted file mode 100644
index 98cbcd11b..000000000
--- a/frontend/src/System/Backup/RestoreBackupModalConnector.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { connect } from 'react-redux';
-import { clearRestoreBackup } from 'Store/Actions/systemActions';
-import RestoreBackupModal from './RestoreBackupModal';
-
-function createMapDispatchToProps(dispatch, props) {
- return {
- onModalClose() {
- dispatch(clearRestoreBackup());
-
- props.onModalClose();
- }
- };
-}
-
-export default connect(null, createMapDispatchToProps)(RestoreBackupModal);
diff --git a/frontend/src/System/Backup/RestoreBackupModalContent.css b/frontend/src/System/Backup/RestoreBackupModalContent.css
deleted file mode 100644
index 2775e8e08..000000000
--- a/frontend/src/System/Backup/RestoreBackupModalContent.css
+++ /dev/null
@@ -1,24 +0,0 @@
-.additionalInfo {
- flex-grow: 1;
- color: #777;
-}
-
-.steps {
- margin-top: 20px;
-}
-
-.step {
- display: flex;
- font-size: $largeFontSize;
- line-height: 20px;
-}
-
-.stepState {
- margin-right: 8px;
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- composes: modalFooter from '~Components/Modal/ModalFooter.css';
-
- flex-wrap: wrap;
-}
diff --git a/frontend/src/System/Backup/RestoreBackupModalContent.css.d.ts b/frontend/src/System/Backup/RestoreBackupModalContent.css.d.ts
deleted file mode 100644
index 6603c6533..000000000
--- a/frontend/src/System/Backup/RestoreBackupModalContent.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'additionalInfo': string;
- 'step': string;
- 'stepState': string;
- 'steps': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Backup/RestoreBackupModalContent.js b/frontend/src/System/Backup/RestoreBackupModalContent.js
deleted file mode 100644
index d6cfb0c81..000000000
--- a/frontend/src/System/Backup/RestoreBackupModalContent.js
+++ /dev/null
@@ -1,239 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import TextInput from 'Components/Form/TextInput';
-import Icon from 'Components/Icon';
-import Button from 'Components/Link/Button';
-import SpinnerButton from 'Components/Link/SpinnerButton';
-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 { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './RestoreBackupModalContent.css';
-
-function getErrorMessage(error) {
- if (!error || !error.responseJSON || !error.responseJSON.message) {
- return translate('ErrorRestoringBackup');
- }
-
- return error.responseJSON.message;
-}
-
-function getStepIconProps(isExecuting, hasExecuted, error) {
- if (isExecuting) {
- return {
- name: icons.SPINNER,
- isSpinning: true
- };
- }
-
- if (hasExecuted) {
- return {
- name: icons.CHECK,
- kind: kinds.SUCCESS
- };
- }
-
- if (error) {
- return {
- name: icons.FATAL,
- kinds: kinds.DANGER,
- title: getErrorMessage(error)
- };
- }
-
- return {
- name: icons.PENDING
- };
-}
-
-class RestoreBackupModalContent extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- file: null,
- path: '',
- isRestored: false,
- isRestarted: false,
- isReloading: false
- };
- }
-
- componentDidUpdate(prevProps) {
- const {
- isRestoring,
- restoreError,
- isRestarting,
- dispatchRestart
- } = this.props;
-
- if (prevProps.isRestoring && !isRestoring && !restoreError) {
- this.setState({ isRestored: true }, () => {
- dispatchRestart();
- });
- }
-
- if (prevProps.isRestarting && !isRestarting) {
- this.setState({
- isRestarted: true,
- isReloading: true
- }, () => {
- location.reload();
- });
- }
- }
-
- //
- // Listeners
-
- onPathChange = ({ value, files }) => {
- this.setState({
- file: files[0],
- path: value
- });
- };
-
- onRestorePress = () => {
- const {
- id,
- onRestorePress
- } = this.props;
-
- onRestorePress({
- id,
- file: this.state.file
- });
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- name,
- isRestoring,
- restoreError,
- isRestarting,
- onModalClose
- } = this.props;
-
- const {
- path,
- isRestored,
- isRestarted,
- isReloading
- } = this.state;
-
- const isRestoreDisabled = (
- (!id && !path) ||
- isRestoring ||
- isRestarting ||
- isReloading
- );
-
- return (
-
-
- Restore Backup
-
-
-
- {
- !!id && translate('WouldYouLikeToRestoreBackup', { name })
- }
-
- {
- !id &&
-
- }
-
-
-
-
-
-
-
-
- {translate('Restore')}
-
-
-
-
-
-
-
-
-
- {translate('Restart')}
-
-
-
-
-
-
-
-
-
- {translate('Reload')}
-
-
-
-
-
-
-
- {translate('RestoreBackupAdditionalInfo')}
-
-
-
- {translate('Cancel')}
-
-
-
- {translate('Restore')}
-
-
-
- );
- }
-}
-
-RestoreBackupModalContent.propTypes = {
- id: PropTypes.number,
- name: PropTypes.string,
- path: PropTypes.string,
- isRestoring: PropTypes.bool.isRequired,
- restoreError: PropTypes.object,
- isRestarting: PropTypes.bool.isRequired,
- dispatchRestart: PropTypes.func.isRequired,
- onRestorePress: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default RestoreBackupModalContent;
diff --git a/frontend/src/System/Backup/RestoreBackupModalContentConnector.js b/frontend/src/System/Backup/RestoreBackupModalContentConnector.js
deleted file mode 100644
index d408d0f50..000000000
--- a/frontend/src/System/Backup/RestoreBackupModalContentConnector.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { restart, restoreBackup } from 'Store/Actions/systemActions';
-import RestoreBackupModalContent from './RestoreBackupModalContent';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.backups,
- (state) => state.app.isRestarting,
- (backups, isRestarting) => {
- const {
- isRestoring,
- restoreError
- } = backups;
-
- return {
- isRestoring,
- restoreError,
- isRestarting
- };
- }
- );
-}
-
-function createMapDispatchToProps(dispatch, props) {
- return {
- onRestorePress(payload) {
- dispatch(restoreBackup(payload));
- },
-
- dispatchRestart() {
- dispatch(restart());
- }
- };
-}
-
-export default connect(createMapStateToProps, createMapDispatchToProps)(RestoreBackupModalContent);
diff --git a/frontend/src/System/Events/LogsTable.js b/frontend/src/System/Events/LogsTable.js
deleted file mode 100644
index 1c37a03ba..000000000
--- a/frontend/src/System/Events/LogsTable.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Alert from 'Components/Alert';
-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 PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
-import TablePager from 'Components/Table/TablePager';
-import { align, icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import LogsTableRow from './LogsTableRow';
-
-function LogsTable(props) {
- const {
- isFetching,
- isPopulated,
- error,
- items,
- columns,
- selectedFilterKey,
- filters,
- totalRecords,
- clearLogExecuting,
- onRefreshPress,
- onClearLogsPress,
- onFilterSelect,
- ...otherProps
- } = props;
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- isPopulated && !error && !items.length &&
-
- {translate('NoEventsFound')}
-
- }
-
- {
- isPopulated && !error && !!items.length &&
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
- }
-
-
- );
-}
-
-LogsTable.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- selectedFilterKey: PropTypes.string.isRequired,
- filters: PropTypes.arrayOf(PropTypes.object).isRequired,
- totalRecords: PropTypes.number,
- clearLogExecuting: PropTypes.bool.isRequired,
- onFilterSelect: PropTypes.func.isRequired,
- onRefreshPress: PropTypes.func.isRequired,
- onClearLogsPress: PropTypes.func.isRequired
-};
-
-export default LogsTable;
diff --git a/frontend/src/System/Events/LogsTableConnector.js b/frontend/src/System/Events/LogsTableConnector.js
deleted file mode 100644
index a717cba15..000000000
--- a/frontend/src/System/Events/LogsTableConnector.js
+++ /dev/null
@@ -1,148 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import withCurrentPage from 'Components/withCurrentPage';
-import { executeCommand } from 'Store/Actions/commandActions';
-import * as systemActions from 'Store/Actions/systemActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import LogsTable from './LogsTable';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.logs,
- createCommandExecutingSelector(commandNames.CLEAR_LOGS),
- (logs, clearLogExecuting) => {
- return {
- clearLogExecuting,
- ...logs
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- executeCommand,
- ...systemActions
-};
-
-class LogsTableConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- useCurrentPage,
- fetchLogs,
- gotoLogsFirstPage
- } = this.props;
-
- if (useCurrentPage) {
- fetchLogs();
- } else {
- gotoLogsFirstPage();
- }
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.clearLogExecuting && !this.props.clearLogExecuting) {
- this.props.gotoLogsFirstPage();
- }
- }
-
- //
- // Listeners
-
- onFirstPagePress = () => {
- this.props.gotoLogsFirstPage();
- };
-
- onPreviousPagePress = () => {
- this.props.gotoLogsPreviousPage();
- };
-
- onNextPagePress = () => {
- this.props.gotoLogsNextPage();
- };
-
- onLastPagePress = () => {
- this.props.gotoLogsLastPage();
- };
-
- onPageSelect = (page) => {
- this.props.gotoLogsPage({ page });
- };
-
- onSortPress = (sortKey) => {
- this.props.setLogsSort({ sortKey });
- };
-
- onFilterSelect = (selectedFilterKey) => {
- this.props.setLogsFilter({ selectedFilterKey });
- };
-
- onTableOptionChange = (payload) => {
- this.props.setLogsTableOption(payload);
-
- if (payload.pageSize) {
- this.props.gotoLogsFirstPage();
- }
- };
-
- onRefreshPress = () => {
- this.props.gotoLogsFirstPage();
- };
-
- onClearLogsPress = () => {
- this.props.executeCommand({
- name: commandNames.CLEAR_LOGS,
- commandFinished: this.onCommandFinished
- });
- };
-
- onCommandFinished = () => {
- this.props.gotoLogsFirstPage();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-LogsTableConnector.propTypes = {
- useCurrentPage: PropTypes.bool.isRequired,
- clearLogExecuting: PropTypes.bool.isRequired,
- fetchLogs: PropTypes.func.isRequired,
- gotoLogsFirstPage: PropTypes.func.isRequired,
- gotoLogsPreviousPage: PropTypes.func.isRequired,
- gotoLogsNextPage: PropTypes.func.isRequired,
- gotoLogsLastPage: PropTypes.func.isRequired,
- gotoLogsPage: PropTypes.func.isRequired,
- setLogsSort: PropTypes.func.isRequired,
- setLogsFilter: PropTypes.func.isRequired,
- setLogsTableOption: PropTypes.func.isRequired,
- executeCommand: PropTypes.func.isRequired
-};
-
-export default withCurrentPage(
- connect(createMapStateToProps, mapDispatchToProps)(LogsTableConnector)
-);
diff --git a/frontend/src/System/Events/LogsTableDetailsModal.css b/frontend/src/System/Events/LogsTableDetailsModal.css
deleted file mode 100644
index 3e1333dec..000000000
--- a/frontend/src/System/Events/LogsTableDetailsModal.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.detailsText {
- composes: scroller from '~Components/Scroller/Scroller.css';
-
- display: block;
- margin: 0 0 10.5px;
- padding: 10px;
- border: 1px solid #ccc;
- border-radius: 4px;
- background-color: var(--logEventsBackgroundColor);
- color: var(--textColor);
- white-space: pre;
- word-wrap: break-word;
- word-break: break-all;
- font-size: 13px;
- font-family: $monoSpaceFontFamily;
- line-height: 1.52857143;
-}
diff --git a/frontend/src/System/Events/LogsTableDetailsModal.css.d.ts b/frontend/src/System/Events/LogsTableDetailsModal.css.d.ts
deleted file mode 100644
index 09b8fe302..000000000
--- a/frontend/src/System/Events/LogsTableDetailsModal.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'detailsText': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Events/LogsTableDetailsModal.js b/frontend/src/System/Events/LogsTableDetailsModal.js
deleted file mode 100644
index 87dc4a4ee..000000000
--- a/frontend/src/System/Events/LogsTableDetailsModal.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Button from 'Components/Link/Button';
-import Modal from 'Components/Modal/Modal';
-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 Scroller from 'Components/Scroller/Scroller';
-import { scrollDirections } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import styles from './LogsTableDetailsModal.css';
-
-function LogsTableDetailsModal(props) {
- const {
- isOpen,
- message,
- exception,
- onModalClose
- } = props;
-
- return (
-
-
-
- Details
-
-
-
-
- {translate('Message')}
-
-
-
- {message}
-
-
- {
- !!exception &&
-
-
- {translate('Exception')}
-
-
- {exception}
-
-
- }
-
-
-
-
- Close
-
-
-
-
- );
-}
-
-LogsTableDetailsModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- message: PropTypes.string.isRequired,
- exception: PropTypes.string,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default LogsTableDetailsModal;
diff --git a/frontend/src/System/Events/LogsTableRow.css b/frontend/src/System/Events/LogsTableRow.css
deleted file mode 100644
index 0c5a3e1c6..000000000
--- a/frontend/src/System/Events/LogsTableRow.css
+++ /dev/null
@@ -1,35 +0,0 @@
-.level {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 20px;
-}
-
-.info {
- color: #1e90ff;
-}
-
-.debug {
- color: #808080;
-}
-
-.trace {
- color: #d3d3d3;
-}
-
-.warn {
- color: var(--warningColor);
-}
-
-.error {
- color: var(--dangerColor);
-}
-
-.fatal {
- color: var(--purple);
-}
-
-.actions {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 45px;
-}
diff --git a/frontend/src/System/Events/LogsTableRow.css.d.ts b/frontend/src/System/Events/LogsTableRow.css.d.ts
deleted file mode 100644
index c0267e838..000000000
--- a/frontend/src/System/Events/LogsTableRow.css.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'debug': string;
- 'error': string;
- 'fatal': string;
- 'info': string;
- 'level': string;
- 'trace': string;
- 'warn': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Events/LogsTableRow.js b/frontend/src/System/Events/LogsTableRow.js
deleted file mode 100644
index 8d2d5f541..000000000
--- a/frontend/src/System/Events/LogsTableRow.js
+++ /dev/null
@@ -1,157 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Icon from 'Components/Icon';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableRowButton from 'Components/Table/TableRowButton';
-import { icons } from 'Helpers/Props';
-import LogsTableDetailsModal from './LogsTableDetailsModal';
-import styles from './LogsTableRow.css';
-
-function getIconName(level) {
- switch (level) {
- case 'trace':
- case 'debug':
- case 'info':
- return icons.INFO;
- case 'warn':
- return icons.DANGER;
- case 'error':
- return icons.BUG;
- case 'fatal':
- return icons.FATAL;
- default:
- return icons.UNKNOWN;
- }
-}
-
-class LogsTableRow extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isDetailsModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onPress = () => {
- // Don't re-open the modal if it's already open
- if (!this.state.isDetailsModalOpen) {
- this.setState({ isDetailsModalOpen: true });
- }
- };
-
- onModalClose = () => {
- this.setState({ isDetailsModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- level,
- time,
- logger,
- message,
- exception,
- columns
- } = this.props;
-
- return (
-
- {
- columns.map((column) => {
- const {
- name,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- if (name === 'level') {
- return (
-
-
-
- );
- }
-
- if (name === 'time') {
- return (
-
- );
- }
-
- if (name === 'logger') {
- return (
-
- {logger}
-
- );
- }
-
- if (name === 'message') {
- return (
-
- {message}
-
- );
- }
-
- if (name === 'actions') {
- return (
-
- );
- }
-
- return null;
- })
- }
-
-
-
- );
- }
-
-}
-
-LogsTableRow.propTypes = {
- level: PropTypes.string.isRequired,
- time: PropTypes.string.isRequired,
- logger: PropTypes.string.isRequired,
- message: PropTypes.string.isRequired,
- exception: PropTypes.string,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired
-};
-
-export default LogsTableRow;
diff --git a/frontend/src/System/Logs/Files/LogFiles.js b/frontend/src/System/Logs/Files/LogFiles.js
deleted file mode 100644
index 5339a8590..000000000
--- a/frontend/src/System/Logs/Files/LogFiles.js
+++ /dev/null
@@ -1,143 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import { icons, kinds } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import LogsNavMenu from '../LogsNavMenu';
-import LogFilesTableRow from './LogFilesTableRow';
-
-const columns = [
- {
- name: 'filename',
- label: () => translate('Filename'),
- isVisible: true
- },
- {
- name: 'lastWriteTime',
- label: () => translate('LastWriteTime'),
- isVisible: true
- },
- {
- name: 'download',
- isVisible: true
- }
-];
-
-class LogFiles extends Component {
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- items,
- deleteFilesExecuting,
- currentLogView,
- location,
- onRefreshPress,
- onDeleteFilesPress,
- ...otherProps
- } = this.props;
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {translate('LogFilesLocation', {
- location
- })}
-
-
- {currentLogView === 'Log Files' ? (
-
-
-
- ) : null}
-
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching && !!items.length &&
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
- }
-
- {
- !isFetching && !items.length &&
-
- {translate('NoLogFiles')}
-
- }
-
-
- );
- }
-
-}
-
-LogFiles.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- items: PropTypes.array.isRequired,
- deleteFilesExecuting: PropTypes.bool.isRequired,
- currentLogView: PropTypes.string.isRequired,
- location: PropTypes.string.isRequired,
- onRefreshPress: PropTypes.func.isRequired,
- onDeleteFilesPress: PropTypes.func.isRequired
-};
-
-export default LogFiles;
diff --git a/frontend/src/System/Logs/Files/LogFilesConnector.js b/frontend/src/System/Logs/Files/LogFilesConnector.js
deleted file mode 100644
index 98a55f32f..000000000
--- a/frontend/src/System/Logs/Files/LogFilesConnector.js
+++ /dev/null
@@ -1,91 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { fetchLogFiles } from 'Store/Actions/systemActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import combinePath from 'Utilities/String/combinePath';
-import LogFiles from './LogFiles';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.logFiles,
- (state) => state.system.status.item,
- createCommandExecutingSelector(commandNames.DELETE_LOG_FILES),
- (logFiles, status, deleteFilesExecuting) => {
- const {
- isFetching,
- items
- } = logFiles;
-
- const {
- appData,
- isWindows
- } = status;
-
- return {
- isFetching,
- items,
- deleteFilesExecuting,
- currentLogView: 'Log Files',
- location: combinePath(isWindows, appData, ['logs'])
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchLogFiles,
- executeCommand
-};
-
-class LogFilesConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchLogFiles();
- }
-
- //
- // Listeners
-
- onRefreshPress = () => {
- this.props.fetchLogFiles();
- };
-
- onDeleteFilesPress = () => {
- this.props.executeCommand({
- name: commandNames.DELETE_LOG_FILES,
- commandFinished: this.onCommandFinished
- });
- };
-
- onCommandFinished = () => {
- this.props.fetchLogFiles();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-LogFilesConnector.propTypes = {
- deleteFilesExecuting: PropTypes.bool.isRequired,
- fetchLogFiles: PropTypes.func.isRequired,
- executeCommand: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(LogFilesConnector);
diff --git a/frontend/src/System/Logs/Files/LogFilesTableRow.css b/frontend/src/System/Logs/Files/LogFilesTableRow.css
deleted file mode 100644
index 313f50cc0..000000000
--- a/frontend/src/System/Logs/Files/LogFilesTableRow.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.download {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 100px;
-}
diff --git a/frontend/src/System/Logs/Files/LogFilesTableRow.css.d.ts b/frontend/src/System/Logs/Files/LogFilesTableRow.css.d.ts
deleted file mode 100644
index 0a1fbfe07..000000000
--- a/frontend/src/System/Logs/Files/LogFilesTableRow.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'download': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Logs/Files/LogFilesTableRow.js b/frontend/src/System/Logs/Files/LogFilesTableRow.js
deleted file mode 100644
index ef08ada4e..000000000
--- a/frontend/src/System/Logs/Files/LogFilesTableRow.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Link from 'Components/Link/Link';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableRow from 'Components/Table/TableRow';
-import styles from './LogFilesTableRow.css';
-
-class LogFilesTableRow extends Component {
-
- //
- // Render
-
- render() {
- const {
- filename,
- lastWriteTime,
- downloadUrl
- } = this.props;
-
- return (
-
- {filename}
-
-
-
-
-
- Download
-
-
-
- );
- }
-
-}
-
-LogFilesTableRow.propTypes = {
- filename: PropTypes.string.isRequired,
- lastWriteTime: PropTypes.string.isRequired,
- downloadUrl: PropTypes.string.isRequired
-};
-
-export default LogFilesTableRow;
diff --git a/frontend/src/System/Logs/Logs.js b/frontend/src/System/Logs/Logs.js
deleted file mode 100644
index fa0be453e..000000000
--- a/frontend/src/System/Logs/Logs.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import React, { Component } from 'react';
-import { Route } from 'react-router-dom';
-import Switch from 'Components/Router/Switch';
-import LogFilesConnector from './Files/LogFilesConnector';
-import UpdateLogFilesConnector from './Updates/UpdateLogFilesConnector';
-
-class Logs extends Component {
-
- //
- // Render
-
- render() {
- return (
-
-
-
-
-
- );
- }
-}
-
-export default Logs;
diff --git a/frontend/src/System/Logs/LogsNavMenu.js b/frontend/src/System/Logs/LogsNavMenu.js
deleted file mode 100644
index cc485f270..000000000
--- a/frontend/src/System/Logs/LogsNavMenu.js
+++ /dev/null
@@ -1,71 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Menu from 'Components/Menu/Menu';
-import MenuButton from 'Components/Menu/MenuButton';
-import MenuContent from 'Components/Menu/MenuContent';
-import MenuItem from 'Components/Menu/MenuItem';
-
-class LogsNavMenu extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isMenuOpen: false
- };
- }
-
- //
- // Listeners
-
- onMenuButtonPress = () => {
- this.setState({ isMenuOpen: !this.state.isMenuOpen });
- };
-
- onMenuItemPress = () => {
- this.setState({ isMenuOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- current
- } = this.props;
-
- return (
-
-
- {current}
-
-
-
- Log Files
-
-
-
- Updater Log Files
-
-
-
- );
- }
-}
-
-LogsNavMenu.propTypes = {
- current: PropTypes.string.isRequired
-};
-
-export default LogsNavMenu;
diff --git a/frontend/src/System/Logs/Updates/UpdateLogFilesConnector.js b/frontend/src/System/Logs/Updates/UpdateLogFilesConnector.js
deleted file mode 100644
index 537816014..000000000
--- a/frontend/src/System/Logs/Updates/UpdateLogFilesConnector.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { fetchUpdateLogFiles } from 'Store/Actions/systemActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import combinePath from 'Utilities/String/combinePath';
-import LogFiles from '../Files/LogFiles';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.updateLogFiles,
- (state) => state.system.status.item,
- createCommandExecutingSelector(commandNames.DELETE_UPDATE_LOG_FILES),
- (updateLogFiles, status, deleteFilesExecuting) => {
- const {
- isFetching,
- items
- } = updateLogFiles;
-
- const {
- appData,
- isWindows
- } = status;
-
- return {
- isFetching,
- items,
- deleteFilesExecuting,
- currentLogView: 'Updater Log Files',
- location: combinePath(isWindows, appData, ['UpdateLogs'])
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchUpdateLogFiles,
- executeCommand
-};
-
-class UpdateLogFilesConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchUpdateLogFiles();
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.deleteFilesExecuting && !this.props.deleteFilesExecuting) {
- this.props.fetchUpdateLogFiles();
- }
- }
-
- //
- // Listeners
-
- onRefreshPress = () => {
- this.props.fetchUpdateLogFiles();
- };
-
- onDeleteFilesPress = () => {
- this.props.executeCommand({ name: commandNames.DELETE_UPDATE_LOG_FILES });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-UpdateLogFilesConnector.propTypes = {
- deleteFilesExecuting: PropTypes.bool.isRequired,
- fetchUpdateLogFiles: PropTypes.func.isRequired,
- executeCommand: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(UpdateLogFilesConnector);
diff --git a/frontend/src/System/Status/About/About.css b/frontend/src/System/Status/About/About.css
deleted file mode 100644
index 9886c7ad0..000000000
--- a/frontend/src/System/Status/About/About.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.descriptionList {
- composes: descriptionList from '~Components/DescriptionList/DescriptionList.css';
-
- margin-bottom: 10px;
-}
diff --git a/frontend/src/System/Status/About/About.css.d.ts b/frontend/src/System/Status/About/About.css.d.ts
deleted file mode 100644
index 34c1578a4..000000000
--- a/frontend/src/System/Status/About/About.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'descriptionList': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Status/About/About.js b/frontend/src/System/Status/About/About.js
deleted file mode 100644
index 8af5b4717..000000000
--- a/frontend/src/System/Status/About/About.js
+++ /dev/null
@@ -1,128 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import DescriptionList from 'Components/DescriptionList/DescriptionList';
-import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
-import FieldSet from 'Components/FieldSet';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-import titleCase from 'Utilities/String/titleCase';
-import translate from 'Utilities/String/translate';
-import StartTime from './StartTime';
-import styles from './About.css';
-
-class About extends Component {
-
- //
- // Render
-
- render() {
- const {
- version,
- packageVersion,
- packageAuthor,
- isNetCore,
- isDocker,
- runtimeVersion,
- databaseVersion,
- databaseType,
- migrationVersion,
- appData,
- startupPath,
- mode,
- startTime,
- timeFormat,
- longDateFormat
- } = this.props;
-
- return (
-
-
-
-
- {
- packageVersion &&
- {packageVersion} {' by '} : packageVersion)}
- />
- }
-
- {
- isNetCore &&
-
- }
-
- {
- isDocker &&
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
- }
- />
-
-
- );
- }
-
-}
-
-About.propTypes = {
- version: PropTypes.string.isRequired,
- packageVersion: PropTypes.string,
- packageAuthor: PropTypes.string,
- isNetCore: PropTypes.bool.isRequired,
- runtimeVersion: PropTypes.string.isRequired,
- isDocker: PropTypes.bool.isRequired,
- databaseType: PropTypes.string.isRequired,
- databaseVersion: PropTypes.string.isRequired,
- migrationVersion: PropTypes.number.isRequired,
- appData: PropTypes.string.isRequired,
- startupPath: PropTypes.string.isRequired,
- mode: PropTypes.string.isRequired,
- startTime: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- longDateFormat: PropTypes.string.isRequired
-};
-
-export default About;
diff --git a/frontend/src/System/Status/About/AboutConnector.js b/frontend/src/System/Status/About/AboutConnector.js
deleted file mode 100644
index 475d9778b..000000000
--- a/frontend/src/System/Status/About/AboutConnector.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchStatus } from 'Store/Actions/systemActions';
-import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
-import About from './About';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.status,
- createUISettingsSelector(),
- (status, uiSettings) => {
- return {
- ...status.item,
- timeFormat: uiSettings.timeFormat,
- longDateFormat: uiSettings.longDateFormat
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchStatus
-};
-
-class AboutConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchStatus();
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-AboutConnector.propTypes = {
- fetchStatus: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(AboutConnector);
diff --git a/frontend/src/System/Status/About/StartTime.js b/frontend/src/System/Status/About/StartTime.js
deleted file mode 100644
index 08c820add..000000000
--- a/frontend/src/System/Status/About/StartTime.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import moment from 'moment';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import formatDateTime from 'Utilities/Date/formatDateTime';
-import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
-
-function getUptime(startTime) {
- return formatTimeSpan(moment().diff(startTime));
-}
-
-class StartTime extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- const {
- startTime,
- timeFormat,
- longDateFormat
- } = props;
-
- this._timeoutId = null;
-
- this.state = {
- uptime: getUptime(startTime),
- startTime: formatDateTime(startTime, longDateFormat, timeFormat, { includeSeconds: true })
- };
- }
-
- componentDidMount() {
- this._timeoutId = setTimeout(this.onTimeout, 1000);
- }
-
- componentDidUpdate(prevProps) {
- const {
- startTime,
- timeFormat,
- longDateFormat
- } = this.props;
-
- if (
- startTime !== prevProps.startTime ||
- timeFormat !== prevProps.timeFormat ||
- longDateFormat !== prevProps.longDateFormat
- ) {
- this.setState({
- uptime: getUptime(startTime),
- startTime: formatDateTime(startTime, longDateFormat, timeFormat, { includeSeconds: true })
- });
- }
- }
-
- componentWillUnmount() {
- if (this._timeoutId) {
- this._timeoutId = clearTimeout(this._timeoutId);
- }
- }
-
- //
- // Listeners
-
- onTimeout = () => {
- this.setState({ uptime: getUptime(this.props.startTime) });
- this._timeoutId = setTimeout(this.onTimeout, 1000);
- };
-
- //
- // Render
-
- render() {
- const {
- uptime,
- startTime
- } = this.state;
-
- return (
-
- {uptime}
-
- );
- }
-}
-
-StartTime.propTypes = {
- startTime: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- longDateFormat: PropTypes.string.isRequired
-};
-
-export default StartTime;
diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.css b/frontend/src/System/Status/DiskSpace/DiskSpace.css
deleted file mode 100644
index dd92926d4..000000000
--- a/frontend/src/System/Status/DiskSpace/DiskSpace.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.space {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 150px;
-}
diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.css.d.ts b/frontend/src/System/Status/DiskSpace/DiskSpace.css.d.ts
deleted file mode 100644
index 23a67ff58..000000000
--- a/frontend/src/System/Status/DiskSpace/DiskSpace.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'space': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Status/DiskSpace/DiskSpace.js b/frontend/src/System/Status/DiskSpace/DiskSpace.js
deleted file mode 100644
index 38cf9254a..000000000
--- a/frontend/src/System/Status/DiskSpace/DiskSpace.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import FieldSet from 'Components/FieldSet';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import ProgressBar from 'Components/ProgressBar';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import TableRow from 'Components/Table/TableRow';
-import { kinds, sizes } from 'Helpers/Props';
-import formatBytes from 'Utilities/Number/formatBytes';
-import translate from 'Utilities/String/translate';
-import styles from './DiskSpace.css';
-
-const columns = [
- {
- name: 'path',
- label: () => translate('Location'),
- isVisible: true
- },
- {
- name: 'freeSpace',
- label: () => translate('FreeSpace'),
- isVisible: true
- },
- {
- name: 'totalSpace',
- label: () => translate('TotalSpace'),
- isVisible: true
- },
- {
- name: 'progress',
- isVisible: true
- }
-];
-
-class DiskSpace extends Component {
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- items
- } = this.props;
-
- return (
-
- {
- isFetching &&
-
- }
-
- {
- !isFetching &&
-
-
- {
- items.map((item) => {
- const {
- freeSpace,
- totalSpace
- } = item;
-
- const diskUsage = Math.round(100 - freeSpace / totalSpace * 100);
- let diskUsageKind = kinds.PRIMARY;
-
- if (diskUsage > 90) {
- diskUsageKind = kinds.DANGER;
- } else if (diskUsage > 80) {
- diskUsageKind = kinds.WARNING;
- }
-
- return (
-
-
- {item.path}
-
- {
- item.label &&
- ` (${item.label})`
- }
-
-
-
- {formatBytes(freeSpace)}
-
-
-
- {formatBytes(totalSpace)}
-
-
-
- = 12}
- text={`${diskUsage}%`}
- />
-
-
- );
- })
- }
-
-
- }
-
- );
- }
-
-}
-
-DiskSpace.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- items: PropTypes.array.isRequired
-};
-
-export default DiskSpace;
diff --git a/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js b/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js
deleted file mode 100644
index 3049b2ead..000000000
--- a/frontend/src/System/Status/DiskSpace/DiskSpaceConnector.js
+++ /dev/null
@@ -1,54 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchDiskSpace } from 'Store/Actions/systemActions';
-import DiskSpace from './DiskSpace';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.diskSpace,
- (diskSpace) => {
- const {
- isFetching,
- items
- } = diskSpace;
-
- return {
- isFetching,
- items
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchDiskSpace
-};
-
-class DiskSpaceConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchDiskSpace();
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-DiskSpaceConnector.propTypes = {
- fetchDiskSpace: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(DiskSpaceConnector);
diff --git a/frontend/src/System/Status/Donations/Donations.js b/frontend/src/System/Status/Donations/Donations.js
deleted file mode 100644
index b3bff8dff..000000000
--- a/frontend/src/System/Status/Donations/Donations.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import React, { Component } from 'react';
-import FieldSet from 'Components/FieldSet';
-import Link from 'Components/Link/Link';
-import translate from 'Utilities/String/translate';
-import styles from '../styles.css';
-
-class Donations extends Component {
-
- //
- // Render
-
- render() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-Donations.propTypes = {
-
-};
-
-export default Donations;
diff --git a/frontend/src/System/Status/Health/Health.css b/frontend/src/System/Status/Health/Health.css
deleted file mode 100644
index 1c4cb6a9d..000000000
--- a/frontend/src/System/Status/Health/Health.css
+++ /dev/null
@@ -1,20 +0,0 @@
-.legend {
- display: flex;
- justify-content: space-between;
-}
-
-.loading {
- composes: loading from '~Components/Loading/LoadingIndicator.css';
-
- margin-top: 2px;
- margin-left: 10px;
- text-align: left;
-}
-
-.status {
- width: 20px;
-}
-
-.healthOk {
- margin-bottom: 25px;
-}
diff --git a/frontend/src/System/Status/Health/Health.css.d.ts b/frontend/src/System/Status/Health/Health.css.d.ts
deleted file mode 100644
index f25332f00..000000000
--- a/frontend/src/System/Status/Health/Health.css.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'healthOk': string;
- 'legend': string;
- 'loading': string;
- 'status': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Status/Health/Health.js b/frontend/src/System/Status/Health/Health.js
deleted file mode 100644
index 7d4eaf58e..000000000
--- a/frontend/src/System/Status/Health/Health.js
+++ /dev/null
@@ -1,243 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import FieldSet from 'Components/FieldSet';
-import Icon from 'Components/Icon';
-import IconButton from 'Components/Link/IconButton';
-import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import TableRow from 'Components/Table/TableRow';
-import { icons, kinds } from 'Helpers/Props';
-import titleCase from 'Utilities/String/titleCase';
-import translate from 'Utilities/String/translate';
-import styles from './Health.css';
-
-function getInternalLink(source) {
- switch (source) {
- case 'IndexerRssCheck':
- case 'IndexerSearchCheck':
- case 'IndexerStatusCheck':
- case 'IndexerJackettAllCheck':
- case 'IndexerLongTermStatusCheck':
- return (
-
- );
- case 'DownloadClientCheck':
- case 'DownloadClientStatusCheck':
- case 'ImportMechanismCheck':
- case 'RemotePathMappingCheck':
- return (
-
- );
- case 'NotificationStatusCheck':
- return (
-
- );
- case 'RootFolderCheck':
- return (
-
- );
- case 'UpdateCheck':
- return (
-
- );
- default:
- return;
- }
-}
-
-function getTestLink(source, props) {
- switch (source) {
- case 'IndexerStatusCheck':
- case 'IndexerLongTermStatusCheck':
- return (
-
- );
- case 'DownloadClientCheck':
- case 'DownloadClientStatusCheck':
- return (
-
- );
-
- default:
- break;
- }
-}
-
-const columns = [
- {
- className: styles.status,
- name: 'type',
- isVisible: true
- },
- {
- name: 'message',
- label: () => translate('Message'),
- isVisible: true
- },
- {
- name: 'actions',
- label: () => translate('Actions'),
- isVisible: true
- }
-];
-
-class Health extends Component {
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- isPopulated,
- items
- } = this.props;
-
- const healthIssues = !!items.length;
-
- return (
-
- Health
-
- {
- isFetching && isPopulated &&
-
- }
-
- }
- >
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- !healthIssues &&
-
- No issues with your configuration
-
- }
-
- {
- healthIssues &&
-
-
- {
- items.map((item) => {
- const internalLink = getInternalLink(item.source);
- const testLink = getTestLink(item.source, this.props);
-
- let kind = kinds.WARNING;
- switch (item.type.toLowerCase()) {
- case 'error':
- kind = kinds.DANGER;
- break;
- default:
- case 'warning':
- kind = kinds.WARNING;
- break;
- case 'notice':
- kind = kinds.INFO;
- break;
- }
-
- return (
-
-
-
-
-
- {item.message}
-
-
-
-
- {
- internalLink
- }
-
- {
- !!testLink &&
- testLink
- }
-
-
- );
- })
- }
-
-
- }
- {
- healthIssues &&
-
-
-
- }
-
- );
- }
-
-}
-
-Health.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- items: PropTypes.array.isRequired,
- isTestingAllDownloadClients: PropTypes.bool.isRequired,
- isTestingAllIndexers: PropTypes.bool.isRequired,
- dispatchTestAllDownloadClients: PropTypes.func.isRequired,
- dispatchTestAllIndexers: PropTypes.func.isRequired
-};
-
-export default Health;
diff --git a/frontend/src/System/Status/Health/HealthConnector.js b/frontend/src/System/Status/Health/HealthConnector.js
deleted file mode 100644
index dd13b0a9c..000000000
--- a/frontend/src/System/Status/Health/HealthConnector.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { testAllDownloadClients, testAllIndexers } from 'Store/Actions/settingsActions';
-import { fetchHealth } from 'Store/Actions/systemActions';
-import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector';
-import Health from './Health';
-
-function createMapStateToProps() {
- return createSelector(
- createHealthCheckSelector(),
- (state) => state.system.health,
- (state) => state.settings.downloadClients.isTestingAll,
- (state) => state.settings.indexers.isTestingAll,
- (items, health, isTestingAllDownloadClients, isTestingAllIndexers) => {
- const {
- isFetching,
- isPopulated
- } = health;
-
- return {
- isFetching,
- isPopulated,
- items,
- isTestingAllDownloadClients,
- isTestingAllIndexers
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchHealth: fetchHealth,
- dispatchTestAllDownloadClients: testAllDownloadClients,
- dispatchTestAllIndexers: testAllIndexers
-};
-
-class HealthConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchHealth();
- }
-
- //
- // Render
-
- render() {
- const {
- dispatchFetchHealth,
- ...otherProps
- } = this.props;
-
- return (
-
- );
- }
-}
-
-HealthConnector.propTypes = {
- dispatchFetchHealth: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(HealthConnector);
diff --git a/frontend/src/System/Status/Health/HealthStatusConnector.js b/frontend/src/System/Status/Health/HealthStatusConnector.js
deleted file mode 100644
index e609dd712..000000000
--- a/frontend/src/System/Status/Health/HealthStatusConnector.js
+++ /dev/null
@@ -1,81 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import PageSidebarStatus from 'Components/Page/Sidebar/PageSidebarStatus';
-import { fetchHealth } from 'Store/Actions/systemActions';
-import createHealthCheckSelector from 'Store/Selectors/createHealthCheckSelector';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.app,
- createHealthCheckSelector(),
- (state) => state.system.health,
- (app, items, health) => {
- const count = items.length;
- let errors = false;
- let warnings = false;
-
- items.forEach((item) => {
- if (item.type === 'error') {
- errors = true;
- }
-
- if (item.type === 'warning') {
- warnings = true;
- }
- });
-
- return {
- isConnected: app.isConnected,
- isReconnecting: app.isReconnecting,
- isPopulated: health.isPopulated,
- count,
- errors,
- warnings
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchHealth
-};
-
-class HealthStatusConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- if (!this.props.isPopulated) {
- this.props.fetchHealth();
- }
- }
-
- componentDidUpdate(prevProps) {
- if (this.props.isConnected && prevProps.isReconnecting) {
- this.props.fetchHealth();
- }
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-HealthStatusConnector.propTypes = {
- isConnected: PropTypes.bool.isRequired,
- isReconnecting: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- fetchHealth: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(HealthStatusConnector);
diff --git a/frontend/src/System/Status/MoreInfo/MoreInfo.js b/frontend/src/System/Status/MoreInfo/MoreInfo.js
deleted file mode 100644
index c029a6511..000000000
--- a/frontend/src/System/Status/MoreInfo/MoreInfo.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import React, { Component } from 'react';
-import DescriptionList from 'Components/DescriptionList/DescriptionList';
-import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription';
-import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
-import FieldSet from 'Components/FieldSet';
-import Link from 'Components/Link/Link';
-import translate from 'Utilities/String/translate';
-
-class MoreInfo extends Component {
-
- //
- // Render
-
- render() {
- return (
-
-
- Home page
-
- lidarr.audio
-
-
- Wiki
-
- wiki.servarr.com/lidarr
-
-
- Reddit
-
- /r/Lidarr
-
-
- Discord
-
- lidarr.audio/discord
-
-
- Source
-
- github.com/Lidarr/Lidarr
-
-
- Feature Requests
-
- github.com/Lidarr/Lidarr/issues
-
-
-
-
- );
- }
-}
-
-MoreInfo.propTypes = {
-
-};
-
-export default MoreInfo;
diff --git a/frontend/src/System/Status/Status.js b/frontend/src/System/Status/Status.js
deleted file mode 100644
index c1f5dac3b..000000000
--- a/frontend/src/System/Status/Status.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React, { Component } from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import translate from 'Utilities/String/translate';
-import AboutConnector from './About/AboutConnector';
-import DiskSpaceConnector from './DiskSpace/DiskSpaceConnector';
-import Donations from './Donations/Donations';
-import HealthConnector from './Health/HealthConnector';
-import MoreInfo from './MoreInfo/MoreInfo';
-
-class Status extends Component {
-
- //
- // Render
-
- render() {
- return (
-
-
-
-
-
-
-
-
-
- );
- }
-
-}
-
-export default Status;
diff --git a/frontend/src/System/Status/styles.css b/frontend/src/System/Status/styles.css
deleted file mode 100644
index 44fe69bad..000000000
--- a/frontend/src/System/Status/styles.css
+++ /dev/null
@@ -1,17 +0,0 @@
-.logo {
- margin: auto;
- padding: 9px;
-}
-
-.logoContainer {
- display: inline-block;
- margin: 0.5em;
- width: 50px;
- height: 50px;
- outline: none;
- border: solid 1px #e6e6e6;
- border-radius: 0.5em;
- background: #f8f8ff;
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
- cursor: pointer;
-}
diff --git a/frontend/src/System/Status/styles.css.d.ts b/frontend/src/System/Status/styles.css.d.ts
deleted file mode 100644
index 521c670e6..000000000
--- a/frontend/src/System/Status/styles.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'logo': string;
- 'logoContainer': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRow.css b/frontend/src/System/Tasks/Queued/QueuedTaskRow.css
deleted file mode 100644
index 6e38929c9..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRow.css
+++ /dev/null
@@ -1,31 +0,0 @@
-.trigger {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 50px;
-}
-
-.triggerContent {
- display: flex;
- justify-content: space-between;
- width: 100%;
-}
-
-.queued,
-.started,
-.ended {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 180px;
-}
-
-.duration {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 100px;
-}
-
-.actions {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 60px;
-}
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRow.css.d.ts b/frontend/src/System/Tasks/Queued/QueuedTaskRow.css.d.ts
deleted file mode 100644
index 2c6010533..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRow.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'duration': string;
- 'ended': string;
- 'queued': string;
- 'started': string;
- 'trigger': string;
- 'triggerContent': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx b/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx
deleted file mode 100644
index 4511bcbf4..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRow.tsx
+++ /dev/null
@@ -1,238 +0,0 @@
-import moment from 'moment';
-import React, { useCallback, useEffect, useRef, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import { CommandBody } from 'Commands/Command';
-import Icon from 'Components/Icon';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableRow from 'Components/Table/TableRow';
-import useModalOpenState from 'Helpers/Hooks/useModalOpenState';
-import { icons, kinds } from 'Helpers/Props';
-import { cancelCommand } from 'Store/Actions/commandActions';
-import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
-import formatDate from 'Utilities/Date/formatDate';
-import formatDateTime from 'Utilities/Date/formatDateTime';
-import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
-import titleCase from 'Utilities/String/titleCase';
-import translate from 'Utilities/String/translate';
-import QueuedTaskRowNameCell from './QueuedTaskRowNameCell';
-import styles from './QueuedTaskRow.css';
-
-function getStatusIconProps(status: string, message: string | undefined) {
- const title = titleCase(status);
-
- switch (status) {
- case 'queued':
- return {
- name: icons.PENDING,
- title,
- };
-
- case 'started':
- return {
- name: icons.REFRESH,
- isSpinning: true,
- title,
- };
-
- case 'completed':
- return {
- name: icons.CHECK,
- kind: kinds.SUCCESS,
- title: message === 'Completed' ? title : `${title}: ${message}`,
- };
-
- case 'failed':
- return {
- name: icons.FATAL,
- kind: kinds.DANGER,
- title: `${title}: ${message}`,
- };
-
- default:
- return {
- name: icons.UNKNOWN,
- title,
- };
- }
-}
-
-function getFormattedDates(
- queued: string,
- started: string | undefined,
- ended: string | undefined,
- showRelativeDates: boolean,
- shortDateFormat: string
-) {
- if (showRelativeDates) {
- return {
- queuedAt: moment(queued).fromNow(),
- startedAt: started ? moment(started).fromNow() : '-',
- endedAt: ended ? moment(ended).fromNow() : '-',
- };
- }
-
- return {
- queuedAt: formatDate(queued, shortDateFormat),
- startedAt: started ? formatDate(started, shortDateFormat) : '-',
- endedAt: ended ? formatDate(ended, shortDateFormat) : '-',
- };
-}
-
-interface QueuedTimes {
- queuedAt: string;
- startedAt: string;
- endedAt: string;
-}
-
-export interface QueuedTaskRowProps {
- id: number;
- trigger: string;
- commandName: string;
- queued: string;
- started?: string;
- ended?: string;
- status: string;
- duration?: string;
- message?: string;
- body: CommandBody;
- clientUserAgent?: string;
-}
-
-export default function QueuedTaskRow(props: QueuedTaskRowProps) {
- const {
- id,
- trigger,
- commandName,
- queued,
- started,
- ended,
- status,
- duration,
- message,
- body,
- clientUserAgent,
- } = props;
-
- const dispatch = useDispatch();
- const { longDateFormat, shortDateFormat, showRelativeDates, timeFormat } =
- useSelector(createUISettingsSelector());
-
- const updateTimeTimeoutId = useRef | null>(
- null
- );
- const [times, setTimes] = useState(
- getFormattedDates(
- queued,
- started,
- ended,
- showRelativeDates,
- shortDateFormat
- )
- );
-
- const [
- isCancelConfirmModalOpen,
- openCancelConfirmModal,
- closeCancelConfirmModal,
- ] = useModalOpenState(false);
-
- const handleCancelPress = useCallback(() => {
- dispatch(cancelCommand({ id }));
- }, [id, dispatch]);
-
- useEffect(() => {
- updateTimeTimeoutId.current = setTimeout(() => {
- setTimes(
- getFormattedDates(
- queued,
- started,
- ended,
- showRelativeDates,
- shortDateFormat
- )
- );
- }, 30000);
-
- return () => {
- if (updateTimeTimeoutId.current) {
- clearTimeout(updateTimeTimeoutId.current);
- }
- };
- }, [queued, started, ended, showRelativeDates, shortDateFormat, setTimes]);
-
- const { queuedAt, startedAt, endedAt } = times;
-
- let triggerIcon = icons.QUICK;
-
- if (trigger === 'manual') {
- triggerIcon = icons.INTERACTIVE;
- } else if (trigger === 'scheduled') {
- triggerIcon = icons.SCHEDULED;
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- {queuedAt}
-
-
-
- {startedAt}
-
-
-
- {endedAt}
-
-
-
- {formatTimeSpan(duration)}
-
-
-
- {status === 'queued' && (
-
- )}
-
-
-
-
- );
-}
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css b/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css
deleted file mode 100644
index 41acb33f8..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.commandName {
- display: inline-block;
- min-width: 220px;
-}
-
-.userAgent {
- color: #b0b0b0;
-}
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css.d.ts b/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css.d.ts
deleted file mode 100644
index fc9081492..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'commandName': string;
- 'userAgent': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.tsx b/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.tsx
deleted file mode 100644
index 41a307d5f..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTaskRowNameCell.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import React from 'react';
-import { useSelector } from 'react-redux';
-import { CommandBody } from 'Commands/Command';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import createMultiArtistsSelector from 'Store/Selectors/createMultiArtistsSelector';
-import sortByProp from 'Utilities/Array/sortByProp';
-import translate from 'Utilities/String/translate';
-import styles from './QueuedTaskRowNameCell.css';
-
-function formatTitles(titles: string[]) {
- if (!titles) {
- return null;
- }
-
- if (titles.length > 11) {
- return (
-
- {titles.slice(0, 10).join(', ')}, {titles.length - 10} more
-
- );
- }
-
- return {titles.join(', ')} ;
-}
-
-export interface QueuedTaskRowNameCellProps {
- commandName: string;
- body: CommandBody;
- clientUserAgent?: string;
-}
-
-export default function QueuedTaskRowNameCell(
- props: QueuedTaskRowNameCellProps
-) {
- const { commandName, body, clientUserAgent } = props;
- const movieIds = [...(body.artistIds ?? [])];
-
- if (body.artistId) {
- movieIds.push(body.artistId);
- }
-
- const artists = useSelector(createMultiArtistsSelector(movieIds));
- const sortedArtists = artists.sort(sortByProp('sortName'));
-
- return (
-
-
- {commandName}
- {sortedArtists.length ? (
- - {formatTitles(sortedArtists.map((a) => a.artistName))}
- ) : null}
-
-
- {clientUserAgent ? (
-
- {translate('From')}: {clientUserAgent}
-
- ) : null}
-
- );
-}
diff --git a/frontend/src/System/Tasks/Queued/QueuedTasks.tsx b/frontend/src/System/Tasks/Queued/QueuedTasks.tsx
deleted file mode 100644
index e79deed7c..000000000
--- a/frontend/src/System/Tasks/Queued/QueuedTasks.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import React, { useEffect } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import AppState from 'App/State/AppState';
-import FieldSet from 'Components/FieldSet';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import { fetchCommands } from 'Store/Actions/commandActions';
-import translate from 'Utilities/String/translate';
-import QueuedTaskRow from './QueuedTaskRow';
-
-const columns = [
- {
- name: 'trigger',
- label: '',
- isVisible: true,
- },
- {
- name: 'commandName',
- label: () => translate('Name'),
- isVisible: true,
- },
- {
- name: 'queued',
- label: () => translate('Queued'),
- isVisible: true,
- },
- {
- name: 'started',
- label: () => translate('Started'),
- isVisible: true,
- },
- {
- name: 'ended',
- label: () => translate('Ended'),
- isVisible: true,
- },
- {
- name: 'duration',
- label: () => translate('Duration'),
- isVisible: true,
- },
- {
- name: 'actions',
- isVisible: true,
- },
-];
-
-export default function QueuedTasks() {
- const dispatch = useDispatch();
- const { isFetching, isPopulated, items } = useSelector(
- (state: AppState) => state.commands
- );
-
- useEffect(() => {
- dispatch(fetchCommands());
- }, [dispatch]);
-
- return (
-
- {isFetching && !isPopulated && }
-
- {isPopulated && (
-
-
- {items.map((item) => {
- return ;
- })}
-
-
- )}
-
- );
-}
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css
deleted file mode 100644
index a5c84ee3a..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css
+++ /dev/null
@@ -1,19 +0,0 @@
-.interval {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 150px;
-}
-
-.lastExecution,
-.lastDuration,
-.nextExecution {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 180px;
-}
-
-.actions {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 20px;
-}
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css.d.ts b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css.d.ts
deleted file mode 100644
index 5b9af5313..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'interval': string;
- 'lastDuration': string;
- 'lastExecution': string;
- 'nextExecution': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.js b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.js
deleted file mode 100644
index acb8c8d36..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRow.js
+++ /dev/null
@@ -1,203 +0,0 @@
-import moment from 'moment';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableRow from 'Components/Table/TableRow';
-import { icons } from 'Helpers/Props';
-import formatDate from 'Utilities/Date/formatDate';
-import formatDateTime from 'Utilities/Date/formatDateTime';
-import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
-import styles from './ScheduledTaskRow.css';
-
-function getFormattedDates(props) {
- const {
- lastExecution,
- nextExecution,
- interval,
- showRelativeDates,
- shortDateFormat
- } = props;
-
- const isDisabled = interval === 0;
-
- if (showRelativeDates) {
- return {
- lastExecutionTime: moment(lastExecution).fromNow(),
- nextExecutionTime: isDisabled ? '-' : moment(nextExecution).fromNow()
- };
- }
-
- return {
- lastExecutionTime: formatDate(lastExecution, shortDateFormat),
- nextExecutionTime: isDisabled ? '-' : formatDate(nextExecution, shortDateFormat)
- };
-}
-
-class ScheduledTaskRow extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = getFormattedDates(props);
-
- this._updateTimeoutId = null;
- }
-
- componentDidMount() {
- this.setUpdateTimer();
- }
-
- componentDidUpdate(prevProps) {
- const {
- lastExecution,
- nextExecution
- } = this.props;
-
- if (
- lastExecution !== prevProps.lastExecution ||
- nextExecution !== prevProps.nextExecution
- ) {
- this.setState(getFormattedDates(this.props));
- }
- }
-
- componentWillUnmount() {
- if (this._updateTimeoutId) {
- this._updateTimeoutId = clearTimeout(this._updateTimeoutId);
- }
- }
-
- //
- // Listeners
-
- setUpdateTimer() {
- const { interval } = this.props;
- const timeout = interval < 60 ? 10000 : 60000;
-
- this._updateTimeoutId = setTimeout(() => {
- this.setState(getFormattedDates(this.props));
- this.setUpdateTimer();
- }, timeout);
- }
-
- //
- // Render
-
- render() {
- const {
- name,
- interval,
- lastExecution,
- lastStartTime,
- lastDuration,
- nextExecution,
- isQueued,
- isExecuting,
- longDateFormat,
- timeFormat,
- onExecutePress
- } = this.props;
-
- const {
- lastExecutionTime,
- nextExecutionTime
- } = this.state;
-
- const isDisabled = interval === 0;
- const executeNow = !isDisabled && moment().isAfter(nextExecution);
- const hasNextExecutionTime = !isDisabled && !executeNow;
- const duration = moment.duration(interval, 'minutes').humanize().replace(/an?(?=\s)/, '1');
- const hasLastStartTime = moment(lastStartTime).isAfter('2010-01-01');
-
- return (
-
- {name}
-
- {isDisabled ? 'disabled' : duration}
-
-
-
- {lastExecutionTime}
-
-
- {
- !hasLastStartTime &&
- -
- }
-
- {
- hasLastStartTime &&
-
- {formatTimeSpan(lastDuration)}
-
- }
-
- {
- isDisabled &&
- -
- }
-
- {
- executeNow && isQueued &&
- queued
- }
-
- {
- executeNow && !isQueued &&
- now
- }
-
- {
- hasNextExecutionTime &&
-
- {nextExecutionTime}
-
- }
-
-
-
-
-
- );
- }
-}
-
-ScheduledTaskRow.propTypes = {
- name: PropTypes.string.isRequired,
- interval: PropTypes.number.isRequired,
- lastExecution: PropTypes.string.isRequired,
- lastStartTime: PropTypes.string.isRequired,
- lastDuration: PropTypes.string.isRequired,
- nextExecution: PropTypes.string.isRequired,
- isQueued: PropTypes.bool.isRequired,
- isExecuting: PropTypes.bool.isRequired,
- showRelativeDates: PropTypes.bool.isRequired,
- shortDateFormat: PropTypes.string.isRequired,
- longDateFormat: PropTypes.string.isRequired,
- timeFormat: PropTypes.string.isRequired,
- onExecutePress: PropTypes.func.isRequired
-};
-
-export default ScheduledTaskRow;
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRowConnector.js b/frontend/src/System/Tasks/Scheduled/ScheduledTaskRowConnector.js
deleted file mode 100644
index dae790d68..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTaskRowConnector.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { fetchTask } from 'Store/Actions/systemActions';
-import createCommandsSelector from 'Store/Selectors/createCommandsSelector';
-import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
-import { findCommand, isCommandExecuting } from 'Utilities/Command';
-import ScheduledTaskRow from './ScheduledTaskRow';
-
-function createMapStateToProps() {
- return createSelector(
- (state, { taskName }) => taskName,
- createCommandsSelector(),
- createUISettingsSelector(),
- (taskName, commands, uiSettings) => {
- const command = findCommand(commands, { name: taskName });
-
- return {
- isQueued: !!(command && command.state === 'queued'),
- isExecuting: isCommandExecuting(command),
- showRelativeDates: uiSettings.showRelativeDates,
- shortDateFormat: uiSettings.shortDateFormat,
- longDateFormat: uiSettings.longDateFormat,
- timeFormat: uiSettings.timeFormat
- };
- }
- );
-}
-
-function createMapDispatchToProps(dispatch, props) {
- const taskName = props.taskName;
-
- return {
- dispatchFetchTask() {
- dispatch(fetchTask({
- id: props.id
- }));
- },
-
- onExecutePress() {
- dispatch(executeCommand({
- name: taskName
- }));
- }
- };
-}
-
-class ScheduledTaskRowConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidUpdate(prevProps) {
- const {
- isExecuting,
- dispatchFetchTask
- } = this.props;
-
- if (!isExecuting && prevProps.isExecuting) {
- // Give the host a moment to update after the command completes
- setTimeout(() => {
- dispatchFetchTask();
- }, 1000);
- }
- }
-
- //
- // Render
-
- render() {
- const {
- dispatchFetchTask,
- ...otherProps
- } = this.props;
-
- return (
-
- );
- }
-}
-
-ScheduledTaskRowConnector.propTypes = {
- id: PropTypes.number.isRequired,
- isExecuting: PropTypes.bool.isRequired,
- dispatchFetchTask: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, createMapDispatchToProps)(ScheduledTaskRowConnector);
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js b/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js
deleted file mode 100644
index bec151613..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTasks.js
+++ /dev/null
@@ -1,85 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import FieldSet from 'Components/FieldSet';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import translate from 'Utilities/String/translate';
-import ScheduledTaskRowConnector from './ScheduledTaskRowConnector';
-
-const columns = [
- {
- name: 'name',
- label: () => translate('Name'),
- isVisible: true
- },
- {
- name: 'interval',
- label: () => translate('Interval'),
- isVisible: true
- },
- {
- name: 'lastExecution',
- label: () => translate('LastExecution'),
- isVisible: true
- },
- {
- name: 'lastDuration',
- label: () => translate('LastDuration'),
- isVisible: true
- },
- {
- name: 'nextExecution',
- label: () => translate('NextExecution'),
- isVisible: true
- },
- {
- name: 'actions',
- isVisible: true
- }
-];
-
-function ScheduledTasks(props) {
- const {
- isFetching,
- isPopulated,
- items
- } = props;
-
- return (
-
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- isPopulated &&
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
- }
-
- );
-}
-
-ScheduledTasks.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- items: PropTypes.array.isRequired
-};
-
-export default ScheduledTasks;
diff --git a/frontend/src/System/Tasks/Scheduled/ScheduledTasksConnector.js b/frontend/src/System/Tasks/Scheduled/ScheduledTasksConnector.js
deleted file mode 100644
index 8f418d3bb..000000000
--- a/frontend/src/System/Tasks/Scheduled/ScheduledTasksConnector.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchTasks } from 'Store/Actions/systemActions';
-import ScheduledTasks from './ScheduledTasks';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.system.tasks,
- (tasks) => {
- return tasks;
- }
- );
-}
-
-const mapDispatchToProps = {
- dispatchFetchTasks: fetchTasks
-};
-
-class ScheduledTasksConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.dispatchFetchTasks();
- }
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-ScheduledTasksConnector.propTypes = {
- dispatchFetchTasks: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(ScheduledTasksConnector);
diff --git a/frontend/src/System/Tasks/Tasks.js b/frontend/src/System/Tasks/Tasks.js
deleted file mode 100644
index 03a3b6ce4..000000000
--- a/frontend/src/System/Tasks/Tasks.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React from 'react';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import translate from 'Utilities/String/translate';
-import QueuedTasks from './Queued/QueuedTasks';
-import ScheduledTasksConnector from './Scheduled/ScheduledTasksConnector';
-
-function Tasks() {
- return (
-
-
-
-
-
-
- );
-}
-
-export default Tasks;
diff --git a/frontend/src/System/Updates/UpdateChanges.css b/frontend/src/System/Updates/UpdateChanges.css
deleted file mode 100644
index d21897373..000000000
--- a/frontend/src/System/Updates/UpdateChanges.css
+++ /dev/null
@@ -1,4 +0,0 @@
-.title {
- margin-top: 10px;
- font-size: 16px;
-}
diff --git a/frontend/src/System/Updates/UpdateChanges.css.d.ts b/frontend/src/System/Updates/UpdateChanges.css.d.ts
deleted file mode 100644
index 86bceec06..000000000
--- a/frontend/src/System/Updates/UpdateChanges.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'title': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Updates/UpdateChanges.tsx b/frontend/src/System/Updates/UpdateChanges.tsx
deleted file mode 100644
index 3e5ba1c9b..000000000
--- a/frontend/src/System/Updates/UpdateChanges.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-import styles from './UpdateChanges.css';
-
-interface UpdateChangesProps {
- title: string;
- changes: string[];
-}
-
-function UpdateChanges(props: UpdateChangesProps) {
- const { title, changes } = props;
-
- if (changes.length === 0) {
- return null;
- }
-
- const uniqueChanges = [...new Set(changes)];
-
- return (
-
-
{title}
-
- {uniqueChanges.map((change, index) => {
- const checkChange = change.replace(
- /#\d{4,5}\b/g,
- (match) =>
- `[${match}](https://github.com/Lidarr/Lidarr/issues/${match.substring(
- 1
- )})`
- );
-
- return (
-
-
-
- );
- })}
-
-
- );
-}
-
-export default UpdateChanges;
diff --git a/frontend/src/System/Updates/Updates.css b/frontend/src/System/Updates/Updates.css
deleted file mode 100644
index 6ed588890..000000000
--- a/frontend/src/System/Updates/Updates.css
+++ /dev/null
@@ -1,53 +0,0 @@
-.messageContainer {
- display: flex;
- margin-bottom: 20px;
-}
-
-.upToDateIcon {
- color: #37bc9b;
- font-size: 30px;
-}
-
-.message {
- padding-left: 5px;
- font-size: 18px;
- line-height: 30px;
-}
-
-.loading {
- composes: loading from '~Components/Loading/LoadingIndicator.css';
-
- margin-top: 5px;
- margin-left: auto;
-}
-
-.update {
- margin-top: 20px;
-}
-
-.info {
- display: flex;
- align-items: center;
- margin-bottom: 10px;
- padding-bottom: 5px;
- border-bottom: 1px solid #e5e5e5;
-}
-
-.version {
- font-size: 21px;
-}
-
-.space {
- padding: 0 5px;
-}
-
-.date {
- font-size: 16px;
-}
-
-.label {
- composes: label from '~Components/Label.css';
-
- margin-left: 10px;
- font-size: 14px;
-}
diff --git a/frontend/src/System/Updates/Updates.css.d.ts b/frontend/src/System/Updates/Updates.css.d.ts
deleted file mode 100644
index ed1f5434f..000000000
--- a/frontend/src/System/Updates/Updates.css.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'date': string;
- 'info': string;
- 'label': string;
- 'loading': string;
- 'message': string;
- 'messageContainer': string;
- 'space': string;
- 'upToDateIcon': string;
- 'update': string;
- 'version': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/System/Updates/Updates.tsx b/frontend/src/System/Updates/Updates.tsx
deleted file mode 100644
index 300ab1f99..000000000
--- a/frontend/src/System/Updates/Updates.tsx
+++ /dev/null
@@ -1,303 +0,0 @@
-import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { useDispatch, useSelector } from 'react-redux';
-import { createSelector } from 'reselect';
-import AppState from 'App/State/AppState';
-import * as commandNames from 'Commands/commandNames';
-import Alert from 'Components/Alert';
-import Icon from 'Components/Icon';
-import Label from 'Components/Label';
-import SpinnerButton from 'Components/Link/SpinnerButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import InlineMarkdown from 'Components/Markdown/InlineMarkdown';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import { icons, kinds } from 'Helpers/Props';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { fetchGeneralSettings } from 'Store/Actions/settingsActions';
-import { fetchUpdates } from 'Store/Actions/systemActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
-import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
-import { UpdateMechanism } from 'typings/Settings/General';
-import formatDate from 'Utilities/Date/formatDate';
-import formatDateTime from 'Utilities/Date/formatDateTime';
-import translate from 'Utilities/String/translate';
-import UpdateChanges from './UpdateChanges';
-import styles from './Updates.css';
-
-const VERSION_REGEX = /\d+\.\d+\.\d+\.\d+/i;
-
-function createUpdatesSelector() {
- return createSelector(
- (state: AppState) => state.system.updates,
- (state: AppState) => state.settings.general,
- (updates, generalSettings) => {
- const { error: updatesError, items } = updates;
-
- const isFetching = updates.isFetching || generalSettings.isFetching;
- const isPopulated = updates.isPopulated && generalSettings.isPopulated;
-
- return {
- isFetching,
- isPopulated,
- updatesError,
- generalSettingsError: generalSettings.error,
- items,
- updateMechanism: generalSettings.item.updateMechanism,
- };
- }
- );
-}
-
-function Updates() {
- const currentVersion = useSelector((state: AppState) => state.app.version);
- const { packageUpdateMechanismMessage } = useSelector(
- createSystemStatusSelector()
- );
- const { shortDateFormat, longDateFormat, timeFormat } = useSelector(
- createUISettingsSelector()
- );
- const isInstallingUpdate = useSelector(
- createCommandExecutingSelector(commandNames.APPLICATION_UPDATE)
- );
-
- const {
- isFetching,
- isPopulated,
- updatesError,
- generalSettingsError,
- items,
- updateMechanism,
- } = useSelector(createUpdatesSelector());
-
- const dispatch = useDispatch();
- const [isMajorUpdateModalOpen, setIsMajorUpdateModalOpen] = useState(false);
- const hasError = !!(updatesError || generalSettingsError);
- const hasUpdates = isPopulated && !hasError && items.length > 0;
- const noUpdates = isPopulated && !hasError && !items.length;
-
- const externalUpdaterPrefix = translate('UpdateAppDirectlyLoadError');
- const externalUpdaterMessages: Partial> = {
- external: translate('ExternalUpdater'),
- apt: translate('AptUpdater'),
- docker: translate('DockerUpdater'),
- };
-
- const { isMajorUpdate, hasUpdateToInstall } = useMemo(() => {
- const majorVersion = parseInt(
- currentVersion.match(VERSION_REGEX)?.[0] ?? '0'
- );
-
- const latestVersion = items[0]?.version;
- const latestMajorVersion = parseInt(
- latestVersion?.match(VERSION_REGEX)?.[0] ?? '0'
- );
-
- return {
- isMajorUpdate: latestMajorVersion > majorVersion,
- hasUpdateToInstall: items.some(
- (update) => update.installable && update.latest
- ),
- };
- }, [currentVersion, items]);
-
- const noUpdateToInstall = hasUpdates && !hasUpdateToInstall;
-
- const handleInstallLatestPress = useCallback(() => {
- if (isMajorUpdate) {
- setIsMajorUpdateModalOpen(true);
- } else {
- dispatch(executeCommand({ name: commandNames.APPLICATION_UPDATE }));
- }
- }, [isMajorUpdate, setIsMajorUpdateModalOpen, dispatch]);
-
- const handleInstallLatestMajorVersionPress = useCallback(() => {
- setIsMajorUpdateModalOpen(false);
-
- dispatch(
- executeCommand({
- name: commandNames.APPLICATION_UPDATE,
- installMajorUpdate: true,
- })
- );
- }, [setIsMajorUpdateModalOpen, dispatch]);
-
- const handleCancelMajorVersionPress = useCallback(() => {
- setIsMajorUpdateModalOpen(false);
- }, [setIsMajorUpdateModalOpen]);
-
- useEffect(() => {
- dispatch(fetchUpdates());
- dispatch(fetchGeneralSettings());
- }, [dispatch]);
-
- return (
-
-
- {isPopulated || hasError ? null : }
-
- {noUpdates ? (
- {translate('NoUpdatesAreAvailable')}
- ) : null}
-
- {hasUpdateToInstall ? (
-
- {updateMechanism === 'builtIn' || updateMechanism === 'script' ? (
-
- {translate('InstallLatest')}
-
- ) : (
- <>
-
-
-
- {externalUpdaterPrefix}{' '}
-
-
- >
- )}
-
- {isFetching ? (
-
- ) : null}
-
- ) : null}
-
- {noUpdateToInstall && (
-
-
-
{translate('OnLatestVersion')}
-
- {isFetching && (
-
- )}
-
- )}
-
- {hasUpdates && (
-
- {items.map((update) => {
- return (
-
-
-
{update.version}
-
—
-
- {formatDate(update.releaseDate, shortDateFormat)}
-
-
- {update.branch === 'master' ? null : (
-
{update.branch}
- )}
-
- {update.version === currentVersion ? (
-
- {translate('CurrentlyInstalled')}
-
- ) : null}
-
- {update.version !== currentVersion && update.installedOn ? (
-
- {translate('PreviouslyInstalled')}
-
- ) : null}
-
-
- {update.changes ? (
-
-
-
-
-
- ) : (
-
{translate('MaintenanceRelease')}
- )}
-
- );
- })}
-
- )}
-
- {updatesError ? (
-
- {translate('FailedToFetchUpdates')}
-
- ) : null}
-
- {generalSettingsError ? (
-
- {translate('FailedToFetchSettings')}
-
- ) : null}
-
-
- {translate('InstallMajorVersionUpdateMessage')}
-
-
-
-
- }
- confirmLabel={translate('Install')}
- onConfirm={handleInstallLatestMajorVersionPress}
- onCancel={handleCancelMajorVersionPress}
- />
-
-
- );
-}
-
-export default Updates;
diff --git a/frontend/src/Track/Track.ts b/frontend/src/Track/Track.ts
deleted file mode 100644
index 7c080290a..000000000
--- a/frontend/src/Track/Track.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-interface Track extends ModelBase {
- artistId: number;
- foreignTrackId: string;
- foreignRecordingId: string;
- trackFileId: number;
- albumId: number;
- explicit: boolean;
- absoluteTrackNumber: number;
- trackNumber: string;
- title: string;
- duration: number;
- trackFile?: object;
- mediumNumber: number;
- hasFile: boolean;
-}
-
-export default Track;
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorModal.js b/frontend/src/TrackFile/Editor/TrackFileEditorModal.js
deleted file mode 100644
index 7f52aca05..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorModal.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Modal from 'Components/Modal/Modal';
-import TrackFileEditorModalContentConnector from './TrackFileEditorModalContentConnector';
-
-function TrackFileEditorModal(props) {
- const {
- isOpen,
- onModalClose,
- ...otherProps
- } = props;
-
- return (
-
- {
- isOpen &&
-
- }
-
- );
-}
-
-TrackFileEditorModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default TrackFileEditorModal;
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css b/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css
deleted file mode 100644
index 49e946826..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.actions {
- display: flex;
- margin-right: auto;
-}
-
-.selectInput {
- margin-left: 10px;
-}
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css.d.ts b/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css.d.ts
deleted file mode 100644
index 3c384a307..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'selectInput': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.js b/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.js
deleted file mode 100644
index 0e387f39f..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorModalContent.js
+++ /dev/null
@@ -1,263 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import SelectInput from 'Components/Form/SelectInput';
-import Button from 'Components/Link/Button';
-import SpinnerButton from 'Components/Link/SpinnerButton';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-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 Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import { kinds } from 'Helpers/Props';
-import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
-import translate from 'Utilities/String/translate';
-import getSelectedIds from 'Utilities/Table/getSelectedIds';
-import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
-import selectAll from 'Utilities/Table/selectAll';
-import toggleSelected from 'Utilities/Table/toggleSelected';
-import TrackFileEditorRow from './TrackFileEditorRow';
-import styles from './TrackFileEditorModalContent.css';
-
-const columns = [
- {
- name: 'trackNumber',
- label: () => translate('Track'),
- isVisible: true
- },
- {
- name: 'path',
- label: () => translate('Path'),
- isVisible: true
- },
- {
- name: 'quality',
- label: () => translate('Quality'),
- isVisible: true
- }
-];
-
-class TrackFileEditorModalContent extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- allSelected: false,
- allUnselected: false,
- lastToggled: null,
- selectedState: {},
- isConfirmDeleteModalOpen: false
- };
- }
-
- componentDidUpdate(prevProps) {
- if (hasDifferentItems(prevProps.items, this.props.items)) {
- this.setState((state) => {
- return removeOldSelectedState(state, prevProps.items);
- });
- }
- }
-
- //
- // Control
-
- getSelectedIds = () => {
- const selectedIds = getSelectedIds(this.state.selectedState);
-
- return selectedIds.reduce((acc, id) => {
- const matchingItem = this.props.items.find((item) => item.id === id);
-
- if (matchingItem && !acc.includes(matchingItem.trackFileId)) {
- acc.push(matchingItem.trackFileId);
- }
-
- return acc;
- }, []);
- };
-
- //
- // 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);
- });
- };
-
- onDeletePress = () => {
- this.setState({ isConfirmDeleteModalOpen: true });
- };
-
- onConfirmDelete = () => {
- this.setState({ isConfirmDeleteModalOpen: false });
- this.props.onDeletePress(this.getSelectedIds());
- };
-
- onConfirmDeleteModalClose = () => {
- this.setState({ isConfirmDeleteModalOpen: false });
- };
-
- onQualityChange = ({ value }) => {
- const selectedIds = this.getSelectedIds();
-
- if (!selectedIds.length) {
- return;
- }
-
- this.props.onQualityChange(selectedIds, parseInt(value));
- };
-
- //
- // Render
-
- render() {
- const {
- isDeleting,
- isFetching,
- isPopulated,
- error,
- items,
- qualities,
- onModalClose
- } = this.props;
-
- const {
- allSelected,
- allUnselected,
- selectedState,
- isConfirmDeleteModalOpen
- } = this.state;
-
- const qualityOptions = _.reduceRight(qualities, (acc, quality) => {
- acc.push({
- key: quality.id,
- value: quality.name
- });
-
- return acc;
- }, [{ key: 'selectQuality', value: translate('SelectQuality'), isDisabled: true }]);
-
- const hasSelectedFiles = this.getSelectedIds().length > 0;
-
- return (
-
-
- Manage Tracks
-
-
-
- {
- isFetching && !isPopulated ?
- :
- null
- }
-
- {
- !isFetching && error ?
- {error}
:
- null
- }
-
- {
- isPopulated && !items.length ?
-
- No track files to manage.
-
:
- null
- }
-
- {
- isPopulated && items.length ?
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
:
- null
- }
-
-
-
-
-
-
- {translate('Close')}
-
-
-
-
-
- );
- }
-}
-
-TrackFileEditorModalContent.propTypes = {
- isDeleting: PropTypes.bool.isRequired,
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
- onDeletePress: PropTypes.func.isRequired,
- onQualityChange: PropTypes.func.isRequired,
- onModalClose: PropTypes.func.isRequired
-};
-
-export default TrackFileEditorModalContent;
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorModalContentConnector.js b/frontend/src/TrackFile/Editor/TrackFileEditorModalContentConnector.js
deleted file mode 100644
index 71bb1a4f4..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorModalContentConnector.js
+++ /dev/null
@@ -1,174 +0,0 @@
-/* eslint max-params: 0 */
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import { fetchQualityProfileSchema } from 'Store/Actions/settingsActions';
-import { clearTracks, fetchTracks } from 'Store/Actions/trackActions';
-import { deleteTrackFiles, updateTrackFiles } from 'Store/Actions/trackFileActions';
-import createArtistSelector from 'Store/Selectors/createArtistSelector';
-import getQualities from 'Utilities/Quality/getQualities';
-import TrackFileEditorModalContent from './TrackFileEditorModalContent';
-
-function createSchemaSelector() {
- return createSelector(
- (state) => state.settings.qualityProfiles,
- (qualityProfiles) => {
- const qualities = getQualities(qualityProfiles.schema.items);
-
- let error = null;
-
- if (qualityProfiles.schemaError) {
- error = 'Unable to load qualities';
- }
-
- return {
- isFetching: qualityProfiles.isSchemaFetching,
- isPopulated: qualityProfiles.isSchemaPopulated,
- error,
- qualities
- };
- }
- );
-}
-
-function createMapStateToProps() {
- return createSelector(
- (state, { albumId }) => albumId,
- (state) => state.tracks,
- (state) => state.trackFiles,
- createSchemaSelector(),
- createArtistSelector(),
- (
- albumId,
- tracks,
- trackFiles,
- schema,
- artist
- ) => {
- const filtered = _.filter(tracks.items, (track) => {
- if (albumId >= 0 && track.albumId !== albumId) {
- return false;
- }
-
- if (!track.trackFileId) {
- return false;
- }
-
- return _.some(trackFiles.items, { id: track.trackFileId });
- });
-
- const sorted = _.orderBy(filtered, ['albumId', 'mediumNumber', 'absoluteTrackNumber'], ['desc', 'asc', 'asc']);
-
- const items = _.map(sorted, (track) => {
- const trackFile = _.find(trackFiles.items, { id: track.trackFileId });
-
- return {
- path: trackFile.path,
- quality: trackFile.quality,
- qualityCutoffNotMet: trackFile.qualityCutoffNotMet,
- ...track
- };
- });
-
- return {
- ...schema,
- items,
- artistType: artist.artistType,
- isDeleting: trackFiles.isDeleting,
- isSaving: trackFiles.isSaving
- };
- }
- );
-}
-
-function createMapDispatchToProps(dispatch, props) {
- return {
- dispatchClearTracks() {
- dispatch(clearTracks());
- },
-
- dispatchFetchTracks(updateProps) {
- dispatch(fetchTracks(updateProps));
- },
-
- dispatchFetchQualityProfileSchema(name, path) {
- dispatch(fetchQualityProfileSchema());
- },
-
- dispatchUpdateTrackFiles(updateProps) {
- dispatch(updateTrackFiles(updateProps));
- },
-
- onDeletePress(trackFileIds) {
- dispatch(deleteTrackFiles({ trackFileIds }));
- }
- };
-}
-
-class TrackFileEditorModalContentConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const artistId = this.props.artistId;
- const albumId = this.props.albumId;
-
- this.props.dispatchFetchTracks({ artistId, albumId });
-
- this.props.dispatchFetchQualityProfileSchema();
- }
-
- componentWillUnmount() {
- this.props.dispatchClearTracks();
- }
-
- //
- // Listeners
-
- onQualityChange = (trackFileIds, qualityId) => {
- const quality = {
- quality: _.find(this.props.qualities, { id: qualityId }),
- revision: {
- version: 1,
- real: 0
- }
- };
-
- this.props.dispatchUpdateTrackFiles({ trackFileIds, quality });
- };
-
- //
- // Render
-
- render() {
- const {
- dispatchFetchQualityProfileSchema,
- dispatchUpdateTrackFiles,
- dispatchFetchTracks,
- dispatchClearTracks,
- ...otherProps
- } = this.props;
-
- return (
-
- );
- }
-}
-
-TrackFileEditorModalContentConnector.propTypes = {
- artistId: PropTypes.number.isRequired,
- albumId: PropTypes.number,
- qualities: PropTypes.arrayOf(PropTypes.object).isRequired,
- dispatchFetchTracks: PropTypes.func.isRequired,
- dispatchClearTracks: PropTypes.func.isRequired,
- dispatchFetchQualityProfileSchema: PropTypes.func.isRequired,
- dispatchUpdateTrackFiles: PropTypes.func.isRequired
-};
-
-export default connect(createMapStateToProps, createMapDispatchToProps)(TrackFileEditorModalContentConnector);
diff --git a/frontend/src/TrackFile/Editor/TrackFileEditorRow.js b/frontend/src/TrackFile/Editor/TrackFileEditorRow.js
deleted file mode 100644
index a2e616de8..000000000
--- a/frontend/src/TrackFile/Editor/TrackFileEditorRow.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import TrackQuality from 'Album/TrackQuality';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
-import TableRow from 'Components/Table/TableRow';
-import padNumber from 'Utilities/Number/padNumber';
-
-function TrackFileEditorRow(props) {
- const {
- id,
- trackNumber,
- path,
- quality,
- qualityCutoffNotMet,
- isSelected,
- onSelectedChange
- } = props;
-
- return (
-
-
-
-
- {padNumber(trackNumber, 2)}
-
-
-
- {path}
-
-
-
-
-
-
- );
-}
-
-TrackFileEditorRow.propTypes = {
- id: PropTypes.number.isRequired,
- trackNumber: PropTypes.string.isRequired,
- path: PropTypes.string.isRequired,
- quality: PropTypes.object.isRequired,
- qualityCutoffNotMet: PropTypes.bool.isRequired,
- isSelected: PropTypes.bool,
- onSelectedChange: PropTypes.func.isRequired
-};
-
-export default TrackFileEditorRow;
diff --git a/frontend/src/TrackFile/ExpandingFileDetails.css b/frontend/src/TrackFile/ExpandingFileDetails.css
deleted file mode 100644
index 23af8caf7..000000000
--- a/frontend/src/TrackFile/ExpandingFileDetails.css
+++ /dev/null
@@ -1,61 +0,0 @@
-.fileDetails {
- margin-bottom: 20px;
- border: 1px solid var(--borderColor);
- border-radius: 4px;
- background-color: var(--cardBackgroundColor);
-
- &:last-of-type {
- margin-bottom: 0;
- }
-}
-
-.filename {
- flex-grow: 1;
- margin-right: 10px;
- margin-left: 10px;
- font-size: 14px;
- font-family: $monoSpaceFontFamily;
-}
-
-.header {
- position: relative;
- display: flex;
- align-items: center;
- width: 100%;
- font-size: 18px;
-}
-
-.expandButton {
- position: relative;
- width: 60px;
- height: 60px;
-}
-
-.actionButton {
- composes: button from '~Components/Link/IconButton.css';
-
- width: 30px;
-}
-
-.expandButtonIcon {
- composes: actionButton;
-
- position: absolute;
- top: 50%;
- left: 50%;
- margin-top: -12px;
- margin-left: -15px;
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- .medium {
- border-right: 0;
- border-left: 0;
- border-radius: 0;
- }
-
- .expandButtonIcon {
- position: static;
- margin: 0;
- }
-}
diff --git a/frontend/src/TrackFile/ExpandingFileDetails.css.d.ts b/frontend/src/TrackFile/ExpandingFileDetails.css.d.ts
deleted file mode 100644
index 55c305cf3..000000000
--- a/frontend/src/TrackFile/ExpandingFileDetails.css.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actionButton': string;
- 'expandButton': string;
- 'expandButtonIcon': string;
- 'fileDetails': string;
- 'filename': string;
- 'header': string;
- 'medium': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/TrackFile/ExpandingFileDetails.js b/frontend/src/TrackFile/ExpandingFileDetails.js
deleted file mode 100644
index 15e5d3625..000000000
--- a/frontend/src/TrackFile/ExpandingFileDetails.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Icon from 'Components/Icon';
-import { icons } from 'Helpers/Props';
-import translate from 'Utilities/String/translate';
-import FileDetails from './FileDetails';
-import styles from './ExpandingFileDetails.css';
-
-class ExpandingFileDetails extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isExpanded: props.isExpanded
- };
- }
-
- //
- // Listeners
-
- onExpandPress = () => {
- const {
- isExpanded
- } = this.state;
- this.setState({ isExpanded: !isExpanded });
- };
-
- //
- // Render
-
- render() {
- const {
- filename,
- audioTags,
- rejections
- } = this.props;
-
- const {
- isExpanded
- } = this.state;
-
- return (
-
-
-
- {filename}
-
-
-
-
-
-
-
- {
- isExpanded &&
-
- }
-
- );
- }
-}
-
-ExpandingFileDetails.propTypes = {
- audioTags: PropTypes.object.isRequired,
- filename: PropTypes.string.isRequired,
- rejections: PropTypes.arrayOf(PropTypes.object),
- isExpanded: PropTypes.bool
-};
-
-export default ExpandingFileDetails;
diff --git a/frontend/src/TrackFile/FileDetails.css b/frontend/src/TrackFile/FileDetails.css
deleted file mode 100644
index f157f7b7b..000000000
--- a/frontend/src/TrackFile/FileDetails.css
+++ /dev/null
@@ -1,12 +0,0 @@
-.audioTags {
- padding-top: 15px;
- padding-bottom: 15px;
- word-break: break-word;
- /* border-top: 1px solid $borderColor; */
-}
-
-.filename {
- composes: description from '~Components/DescriptionList/DescriptionListItemDescription.css';
-
- font-family: $monoSpaceFontFamily;
-}
diff --git a/frontend/src/TrackFile/FileDetails.css.d.ts b/frontend/src/TrackFile/FileDetails.css.d.ts
deleted file mode 100644
index b327cff06..000000000
--- a/frontend/src/TrackFile/FileDetails.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'audioTags': string;
- 'filename': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/TrackFile/FileDetails.js b/frontend/src/TrackFile/FileDetails.js
deleted file mode 100644
index ae2520cd0..000000000
--- a/frontend/src/TrackFile/FileDetails.js
+++ /dev/null
@@ -1,207 +0,0 @@
-import _ from 'lodash';
-import PropTypes from 'prop-types';
-import React, { Fragment } from 'react';
-import DescriptionList from 'Components/DescriptionList/DescriptionList';
-import DescriptionListItem from 'Components/DescriptionList/DescriptionListItem';
-import DescriptionListItemDescription from 'Components/DescriptionList/DescriptionListItemDescription';
-import DescriptionListItemTitle from 'Components/DescriptionList/DescriptionListItemTitle';
-import Link from 'Components/Link/Link';
-import formatTimeSpan from 'Utilities/Date/formatTimeSpan';
-import translate from 'Utilities/String/translate';
-import styles from './FileDetails.css';
-
-function renderRejections(rejections) {
- return (
-
-
- Rejections
-
- {
- _.map(rejections, (item, key) => {
- return (
-
- {item.reason}
-
- );
- })
- }
-
- );
-}
-
-function FileDetails(props) {
-
- const {
- filename,
- audioTags,
- rejections
- } = props;
-
- return (
-
-
-
- {
- filename &&
-
- }
- {
- audioTags.title !== undefined &&
-
- }
- {
- audioTags.trackNumbers[0] > 0 &&
-
- }
- {
- audioTags.discNumber > 0 &&
-
- }
- {
- audioTags.discCount > 0 &&
-
- }
- {
- audioTags.albumTitle !== undefined &&
-
- }
- {
- audioTags.artistTitle !== undefined &&
-
- }
- {
- audioTags.country !== undefined &&
-
- }
- {
- audioTags.year > 0 &&
-
- }
- {
- audioTags.label !== undefined &&
-
- }
- {
- audioTags.catalogNumber !== undefined &&
-
- }
- {
- audioTags.disambiguation !== undefined &&
-
- }
- {
- audioTags.duration !== undefined &&
-
- }
- {
- audioTags.artistMBId !== undefined &&
-
-
-
- }
- {
- audioTags.albumMBId !== undefined &&
-
-
-
- }
- {
- audioTags.releaseMBId !== undefined &&
-
-
-
- }
- {
- audioTags.recordingMBId !== undefined &&
-
-
-
- }
- {
- audioTags.trackMBId !== undefined &&
-
-
-
- }
- {
- !!rejections && rejections.length > 0 &&
- renderRejections(rejections)
- }
-
-
-
- );
-}
-
-FileDetails.propTypes = {
- filename: PropTypes.string,
- audioTags: PropTypes.object.isRequired,
- rejections: PropTypes.arrayOf(PropTypes.object)
-};
-
-export default FileDetails;
diff --git a/frontend/src/TrackFile/FileDetailsConnector.js b/frontend/src/TrackFile/FileDetailsConnector.js
deleted file mode 100644
index 28f8766d0..000000000
--- a/frontend/src/TrackFile/FileDetailsConnector.js
+++ /dev/null
@@ -1,77 +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 LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import { fetchTrackFiles } from 'Store/Actions/trackFileActions';
-import getErrorMessage from 'Utilities/Object/getErrorMessage';
-import FileDetails from './FileDetails';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.trackFiles,
- (trackFiles) => {
- return {
- ...trackFiles
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- fetchTrackFiles
-};
-
-class FileDetailsConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- this.props.fetchTrackFiles({ id: this.props.id });
- }
-
- //
- // Render
-
- render() {
- const {
- items,
- id,
- isFetching,
- error
- } = this.props;
-
- const item = _.find(items, { id });
- const errorMessage = getErrorMessage(error, 'Unable to load manual import items');
-
- if (isFetching || !item.audioTags) {
- return (
-
- );
- } else if (error) {
- return (
- {errorMessage}
- );
- }
-
- return (
-
- );
-
- }
-}
-
-FileDetailsConnector.propTypes = {
- fetchTrackFiles: PropTypes.func.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- id: PropTypes.number.isRequired,
- isFetching: PropTypes.bool.isRequired,
- error: PropTypes.object
-};
-
-export default connect(createMapStateToProps, mapDispatchToProps)(FileDetailsConnector);
diff --git a/frontend/src/TrackFile/FileDetailsModal.js b/frontend/src/TrackFile/FileDetailsModal.js
deleted file mode 100644
index d9ebe2f3b..000000000
--- a/frontend/src/TrackFile/FileDetailsModal.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import Button from 'Components/Link/Button';
-import Modal from 'Components/Modal/Modal';
-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 FileDetailsConnector from './FileDetailsConnector';
-
-function FileDetailsModal(props) {
- const {
- isOpen,
- onModalClose,
- id
- } = props;
-
- return (
-
-
-
- Details
-
-
-
-
-
-
-
-
- Close
-
-
-
-
- );
-}
-
-FileDetailsModal.propTypes = {
- isOpen: PropTypes.bool.isRequired,
- onModalClose: PropTypes.func.isRequired,
- id: PropTypes.number.isRequired
-};
-
-export default FileDetailsModal;
diff --git a/frontend/src/TrackFile/MediaInfo.js b/frontend/src/TrackFile/MediaInfo.js
deleted file mode 100644
index 3f50fb70e..000000000
--- a/frontend/src/TrackFile/MediaInfo.js
+++ /dev/null
@@ -1,78 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import * as mediaInfoTypes from './mediaInfoTypes';
-
-function MediaInfo(props) {
- const {
- type,
- audioChannels,
- audioCodec,
- audioBitRate,
- audioBits,
- audioSampleRate
- } = props;
-
- if (type === mediaInfoTypes.AUDIO) {
- return (
-
- {
- !!audioCodec &&
- audioCodec
- }
-
- {
- !!audioCodec && !!audioChannels &&
- ' - '
- }
-
- {
- !!audioChannels &&
- audioChannels.toFixed(1)
- }
-
- {
- ((!!audioCodec && !!audioBitRate) || (!!audioChannels && !!audioBitRate)) &&
- ' - '
- }
-
- {
- !!audioBitRate &&
- audioBitRate
- }
-
- {
- ((!!audioCodec && !!audioSampleRate) || (!!audioChannels && !!audioSampleRate) || (!!audioBitRate && !!audioSampleRate)) &&
- ' - '
- }
-
- {
- !!audioSampleRate &&
- audioSampleRate
- }
-
- {
- ((!!audioCodec && !!audioBits) || (!!audioChannels && !!audioBits) || (!!audioBitRate && !!audioBits) || (!!audioSampleRate && !!audioBits)) &&
- ' - '
- }
-
- {
- !!audioBits &&
- audioBits
- }
-
- );
- }
-
- return null;
-}
-
-MediaInfo.propTypes = {
- type: PropTypes.string.isRequired,
- audioChannels: PropTypes.number,
- audioCodec: PropTypes.string,
- audioBitRate: PropTypes.string,
- audioBits: PropTypes.string,
- audioSampleRate: PropTypes.string
-};
-
-export default MediaInfo;
diff --git a/frontend/src/TrackFile/MediaInfoConnector.js b/frontend/src/TrackFile/MediaInfoConnector.js
deleted file mode 100644
index 5f3a1386b..000000000
--- a/frontend/src/TrackFile/MediaInfoConnector.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import createTrackFileSelector from 'Store/Selectors/createTrackFileSelector';
-import MediaInfo from './MediaInfo';
-
-function createMapStateToProps() {
- return createSelector(
- createTrackFileSelector(),
- (trackFile) => {
- if (trackFile) {
- return {
- ...trackFile.mediaInfo
- };
- }
-
- return {};
- }
- );
-}
-
-export default connect(createMapStateToProps)(MediaInfo);
diff --git a/frontend/src/TrackFile/TrackFile.ts b/frontend/src/TrackFile/TrackFile.ts
deleted file mode 100644
index ef4dc65f3..000000000
--- a/frontend/src/TrackFile/TrackFile.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import ModelBase from 'App/ModelBase';
-import { QualityModel } from 'Quality/Quality';
-import CustomFormat from 'typings/CustomFormat';
-import MediaInfo from 'typings/MediaInfo';
-
-export interface TrackFile extends ModelBase {
- artistId: number;
- albumId: number;
- path: string;
- size: number;
- dateAdded: string;
- sceneName: string;
- releaseGroup: string;
- quality: QualityModel;
- customFormats: CustomFormat[];
- indexerFlags: number;
- mediaInfo: MediaInfo;
- qualityCutoffNotMet: boolean;
-}
diff --git a/frontend/src/TrackFile/mediaInfoTypes.js b/frontend/src/TrackFile/mediaInfoTypes.js
deleted file mode 100644
index 5e5a78e64..000000000
--- a/frontend/src/TrackFile/mediaInfoTypes.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const AUDIO = 'audio';
-export const VIDEO = 'video';
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTable.js b/frontend/src/UnmappedFiles/UnmappedFilesTable.js
deleted file mode 100644
index a326f91e0..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTable.js
+++ /dev/null
@@ -1,290 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
-import VirtualTable from 'Components/Table/VirtualTable';
-import VirtualTableRow from 'Components/Table/VirtualTableRow';
-import { align, icons, kinds, sortDirections } from 'Helpers/Props';
-import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
-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 UnmappedFilesTableHeader from './UnmappedFilesTableHeader';
-import UnmappedFilesTableRow from './UnmappedFilesTableRow';
-
-class UnmappedFilesTable extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.scrollerRef = React.createRef();
-
- this.state = {
- allSelected: false,
- allUnselected: false,
- lastToggled: null,
- selectedState: {}
- };
- }
-
- componentDidMount() {
- this.setSelectedState();
- }
-
- componentDidUpdate(prevProps) {
- const {
- items,
- sortKey,
- sortDirection,
- isDeleting,
- deleteError
- } = this.props;
-
- if (sortKey !== prevProps.sortKey ||
- sortDirection !== prevProps.sortDirection ||
- hasDifferentItemsOrOrder(prevProps.items, items)
- ) {
- this.setSelectedState();
- }
-
- const hasFinishedDeleting = prevProps.isDeleting &&
- !isDeleting &&
- !deleteError;
-
- if (hasFinishedDeleting) {
- this.onSelectAllChange({ value: false });
- }
- }
-
- getSelectedIds = () => {
- if (this.state.allUnselected) {
- return [];
- }
- return getSelectedIds(this.state.selectedState);
- };
-
- setSelectedState() {
- const {
- items
- } = this.props;
-
- const {
- selectedState
- } = this.state;
-
- const newSelectedState = {};
-
- items.forEach((file) => {
- const isItemSelected = selectedState[file.id];
-
- if (isItemSelected) {
- newSelectedState[file.id] = isItemSelected;
- } else {
- newSelectedState[file.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 });
- }
-
- onSelectAllChange = ({ value }) => {
- this.setState(selectAll(this.state.selectedState, value));
- };
-
- onSelectAllPress = () => {
- this.onSelectAllChange({ value: !this.state.allSelected });
- };
-
- onSelectedChange = ({ id, value, shiftKey = false }) => {
- this.setState((state) => {
- return toggleSelected(state, this.props.items, id, value, shiftKey);
- });
- };
-
- onDeleteUnmappedFilesPress = () => {
- const selectedIds = this.getSelectedIds();
-
- this.props.deleteUnmappedFiles(selectedIds);
- };
-
- rowRenderer = ({ key, rowIndex, style }) => {
- const {
- items,
- columns,
- deleteUnmappedFile
- } = this.props;
-
- const {
- selectedState
- } = this.state;
-
- const item = items[rowIndex];
-
- return (
-
-
-
- );
- };
-
- render() {
-
- const {
- isFetching,
- isPopulated,
- isDeleting,
- error,
- items,
- columns,
- sortKey,
- sortDirection,
- onTableOptionChange,
- onSortPress,
- isScanningFolders,
- onAddMissingArtistsPress,
- deleteUnmappedFiles,
- ...otherProps
- } = this.props;
-
- const {
- allSelected,
- allUnselected,
- selectedState
- } = this.state;
-
- const selectedTrackFileIds = this.getSelectedIds();
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- isFetching && !isPopulated &&
-
- }
-
- {
- isPopulated && !error && !items.length &&
-
- Success! My work is done, all files on disk are matched to known tracks.
-
- }
-
- {
- isPopulated &&
- !error &&
- !!items.length &&
- this.scrollerRef.current ?
-
- }
- selectedState={selectedState}
- sortKey={sortKey}
- sortDirection={sortDirection}
- /> :
- null
- }
-
-
- );
- }
-}
-
-UnmappedFilesTable.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- isDeleting: PropTypes.bool.isRequired,
- deleteError: PropTypes.object,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- sortKey: PropTypes.string,
- sortDirection: PropTypes.oneOf(sortDirections.all),
- onTableOptionChange: PropTypes.func.isRequired,
- onSortPress: PropTypes.func.isRequired,
- deleteUnmappedFile: PropTypes.func.isRequired,
- deleteUnmappedFiles: PropTypes.func.isRequired,
- isScanningFolders: PropTypes.bool.isRequired,
- onAddMissingArtistsPress: PropTypes.func.isRequired
-};
-
-export default UnmappedFilesTable;
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableConnector.js b/frontend/src/UnmappedFiles/UnmappedFilesTableConnector.js
deleted file mode 100644
index 63484b210..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableConnector.js
+++ /dev/null
@@ -1,120 +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 * as commandNames from 'Commands/commandNames';
-import withCurrentPage from 'Components/withCurrentPage';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { deleteTrackFile, deleteTrackFiles, fetchTrackFiles, setTrackFilesSort, setTrackFilesTableOption } from 'Store/Actions/trackFileActions';
-import createClientSideCollectionSelector from 'Store/Selectors/createClientSideCollectionSelector';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
-import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
-import UnmappedFilesTable from './UnmappedFilesTable';
-
-function createMapStateToProps() {
- return createSelector(
- createClientSideCollectionSelector('trackFiles'),
- createCommandExecutingSelector(commandNames.RESCAN_FOLDERS),
- createDimensionsSelector(),
- (
- trackFiles,
- isScanningFolders,
- dimensionsState
- ) => {
- // trackFiles could pick up mapped entries via signalR so filter again here
- const {
- items,
- ...otherProps
- } = trackFiles;
-
- const unmappedFiles = _.filter(items, { albumId: 0 });
-
- return {
- items: unmappedFiles,
- ...otherProps,
- isScanningFolders,
- isSmallScreen: dimensionsState.isSmallScreen
- };
- }
- );
-}
-
-function createMapDispatchToProps(dispatch, props) {
- return {
- onTableOptionChange(payload) {
- dispatch(setTrackFilesTableOption(payload));
- },
-
- onSortPress(sortKey) {
- dispatch(setTrackFilesSort({ sortKey }));
- },
-
- fetchUnmappedFiles() {
- dispatch(fetchTrackFiles({ unmapped: true }));
- },
-
- deleteUnmappedFile(id) {
- dispatch(deleteTrackFile({ id }));
- },
-
- deleteUnmappedFiles(trackFileIds) {
- dispatch(deleteTrackFiles({ trackFileIds }));
- },
-
- onAddMissingArtistsPress() {
- dispatch(executeCommand({
- name: commandNames.RESCAN_FOLDERS,
- filter: 'matched'
- }));
- }
- };
-}
-
-class UnmappedFilesTableConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- registerPagePopulator(this.repopulate, ['trackFileUpdated']);
-
- this.repopulate();
- }
-
- componentWillUnmount() {
- unregisterPagePopulator(this.repopulate);
- }
-
- //
- // Control
-
- repopulate = () => {
- this.props.fetchUnmappedFiles();
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-UnmappedFilesTableConnector.propTypes = {
- isSmallScreen: PropTypes.bool.isRequired,
- onSortPress: PropTypes.func.isRequired,
- onTableOptionChange: PropTypes.func.isRequired,
- fetchUnmappedFiles: PropTypes.func.isRequired,
- deleteUnmappedFile: PropTypes.func.isRequired,
- deleteUnmappedFiles: PropTypes.func.isRequired
-};
-
-export default withCurrentPage(
- connect(createMapStateToProps, createMapDispatchToProps)(UnmappedFilesTableConnector)
-);
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css b/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css
deleted file mode 100644
index 184c69af1..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css
+++ /dev/null
@@ -1,19 +0,0 @@
-.quality,
-.size,
-.dateAdded {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- flex: 0 0 120px;
-}
-
-.path {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- flex: 4 0 400px;
-}
-
-.actions {
- composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
-
- flex: 0 1 95px;
-}
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css.d.ts b/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css.d.ts
deleted file mode 100644
index 551eacade..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.css.d.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'dateAdded': string;
- 'path': string;
- 'quality': string;
- 'size': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.js b/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.js
deleted file mode 100644
index 3b0715654..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableHeader.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import IconButton from 'Components/Link/IconButton';
-import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
-import VirtualTableHeader from 'Components/Table/VirtualTableHeader';
-import VirtualTableHeaderCell from 'Components/Table/VirtualTableHeaderCell';
-import VirtualTableSelectAllHeaderCell from 'Components/Table/VirtualTableSelectAllHeaderCell';
-import { icons } from 'Helpers/Props';
-// import hasGrowableColumns from './hasGrowableColumns';
-import styles from './UnmappedFilesTableHeader.css';
-
-function UnmappedFilesTableHeader(props) {
- const {
- columns,
- onTableOptionChange,
- allSelected,
- allUnselected,
- onSelectAllChange,
- ...otherProps
- } = props;
-
- return (
-
- {
- columns.map((column) => {
- const {
- name,
- label,
- isSortable,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- if (name === 'select') {
- return (
-
- );
- }
-
- if (name === 'actions') {
- return (
-
-
-
-
-
-
- );
- }
-
- return (
-
- {typeof label === 'function' ? label() : label}
-
- );
- })
- }
-
- );
-}
-
-UnmappedFilesTableHeader.propTypes = {
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- allSelected: PropTypes.bool.isRequired,
- allUnselected: PropTypes.bool.isRequired,
- onSelectAllChange: PropTypes.func.isRequired,
- onTableOptionChange: PropTypes.func.isRequired
-};
-
-export default UnmappedFilesTableHeader;
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css b/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css
deleted file mode 100644
index e89cfbc31..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css
+++ /dev/null
@@ -1,28 +0,0 @@
-.path {
- composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
-
- flex: 4 0 400px;
- font-size: 13px;
- font-family: $monoSpaceFontFamily;
-}
-
-.quality,
-.dateAdded,
-.size {
- composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
-
- flex: 0 0 120px;
- white-space: nowrap;
-}
-
-.actions {
- composes: cell from '~Components/Table/Cells/VirtualTableRowCell.css';
-
- flex: 0 0 95px;
-}
-
-.checkInput {
- composes: input from '~Components/Form/CheckInput.css';
-
- margin-top: 0;
-}
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css.d.ts b/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css.d.ts
deleted file mode 100644
index b455e5f7a..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.css.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'actions': string;
- 'checkInput': string;
- 'dateAdded': string;
- 'path': string;
- 'quality': string;
- 'size': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.js b/frontend/src/UnmappedFiles/UnmappedFilesTableRow.js
deleted file mode 100644
index 7b84a04a5..000000000
--- a/frontend/src/UnmappedFiles/UnmappedFilesTableRow.js
+++ /dev/null
@@ -1,232 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import TrackQuality from 'Album/TrackQuality';
-import IconButton from 'Components/Link/IconButton';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import VirtualTableRowCell from 'Components/Table/Cells/VirtualTableRowCell';
-import VirtualTableSelectCell from 'Components/Table/Cells/VirtualTableSelectCell';
-import { icons, kinds } from 'Helpers/Props';
-import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
-import FileDetailsModal from 'TrackFile/FileDetailsModal';
-import formatBytes from 'Utilities/Number/formatBytes';
-import translate from 'Utilities/String/translate';
-import styles from './UnmappedFilesTableRow.css';
-
-class UnmappedFilesTableRow extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- isDetailsModalOpen: false,
- isInteractiveImportModalOpen: false,
- isConfirmDeleteModalOpen: false
- };
- }
-
- //
- // Listeners
-
- onDetailsPress = () => {
- this.setState({ isDetailsModalOpen: true });
- };
-
- onDetailsModalClose = () => {
- this.setState({ isDetailsModalOpen: false });
- };
-
- onInteractiveImportPress = () => {
- this.setState({ isInteractiveImportModalOpen: true });
- };
-
- onInteractiveImportModalClose = () => {
- this.setState({ isInteractiveImportModalOpen: false });
- };
-
- onDeleteFilePress = () => {
- this.setState({ isConfirmDeleteModalOpen: true });
- };
-
- onConfirmDelete = () => {
- this.setState({ isConfirmDeleteModalOpen: false });
- this.props.deleteUnmappedFile(this.props.id);
- };
-
- onConfirmDeleteModalClose = () => {
- this.setState({ isConfirmDeleteModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- id,
- path,
- size,
- dateAdded,
- quality,
- columns,
- isSelected,
- onSelectedChange
- } = this.props;
-
- const folder = path.substring(0, Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')));
-
- const {
- isInteractiveImportModalOpen,
- isDetailsModalOpen,
- isConfirmDeleteModalOpen
- } = this.state;
-
- return (
- <>
- {
- columns.map((column) => {
- const {
- name,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- if (name === 'select') {
- return (
-
- );
- }
-
- if (name === 'path') {
- return (
-
- {path}
-
- );
- }
-
- if (name === 'size') {
- return (
-
- {formatBytes(size)}
-
- );
- }
-
- if (name === 'dateAdded') {
- return (
-
- );
- }
-
- if (name === 'quality') {
- return (
-
-
-
- );
- }
-
- if (name === 'actions') {
- return (
-
-
-
-
-
-
-
-
- );
- }
-
- return null;
- })
- }
-
-
-
-
-
-
-
- >
- );
- }
-
-}
-
-UnmappedFilesTableRow.propTypes = {
- id: PropTypes.number.isRequired,
- path: PropTypes.string.isRequired,
- size: PropTypes.number.isRequired,
- quality: PropTypes.object.isRequired,
- dateAdded: PropTypes.string.isRequired,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- isSelected: PropTypes.bool,
- onSelectedChange: PropTypes.func.isRequired,
- deleteUnmappedFile: PropTypes.func.isRequired
-};
-
-export default UnmappedFilesTableRow;
diff --git a/frontend/src/Utilities/Album/getNewAlbum.js b/frontend/src/Utilities/Album/getNewAlbum.js
deleted file mode 100644
index 608358dde..000000000
--- a/frontend/src/Utilities/Album/getNewAlbum.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import getNewArtist from 'Utilities/Artist/getNewArtist';
-
-function getNewAlbum(album, payload) {
- const {
- searchForNewAlbum = false
- } = payload;
-
- if (!('id' in album.artist) || album.artist.id === 0) {
- getNewArtist(album.artist, payload);
- }
-
- album.addOptions = {
- searchForNewAlbum
- };
- album.monitored = true;
-
- return album;
-}
-
-export default getNewAlbum;
diff --git a/frontend/src/Utilities/Album/updateAlbums.js b/frontend/src/Utilities/Album/updateAlbums.js
deleted file mode 100644
index 259ef510e..000000000
--- a/frontend/src/Utilities/Album/updateAlbums.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import _ from 'lodash';
-import { update } from 'Store/Actions/baseActions';
-
-function updateAlbums(section, albums, albumIds, options) {
- const data = _.reduce(albums, (result, item) => {
- if (albumIds.indexOf(item.id) > -1) {
- result.push({
- ...item,
- ...options
- });
- } else {
- result.push(item);
- }
-
- return result;
- }, []);
-
- return update({ section, data });
-}
-
-export default updateAlbums;
diff --git a/frontend/src/Utilities/Array/getIndexOfFirstCharacter.js b/frontend/src/Utilities/Array/getIndexOfFirstCharacter.js
deleted file mode 100644
index cec7fb09a..000000000
--- a/frontend/src/Utilities/Array/getIndexOfFirstCharacter.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default function getIndexOfFirstCharacter(items, character) {
- return items.findIndex((item) => {
- const firstCharacter = item.sortName.charAt(0);
-
- if (character === '#') {
- return !isNaN(firstCharacter);
- }
-
- return firstCharacter === character;
- });
-}
diff --git a/frontend/src/Utilities/Array/sortByProp.ts b/frontend/src/Utilities/Array/sortByProp.ts
deleted file mode 100644
index 8fbde08c9..000000000
--- a/frontend/src/Utilities/Array/sortByProp.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { StringKey } from 'typings/Helpers/KeysMatching';
-
-export function sortByProp<
- // eslint-disable-next-line no-use-before-define
- T extends Record,
- K extends StringKey
->(sortKey: K) {
- return (a: T, b: T) => {
- return a[sortKey].localeCompare(b[sortKey], undefined, { numeric: true });
- };
-}
-
-export default sortByProp;
diff --git a/frontend/src/Utilities/Artist/getNewArtist.js b/frontend/src/Utilities/Artist/getNewArtist.js
deleted file mode 100644
index ed1a6fb11..000000000
--- a/frontend/src/Utilities/Artist/getNewArtist.js
+++ /dev/null
@@ -1,31 +0,0 @@
-
-function getNewArtist(artist, payload) {
- const {
- rootFolderPath,
- monitor,
- monitorNewItems,
- qualityProfileId,
- metadataProfileId,
- artistType,
- tags,
- searchForMissingAlbums = false
- } = payload;
-
- const addOptions = {
- monitor,
- searchForMissingAlbums
- };
-
- artist.addOptions = addOptions;
- artist.monitored = true;
- artist.monitorNewItems = monitorNewItems;
- artist.qualityProfileId = qualityProfileId;
- artist.metadataProfileId = metadataProfileId;
- artist.rootFolderPath = rootFolderPath;
- artist.artistType = artistType;
- artist.tags = tags;
-
- return artist;
-}
-
-export default getNewArtist;
diff --git a/frontend/src/Utilities/Artist/getProgressBarKind.ts b/frontend/src/Utilities/Artist/getProgressBarKind.ts
deleted file mode 100644
index f45387024..000000000
--- a/frontend/src/Utilities/Artist/getProgressBarKind.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { kinds } from 'Helpers/Props';
-
-function getProgressBarKind(
- status: string,
- monitored: boolean,
- progress: number,
- isDownloading: boolean
-) {
- if (isDownloading) {
- return kinds.PURPLE;
- }
-
- if (progress === 100) {
- return status === 'ended' ? kinds.SUCCESS : kinds.PRIMARY;
- }
-
- if (monitored) {
- return kinds.DANGER;
- }
-
- return kinds.WARNING;
-}
-
-export default getProgressBarKind;
diff --git a/frontend/src/Utilities/Artist/monitorNewItemsOptions.js b/frontend/src/Utilities/Artist/monitorNewItemsOptions.js
deleted file mode 100644
index f45095b6e..000000000
--- a/frontend/src/Utilities/Artist/monitorNewItemsOptions.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import translate from 'Utilities/String/translate';
-
-const monitorNewItemsOptions = [
- {
- key: 'all',
- get value() {
- return translate('MonitorAllAlbums');
- }
- },
- {
- key: 'none',
- get value() {
- return translate('MonitorNoNewAlbums');
- }
- },
- {
- key: 'new',
- get value() {
- return translate('MonitorNewAlbums');
- }
- }
-];
-
-export default monitorNewItemsOptions;
diff --git a/frontend/src/Utilities/Artist/monitorOptions.js b/frontend/src/Utilities/Artist/monitorOptions.js
deleted file mode 100644
index a06a79a96..000000000
--- a/frontend/src/Utilities/Artist/monitorOptions.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import translate from 'Utilities/String/translate';
-
-const monitorOptions = [
- {
- key: 'all',
- get value() {
- return translate('MonitorAllAlbums');
- }
- },
- {
- key: 'future',
- get value() {
- return translate('MonitorFutureAlbums');
- }
- },
- {
- key: 'missing',
- get value() {
- return translate('MonitorMissingAlbums');
- }
- },
- {
- key: 'existing',
- get value() {
- return translate('MonitorExistingAlbums');
- }
- },
- {
- key: 'first',
- get value() {
- return translate('MonitorFirstAlbum');
- }
- },
- {
- key: 'latest',
- get value() {
- return translate('MonitorLastestAlbum');
- }
- },
- {
- key: 'none',
- get value() {
- return translate('MonitorNoAlbums');
- }
- }
-];
-
-export default monitorOptions;
diff --git a/frontend/src/Utilities/Command/findCommand.js b/frontend/src/Utilities/Command/findCommand.js
deleted file mode 100644
index cf7d5444a..000000000
--- a/frontend/src/Utilities/Command/findCommand.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import _ from 'lodash';
-import isSameCommand from './isSameCommand';
-
-function findCommand(commands, options) {
- return _.findLast(commands, (command) => {
- return isSameCommand(command.body, options);
- });
-}
-
-export default findCommand;
diff --git a/frontend/src/Utilities/Command/index.js b/frontend/src/Utilities/Command/index.js
deleted file mode 100644
index 66043bf03..000000000
--- a/frontend/src/Utilities/Command/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export { default as findCommand } from './findCommand';
-export { default as isCommandComplete } from './isCommandComplete';
-export { default as isCommandExecuting } from './isCommandExecuting';
-export { default as isCommandFailed } from './isCommandFailed';
-export { default as isSameCommand } from './isSameCommand';
diff --git a/frontend/src/Utilities/Command/isCommandComplete.js b/frontend/src/Utilities/Command/isCommandComplete.js
deleted file mode 100644
index 558ab801b..000000000
--- a/frontend/src/Utilities/Command/isCommandComplete.js
+++ /dev/null
@@ -1,9 +0,0 @@
-function isCommandComplete(command) {
- if (!command) {
- return false;
- }
-
- return command.status === 'complete';
-}
-
-export default isCommandComplete;
diff --git a/frontend/src/Utilities/Command/isCommandExecuting.js b/frontend/src/Utilities/Command/isCommandExecuting.js
deleted file mode 100644
index 8e637704e..000000000
--- a/frontend/src/Utilities/Command/isCommandExecuting.js
+++ /dev/null
@@ -1,9 +0,0 @@
-function isCommandExecuting(command) {
- if (!command) {
- return false;
- }
-
- return command.status === 'queued' || command.status === 'started';
-}
-
-export default isCommandExecuting;
diff --git a/frontend/src/Utilities/Command/isCommandFailed.js b/frontend/src/Utilities/Command/isCommandFailed.js
deleted file mode 100644
index 00e5ccdf2..000000000
--- a/frontend/src/Utilities/Command/isCommandFailed.js
+++ /dev/null
@@ -1,12 +0,0 @@
-function isCommandFailed(command) {
- if (!command) {
- return false;
- }
-
- return command.status === 'failed' ||
- command.status === 'aborted' ||
- command.status === 'cancelled' ||
- command.status === 'orphaned';
-}
-
-export default isCommandFailed;
diff --git a/frontend/src/Utilities/Command/isSameCommand.js b/frontend/src/Utilities/Command/isSameCommand.js
deleted file mode 100644
index d0acb24b5..000000000
--- a/frontend/src/Utilities/Command/isSameCommand.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import _ from 'lodash';
-
-function isSameCommand(commandA, commandB) {
- if (commandA.name.toLocaleLowerCase() !== commandB.name.toLocaleLowerCase()) {
- return false;
- }
-
- for (const key in commandB) {
- if (key !== 'name') {
- const value = commandB[key];
- if (Array.isArray(value)) {
- if (_.difference(value, commandA[key]).length > 0) {
- return false;
- }
- } else if (value !== commandA[key]) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-export default isSameCommand;
diff --git a/frontend/src/Utilities/Constants/keyCodes.js b/frontend/src/Utilities/Constants/keyCodes.js
deleted file mode 100644
index 9285b10fe..000000000
--- a/frontend/src/Utilities/Constants/keyCodes.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export const TAB = 9;
-export const ENTER = 13;
-export const SHIFT = 16;
-export const CONTROL = 17;
-export const ESCAPE = 27;
-export const UP_ARROW = 38;
-export const DOWN_ARROW = 40;
diff --git a/frontend/src/Utilities/Date/dateFilterPredicate.js b/frontend/src/Utilities/Date/dateFilterPredicate.js
deleted file mode 100644
index 59407e3ba..000000000
--- a/frontend/src/Utilities/Date/dateFilterPredicate.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import moment from 'moment';
-import * as filterTypes from 'Helpers/Props/filterTypes';
-import isAfter from 'Utilities/Date/isAfter';
-import isBefore from 'Utilities/Date/isBefore';
-
-export default function(itemValue, filterValue, type) {
- if (!itemValue) {
- return false;
- }
-
- switch (type) {
- case filterTypes.LESS_THAN:
- return moment(itemValue).isBefore(filterValue);
-
- case filterTypes.GREATER_THAN:
- return moment(itemValue).isAfter(filterValue);
-
- case filterTypes.IN_LAST:
- return (
- isAfter(itemValue, { [filterValue.time]: filterValue.value * -1 }) &&
- isBefore(itemValue)
- );
-
- case filterTypes.NOT_IN_LAST:
- return (
- isBefore(itemValue, { [filterValue.time]: filterValue.value * -1 })
- );
-
- case filterTypes.IN_NEXT:
- return (
- isAfter(itemValue) &&
- isBefore(itemValue, { [filterValue.time]: filterValue.value })
- );
-
- case filterTypes.NOT_IN_NEXT:
- return (
- isAfter(itemValue, { [filterValue.time]: filterValue.value })
- );
-
- default:
- return false;
- }
-}
diff --git a/frontend/src/Utilities/Date/formatDate.js b/frontend/src/Utilities/Date/formatDate.js
deleted file mode 100644
index 92eb57840..000000000
--- a/frontend/src/Utilities/Date/formatDate.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function formatDate(date, dateFormat) {
- if (!date) {
- return '';
- }
-
- return moment(date).format(dateFormat);
-}
-
-export default formatDate;
diff --git a/frontend/src/Utilities/Date/formatDateTime.js b/frontend/src/Utilities/Date/formatDateTime.js
deleted file mode 100644
index fb50230e1..000000000
--- a/frontend/src/Utilities/Date/formatDateTime.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import moment from 'moment';
-import translate from 'Utilities/String/translate';
-import formatTime from './formatTime';
-import isToday from './isToday';
-import isTomorrow from './isTomorrow';
-import isYesterday from './isYesterday';
-
-function getRelativeDay(date, includeRelativeDate) {
- if (!includeRelativeDate) {
- return '';
- }
-
- if (isYesterday(date)) {
- return translate('Yesterday');
- }
-
- if (isToday(date)) {
- return translate('Today');
- }
-
- if (isTomorrow(date)) {
- return translate('Tomorrow');
- }
-
- return '';
-}
-
-function formatDateTime(date, dateFormat, timeFormat, { includeSeconds = false, includeRelativeDay = false } = {}) {
- if (!date) {
- return '';
- }
-
- const relativeDay = getRelativeDay(date, includeRelativeDay);
- const formattedDate = moment(date).format(dateFormat);
- const formattedTime = formatTime(date, timeFormat, { includeMinuteZero: true, includeSeconds });
-
- if (relativeDay) {
- return translate('FormatDateTimeRelative', { relativeDay, formattedDate, formattedTime });
- }
- return translate('FormatDateTime', { formattedDate, formattedTime });
-}
-
-export default formatDateTime;
diff --git a/frontend/src/Utilities/Date/formatShortTimeSpan.js b/frontend/src/Utilities/Date/formatShortTimeSpan.js
deleted file mode 100644
index 148dc2627..000000000
--- a/frontend/src/Utilities/Date/formatShortTimeSpan.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import moment from 'moment';
-import translate from 'Utilities/String/translate';
-
-function formatShortTimeSpan(timeSpan) {
- if (!timeSpan) {
- return '';
- }
-
- const duration = moment.duration(timeSpan);
-
- const hours = Math.floor(duration.asHours());
- const minutes = Math.floor(duration.asMinutes());
- const seconds = Math.floor(duration.asSeconds());
-
- if (hours > 0) {
- return translate('FormatShortTimeSpanHours', { hours });
- }
-
- if (minutes > 0) {
- return translate('FormatShortTimeSpanMinutes', { minutes });
- }
-
- return translate('FormatShortTimeSpanSeconds', { seconds });
-}
-
-export default formatShortTimeSpan;
diff --git a/frontend/src/Utilities/Date/formatTime.js b/frontend/src/Utilities/Date/formatTime.js
deleted file mode 100644
index 226b0cd97..000000000
--- a/frontend/src/Utilities/Date/formatTime.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import moment from 'moment';
-
-function formatTime(date, timeFormat, { includeMinuteZero = false, includeSeconds = false } = {}) {
- if (!date) {
- return '';
- }
-
- const time = moment(date);
-
- if (includeSeconds) {
- timeFormat = timeFormat.replace(/\(?:mm\)?/, ':mm:ss');
- } else if (includeMinuteZero || time.minute() !== 0) {
- timeFormat = timeFormat.replace('(:mm)', ':mm');
- } else {
- timeFormat = timeFormat.replace('(:mm)', '');
- }
-
- return time.format(timeFormat);
-}
-
-export default formatTime;
diff --git a/frontend/src/Utilities/Date/formatTimeSpan.js b/frontend/src/Utilities/Date/formatTimeSpan.js
deleted file mode 100644
index 2422e19d5..000000000
--- a/frontend/src/Utilities/Date/formatTimeSpan.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import moment from 'moment';
-import padNumber from 'Utilities/Number/padNumber';
-import translate from 'Utilities/String/translate';
-
-function formatTimeSpan(timeSpan) {
- if (!timeSpan) {
- return '';
- }
-
- const duration = moment.duration(timeSpan);
-
- const days = Math.floor(duration.asDays());
- const hours = padNumber(duration.get('hours'), 2);
- const minutes = padNumber(duration.get('minutes'), 2);
- const seconds = padNumber(duration.get('seconds'), 2);
-
- const time = `${hours}:${minutes}:${seconds}`;
-
- if (days > 0) {
- return translate('FormatTimeSpanDays', { days, time });
- }
-
- return time;
-}
-
-export default formatTimeSpan;
diff --git a/frontend/src/Utilities/Date/getRelativeDate.ts b/frontend/src/Utilities/Date/getRelativeDate.ts
deleted file mode 100644
index 178d14fb7..000000000
--- a/frontend/src/Utilities/Date/getRelativeDate.ts
+++ /dev/null
@@ -1,61 +0,0 @@
-import moment from 'moment';
-import formatTime from 'Utilities/Date/formatTime';
-import isInNextWeek from 'Utilities/Date/isInNextWeek';
-import isToday from 'Utilities/Date/isToday';
-import isTomorrow from 'Utilities/Date/isTomorrow';
-import isYesterday from 'Utilities/Date/isYesterday';
-import translate from 'Utilities/String/translate';
-
-interface GetRelativeDateOptions {
- timeFormat?: string;
- includeSeconds?: boolean;
- timeForToday?: boolean;
-}
-
-function getRelativeDate(
- date: string | undefined,
- shortDateFormat: string,
- showRelativeDates: boolean,
- {
- timeFormat,
- includeSeconds = false,
- timeForToday = false,
- }: GetRelativeDateOptions = {}
-) {
- if (!date) {
- return '';
- }
-
- const isTodayDate = isToday(date);
-
- if (isTodayDate && timeForToday && timeFormat) {
- return formatTime(date, timeFormat, {
- includeMinuteZero: true,
- includeSeconds,
- });
- }
-
- if (!showRelativeDates) {
- return moment(date).format(shortDateFormat);
- }
-
- if (isYesterday(date)) {
- return translate('Yesterday');
- }
-
- if (isTodayDate) {
- return translate('Today');
- }
-
- if (isTomorrow(date)) {
- return translate('Tomorrow');
- }
-
- if (isInNextWeek(date)) {
- return moment(date).format('dddd');
- }
-
- return moment(date).format(shortDateFormat);
-}
-
-export default getRelativeDate;
diff --git a/frontend/src/Utilities/Date/isAfter.js b/frontend/src/Utilities/Date/isAfter.js
deleted file mode 100644
index 4bbd8660b..000000000
--- a/frontend/src/Utilities/Date/isAfter.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import moment from 'moment';
-
-function isAfter(date, offsets = {}) {
- if (!date) {
- return false;
- }
-
- const offsetTime = moment();
-
- Object.keys(offsets).forEach((key) => {
- offsetTime.add(offsets[key], key);
- });
-
- return moment(date).isAfter(offsetTime);
-}
-
-export default isAfter;
diff --git a/frontend/src/Utilities/Date/isBefore.js b/frontend/src/Utilities/Date/isBefore.js
deleted file mode 100644
index 3e1e81f67..000000000
--- a/frontend/src/Utilities/Date/isBefore.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import moment from 'moment';
-
-function isBefore(date, offsets = {}) {
- if (!date) {
- return false;
- }
-
- const offsetTime = moment();
-
- Object.keys(offsets).forEach((key) => {
- offsetTime.add(offsets[key], key);
- });
-
- return moment(date).isBefore(offsetTime);
-}
-
-export default isBefore;
diff --git a/frontend/src/Utilities/Date/isInNextWeek.js b/frontend/src/Utilities/Date/isInNextWeek.js
deleted file mode 100644
index 7b5fd7cc7..000000000
--- a/frontend/src/Utilities/Date/isInNextWeek.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function isInNextWeek(date) {
- if (!date) {
- return false;
- }
- const now = moment();
- return moment(date).isBetween(now, now.clone().add(6, 'days').endOf('day'));
-}
-
-export default isInNextWeek;
diff --git a/frontend/src/Utilities/Date/isSameWeek.js b/frontend/src/Utilities/Date/isSameWeek.js
deleted file mode 100644
index 14b76ffb7..000000000
--- a/frontend/src/Utilities/Date/isSameWeek.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function isSameWeek(date) {
- if (!date) {
- return false;
- }
-
- return moment(date).isSame(moment(), 'week');
-}
-
-export default isSameWeek;
diff --git a/frontend/src/Utilities/Date/isToday.js b/frontend/src/Utilities/Date/isToday.js
deleted file mode 100644
index 31502951f..000000000
--- a/frontend/src/Utilities/Date/isToday.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function isToday(date) {
- if (!date) {
- return false;
- }
-
- return moment(date).isSame(moment(), 'day');
-}
-
-export default isToday;
diff --git a/frontend/src/Utilities/Date/isTomorrow.js b/frontend/src/Utilities/Date/isTomorrow.js
deleted file mode 100644
index d22386dbd..000000000
--- a/frontend/src/Utilities/Date/isTomorrow.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function isTomorrow(date) {
- if (!date) {
- return false;
- }
-
- return moment(date).isSame(moment().add(1, 'day'), 'day');
-}
-
-export default isTomorrow;
diff --git a/frontend/src/Utilities/Date/isYesterday.js b/frontend/src/Utilities/Date/isYesterday.js
deleted file mode 100644
index 9de21d82a..000000000
--- a/frontend/src/Utilities/Date/isYesterday.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import moment from 'moment';
-
-function isYesterday(date) {
- if (!date) {
- return false;
- }
-
- return moment(date).isSame(moment().subtract(1, 'day'), 'day');
-}
-
-export default isYesterday;
diff --git a/frontend/src/Utilities/Filter/findSelectedFilters.js b/frontend/src/Utilities/Filter/findSelectedFilters.js
deleted file mode 100644
index 1c104073c..000000000
--- a/frontend/src/Utilities/Filter/findSelectedFilters.js
+++ /dev/null
@@ -1,19 +0,0 @@
-export default function findSelectedFilters(selectedFilterKey, filters = [], customFilters = []) {
- if (!selectedFilterKey) {
- return [];
- }
-
- let selectedFilter = filters.find((f) => f.key === selectedFilterKey);
-
- if (!selectedFilter) {
- selectedFilter = customFilters.find((f) => f.id === selectedFilterKey);
- }
-
- if (!selectedFilter) {
- // TODO: throw in dev
- console.error('Matching filter not found');
- return [];
- }
-
- return selectedFilter.filters;
-}
diff --git a/frontend/src/Utilities/Filter/getFilterValue.js b/frontend/src/Utilities/Filter/getFilterValue.js
deleted file mode 100644
index 70b0b51f1..000000000
--- a/frontend/src/Utilities/Filter/getFilterValue.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default function getFilterValue(filters, filterKey, filterValueKey, defaultValue) {
- const filter = filters.find((f) => f.key === filterKey);
-
- if (!filter) {
- return defaultValue;
- }
-
- const filterValue = filter.filters.find((f) => f.key === filterValueKey);
-
- return filterValue ? filterValue.value : defaultValue;
-}
diff --git a/frontend/src/Utilities/Number/convertToBytes.js b/frontend/src/Utilities/Number/convertToBytes.js
deleted file mode 100644
index 88357944f..000000000
--- a/frontend/src/Utilities/Number/convertToBytes.js
+++ /dev/null
@@ -1,15 +0,0 @@
-function convertToBytes(input, power, binaryPrefix) {
- const size = Number(input);
-
- if (isNaN(size)) {
- return '';
- }
-
- const prefix = binaryPrefix ? 1024 : 1000;
- const multiplier = Math.pow(prefix, power);
- const result = size * multiplier;
-
- return Math.round(result);
-}
-
-export default convertToBytes;
diff --git a/frontend/src/Utilities/Number/formatAge.js b/frontend/src/Utilities/Number/formatAge.js
deleted file mode 100644
index a8f0e9f65..000000000
--- a/frontend/src/Utilities/Number/formatAge.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import translate from 'Utilities/String/translate';
-
-function formatAge(age, ageHours, ageMinutes) {
- age = Math.round(age);
- ageHours = parseFloat(ageHours);
- ageMinutes = ageMinutes && parseFloat(ageMinutes);
-
- if (age < 2 && ageHours) {
- if (ageHours < 2 && !!ageMinutes) {
- return `${ageMinutes.toFixed(0)} ${ageHours === 1 ? translate('FormatAgeMinute') : translate('FormatAgeMinutes')}`;
- }
-
- return `${ageHours.toFixed(1)} ${ageHours === 1 ? translate('FormatAgeHour') : translate('FormatAgeHours')}`;
- }
-
- return `${age} ${age === 1 ? translate('FormatAgeDay') : translate('FormatAgeDays')}`;
-}
-
-export default formatAge;
diff --git a/frontend/src/Utilities/Number/formatBytes.js b/frontend/src/Utilities/Number/formatBytes.js
deleted file mode 100644
index 273452031..000000000
--- a/frontend/src/Utilities/Number/formatBytes.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { filesize } from 'filesize';
-
-function formatBytes(input, showBits = false) {
- const size = Number(input);
-
- if (isNaN(size)) {
- return '';
- }
-
- return `${filesize(size, {
- base: 2,
- round: 1,
- bits: showBits
- })}`;
-}
-
-export default formatBytes;
diff --git a/frontend/src/Utilities/Number/formatCustomFormatScore.ts b/frontend/src/Utilities/Number/formatCustomFormatScore.ts
deleted file mode 100644
index b4da3a2cd..000000000
--- a/frontend/src/Utilities/Number/formatCustomFormatScore.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-function formatCustomFormatScore(
- input?: number,
- customFormatsLength = 0
-): string {
- const score = Number(input);
-
- if (score > 0) {
- return `+${score}`;
- }
-
- if (score < 0) {
- return `${score}`;
- }
-
- return customFormatsLength > 0 ? '+0' : '';
-}
-
-export default formatCustomFormatScore;
diff --git a/frontend/src/Utilities/Number/padNumber.js b/frontend/src/Utilities/Number/padNumber.js
deleted file mode 100644
index 53ae69cac..000000000
--- a/frontend/src/Utilities/Number/padNumber.js
+++ /dev/null
@@ -1,10 +0,0 @@
-function padNumber(input, width, paddingCharacter = 0) {
- if (input == null) {
- return '';
- }
-
- input = `${input}`;
- return input.length >= width ? input : new Array(width - input.length + 1).join(paddingCharacter) + input;
-}
-
-export default padNumber;
diff --git a/frontend/src/Utilities/Number/roundNumber.js b/frontend/src/Utilities/Number/roundNumber.js
deleted file mode 100644
index e1a19018f..000000000
--- a/frontend/src/Utilities/Number/roundNumber.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default function roundNumber(input, decimalPlaces = 1) {
- const multiplier = Math.pow(10, decimalPlaces);
-
- return Math.round(input * multiplier) / multiplier;
-}
diff --git a/frontend/src/Utilities/Object/getErrorMessage.js b/frontend/src/Utilities/Object/getErrorMessage.js
deleted file mode 100644
index 1ba874660..000000000
--- a/frontend/src/Utilities/Object/getErrorMessage.js
+++ /dev/null
@@ -1,11 +0,0 @@
-function getErrorMessage(xhr, fallbackErrorMessage) {
- if (!xhr || !xhr.responseJSON || !xhr.responseJSON.message) {
- return fallbackErrorMessage;
- }
-
- const message = xhr.responseJSON.message;
-
- return message || fallbackErrorMessage;
-}
-
-export default getErrorMessage;
diff --git a/frontend/src/Utilities/Object/getRemovedItems.js b/frontend/src/Utilities/Object/getRemovedItems.js
deleted file mode 100644
index df7ada3a8..000000000
--- a/frontend/src/Utilities/Object/getRemovedItems.js
+++ /dev/null
@@ -1,15 +0,0 @@
-function getRemovedItems(prevItems, currentItems, idProp = 'id') {
- if (prevItems === currentItems) {
- return [];
- }
-
- const currentItemIds = new Set();
-
- currentItems.forEach((currentItem) => {
- currentItemIds.add(currentItem[idProp]);
- });
-
- return prevItems.filter((prevItem) => !currentItemIds.has(prevItem[idProp]));
-}
-
-export default getRemovedItems;
diff --git a/frontend/src/Utilities/Object/hasDifferentItems.js b/frontend/src/Utilities/Object/hasDifferentItems.js
deleted file mode 100644
index d3c0046e4..000000000
--- a/frontend/src/Utilities/Object/hasDifferentItems.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function hasDifferentItems(prevItems, currentItems, idProp = 'id') {
- if (prevItems === currentItems) {
- return false;
- }
-
- if (prevItems.length !== currentItems.length) {
- return true;
- }
-
- const currentItemIds = new Set();
-
- currentItems.forEach((currentItem) => {
- currentItemIds.add(currentItem[idProp]);
- });
-
- return prevItems.some((prevItem) => !currentItemIds.has(prevItem[idProp]));
-}
-
-export default hasDifferentItems;
diff --git a/frontend/src/Utilities/Object/hasDifferentItemsOrOrder.js b/frontend/src/Utilities/Object/hasDifferentItemsOrOrder.js
deleted file mode 100644
index e2acbc5c0..000000000
--- a/frontend/src/Utilities/Object/hasDifferentItemsOrOrder.js
+++ /dev/null
@@ -1,21 +0,0 @@
-function hasDifferentItemsOrOrder(prevItems, currentItems, idProp = 'id') {
- if (prevItems === currentItems) {
- return false;
- }
-
- const len = prevItems.length;
-
- if (len !== currentItems.length) {
- return true;
- }
-
- for (let i = 0; i < len; i++) {
- if (prevItems[i][idProp] !== currentItems[i][idProp]) {
- return true;
- }
- }
-
- return false;
-}
-
-export default hasDifferentItemsOrOrder;
diff --git a/frontend/src/Utilities/Object/selectUniqueIds.js b/frontend/src/Utilities/Object/selectUniqueIds.js
deleted file mode 100644
index c2c0c17e3..000000000
--- a/frontend/src/Utilities/Object/selectUniqueIds.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import _ from 'lodash';
-
-function selectUniqueIds(items, idProp) {
- const ids = _.reduce(items, (result, item) => {
- if (item[idProp]) {
- result.push(item[idProp]);
- }
-
- return result;
- }, []);
-
- return _.uniq(ids);
-}
-
-export default selectUniqueIds;
diff --git a/frontend/src/Utilities/Quality/getQualities.js b/frontend/src/Utilities/Quality/getQualities.js
deleted file mode 100644
index da09851ea..000000000
--- a/frontend/src/Utilities/Quality/getQualities.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export default function getQualities(qualities) {
- if (!qualities) {
- return [];
- }
-
- return qualities.reduce((acc, item) => {
- if (item.quality) {
- acc.push(item.quality);
- } else {
- const groupQualities = item.items.map((i) => i.quality);
- acc.push(...groupQualities);
- }
-
- return acc;
- }, []);
-}
diff --git a/frontend/src/Utilities/ResolutionUtility.js b/frontend/src/Utilities/ResolutionUtility.js
deleted file mode 100644
index 358448ca9..000000000
--- a/frontend/src/Utilities/ResolutionUtility.js
+++ /dev/null
@@ -1,26 +0,0 @@
-import $ from 'jquery';
-
-module.exports = {
- resolutions: {
- desktopLarge: 1200,
- desktop: 992,
- tablet: 768,
- mobile: 480
- },
-
- isDesktopLarge() {
- return $(window).width() < this.resolutions.desktopLarge;
- },
-
- isDesktop() {
- return $(window).width() < this.resolutions.desktop;
- },
-
- isTablet() {
- return $(window).width() < this.resolutions.tablet;
- },
-
- isMobile() {
- return $(window).width() < this.resolutions.mobile;
- }
-};
diff --git a/frontend/src/Utilities/State/getNextId.js b/frontend/src/Utilities/State/getNextId.js
deleted file mode 100644
index 204aac95a..000000000
--- a/frontend/src/Utilities/State/getNextId.js
+++ /dev/null
@@ -1,5 +0,0 @@
-function getNextId(items) {
- return items.reduce((id, x) => Math.max(id, x.id), 1) + 1;
-}
-
-export default getNextId;
diff --git a/frontend/src/Utilities/State/getProviderState.js b/frontend/src/Utilities/State/getProviderState.js
deleted file mode 100644
index 4159905b8..000000000
--- a/frontend/src/Utilities/State/getProviderState.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import _ from 'lodash';
-import getSectionState from 'Utilities/State/getSectionState';
-
-function getProviderState(payload, getState, section, keyValueOnly=true) {
- const {
- id,
- ...otherPayload
- } = payload;
-
- const state = getSectionState(getState(), section, true);
- const pendingChanges = Object.assign({}, state.pendingChanges, otherPayload);
- const pendingFields = state.pendingChanges.fields || {};
- delete pendingChanges.fields;
-
- const item = id ? _.find(state.items, { id }) : state.selectedSchema || state.schema || {};
-
- if (item.fields) {
- pendingChanges.fields = _.reduce(item.fields, (result, field) => {
- const name = field.name;
-
- const value = pendingFields.hasOwnProperty(name) ?
- pendingFields[name] :
- field.value;
-
- // Only send the name and value to the server
- if (keyValueOnly) {
- result.push({
- name,
- value
- });
- } else {
- result.push({
- ...field,
- value
- });
- }
-
- return result;
- }, []);
- }
-
- const result = Object.assign({}, item, pendingChanges);
-
- delete result.presets;
-
- return result;
-}
-
-export default getProviderState;
diff --git a/frontend/src/Utilities/State/getSectionState.js b/frontend/src/Utilities/State/getSectionState.js
deleted file mode 100644
index 00871bed2..000000000
--- a/frontend/src/Utilities/State/getSectionState.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import _ from 'lodash';
-
-function getSectionState(state, section, isFullStateTree = false) {
- if (isFullStateTree) {
- return _.get(state, section);
- }
-
- const [, subSection] = section.split('.');
-
- if (subSection) {
- return Object.assign({}, state[subSection]);
- }
-
- // TODO: Remove in favour of using subSection
- if (state.hasOwnProperty(section)) {
- return Object.assign({}, state[section]);
- }
-
- return Object.assign({}, state);
-}
-
-export default getSectionState;
diff --git a/frontend/src/Utilities/State/selectProviderSchema.js b/frontend/src/Utilities/State/selectProviderSchema.js
deleted file mode 100644
index c8a31760c..000000000
--- a/frontend/src/Utilities/State/selectProviderSchema.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import _ from 'lodash';
-import getSectionState from 'Utilities/State/getSectionState';
-import updateSectionState from 'Utilities/State/updateSectionState';
-
-function applySchemaDefaults(selectedSchema, schemaDefaults) {
- if (!schemaDefaults) {
- return selectedSchema;
- } else if (_.isFunction(schemaDefaults)) {
- return schemaDefaults(selectedSchema);
- }
-
- return Object.assign(selectedSchema, schemaDefaults);
-}
-
-function selectProviderSchema(state, section, payload, schemaDefaults) {
- const newState = getSectionState(state, section);
-
- const {
- implementation,
- presetName
- } = payload;
-
- const selectedImplementation = _.find(newState.schema, { implementation });
-
- const selectedSchema = presetName ?
- _.find(selectedImplementation.presets, { name: presetName }) :
- selectedImplementation;
-
- newState.selectedSchema = applySchemaDefaults(_.cloneDeep(selectedSchema), schemaDefaults);
-
- return updateSectionState(state, section, newState);
-}
-
-export default selectProviderSchema;
diff --git a/frontend/src/Utilities/State/updateSectionState.js b/frontend/src/Utilities/State/updateSectionState.js
deleted file mode 100644
index 81b33ecaf..000000000
--- a/frontend/src/Utilities/State/updateSectionState.js
+++ /dev/null
@@ -1,16 +0,0 @@
-function updateSectionState(state, section, newState) {
- const [, subSection] = section.split('.');
-
- if (subSection) {
- return Object.assign({}, state, { [subSection]: newState });
- }
-
- // TODO: Remove in favour of using subSection
- if (state.hasOwnProperty(section)) {
- return Object.assign({}, state, { [section]: newState });
- }
-
- return Object.assign({}, state, newState);
-}
-
-export default updateSectionState;
diff --git a/frontend/src/Utilities/String/combinePath.js b/frontend/src/Utilities/String/combinePath.js
deleted file mode 100644
index 9e4e9abe8..000000000
--- a/frontend/src/Utilities/String/combinePath.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default function combinePath(isWindows, basePath, paths = []) {
- const slash = isWindows ? '\\' : '/';
-
- return `${basePath}${slash}${paths.join(slash)}`;
-}
diff --git a/frontend/src/Utilities/String/firstCharToUpper.js b/frontend/src/Utilities/String/firstCharToUpper.js
deleted file mode 100644
index 1ce64831c..000000000
--- a/frontend/src/Utilities/String/firstCharToUpper.js
+++ /dev/null
@@ -1,9 +0,0 @@
-function firstCharToUpper(input) {
- if (!input) {
- return '';
- }
-
- return [].map.call(input, (char, i) => (i ? char : char.toUpperCase())).join('');
-}
-
-export default firstCharToUpper;
diff --git a/frontend/src/Utilities/String/generateUUIDv4.js b/frontend/src/Utilities/String/generateUUIDv4.js
deleted file mode 100644
index 51b15ec60..000000000
--- a/frontend/src/Utilities/String/generateUUIDv4.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export default function generateUUIDv4() {
- return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, (c) =>
- // eslint-disable-next-line no-bitwise
- (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
- );
-}
diff --git a/frontend/src/Utilities/String/isString.js b/frontend/src/Utilities/String/isString.js
deleted file mode 100644
index 1e7c3dff8..000000000
--- a/frontend/src/Utilities/String/isString.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function isString(possibleString) {
- return typeof possibleString === 'string' || possibleString instanceof String;
-}
diff --git a/frontend/src/Utilities/String/naturalExpansion.js b/frontend/src/Utilities/String/naturalExpansion.js
deleted file mode 100644
index 2cdd69b86..000000000
--- a/frontend/src/Utilities/String/naturalExpansion.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const regex = /\d+/g;
-
-function naturalExpansion(input) {
- if (!input) {
- return '';
- }
-
- return input.replace(regex, (n) => n.padStart(8, '0'));
-}
-
-export default naturalExpansion;
diff --git a/frontend/src/Utilities/String/parseUrl.js b/frontend/src/Utilities/String/parseUrl.js
deleted file mode 100644
index 93341f85f..000000000
--- a/frontend/src/Utilities/String/parseUrl.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import _ from 'lodash';
-import qs from 'qs';
-
-// See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils
-const anchor = document.createElement('a');
-
-export default function parseUrl(url) {
- anchor.href = url;
-
- // The `origin`, `password`, and `username` properties are unavailable in
- // Opera Presto. We synthesize `origin` if it's not present. While `password`
- // and `username` are ignored intentionally.
- const properties = _.pick(
- anchor,
- 'hash',
- 'host',
- 'hostname',
- 'href',
- 'origin',
- 'pathname',
- 'port',
- 'protocol',
- 'search'
- );
-
- properties.isAbsolute = (/^[\w:]*\/\//).test(url);
-
- if (properties.search) {
- // Remove leading ? from querystring before parsing.
- properties.params = qs.parse(properties.search.substring(1));
- } else {
- properties.params = {};
- }
-
- return properties;
-}
diff --git a/frontend/src/Utilities/String/shortenList.js b/frontend/src/Utilities/String/shortenList.js
deleted file mode 100644
index 66085db4d..000000000
--- a/frontend/src/Utilities/String/shortenList.js
+++ /dev/null
@@ -1,7 +0,0 @@
-export default function shortenList(input, startCount = 3, endCount = 1, separator = ', ') {
- const sorted = [...input].sort();
- if (sorted.length <= startCount + endCount) {
- return sorted.join(separator);
- }
- return [...sorted.slice(0, startCount), '...', sorted.slice(-endCount)].join(separator);
-}
diff --git a/frontend/src/Utilities/String/split.js b/frontend/src/Utilities/String/split.js
deleted file mode 100644
index 0e57e7545..000000000
--- a/frontend/src/Utilities/String/split.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import _ from 'lodash';
-
-function split(input, separator = ',') {
- if (!input) {
- return [];
- }
-
- return _.reduce(input.split(separator), (result, s) => {
- if (s) {
- result.push(s);
- }
-
- return result;
- }, []);
-}
-
-export default split;
diff --git a/frontend/src/Utilities/String/titleCase.js b/frontend/src/Utilities/String/titleCase.js
deleted file mode 100644
index 03573b9e3..000000000
--- a/frontend/src/Utilities/String/titleCase.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const regex = /\b\w+/g;
-
-function titleCase(input) {
- if (!input) {
- return '';
- }
-
- return input.replace(regex, (match) => {
- return match.charAt(0).toUpperCase() + match.substr(1).toLowerCase();
- });
-}
-
-export default titleCase;
diff --git a/frontend/src/Utilities/String/translate.ts b/frontend/src/Utilities/String/translate.ts
deleted file mode 100644
index 5571ef6b0..000000000
--- a/frontend/src/Utilities/String/translate.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import createAjaxRequest from 'Utilities/createAjaxRequest';
-
-function getTranslations() {
- return createAjaxRequest({
- global: false,
- dataType: 'json',
- url: '/localization',
- }).request;
-}
-
-let translations: Record = {};
-
-export async function fetchTranslations(): Promise {
- return new Promise(async (resolve) => {
- try {
- const data = await getTranslations();
- translations = data.strings;
-
- resolve(true);
- } catch {
- resolve(false);
- }
- });
-}
-
-export default function translate(
- key: string,
- tokens: Record = {}
-) {
- const { isProduction = true } = window.Lidarr;
-
- if (!isProduction && !(key in translations)) {
- console.warn(`Missing translation for key: ${key}`);
- }
-
- const translation = translations[key] || key;
-
- tokens.appName = 'Lidarr';
-
- // Fallback to the old behaviour for translations not yet updated to use named tokens
- Object.values(tokens).forEach((value, index) => {
- tokens[index] = value;
- });
-
- return translation.replace(/\{([a-z0-9]+?)\}/gi, (match, tokenMatch) =>
- String(tokens[tokenMatch] ?? match)
- );
-}
diff --git a/frontend/src/Utilities/Table/areAllSelected.js b/frontend/src/Utilities/Table/areAllSelected.js
deleted file mode 100644
index 26102f89b..000000000
--- a/frontend/src/Utilities/Table/areAllSelected.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export default function areAllSelected(selectedState) {
- let allSelected = true;
- let allUnselected = true;
-
- Object.keys(selectedState).forEach((key) => {
- if (selectedState[key]) {
- allUnselected = false;
- } else {
- allSelected = false;
- }
- });
-
- return {
- allSelected,
- allUnselected
- };
-}
diff --git a/frontend/src/Utilities/Table/getSelectedIds.ts b/frontend/src/Utilities/Table/getSelectedIds.ts
deleted file mode 100644
index b84db6245..000000000
--- a/frontend/src/Utilities/Table/getSelectedIds.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { reduce } from 'lodash';
-import { SelectedState } from 'Helpers/Hooks/useSelectState';
-
-function getSelectedIds(selectedState: SelectedState): number[] {
- return reduce(
- selectedState,
- (result: number[], value, id) => {
- if (value) {
- result.push(parseInt(id));
- }
-
- return result;
- },
- []
- );
-}
-
-export default getSelectedIds;
diff --git a/frontend/src/Utilities/Table/getToggledRange.js b/frontend/src/Utilities/Table/getToggledRange.js
deleted file mode 100644
index c0cc44fe5..000000000
--- a/frontend/src/Utilities/Table/getToggledRange.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import _ from 'lodash';
-
-function getToggledRange(items, id, lastToggled) {
- const lastToggledIndex = _.findIndex(items, { id: lastToggled });
- const changedIndex = _.findIndex(items, { id });
- let lower = 0;
- let upper = 0;
-
- if (lastToggledIndex > changedIndex) {
- lower = changedIndex;
- upper = lastToggledIndex + 1;
- } else {
- lower = lastToggledIndex;
- upper = changedIndex;
- }
-
- return {
- lower,
- upper
- };
-}
-
-export default getToggledRange;
diff --git a/frontend/src/Utilities/Table/removeOldSelectedState.js b/frontend/src/Utilities/Table/removeOldSelectedState.js
deleted file mode 100644
index ff3a4fe11..000000000
--- a/frontend/src/Utilities/Table/removeOldSelectedState.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import areAllSelected from './areAllSelected';
-
-export default function removeOldSelectedState(state, prevItems) {
- const selectedState = {
- ...state.selectedState
- };
-
- prevItems.forEach((item) => {
- delete selectedState[item.id];
- });
-
- return {
- ...areAllSelected(selectedState),
- selectedState
- };
-}
diff --git a/frontend/src/Utilities/Table/selectAll.js b/frontend/src/Utilities/Table/selectAll.js
deleted file mode 100644
index ffaaeaddf..000000000
--- a/frontend/src/Utilities/Table/selectAll.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import _ from 'lodash';
-
-function selectAll(selectedState, selected) {
- const newSelectedState = _.reduce(Object.keys(selectedState), (result, item) => {
- result[item] = selected;
- return result;
- }, {});
-
- return {
- allSelected: selected,
- allUnselected: !selected,
- lastToggled: null,
- selectedState: newSelectedState
- };
-}
-
-export default selectAll;
diff --git a/frontend/src/Utilities/Table/toggleSelected.js b/frontend/src/Utilities/Table/toggleSelected.js
deleted file mode 100644
index ec8870b0b..000000000
--- a/frontend/src/Utilities/Table/toggleSelected.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import areAllSelected from './areAllSelected';
-import getToggledRange from './getToggledRange';
-
-function toggleSelected(selectedState, items, id, selected, shiftKey) {
- const lastToggled = selectedState.lastToggled;
- const nextSelectedState = {
- ...selectedState.selectedState,
- [id]: selected
- };
-
- if (selected == null) {
- delete nextSelectedState[id];
- }
-
- if (shiftKey && lastToggled) {
- const { lower, upper } = getToggledRange(items, id, lastToggled);
-
- for (let i = lower; i < upper; i++) {
- nextSelectedState[items[i].id] = selected;
- }
- }
-
- return {
- ...areAllSelected(nextSelectedState),
- lastToggled: id,
- selectedState: nextSelectedState
- };
-}
-
-export default toggleSelected;
diff --git a/frontend/src/Utilities/browser.js b/frontend/src/Utilities/browser.js
deleted file mode 100644
index ff896e801..000000000
--- a/frontend/src/Utilities/browser.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import MobileDetect from 'mobile-detect';
-
-const mobileDetect = new MobileDetect(window.navigator.userAgent);
-
-export function isMobile() {
-
- return mobileDetect.mobile() != null;
-}
-
-export function isIOS() {
- return mobileDetect.is('iOS');
-}
-
-export function isFirefox() {
- return window.navigator.userAgent.toLowerCase().indexOf('firefox/') >= 0;
-}
diff --git a/frontend/src/Utilities/createAjaxRequest.js b/frontend/src/Utilities/createAjaxRequest.js
deleted file mode 100644
index d4836cadc..000000000
--- a/frontend/src/Utilities/createAjaxRequest.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import $ from 'jquery';
-
-const absUrlRegex = /^(https?:)?\/\//i;
-const apiRoot = window.Lidarr.apiRoot;
-
-function isRelative(ajaxOptions) {
- return !absUrlRegex.test(ajaxOptions.url);
-}
-
-function addRootUrl(ajaxOptions) {
- ajaxOptions.url = apiRoot + ajaxOptions.url;
-}
-
-function addApiKey(ajaxOptions) {
- ajaxOptions.headers = ajaxOptions.headers || {};
- ajaxOptions.headers['X-Api-Key'] = window.Lidarr.apiKey;
-}
-
-function addContentType(ajaxOptions) {
- if (
- ajaxOptions.contentType == null &&
- ajaxOptions.dataType === 'json' &&
- (ajaxOptions.method === 'PUT' || ajaxOptions.method === 'POST' || ajaxOptions.method === 'DELETE')) {
- ajaxOptions.contentType = 'application/json';
- }
-}
-
-export default function createAjaxRequest(originalAjaxOptions) {
- const requestXHR = new window.XMLHttpRequest();
- let aborted = false;
- let complete = false;
-
- function abortRequest() {
- if (!complete) {
- aborted = true;
- requestXHR.abort();
- }
- }
-
- const ajaxOptions = { ...originalAjaxOptions };
-
- if (isRelative(ajaxOptions)) {
- addRootUrl(ajaxOptions);
- addApiKey(ajaxOptions);
- addContentType(ajaxOptions);
- }
-
- const request = $.ajax({
- xhr: () => requestXHR,
- ...ajaxOptions
- }).then(null, (xhr, textStatus, errorThrown) => {
- xhr.aborted = aborted;
-
- return $.Deferred().reject(xhr, textStatus, errorThrown).promise();
- }).always(() => {
- complete = true;
- });
-
- return {
- request,
- abortRequest
- };
-}
diff --git a/frontend/src/Utilities/getPathWithUrlBase.js b/frontend/src/Utilities/getPathWithUrlBase.js
deleted file mode 100644
index 292e98dba..000000000
--- a/frontend/src/Utilities/getPathWithUrlBase.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function getPathWithUrlBase(path) {
- return `${window.Lidarr.urlBase}${path}`;
-}
diff --git a/frontend/src/Utilities/getUniqueElementId.js b/frontend/src/Utilities/getUniqueElementId.js
deleted file mode 100644
index dae5150b7..000000000
--- a/frontend/src/Utilities/getUniqueElementId.js
+++ /dev/null
@@ -1,7 +0,0 @@
-let i = 0;
-
-// returns a HTML 4.0 compliant element IDs (http://stackoverflow.com/a/79022)
-
-export default function getUniqueElementId() {
- return `id-${i++}`;
-}
diff --git a/frontend/src/Utilities/pagePopulator.js b/frontend/src/Utilities/pagePopulator.js
deleted file mode 100644
index f58dbe803..000000000
--- a/frontend/src/Utilities/pagePopulator.js
+++ /dev/null
@@ -1,28 +0,0 @@
-let currentPopulator = null;
-let currentReasons = [];
-
-export function registerPagePopulator(populator, reasons = []) {
- currentPopulator = populator;
- currentReasons = reasons;
-}
-
-export function unregisterPagePopulator(populator) {
- if (currentPopulator === populator) {
- currentPopulator = null;
- currentReasons = [];
- }
-}
-
-export function repopulatePage(reason) {
- if (!currentPopulator) {
- return;
- }
-
- if (!reason) {
- currentPopulator();
- }
-
- if (reason && currentReasons.includes(reason)) {
- currentPopulator();
- }
-}
diff --git a/frontend/src/Utilities/pages.js b/frontend/src/Utilities/pages.js
deleted file mode 100644
index 1355442d9..000000000
--- a/frontend/src/Utilities/pages.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const pages = {
- FIRST: 'first',
- PREVIOUS: 'previous',
- NEXT: 'next',
- LAST: 'last',
- EXACT: 'exact'
-};
-
-export default pages;
diff --git a/frontend/src/Utilities/requestAction.js b/frontend/src/Utilities/requestAction.js
deleted file mode 100644
index ed69cf5ad..000000000
--- a/frontend/src/Utilities/requestAction.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import $ from 'jquery';
-import _ from 'lodash';
-import createAjaxRequest from './createAjaxRequest';
-
-function flattenProviderData(providerData) {
- return _.reduce(Object.keys(providerData), (result, key) => {
- const property = providerData[key];
-
- if (key === 'fields') {
- result[key] = property;
- } else {
- result[key] = property.value;
- }
-
- return result;
- }, {});
-}
-
-function requestAction(payload) {
- const {
- provider,
- action,
- providerData,
- queryParams
- } = payload;
-
- const ajaxOptions = {
- url: `/${provider}/action/${action}`,
- contentType: 'application/json',
- method: 'POST',
- data: JSON.stringify(flattenProviderData(providerData))
- };
-
- if (queryParams) {
- ajaxOptions.url += `?${$.param(queryParams, true)}`;
- }
-
- return createAjaxRequest(ajaxOptions).request;
-}
-
-export default requestAction;
diff --git a/frontend/src/Utilities/scrollLock.js b/frontend/src/Utilities/scrollLock.js
deleted file mode 100644
index cff50a34b..000000000
--- a/frontend/src/Utilities/scrollLock.js
+++ /dev/null
@@ -1,13 +0,0 @@
-// Allow iOS devices to disable scrolling of the body/virtual table
-// when a modal is open. This will prevent focusing an input in a
-// modal causing the modal to close due to scrolling.
-
-let scrollLock = false;
-
-export function isLocked() {
- return scrollLock;
-}
-
-export function setScrollLock(locked) {
- scrollLock = locked;
-}
diff --git a/frontend/src/Utilities/sectionTypes.js b/frontend/src/Utilities/sectionTypes.js
deleted file mode 100644
index 5479b32b9..000000000
--- a/frontend/src/Utilities/sectionTypes.js
+++ /dev/null
@@ -1,6 +0,0 @@
-const sectionTypes = {
- COLLECTION: 'collection',
- MODEL: 'model'
-};
-
-export default sectionTypes;
diff --git a/frontend/src/Utilities/serverSideCollectionHandlers.js b/frontend/src/Utilities/serverSideCollectionHandlers.js
deleted file mode 100644
index 03fa39c00..000000000
--- a/frontend/src/Utilities/serverSideCollectionHandlers.js
+++ /dev/null
@@ -1,12 +0,0 @@
-const serverSideCollectionHandlers = {
- FETCH: 'fetch',
- FIRST_PAGE: 'firstPage',
- PREVIOUS_PAGE: 'previousPage',
- NEXT_PAGE: 'nextPage',
- LAST_PAGE: 'lastPage',
- EXACT_PAGE: 'exactPage',
- SORT: 'sort',
- FILTER: 'filter'
-};
-
-export default serverSideCollectionHandlers;
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmet.js b/frontend/src/Wanted/CutoffUnmet/CutoffUnmet.js
deleted file mode 100644
index 6710118b1..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmet.js
+++ /dev/null
@@ -1,296 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import FilterMenu from 'Components/Menu/FilterMenu';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
-import TablePager from 'Components/Table/TablePager';
-import { align, icons, kinds } from 'Helpers/Props';
-import getFilterValue from 'Utilities/Filter/getFilterValue';
-import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
-import translate from 'Utilities/String/translate';
-import getSelectedIds from 'Utilities/Table/getSelectedIds';
-import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
-import selectAll from 'Utilities/Table/selectAll';
-import toggleSelected from 'Utilities/Table/toggleSelected';
-import CutoffUnmetRowConnector from './CutoffUnmetRowConnector';
-
-function getMonitoredValue(props) {
- const {
- filters,
- selectedFilterKey
- } = props;
-
- return getFilterValue(filters, selectedFilterKey, 'monitored', false);
-}
-
-class CutoffUnmet extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- allSelected: false,
- allUnselected: false,
- lastToggled: null,
- selectedState: {},
- isConfirmSearchAllCutoffUnmetModalOpen: false,
- isInteractiveImportModalOpen: false
- };
- }
-
- componentDidUpdate(prevProps) {
- if (hasDifferentItems(prevProps.items, this.props.items)) {
- this.setState((state) => {
- return removeOldSelectedState(state, prevProps.items);
- });
- }
- }
-
- //
- // Control
-
- getSelectedIds = () => {
- return getSelectedIds(this.state.selectedState);
- };
-
- //
- // 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);
- });
- };
-
- onSearchSelectedPress = () => {
- const selected = this.getSelectedIds();
-
- this.props.onSearchSelectedPress(selected);
- };
-
- onToggleSelectedPress = () => {
- const albumIds = this.getSelectedIds();
-
- this.props.batchToggleCutoffUnmetAlbums({
- albumIds,
- monitored: !getMonitoredValue(this.props)
- });
- };
-
- onSearchAllCutoffUnmetPress = () => {
- this.setState({ isConfirmSearchAllCutoffUnmetModalOpen: true });
- };
-
- onSearchAllCutoffUnmetConfirmed = () => {
- this.props.onSearchAllCutoffUnmetPress();
- this.setState({ isConfirmSearchAllCutoffUnmetModalOpen: false });
- };
-
- onConfirmSearchAllCutoffUnmetModalClose = () => {
- this.setState({ isConfirmSearchAllCutoffUnmetModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- isPopulated,
- error,
- items,
- isArtistFetching,
- isArtistPopulated,
- selectedFilterKey,
- filters,
- columns,
- totalRecords,
- isSearchingForCutoffUnmetAlbums,
- isSaving,
- onFilterSelect,
- ...otherProps
- } = this.props;
-
- const {
- allSelected,
- allUnselected,
- selectedState,
- isConfirmSearchAllCutoffUnmetModalOpen
- } = this.state;
-
- const isAllPopulated = isPopulated && isArtistPopulated;
- const isAnyFetching = isFetching || isArtistFetching;
-
- const itemsSelected = !!this.getSelectedIds().length;
- const isShowingMonitored = getMonitoredValue(this.props);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- isAnyFetching && !isAllPopulated &&
-
- }
-
- {
- !isAnyFetching && error &&
-
- Error fetching cutoff unmet
-
- }
-
- {
- isAllPopulated && !error && !items.length &&
-
- {translate('NoCutoffUnmetItems')}
-
- }
-
- {
- isAllPopulated && !error && !!items.length &&
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
- {translate('SearchForAllCutoffUnmetAlbumsConfirmationCount', { totalRecords })}
-
-
- {translate('MassSearchCancelWarning')}
-
-
- }
- confirmLabel={translate('Search')}
- onConfirm={this.onSearchAllCutoffUnmetConfirmed}
- onCancel={this.onConfirmSearchAllCutoffUnmetModalClose}
- />
-
- }
-
-
- );
- }
-}
-
-CutoffUnmet.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- isArtistFetching: PropTypes.bool.isRequired,
- isArtistPopulated: PropTypes.bool.isRequired,
- selectedFilterKey: PropTypes.string.isRequired,
- filters: PropTypes.arrayOf(PropTypes.object).isRequired,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- totalRecords: PropTypes.number,
- isSearchingForCutoffUnmetAlbums: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- onFilterSelect: PropTypes.func.isRequired,
- onSearchSelectedPress: PropTypes.func.isRequired,
- batchToggleCutoffUnmetAlbums: PropTypes.func.isRequired,
- onSearchAllCutoffUnmetPress: PropTypes.func.isRequired
-};
-
-export default CutoffUnmet;
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetConnector.js b/frontend/src/Wanted/CutoffUnmet/CutoffUnmetConnector.js
deleted file mode 100644
index 1dd9870d1..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetConnector.js
+++ /dev/null
@@ -1,191 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import withCurrentPage from 'Components/withCurrentPage';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
-import { clearTrackFiles, fetchTrackFiles } from 'Store/Actions/trackFileActions';
-import * as wantedActions from 'Store/Actions/wantedActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
-import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
-import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
-import CutoffUnmet from './CutoffUnmet';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.wanted.cutoffUnmet,
- (state) => state.artist,
- createCommandExecutingSelector(commandNames.CUTOFF_UNMET_ALBUM_SEARCH),
- (cutoffUnmet, artist, isSearchingForCutoffUnmetAlbums) => {
-
- return {
- isArtistFetching: artist.isFetching,
- isArtistPopulated: artist.isPopulated,
- isSearchingForCutoffUnmetAlbums,
- isSaving: cutoffUnmet.items.filter((m) => m.isSaving).length > 1,
- ...cutoffUnmet
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- ...wantedActions,
- executeCommand,
- fetchQueueDetails,
- clearQueueDetails,
- fetchTrackFiles,
- clearTrackFiles
-};
-
-class CutoffUnmetConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- useCurrentPage,
- fetchCutoffUnmet,
- gotoCutoffUnmetFirstPage
- } = this.props;
-
- registerPagePopulator(this.repopulate, ['trackFileUpdated', 'trackFileDeleted']);
-
- if (useCurrentPage) {
- fetchCutoffUnmet();
- } else {
- gotoCutoffUnmetFirstPage();
- }
- }
-
- componentDidUpdate(prevProps) {
- if (hasDifferentItems(prevProps.items, this.props.items)) {
- const albumIds = selectUniqueIds(this.props.items, 'id');
- const trackFileIds = selectUniqueIds(this.props.items, 'trackFileId');
-
- this.props.fetchQueueDetails({ albumIds });
-
- if (trackFileIds.length) {
- this.props.fetchTrackFiles({ trackFileIds });
- }
- }
- }
-
- componentWillUnmount() {
- unregisterPagePopulator(this.repopulate);
- this.props.clearCutoffUnmet();
- this.props.clearQueueDetails();
- this.props.clearTrackFiles();
- }
-
- //
- // Control
-
- repopulate = () => {
- this.props.fetchCutoffUnmet();
- };
-
- //
- // Listeners
-
- onFirstPagePress = () => {
- this.props.gotoCutoffUnmetFirstPage();
- };
-
- onPreviousPagePress = () => {
- this.props.gotoCutoffUnmetPreviousPage();
- };
-
- onNextPagePress = () => {
- this.props.gotoCutoffUnmetNextPage();
- };
-
- onLastPagePress = () => {
- this.props.gotoCutoffUnmetLastPage();
- };
-
- onPageSelect = (page) => {
- this.props.gotoCutoffUnmetPage({ page });
- };
-
- onSortPress = (sortKey) => {
- this.props.setCutoffUnmetSort({ sortKey });
- };
-
- onFilterSelect = (selectedFilterKey) => {
- this.props.setCutoffUnmetFilter({ selectedFilterKey });
- };
-
- onTableOptionChange = (payload) => {
- this.props.setCutoffUnmetTableOption(payload);
-
- if (payload.pageSize) {
- this.props.gotoCutoffUnmetFirstPage();
- }
- };
-
- onSearchSelectedPress = (selected) => {
- this.props.executeCommand({
- name: commandNames.ALBUM_SEARCH,
- albumIds: selected,
- commandFinished: this.repopulate
- });
- };
-
- onSearchAllCutoffUnmetPress = () => {
- this.props.executeCommand({
- name: commandNames.CUTOFF_UNMET_ALBUM_SEARCH,
- commandFinished: this.repopulate
- });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-CutoffUnmetConnector.propTypes = {
- useCurrentPage: PropTypes.bool.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- fetchCutoffUnmet: PropTypes.func.isRequired,
- gotoCutoffUnmetFirstPage: PropTypes.func.isRequired,
- gotoCutoffUnmetPreviousPage: PropTypes.func.isRequired,
- gotoCutoffUnmetNextPage: PropTypes.func.isRequired,
- gotoCutoffUnmetLastPage: PropTypes.func.isRequired,
- gotoCutoffUnmetPage: PropTypes.func.isRequired,
- setCutoffUnmetSort: PropTypes.func.isRequired,
- setCutoffUnmetFilter: PropTypes.func.isRequired,
- setCutoffUnmetTableOption: PropTypes.func.isRequired,
- clearCutoffUnmet: PropTypes.func.isRequired,
- executeCommand: PropTypes.func.isRequired,
- fetchQueueDetails: PropTypes.func.isRequired,
- clearQueueDetails: PropTypes.func.isRequired,
- fetchTrackFiles: PropTypes.func.isRequired,
- clearTrackFiles: PropTypes.func.isRequired
-};
-
-export default withCurrentPage(
- connect(createMapStateToProps, mapDispatchToProps)(CutoffUnmetConnector)
-);
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css b/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css
deleted file mode 100644
index 106842b2b..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.episode,
-.status {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 100px;
-}
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css.d.ts b/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css.d.ts
deleted file mode 100644
index 6afcbf6d6..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.css.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
- 'episode': string;
- 'status': string;
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.js b/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.js
deleted file mode 100644
index 452e2947a..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRow.js
+++ /dev/null
@@ -1,152 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import albumEntities from 'Album/albumEntities';
-import AlbumSearchCellConnector from 'Album/AlbumSearchCellConnector';
-import AlbumTitleLink from 'Album/AlbumTitleLink';
-import EpisodeStatusConnector from 'Album/EpisodeStatusConnector';
-import ArtistNameLink from 'Artist/ArtistNameLink';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
-import TableRow from 'Components/Table/TableRow';
-import styles from './CutoffUnmetRow.css';
-
-function CutoffUnmetRow(props) {
- const {
- id,
- trackFileId,
- artist,
- releaseDate,
- foreignAlbumId,
- albumType,
- title,
- lastSearchTime,
- disambiguation,
- isSelected,
- columns,
- onSelectedChange
- } = props;
-
- if (!artist) {
- return null;
- }
-
- return (
-
-
-
- {
- columns.map((column) => {
- const {
- name,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- if (name === 'artists.sortName') {
- return (
-
-
-
- );
- }
-
- if (name === 'albums.title') {
- return (
-
-
-
- );
- }
-
- if (name === 'albumType') {
- return (
-
- {albumType}
-
- );
- }
-
- if (name === 'releaseDate') {
- return (
-
- );
- }
-
- if (name === 'albums.lastSearchTime') {
- return (
-
- );
- }
-
- if (name === 'status') {
- return (
-
-
-
- );
- }
-
- if (name === 'actions') {
- return (
-
- );
- }
-
- return null;
- })
- }
-
- );
-}
-
-CutoffUnmetRow.propTypes = {
- id: PropTypes.number.isRequired,
- trackFileId: PropTypes.number,
- artist: PropTypes.object.isRequired,
- releaseDate: PropTypes.string.isRequired,
- foreignAlbumId: PropTypes.string.isRequired,
- albumType: PropTypes.string.isRequired,
- title: PropTypes.string.isRequired,
- lastSearchTime: PropTypes.string,
- disambiguation: PropTypes.string,
- isSelected: PropTypes.bool,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- onSelectedChange: PropTypes.func.isRequired
-};
-
-export default CutoffUnmetRow;
diff --git a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRowConnector.js b/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRowConnector.js
deleted file mode 100644
index 625055c57..000000000
--- a/frontend/src/Wanted/CutoffUnmet/CutoffUnmetRowConnector.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import createArtistSelector from 'Store/Selectors/createArtistSelector';
-import CutoffUnmetRow from './CutoffUnmetRow';
-
-function createMapStateToProps() {
- return createSelector(
- createArtistSelector(),
- (artist) => {
- return {
- artist
- };
- }
- );
-}
-
-export default connect(createMapStateToProps)(CutoffUnmetRow);
diff --git a/frontend/src/Wanted/Missing/Missing.js b/frontend/src/Wanted/Missing/Missing.js
deleted file mode 100644
index 52bfbc30d..000000000
--- a/frontend/src/Wanted/Missing/Missing.js
+++ /dev/null
@@ -1,319 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import Alert from 'Components/Alert';
-import LoadingIndicator from 'Components/Loading/LoadingIndicator';
-import FilterMenu from 'Components/Menu/FilterMenu';
-import ConfirmModal from 'Components/Modal/ConfirmModal';
-import PageContent from 'Components/Page/PageContent';
-import PageContentBody from 'Components/Page/PageContentBody';
-import PageToolbar from 'Components/Page/Toolbar/PageToolbar';
-import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
-import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
-import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
-import Table from 'Components/Table/Table';
-import TableBody from 'Components/Table/TableBody';
-import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
-import TablePager from 'Components/Table/TablePager';
-import { align, icons, kinds } from 'Helpers/Props';
-import InteractiveImportModal from 'InteractiveImport/InteractiveImportModal';
-import getFilterValue from 'Utilities/Filter/getFilterValue';
-import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
-import translate from 'Utilities/String/translate';
-import getSelectedIds from 'Utilities/Table/getSelectedIds';
-import removeOldSelectedState from 'Utilities/Table/removeOldSelectedState';
-import selectAll from 'Utilities/Table/selectAll';
-import toggleSelected from 'Utilities/Table/toggleSelected';
-import MissingRowConnector from './MissingRowConnector';
-
-function getMonitoredValue(props) {
- const {
- filters,
- selectedFilterKey
- } = props;
-
- return getFilterValue(filters, selectedFilterKey, 'monitored', false);
-}
-
-class Missing extends Component {
-
- //
- // Lifecycle
-
- constructor(props, context) {
- super(props, context);
-
- this.state = {
- allSelected: false,
- allUnselected: false,
- lastToggled: null,
- selectedState: {},
- isConfirmSearchAllMissingModalOpen: false,
- isInteractiveImportModalOpen: false
- };
- }
-
- componentDidUpdate(prevProps) {
- if (hasDifferentItems(prevProps.items, this.props.items)) {
- this.setState((state) => {
- return removeOldSelectedState(state, prevProps.items);
- });
- }
- }
-
- //
- // Control
-
- getSelectedIds = () => {
- return getSelectedIds(this.state.selectedState);
- };
-
- //
- // 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);
- });
- };
-
- onSearchSelectedPress = () => {
- const selected = this.getSelectedIds();
-
- this.props.onSearchSelectedPress(selected);
- };
-
- onToggleSelectedPress = () => {
- const albumIds = this.getSelectedIds();
-
- this.props.batchToggleMissingAlbums({
- albumIds,
- monitored: !getMonitoredValue(this.props)
- });
- };
-
- onSearchAllMissingPress = () => {
- this.setState({ isConfirmSearchAllMissingModalOpen: true });
- };
-
- onSearchAllMissingConfirmed = () => {
- this.props.onSearchAllMissingPress();
- this.setState({ isConfirmSearchAllMissingModalOpen: false });
- };
-
- onConfirmSearchAllMissingModalClose = () => {
- this.setState({ isConfirmSearchAllMissingModalOpen: false });
- };
-
- onInteractiveImportPress = () => {
- this.setState({ isInteractiveImportModalOpen: true });
- };
-
- onInteractiveImportModalClose = () => {
- this.setState({ isInteractiveImportModalOpen: false });
- };
-
- //
- // Render
-
- render() {
- const {
- isFetching,
- isPopulated,
- error,
- items,
- isArtistFetching,
- isArtistPopulated,
- selectedFilterKey,
- filters,
- columns,
- totalRecords,
- isSearchingForMissingAlbums,
- isSaving,
- onFilterSelect,
- ...otherProps
- } = this.props;
-
- const {
- allSelected,
- allUnselected,
- selectedState,
- isConfirmSearchAllMissingModalOpen,
- isInteractiveImportModalOpen
- } = this.state;
-
- const isAllPopulated = isPopulated && isArtistPopulated;
- const isAnyFetching = isFetching || isArtistFetching;
-
- const itemsSelected = !!this.getSelectedIds().length;
- const isShowingMonitored = getMonitoredValue(this.props);
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- isAnyFetching && !isAllPopulated &&
-
- }
-
- {
- !isAnyFetching && error &&
-
- Error fetching missing items
-
- }
-
- {
- isAllPopulated && !error && !items.length &&
-
- {translate('NoMissingItems')}
-
- }
-
- {
- isAllPopulated && !error && !!items.length &&
-
-
-
- {
- items.map((item) => {
- return (
-
- );
- })
- }
-
-
-
-
-
-
-
- {translate('SearchForAllMissingAlbumsConfirmationCount', { totalRecords })}
-
-
- {translate('MassSearchCancelWarning')}
-
-
- }
- confirmLabel={translate('Search')}
- onConfirm={this.onSearchAllMissingConfirmed}
- onCancel={this.onConfirmSearchAllMissingModalClose}
- />
-
- }
-
-
-
-
- );
- }
-}
-
-Missing.propTypes = {
- isFetching: PropTypes.bool.isRequired,
- isPopulated: PropTypes.bool.isRequired,
- error: PropTypes.object,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- isArtistFetching: PropTypes.bool.isRequired,
- isArtistPopulated: PropTypes.bool.isRequired,
- selectedFilterKey: PropTypes.string.isRequired,
- filters: PropTypes.arrayOf(PropTypes.object).isRequired,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- totalRecords: PropTypes.number,
- isSearchingForMissingAlbums: PropTypes.bool.isRequired,
- isSaving: PropTypes.bool.isRequired,
- onFilterSelect: PropTypes.func.isRequired,
- onSearchSelectedPress: PropTypes.func.isRequired,
- batchToggleMissingAlbums: PropTypes.func.isRequired,
- onSearchAllMissingPress: PropTypes.func.isRequired
-};
-
-export default Missing;
diff --git a/frontend/src/Wanted/Missing/MissingConnector.js b/frontend/src/Wanted/Missing/MissingConnector.js
deleted file mode 100644
index 008f1a149..000000000
--- a/frontend/src/Wanted/Missing/MissingConnector.js
+++ /dev/null
@@ -1,179 +0,0 @@
-import PropTypes from 'prop-types';
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import * as commandNames from 'Commands/commandNames';
-import withCurrentPage from 'Components/withCurrentPage';
-import { executeCommand } from 'Store/Actions/commandActions';
-import { clearQueueDetails, fetchQueueDetails } from 'Store/Actions/queueActions';
-import * as wantedActions from 'Store/Actions/wantedActions';
-import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
-import hasDifferentItems from 'Utilities/Object/hasDifferentItems';
-import selectUniqueIds from 'Utilities/Object/selectUniqueIds';
-import { registerPagePopulator, unregisterPagePopulator } from 'Utilities/pagePopulator';
-import Missing from './Missing';
-
-function createMapStateToProps() {
- return createSelector(
- (state) => state.wanted.missing,
- (state) => state.artist,
- createCommandExecutingSelector(commandNames.MISSING_ALBUM_SEARCH),
- (missing, artist, isSearchingForMissingAlbums) => {
-
- return {
- isArtistFetching: artist.isFetching,
- isArtistPopulated: artist.isPopulated,
- isSearchingForMissingAlbums,
- isSaving: missing.items.filter((m) => m.isSaving).length > 1,
- ...missing
- };
- }
- );
-}
-
-const mapDispatchToProps = {
- ...wantedActions,
- executeCommand,
- fetchQueueDetails,
- clearQueueDetails
-};
-
-class MissingConnector extends Component {
-
- //
- // Lifecycle
-
- componentDidMount() {
- const {
- useCurrentPage,
- fetchMissing,
- gotoMissingFirstPage
- } = this.props;
-
- registerPagePopulator(this.repopulate, ['trackFileUpdated', 'trackFileDeleted']);
-
- if (useCurrentPage) {
- fetchMissing();
- } else {
- gotoMissingFirstPage();
- }
- }
-
- componentDidUpdate(prevProps) {
- if (hasDifferentItems(prevProps.items, this.props.items)) {
- const albumIds = selectUniqueIds(this.props.items, 'id');
- this.props.fetchQueueDetails({ albumIds });
- }
- }
-
- componentWillUnmount() {
- unregisterPagePopulator(this.repopulate);
- this.props.clearMissing();
- this.props.clearQueueDetails();
- }
-
- //
- // Control
-
- repopulate = () => {
- this.props.fetchMissing();
- };
-
- //
- // Listeners
-
- onFirstPagePress = () => {
- this.props.gotoMissingFirstPage();
- };
-
- onPreviousPagePress = () => {
- this.props.gotoMissingPreviousPage();
- };
-
- onNextPagePress = () => {
- this.props.gotoMissingNextPage();
- };
-
- onLastPagePress = () => {
- this.props.gotoMissingLastPage();
- };
-
- onPageSelect = (page) => {
- this.props.gotoMissingPage({ page });
- };
-
- onSortPress = (sortKey) => {
- this.props.setMissingSort({ sortKey });
- };
-
- onFilterSelect = (selectedFilterKey) => {
- this.props.setMissingFilter({ selectedFilterKey });
- };
-
- onTableOptionChange = (payload) => {
- this.props.setMissingTableOption(payload);
-
- if (payload.pageSize) {
- this.props.gotoMissingFirstPage();
- }
- };
-
- onSearchSelectedPress = (selected) => {
- this.props.executeCommand({
- name: commandNames.ALBUM_SEARCH,
- albumIds: selected,
- commandFinished: this.repopulate
- });
- };
-
- onSearchAllMissingPress = () => {
- this.props.executeCommand({
- name: commandNames.MISSING_ALBUM_SEARCH,
- commandFinished: this.repopulate
- });
- };
-
- //
- // Render
-
- render() {
- return (
-
- );
- }
-}
-
-MissingConnector.propTypes = {
- useCurrentPage: PropTypes.bool.isRequired,
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- fetchMissing: PropTypes.func.isRequired,
- gotoMissingFirstPage: PropTypes.func.isRequired,
- gotoMissingPreviousPage: PropTypes.func.isRequired,
- gotoMissingNextPage: PropTypes.func.isRequired,
- gotoMissingLastPage: PropTypes.func.isRequired,
- gotoMissingPage: PropTypes.func.isRequired,
- setMissingSort: PropTypes.func.isRequired,
- setMissingFilter: PropTypes.func.isRequired,
- setMissingTableOption: PropTypes.func.isRequired,
- clearMissing: PropTypes.func.isRequired,
- executeCommand: PropTypes.func.isRequired,
- fetchQueueDetails: PropTypes.func.isRequired,
- clearQueueDetails: PropTypes.func.isRequired
-};
-
-export default withCurrentPage(
- connect(createMapStateToProps, mapDispatchToProps)(MissingConnector)
-);
diff --git a/frontend/src/Wanted/Missing/MissingRow.css b/frontend/src/Wanted/Missing/MissingRow.css
deleted file mode 100644
index 1794c2530..000000000
--- a/frontend/src/Wanted/Missing/MissingRow.css
+++ /dev/null
@@ -1,5 +0,0 @@
-.status {
- composes: cell from '~Components/Table/Cells/TableRowCell.css';
-
- width: 100px;
-}
diff --git a/frontend/src/Wanted/Missing/MissingRow.js b/frontend/src/Wanted/Missing/MissingRow.js
deleted file mode 100644
index 6c0b5a0c6..000000000
--- a/frontend/src/Wanted/Missing/MissingRow.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import albumEntities from 'Album/albumEntities';
-import AlbumSearchCellConnector from 'Album/AlbumSearchCellConnector';
-import AlbumTitleLink from 'Album/AlbumTitleLink';
-import ArtistNameLink from 'Artist/ArtistNameLink';
-import RelativeDateCellConnector from 'Components/Table/Cells/RelativeDateCellConnector';
-import TableRowCell from 'Components/Table/Cells/TableRowCell';
-import TableSelectCell from 'Components/Table/Cells/TableSelectCell';
-import TableRow from 'Components/Table/TableRow';
-
-function MissingRow(props) {
- const {
- id,
- artist,
- releaseDate,
- albumType,
- foreignAlbumId,
- title,
- lastSearchTime,
- disambiguation,
- isSelected,
- columns,
- onSelectedChange
- } = props;
-
- if (!artist) {
- return null;
- }
-
- return (
-
-
-
- {
- columns.map((column) => {
- const {
- name,
- isVisible
- } = column;
-
- if (!isVisible) {
- return null;
- }
-
- if (name === 'artists.sortName') {
- return (
-
-
-
- );
- }
-
- if (name === 'albums.title') {
- return (
-
-
-
- );
- }
-
- if (name === 'albumType') {
- return (
-
- {albumType}
-
- );
- }
-
- if (name === 'releaseDate') {
- return (
-
- );
- }
-
- if (name === 'albums.lastSearchTime') {
- return (
-
- );
- }
-
- if (name === 'actions') {
- return (
-
- );
- }
-
- return null;
- })
- }
-
- );
-}
-
-MissingRow.propTypes = {
- id: PropTypes.number.isRequired,
- artist: PropTypes.object.isRequired,
- releaseDate: PropTypes.string.isRequired,
- foreignAlbumId: PropTypes.string.isRequired,
- albumType: PropTypes.string.isRequired,
- title: PropTypes.string.isRequired,
- lastSearchTime: PropTypes.string,
- disambiguation: PropTypes.string,
- isSelected: PropTypes.bool,
- columns: PropTypes.arrayOf(PropTypes.object).isRequired,
- onSelectedChange: PropTypes.func.isRequired
-};
-
-export default MissingRow;
diff --git a/frontend/src/Wanted/Missing/MissingRowConnector.js b/frontend/src/Wanted/Missing/MissingRowConnector.js
deleted file mode 100644
index f0a30d9cd..000000000
--- a/frontend/src/Wanted/Missing/MissingRowConnector.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { connect } from 'react-redux';
-import { createSelector } from 'reselect';
-import createArtistSelector from 'Store/Selectors/createArtistSelector';
-import MissingRow from './MissingRow';
-
-function createMapStateToProps() {
- return createSelector(
- createArtistSelector(),
- (artist) => {
- return {
- artist
- };
- }
- );
-}
-
-export default connect(createMapStateToProps)(MissingRow);
diff --git a/frontend/src/bootstrap.tsx b/frontend/src/bootstrap.tsx
deleted file mode 100644
index 9ecf27e0e..000000000
--- a/frontend/src/bootstrap.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { createBrowserHistory } from 'history';
-import React from 'react';
-import { createRoot } from 'react-dom/client';
-import createAppStore from 'Store/createAppStore';
-import App from './App/App';
-
-import 'Diag/ConsoleApi';
-
-export async function bootstrap() {
- const history = createBrowserHistory();
- const store = createAppStore(history);
- const container = document.getElementById('root');
-
- const root = createRoot(container!); // createRoot(container!) if you use TypeScript
- root.render( );
-}
diff --git a/frontend/src/index.css b/frontend/src/index.css
deleted file mode 100644
index 2a94ba941..000000000
--- a/frontend/src/index.css
+++ /dev/null
@@ -1,15 +0,0 @@
-html,
-body {
- height: 100%; /* needed for proper layout */
-}
-
-body {
- overflow: hidden;
- background-color: var(--pageBackground);
-}
-
-@media only screen and (max-width: $breakpointSmall) {
- body {
- overflow-y: auto;
- }
-}
diff --git a/frontend/src/index.css.d.ts b/frontend/src/index.css.d.ts
deleted file mode 100644
index 132b232e8..000000000
--- a/frontend/src/index.css.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-// This file is automatically generated.
-// Please do not change this file!
-interface CssExports {
-
-}
-export const cssExports: CssExports;
-export default cssExports;
diff --git a/frontend/src/index.ejs b/frontend/src/index.ejs
deleted file mode 100644
index a893149d5..000000000
--- a/frontend/src/index.ejs
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <% for (key in htmlWebpackPlugin.files.js) { %><% } %>
- <% for (key in htmlWebpackPlugin.files.css) { %> <% } %>
-
- Lidarr
-
-
-
-
-
-
-
-
-
-
diff --git a/frontend/src/index.ts b/frontend/src/index.ts
deleted file mode 100644
index 37e780919..000000000
--- a/frontend/src/index.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import './polyfills';
-import 'Styles/globals.css';
-import './index.css';
-
-const initializeUrl = `${
- window.Lidarr.urlBase
-}/initialize.json?t=${Date.now()}`;
-const response = await fetch(initializeUrl);
-
-window.Lidarr = await response.json();
-
-/* eslint-disable no-undef, @typescript-eslint/ban-ts-comment */
-// @ts-ignore 2304
-__webpack_public_path__ = `${window.Lidarr.urlBase}/`;
-/* eslint-enable no-undef, @typescript-eslint/ban-ts-comment */
-
-const error = console.error;
-
-// Monkey patch console.error to filter out some warnings from React
-// TODO: Remove this after the great TypeScript migration
-
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-function logError(...parameters: any[]) {
- const filter = parameters.find((parameter) => {
- return (
- typeof parameter === 'string' &&
- (parameter.includes(
- 'Support for defaultProps will be removed from function components in a future major release'
- ) ||
- parameter.includes(
- 'findDOMNode is deprecated and will be removed in the next major release'
- ))
- );
- });
-
- if (!filter) {
- error(...parameters);
- }
-}
-
-console.error = logError;
-
-const { bootstrap } = await import('./bootstrap');
-
-await bootstrap();
diff --git a/frontend/src/login.html b/frontend/src/login.html
deleted file mode 100644
index 24d086959..000000000
--- a/frontend/src/login.html
+++ /dev/null
@@ -1,348 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Login - Lidarr
-
-
-
-
-
-
-
-
-
-
-
-
SIGN IN TO CONTINUE
-
-
-
-
-
-
- ©
-
- -
- Lidarr
-
-
-
-
-
-
-
diff --git a/frontend/src/polyfills.js b/frontend/src/polyfills.js
deleted file mode 100644
index ece7aea85..000000000
--- a/frontend/src/polyfills.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/* eslint no-empty-function: 0, no-extend-native: 0, "@typescript-eslint/no-empty-function": 0 */
-
-window.console = window.console || {};
-window.console.log = window.console.log || function() {};
-window.console.group = window.console.group || function() {};
-window.console.groupEnd = window.console.groupEnd || function() {};
-window.console.debug = window.console.debug || function() {};
-window.console.warn = window.console.warn || function() {};
-window.console.assert = window.console.assert || function() {};
-
-if (!String.prototype.startsWith) {
- Object.defineProperty(String.prototype, 'startsWith', {
- enumerable: false,
- configurable: false,
- writable: false,
- value(searchString, position) {
- position = position || 0;
- return this.indexOf(searchString, position) === position;
- }
- });
-}
-
-if (!String.prototype.endsWith) {
- Object.defineProperty(String.prototype, 'endsWith', {
- enumerable: false,
- configurable: false,
- writable: false,
- value(searchString, position) {
- position = position || this.length;
- position = position - searchString.length;
- const lastIndex = this.lastIndexOf(searchString);
- return lastIndex !== -1 && lastIndex === position;
- }
- });
-}
-
-if (!('contains' in String.prototype)) {
- String.prototype.contains = function(str, startIndex) {
- return String.prototype.indexOf.call(this, str, startIndex) !== -1;
- };
-}
diff --git a/frontend/src/preload.js b/frontend/src/preload.js
deleted file mode 100644
index aec17072e..000000000
--- a/frontend/src/preload.js
+++ /dev/null
@@ -1,2 +0,0 @@
-/* eslint no-undef: 0 */
-__webpack_public_path__ = `${window.Lidarr.urlBase}/`;
diff --git a/frontend/src/typings/CustomFormat.ts b/frontend/src/typings/CustomFormat.ts
deleted file mode 100644
index b3cc2a845..000000000
--- a/frontend/src/typings/CustomFormat.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-export interface QualityProfileFormatItem {
- format: number;
- name: string;
- score: number;
-}
-
-interface CustomFormat extends ModelBase {
- name: string;
- includeCustomFormatWhenRenaming: boolean;
-}
-
-export default CustomFormat;
diff --git a/frontend/src/typings/DownloadClient.ts b/frontend/src/typings/DownloadClient.ts
deleted file mode 100644
index 2c032c22a..000000000
--- a/frontend/src/typings/DownloadClient.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-export interface Field {
- order: number;
- name: string;
- label: string;
- value: boolean | number | string;
- type: string;
- advanced: boolean;
- privacy: string;
-}
-
-interface DownloadClient extends ModelBase {
- enable: boolean;
- protocol: string;
- priority: number;
- removeCompletedDownloads: boolean;
- removeFailedDownloads: boolean;
- name: string;
- fields: Field[];
- implementationName: string;
- implementation: string;
- configContract: string;
- infoLink: string;
- tags: number[];
-}
-
-export default DownloadClient;
diff --git a/frontend/src/typings/Helpers/KeysMatching.ts b/frontend/src/typings/Helpers/KeysMatching.ts
deleted file mode 100644
index 0e20206ef..000000000
--- a/frontend/src/typings/Helpers/KeysMatching.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-type KeysMatching = {
- [K in keyof T]-?: T[K] extends V ? K : never;
-}[keyof T];
-
-export type StringKey = KeysMatching;
-
-export default KeysMatching;
diff --git a/frontend/src/typings/History.ts b/frontend/src/typings/History.ts
deleted file mode 100644
index 55e004742..000000000
--- a/frontend/src/typings/History.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { QualityModel } from 'Quality/Quality';
-import CustomFormat from './CustomFormat';
-
-export type HistoryEventType =
- | 'grabbed'
- | 'artistFolderImported'
- | 'trackFileImported'
- | 'downloadFailed'
- | 'trackFileDeleted'
- | 'trackFileRenamed'
- | 'albumImportIncomplete'
- | 'downloadImported'
- | 'trackFileRetagged'
- | 'downloadIgnored';
-
-export default interface History {
- episodeId: number;
- seriesId: number;
- sourceTitle: string;
- quality: QualityModel;
- customFormats: CustomFormat[];
- customFormatScore: number;
- qualityCutoffNotMet: boolean;
- date: string;
- downloadId: string;
- eventType: HistoryEventType;
- data: unknown;
- id: number;
-}
diff --git a/frontend/src/typings/ImportList.ts b/frontend/src/typings/ImportList.ts
deleted file mode 100644
index 7af4c2bbc..000000000
--- a/frontend/src/typings/ImportList.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-export interface Field {
- order: number;
- name: string;
- label: string;
- value: boolean | number | string;
- type: string;
- advanced: boolean;
- privacy: string;
-}
-
-interface ImportList extends ModelBase {
- enable: boolean;
- enableAutomaticAdd: boolean;
- qualityProfileId: number;
- rootFolderPath: string;
- name: string;
- fields: Field[];
- implementationName: string;
- implementation: string;
- configContract: string;
- infoLink: string;
- tags: number[];
-}
-
-export default ImportList;
diff --git a/frontend/src/typings/Indexer.ts b/frontend/src/typings/Indexer.ts
deleted file mode 100644
index e6c23eda2..000000000
--- a/frontend/src/typings/Indexer.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-export interface Field {
- order: number;
- name: string;
- label: string;
- value: boolean | number | string;
- type: string;
- advanced: boolean;
- privacy: string;
-}
-
-interface Indexer extends ModelBase {
- enableRss: boolean;
- enableAutomaticSearch: boolean;
- enableInteractiveSearch: boolean;
- protocol: string;
- priority: number;
- name: string;
- fields: Field[];
- implementationName: string;
- implementation: string;
- configContract: string;
- infoLink: string;
- tags: number[];
-}
-
-export default Indexer;
diff --git a/frontend/src/typings/IndexerFlag.ts b/frontend/src/typings/IndexerFlag.ts
deleted file mode 100644
index 2c7d97a73..000000000
--- a/frontend/src/typings/IndexerFlag.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-interface IndexerFlag {
- id: number;
- name: string;
-}
-
-export default IndexerFlag;
diff --git a/frontend/src/typings/MediaInfo.ts b/frontend/src/typings/MediaInfo.ts
deleted file mode 100644
index ddcbf2569..000000000
--- a/frontend/src/typings/MediaInfo.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-interface MediaInfo {
- audioBitRate: string;
- audioChannels: number;
- audioCodec: string;
- audioBits: string;
- audioSampleRate: string;
-}
-
-export default MediaInfo;
diff --git a/frontend/src/typings/MetadataProfile.ts b/frontend/src/typings/MetadataProfile.ts
deleted file mode 100644
index a02c99c5a..000000000
--- a/frontend/src/typings/MetadataProfile.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-interface PrimaryAlbumType {
- id?: number;
- name?: string;
-}
-
-interface SecondaryAlbumType {
- id?: number;
- name?: string;
-}
-
-interface ReleaseStatus {
- id?: number;
- name?: string;
-}
-
-interface ProfilePrimaryAlbumTypeItem {
- primaryAlbumType?: PrimaryAlbumType;
- allowed: boolean;
-}
-
-interface ProfileSecondaryAlbumTypeItem {
- secondaryAlbumType?: SecondaryAlbumType;
- allowed: boolean;
-}
-
-interface ProfileReleaseStatusItem {
- releaseStatus?: ReleaseStatus;
- allowed: boolean;
-}
-
-interface MetadataProfile {
- name: string;
- primaryAlbumTypes: ProfilePrimaryAlbumTypeItem[];
- secondaryAlbumTypes: ProfileSecondaryAlbumTypeItem[];
- ReleaseStatuses: ProfileReleaseStatusItem[];
- id: number;
-}
-
-export default MetadataProfile;
diff --git a/frontend/src/typings/Notification.ts b/frontend/src/typings/Notification.ts
deleted file mode 100644
index e2b5ad7eb..000000000
--- a/frontend/src/typings/Notification.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-export interface Field {
- order: number;
- name: string;
- label: string;
- value: boolean | number | string;
- type: string;
- advanced: boolean;
- privacy: string;
-}
-
-interface Notification extends ModelBase {
- enable: boolean;
- name: string;
- fields: Field[];
- implementationName: string;
- implementation: string;
- configContract: string;
- infoLink: string;
- tags: number[];
-}
-
-export default Notification;
diff --git a/frontend/src/typings/QualityProfile.ts b/frontend/src/typings/QualityProfile.ts
deleted file mode 100644
index ec4e46648..000000000
--- a/frontend/src/typings/QualityProfile.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import Quality from 'Quality/Quality';
-import { QualityProfileFormatItem } from './CustomFormat';
-
-export interface QualityProfileQualityItem {
- id?: number;
- quality?: Quality;
- items: QualityProfileQualityItem[];
- allowed: boolean;
- name?: string;
-}
-
-interface QualityProfile {
- name: string;
- upgradeAllowed: boolean;
- cutoff: number;
- items: QualityProfileQualityItem[];
- minFormatScore: number;
- cutoffFormatScore: number;
- formatItems: QualityProfileFormatItem[];
- id: number;
-}
-
-export default QualityProfile;
diff --git a/frontend/src/typings/Queue.ts b/frontend/src/typings/Queue.ts
deleted file mode 100644
index 46afdaa7a..000000000
--- a/frontend/src/typings/Queue.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import ModelBase from 'App/ModelBase';
-import { QualityModel } from 'Quality/Quality';
-import CustomFormat from 'typings/CustomFormat';
-
-export type QueueTrackedDownloadStatus = 'ok' | 'warning' | 'error';
-
-export type QueueTrackedDownloadState =
- | 'downloading'
- | 'downloadFailed'
- | 'downloadFailedPending'
- | 'importPending'
- | 'importing'
- | 'importFailed'
- | 'imported'
- | 'ignored';
-
-export interface StatusMessage {
- title: string;
- messages: string[];
-}
-
-interface Queue extends ModelBase {
- quality: QualityModel;
- customFormats: CustomFormat[];
- size: number;
- title: string;
- sizeleft: number;
- timeleft: string;
- estimatedCompletionTime: string;
- added?: string;
- status: string;
- trackedDownloadStatus: QueueTrackedDownloadStatus;
- trackedDownloadState: QueueTrackedDownloadState;
- statusMessages: StatusMessage[];
- errorMessage: string;
- downloadId: string;
- protocol: string;
- downloadClient: string;
- outputPath: string;
- trackFileCount: number;
- trackHasFileCount: number;
- artistId?: number;
- albumId?: number;
-}
-
-export default Queue;
diff --git a/frontend/src/typings/RootFolder.ts b/frontend/src/typings/RootFolder.ts
deleted file mode 100644
index 83c509423..000000000
--- a/frontend/src/typings/RootFolder.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import ModelBase from 'App/ModelBase';
-
-interface RootFolder extends ModelBase {
- id: number;
- name: string;
- path: string;
- accessible: boolean;
- freeSpace?: number;
- unmappedFolders: object[];
-}
-
-export default RootFolder;
diff --git a/frontend/src/typings/Settings/General.ts b/frontend/src/typings/Settings/General.ts
deleted file mode 100644
index c867bed74..000000000
--- a/frontend/src/typings/Settings/General.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-export type UpdateMechanism =
- | 'builtIn'
- | 'script'
- | 'external'
- | 'apt'
- | 'docker';
-
-export default interface General {
- bindAddress: string;
- port: number;
- sslPort: number;
- enableSsl: boolean;
- launchBrowser: boolean;
- authenticationMethod: string;
- authenticationRequired: string;
- analyticsEnabled: boolean;
- username: string;
- password: string;
- passwordConfirmation: string;
- logLevel: string;
- consoleLogLevel: string;
- branch: string;
- apiKey: string;
- sslCertPath: string;
- sslCertPassword: string;
- urlBase: string;
- instanceName: string;
- applicationUrl: string;
- updateAutomatically: boolean;
- updateMechanism: UpdateMechanism;
- updateScriptPath: string;
- proxyEnabled: boolean;
- proxyType: string;
- proxyHostname: string;
- proxyPort: number;
- proxyUsername: string;
- proxyPassword: string;
- proxyBypassFilter: string;
- proxyBypassLocalAddresses: boolean;
- certificateValidation: string;
- backupFolder: string;
- backupInterval: number;
- backupRetention: number;
- id: number;
-}
diff --git a/frontend/src/typings/Settings/UiSettings.ts b/frontend/src/typings/Settings/UiSettings.ts
deleted file mode 100644
index 656c4518b..000000000
--- a/frontend/src/typings/Settings/UiSettings.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-export default interface UiSettings {
- theme: 'auto' | 'dark' | 'light';
- showRelativeDates: boolean;
- shortDateFormat: string;
- longDateFormat: string;
- timeFormat: string;
-}
diff --git a/frontend/src/typings/SystemStatus.ts b/frontend/src/typings/SystemStatus.ts
deleted file mode 100644
index 47f2b3552..000000000
--- a/frontend/src/typings/SystemStatus.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-interface SystemStatus {
- appData: string;
- appName: string;
- authentication: string;
- branch: string;
- buildTime: string;
- instanceName: string;
- isAdmin: boolean;
- isDebug: boolean;
- isDocker: boolean;
- isLinux: boolean;
- isNetCore: boolean;
- isOsx: boolean;
- isProduction: boolean;
- isUserInteractive: boolean;
- isWindows: boolean;
- migrationVersion: number;
- mode: string;
- osName: string;
- osVersion: string;
- packageUpdateMechanism: string;
- packageUpdateMechanismMessage: string;
- runtimeName: string;
- runtimeVersion: string;
- sqliteVersion: string;
- startTime: string;
- startupPath: string;
- urlBase: string;
- version: string;
-}
-
-export default SystemStatus;
diff --git a/frontend/src/typings/Update.ts b/frontend/src/typings/Update.ts
deleted file mode 100644
index 448b1728d..000000000
--- a/frontend/src/typings/Update.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-export interface Changes {
- new: string[];
- fixed: string[];
-}
-
-interface Update {
- version: string;
- branch: string;
- releaseDate: string;
- fileName: string;
- url: string;
- installed: boolean;
- installedOn: string;
- installable: boolean;
- latest: boolean;
- changes: Changes | null;
- hash: string;
-}
-
-export default Update;
diff --git a/frontend/src/typings/callbacks.ts b/frontend/src/typings/callbacks.ts
deleted file mode 100644
index 0114efeb0..000000000
--- a/frontend/src/typings/callbacks.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import SortDirection from 'Helpers/Props/SortDirection';
-
-export type SortCallback = (
- sortKey: string,
- sortDirection: SortDirection
-) => void;
diff --git a/frontend/src/typings/inputs.ts b/frontend/src/typings/inputs.ts
deleted file mode 100644
index 7d202cd44..000000000
--- a/frontend/src/typings/inputs.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export type InputChanged = {
- name: string;
- value: T;
-};
-
-export type InputOnChange = (change: InputChanged) => void;
-
-export type CheckInputChanged = {
- name: string;
- value: boolean;
-};
diff --git a/frontend/src/typings/props.ts b/frontend/src/typings/props.ts
deleted file mode 100644
index 5b87e36b3..000000000
--- a/frontend/src/typings/props.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export interface SelectStateInputProps {
- id: number;
- value: boolean;
- shiftKey: boolean;
-}
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
deleted file mode 100644
index 611c872ed..000000000
--- a/frontend/tsconfig.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "compilerOptions": {
- "target": "esnext",
- "allowJs": true,
- "checkJs": false,
- "baseUrl": "src",
- "jsx": "react",
- "module": "esnext",
- "moduleResolution": "node",
- "allowSyntheticDefaultImports": true,
- "forceConsistentCasingInFileNames": true,
- "noEmit": true,
- "noUnusedLocals": true,
- "noUnusedParameters": true,
- "noImplicitAny": true,
- "noImplicitReturns": true,
- "noImplicitThis": true,
- "strict": true,
- "esModuleInterop": true,
- "typeRoots": ["node_modules/@types", "typings"],
- "paths": {
- "*": [
- "*"
- ]
- },
- "plugins": [{ "name": "typescript-plugin-css-modules" }]
- },
- "include": [
- "./src/**/*",
- "./.eslintrc.js",
- "./build/webpack.config.js",
- "./typings/*.ts",
- ],
- "exclude": [
- "node_modules"
- ]
-}
diff --git a/frontend/typings/Globals.d.ts b/frontend/typings/Globals.d.ts
deleted file mode 100644
index 3509249fc..000000000
--- a/frontend/typings/Globals.d.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-declare module '*.module.css';
-
-interface Window {
- Lidarr: {
- apiKey: string;
- instanceName: string;
- theme: string;
- urlBase: string;
- version: string;
- isProduction: boolean;
- };
-}
diff --git a/gulp/build.js b/gulp/build.js
new file mode 100644
index 000000000..23f457baf
--- /dev/null
+++ b/gulp/build.js
@@ -0,0 +1,18 @@
+var gulp = require('gulp');
+var runSequence = require('run-sequence');
+
+require('./clean');
+require('./less');
+require('./handlebars');
+require('./copy');
+
+gulp.task('build', function() {
+ return runSequence('clean', [
+ 'webpack',
+ 'less',
+ 'handlebars',
+ 'copyHtml',
+ 'copyContent',
+ 'copyJs'
+ ]);
+});
diff --git a/gulp/clean.js b/gulp/clean.js
new file mode 100644
index 000000000..58f9c223f
--- /dev/null
+++ b/gulp/clean.js
@@ -0,0 +1,8 @@
+var gulp = require('gulp');
+var del = require('del');
+
+var paths = require('./paths');
+
+gulp.task('clean', function(cb) {
+ del([paths.dest.root], cb);
+});
diff --git a/gulp/copy.js b/gulp/copy.js
new file mode 100644
index 000000000..ab380855d
--- /dev/null
+++ b/gulp/copy.js
@@ -0,0 +1,31 @@
+var gulp = require('gulp');
+var print = require('gulp-print');
+var cache = require('gulp-cached');
+var livereload = require('gulp-livereload');
+
+var paths = require('./paths.js');
+
+gulp.task('copyJs', function () {
+ return gulp.src(
+ [
+ paths.src.root + 'polyfills.js',
+ paths.src.root + 'JsLibraries/handlebars.runtime.js'
+ ])
+ .pipe(cache('copyJs'))
+ .pipe(print())
+ .pipe(gulp.dest(paths.dest.root))
+ .pipe(livereload());
+});
+
+gulp.task('copyHtml', function () {
+ return gulp.src(paths.src.html)
+ .pipe(cache('copyHtml'))
+ .pipe(gulp.dest(paths.dest.root))
+ .pipe(livereload());
+});
+
+gulp.task('copyContent', function () {
+ return gulp.src([paths.src.content + '**/*.*', '!**/*.less'])
+ .pipe(gulp.dest(paths.dest.content))
+ .pipe(livereload());
+});
diff --git a/gulp/errorHandler.js b/gulp/errorHandler.js
new file mode 100644
index 000000000..db24e1a66
--- /dev/null
+++ b/gulp/errorHandler.js
@@ -0,0 +1,7 @@
+module.exports = {
+ onError : function(error) {
+ //If you want details of the error in the console
+ console.log(error.toString());
+ this.emit('end');
+ }
+};
\ No newline at end of file
diff --git a/gulp/gulpFile.js b/gulp/gulpFile.js
new file mode 100644
index 000000000..428fad285
--- /dev/null
+++ b/gulp/gulpFile.js
@@ -0,0 +1,11 @@
+require('./watch.js');
+require('./build.js');
+require('./clean.js');
+require('./jshint.js');
+require('./handlebars.js');
+require('./copy.js');
+require('./less.js');
+require('./stripBom.js');
+require('./imageMin.js');
+require('./webpack.js');
+require('./start.js');
diff --git a/gulp/handlebars.js b/gulp/handlebars.js
new file mode 100644
index 000000000..aab62f438
--- /dev/null
+++ b/gulp/handlebars.js
@@ -0,0 +1,55 @@
+var gulp = require('gulp');
+var handlebars = require('gulp-handlebars');
+var declare = require('gulp-declare');
+var concat = require('gulp-concat');
+var wrap = require("gulp-wrap");
+var livereload = require('gulp-livereload');
+var path = require('path');
+var streamqueue = require('streamqueue');
+var stripbom = require('gulp-stripbom');
+
+var paths = require('./paths.js');
+
+gulp.task('handlebars', function() {
+
+ var coreStream = gulp.src([
+ paths.src.templates,
+ '!*/**/*Partial.*'
+ ])
+ .pipe(stripbom({ showLog : false }))
+ .pipe(handlebars())
+ .pipe(declare({
+ namespace : 'T',
+ noRedeclare : true,
+ processName : function(filePath) {
+
+ filePath = path.relative(paths.src.root, filePath);
+
+ return filePath.replace(/\\/g, '/')
+ .toLocaleLowerCase()
+ .replace('template', '')
+ .replace('.js', '');
+ }
+ }));
+
+ var partialStream = gulp.src([paths.src.partials])
+ .pipe(stripbom({ showLog : false }))
+ .pipe(handlebars())
+ .pipe(wrap('Handlebars.template(<%= contents %>)'))
+ .pipe(wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, <%= contents %>)', {}, {
+ imports : {
+ processPartialName : function(fileName) {
+ return JSON.stringify(
+ path.basename(fileName, '.js')
+ );
+ }
+ }
+ }));
+
+ return streamqueue({ objectMode : true },
+ partialStream,
+ coreStream
+ ).pipe(concat('templates.js'))
+ .pipe(gulp.dest(paths.dest.root))
+ .pipe(livereload());
+});
diff --git a/gulp/imageMin.js b/gulp/imageMin.js
new file mode 100644
index 000000000..6c8236e03
--- /dev/null
+++ b/gulp/imageMin.js
@@ -0,0 +1,15 @@
+var gulp = require('gulp');
+var print = require('gulp-print');
+var paths = require('./paths.js');
+
+gulp.task('imageMin', function() {
+ var imagemin = require('gulp-imagemin');
+ return gulp.src(paths.src.images)
+ .pipe(imagemin({
+ progressive : false,
+ optimizationLevel : 4,
+ svgoPlugins : [{ removeViewBox : false }]
+ }))
+ .pipe(print())
+ .pipe(gulp.dest(paths.src.content + 'Images/'));
+});
\ No newline at end of file
diff --git a/gulp/jshint.js b/gulp/jshint.js
new file mode 100644
index 000000000..650ad02c2
--- /dev/null
+++ b/gulp/jshint.js
@@ -0,0 +1,15 @@
+var gulp = require('gulp');
+var jshint = require('gulp-jshint');
+var stylish = require('jshint-stylish');
+var cache = require('gulp-cached');
+var paths = require('./paths.js');
+
+gulp.task('jshint', function() {
+ return gulp.src([
+ paths.src.scripts,
+ paths.src.exclude.libs
+ ])
+ .pipe(cache('jshint'))
+ .pipe(jshint())
+ .pipe(jshint.reporter(stylish));
+});
diff --git a/gulp/less.js b/gulp/less.js
new file mode 100644
index 000000000..a1e008380
--- /dev/null
+++ b/gulp/less.js
@@ -0,0 +1,55 @@
+var gulp = require('gulp');
+
+var less = require('gulp-less');
+var postcss = require('gulp-postcss');
+var sourcemaps = require('gulp-sourcemaps');
+var autoprefixer = require('autoprefixer-core');
+var livereload = require('gulp-livereload');
+
+var print = require('gulp-print');
+var phantom = require('./phantom');
+var paths = require('./paths');
+var errorHandler = require('./errorHandler');
+
+gulp.task('less', function() {
+
+ var src = [
+ paths.src.content + 'bootstrap.less',
+ paths.src.content + 'theme.less',
+ paths.src.content + 'overrides.less',
+ paths.src.root + 'Series/series.less',
+ paths.src.root + 'Activity/activity.less',
+ paths.src.root + 'AddSeries/addSeries.less',
+ paths.src.root + 'Calendar/calendar.less',
+ paths.src.root + 'Cells/cells.less',
+ paths.src.root + 'ManualImport/manualimport.less',
+ paths.src.root + 'Settings/settings.less',
+ paths.src.root + 'System/Logs/logs.less',
+ paths.src.root + 'System/Update/update.less',
+ paths.src.root + 'System/Info/info.less'
+ ];
+
+ if (phantom) {
+ src = [
+ paths.src.content + 'Bootstrap/bootstrap.less',
+ paths.src.content + 'Vendor/vendor.less',
+ paths.src.content + 'sonarr.less'
+ ];
+ }
+
+ return gulp.src(src)
+ .pipe(print())
+ .pipe(sourcemaps.init())
+ .pipe(less({
+ dumpLineNumbers : 'false',
+ compress : true,
+ yuicompress : true,
+ ieCompat : true,
+ strictImports : true
+ }))
+ .pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
+ .on('error', errorHandler.onError)
+ .pipe(sourcemaps.write(paths.dest.content))
+ .pipe(gulp.dest(paths.dest.content))
+ .pipe(livereload());
+});
diff --git a/gulp/paths.js b/gulp/paths.js
new file mode 100644
index 000000000..c9fc7711d
--- /dev/null
+++ b/gulp/paths.js
@@ -0,0 +1,45 @@
+var phantom = require('./phantom');
+
+var paths = {
+ src : {
+ root : './src/UI/',
+ templates : './src/UI/**/*.hbs',
+ html : './src/UI/*.html',
+ partials : './src/UI/**/*Partial.hbs',
+ scripts : './src/UI/**/*.js',
+ less : ['./src/UI/**/*.less'],
+ content : './src/UI/Content/',
+ images : './src/UI/Content/Images/**/*',
+ exclude : {
+ libs : '!./src/UI/JsLibraries/**'
+ }
+ },
+ dest : {
+ root : './_output/UI/',
+ content : './_output/UI/Content/'
+ }
+};
+
+if (phantom) {
+ paths = {
+ src : {
+ root : './UI.Phantom/',
+ templates : './UI.Phantom/**/*.hbs',
+ html : './UI.Phantom/*.html',
+ partials : './UI.Phantom/**/*Partial.hbs',
+ scripts : './UI.Phantom/**/*.js',
+ less : ['./UI.Phantom/**/*.less'],
+ content : './UI.Phantom/Content/',
+ images : './UI.Phantom/Content/Images/**/*',
+ exclude : {
+ libs : '!./UI.Phantom/JsLibraries/**'
+ }
+ },
+ dest : {
+ root : './_output/UI.Phantom/',
+ content : './_output/UI.Phantom/Content/'
+ }
+ };
+}
+
+module.exports = paths;
diff --git a/gulp/phantom.js b/gulp/phantom.js
new file mode 100644
index 000000000..54c0620e5
--- /dev/null
+++ b/gulp/phantom.js
@@ -0,0 +1,14 @@
+// Switch to phantom.
+// Example:
+// gulp --phantom
+
+var phantom = false;
+process.argv.forEach(function(val, index, array) {
+ if (val === '--phantom') {
+ phantom = true;
+ }
+});
+
+console.log('Phantom:', phantom);
+
+module.exports = phantom;
\ No newline at end of file
diff --git a/gulp/start.js b/gulp/start.js
new file mode 100644
index 000000000..5b5f88044
--- /dev/null
+++ b/gulp/start.js
@@ -0,0 +1,112 @@
+// will download and run sonarr (server) in a non-windows enviroment
+// you can use this if you don't care about the server code and just want to work
+// with the web code.
+
+var http = require('http');
+var gulp = require('gulp');
+var fs = require('fs');
+var targz = require('tar.gz');
+var del = require('del');
+var print = require('gulp-print');
+var spawn = require('child_process').spawn;
+
+function download(url, dest, cb) {
+ console.log('Downloading ' + url + ' to ' + dest);
+ var file = fs.createWriteStream(dest);
+ var request = http.get(url, function (response) {
+ response.pipe(file);
+ file.on('finish', function () {
+ console.log('Download completed');
+ file.close(cb);
+ });
+ });
+}
+
+function getLatest(cb) {
+ var branch = 'develop';
+ process.argv.forEach(function (val) {
+ var branchMatch = /branch=([\S]*)/.exec(val);
+ if (branchMatch && branchMatch.length > 1) {
+ branch = branchMatch[1];
+ }
+ });
+
+ var url = 'http://services.sonarr.tv/v1/update/' + branch + '?os=osx';
+
+ console.log('Checking for latest version:', url);
+
+ http.get(url, function (res) {
+ var data = '';
+
+ res.on('data', function (chunk) {
+ data += chunk;
+ });
+
+ res.on('end', function () {
+ var updatePackage = JSON.parse(data).updatePackage;
+ console.log('Latest version available: ' + updatePackage.version + ' Release Date: ' + updatePackage.releaseDate);
+ cb(updatePackage);
+ });
+ }).on('error', function (e) {
+ console.log('problem with request: ' + e.message);
+ });
+}
+
+function extract(source, dest, cb) {
+ console.log('extracting download page to ' + dest);
+ new targz().extract(source, dest, function (err) {
+ if (err) {
+ console.log(err);
+ }
+ console.log('Update package extracted.');
+ cb();
+ });
+}
+
+gulp.task('getSonarr', function () {
+
+ //gulp.src('/Users/kayone/git/Sonarr/_start/2.0.0.3288/NzbDrone/*.*')
+ // .pipe(print())
+ // .pipe(gulp.dest('./_output
+
+ //return;
+ try {
+ fs.mkdirSync('./_start/');
+ } catch (e) {
+ if (e.code != 'EEXIST') {
+ throw e;
+ }
+ }
+
+ getLatest(function (package) {
+ var packagePath = "./_start/" + package.filename;
+ var dirName = "./_start/" + package.version;
+ download(package.url, packagePath, function () {
+ extract(packagePath, dirName, function () {
+ // clean old binaries
+ console.log('Cleaning old binaries');
+ del.sync(['./_output/*', '!./_output/UI/']);
+ console.log('copying binaries to target');
+ gulp.src(dirName + '/NzbDrone/*.*')
+ .pipe(gulp.dest('./_output/'));
+ });
+ });
+ });
+});
+
+gulp.task('startSonarr', function () {
+
+ var ls = spawn('mono', ['--debug', './_output/NzbDrone.exe']);
+
+ ls.stdout.on('data', function (data) {
+ process.stdout.write('' + data);
+ });
+
+ ls.stderr.on('data', function (data) {
+ process.stdout.write('' + data);
+ });
+
+ ls.on('close', function (code) {
+ console.log('child process exited with code ' + code);
+ });
+});
diff --git a/gulp/stripBom.js b/gulp/stripBom.js
new file mode 100644
index 000000000..085e6b753
--- /dev/null
+++ b/gulp/stripBom.js
@@ -0,0 +1,21 @@
+var gulp = require('gulp');
+var paths = require('./paths.js');
+var stripbom = require('gulp-stripbom');
+
+var stripBom = function (dest) {
+ gulp.src([paths.src.scripts, paths.src.exclude.libs])
+ .pipe(stripbom({ showLog: false }))
+ .pipe(gulp.dest(dest));
+
+ gulp.src(paths.src.less)
+ .pipe(stripbom({ showLog: false }))
+ .pipe(gulp.dest(dest));
+
+ gulp.src(paths.src.templates)
+ .pipe(stripbom({ showLog: false }))
+ .pipe(gulp.dest(dest));
+};
+
+gulp.task('stripBom', function () {
+ stripBom(paths.src.root);
+});
diff --git a/gulp/watch.js b/gulp/watch.js
new file mode 100644
index 000000000..f9145a464
--- /dev/null
+++ b/gulp/watch.js
@@ -0,0 +1,20 @@
+var gulp = require('gulp');
+var livereload = require('gulp-livereload');
+
+var paths = require('./paths.js');
+
+require('./jshint.js');
+require('./handlebars.js');
+require('./less.js');
+require('./copy.js');
+require('./webpack.js');
+
+gulp.task('watch', ['jshint', 'handlebars', 'less', 'copyHtml', 'copyContent', 'copyJs'], function () {
+ livereload.listen();
+ gulp.start('webpackWatch');
+ gulp.watch([paths.src.scripts, paths.src.exclude.libs], ['jshint', 'copyJs']);
+ gulp.watch(paths.src.templates, ['handlebars']);
+ gulp.watch([paths.src.less, paths.src.exclude.libs], ['less']);
+ gulp.watch([paths.src.html], ['copyHtml']);
+ gulp.watch([paths.src.content + '**/*.*', '!**/*.less'], ['copyContent']);
+});
\ No newline at end of file
diff --git a/gulp/webpack.js b/gulp/webpack.js
new file mode 100644
index 000000000..64570593c
--- /dev/null
+++ b/gulp/webpack.js
@@ -0,0 +1,13 @@
+var gulp = require('gulp');
+var webpackStream = require('webpack-stream');
+var livereload = require('gulp-livereload');
+var webpackConfig = require('../webpack.config');
+
+gulp.task('webpack', function() {
+ return gulp.src('main.js').pipe(webpackStream(webpackConfig)).pipe(gulp.dest(''));
+});
+
+gulp.task('webpackWatch', function() {
+ webpackConfig.watch = true;
+ return gulp.src('main.js').pipe(webpackStream(webpackConfig)).pipe(gulp.dest('')).pipe(livereload());
+});
diff --git a/gulpFile.js b/gulpFile.js
new file mode 100644
index 000000000..28dc9b0f1
--- /dev/null
+++ b/gulpFile.js
@@ -0,0 +1 @@
+require('./gulp/gulpFile.js');
diff --git a/integration_mono.sh b/integration_mono.sh
new file mode 100644
index 000000000..1df48b91f
--- /dev/null
+++ b/integration_mono.sh
@@ -0,0 +1,8 @@
+EXCLUDE="-exclude:Windows -include:IntegrationTest"
+TESTDIR="."
+NUNIT="$TESTDIR/NUnit.Runners.2.6.1/tools/nunit-console-x86.exe"
+
+mono --debug --runtime=v4.0 $NUNIT $EXCLUDE -xml:NzbDrone.Api.Result.xml $TESTDIR/NzbDrone.Api.Test.dll
+mono --debug --runtime=v4.0 $NUNIT $EXCLUDE -xml:NzbDrone.Core.Result.xml $TESTDIR/NzbDrone.Core.Test.dll
+mono --debug --runtime=v4.0 $NUNIT $EXCLUDE -xml:NzbDrone.Integration.Result.xml $TESTDIR/NzbDrone.Integration.Test.dll
+mono --debug --runtime=v4.0 $NUNIT $EXCLUDE -xml:NzbDrone.Common.Result.xml $TESTDIR/NzbDrone.Common.Test.dll
diff --git a/osx/Sonarr b/osx/Sonarr
new file mode 100644
index 000000000..d2de60a86
--- /dev/null
+++ b/osx/Sonarr
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#get the bundle's MacOS directory full path
+DIR=$(cd "$(dirname "$0")"; pwd)
+
+#change these values to match your app
+EXE_PATH="$DIR/NzbDrone.exe"
+APPNAME="Sonarr"
+
+#set up environment
+MONO_FRAMEWORK_PATH=/Library/Frameworks/Mono.framework/Versions/Current
+export DYLD_FALLBACK_LIBRARY_PATH="$DIR:$MONO_FRAMEWORK_PATH/lib:/lib:/usr/lib"
+export PATH="$MONO_FRAMEWORK_PATH/bin:$PATH"
+
+#mono version check
+REQUIRED_MAJOR=3
+REQUIRED_MINOR=10
+
+VERSION_TITLE="Cannot launch $APPNAME"
+VERSION_MSG="$APPNAME requires Mono Runtime Environment(MRE) $REQUIRED_MAJOR.$REQUIRED_MINOR or later."
+DOWNLOAD_URL="http://www.mono-project.com/download/#download-mac"
+
+MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )"
+MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)"
+MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)"
+if [ -z "$MONO_VERSION" ] \
+ || [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \
+ || [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ]
+then
+ osascript \
+ -e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \
+ -e "if button returned of question is equal to \"Download...\" then open location \"$DOWNLOAD_URL\""
+ echo "$VERSION_TITLE"
+ echo "$VERSION_MSG"
+ exit 1
+fi
+
+MONO_EXEC="exec mono --debug"
+
+#run app using mono
+$MONO_EXEC "$EXE_PATH"
\ No newline at end of file
diff --git a/distribution/osx/Lidarr.app/Contents/Info.plist b/osx/Sonarr.app/Contents/Info.plist
similarity index 83%
rename from distribution/osx/Lidarr.app/Contents/Info.plist
rename to osx/Sonarr.app/Contents/Info.plist
index 6e4706fea..eeae50f41 100644
--- a/distribution/osx/Lidarr.app/Contents/Info.plist
+++ b/osx/Sonarr.app/Contents/Info.plist
@@ -11,23 +11,23 @@
CFBundleDevelopmentRegion
English
CFBundleExecutable
- Lidarr
+ Sonarr
CFBundleIconFile
- lidarr.icns
+ sonarr.icns
CFBundleIdentifier
- com.osx.lidarr.audio
+ com.osx.sonarr.tv
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- Lidarr
+ Sonarr
CFBundlePackageType
APPL
CFBundleShortVersionString
- 10.0.0.0
+ 2.0
CFBundleSignature
xmmd
CFBundleVersion
- 10.0.0.0
+ 2.0
NSAppleScriptEnabled
YES
diff --git a/osx/Sonarr.app/Contents/Resources/sonarr.icns b/osx/Sonarr.app/Contents/Resources/sonarr.icns
new file mode 100644
index 000000000..884633ff3
Binary files /dev/null and b/osx/Sonarr.app/Contents/Resources/sonarr.icns differ
diff --git a/package.json b/package.json
index 642d79a12..0d0f0e893 100644
--- a/package.json
+++ b/package.json
@@ -1,155 +1,45 @@
{
- "name": "lidarr",
- "version": "1.0.0",
- "description": "Lidarr",
+ "name": "Sonarr",
+ "version": "2.0.0",
+ "description": "Sonarr",
+ "main": "main.js",
"scripts": {
- "build": "webpack --config ./frontend/build/webpack.config.js",
- "prebuild": "yarn clean",
- "clean": "rimraf ./_output/UI && rimraf --glob \"**/*.js.map\"",
- "start": "webpack --watch --config ./frontend/build/webpack.config.js",
- "watch": "webpack --watch --config ./frontend/build/webpack.config.js",
- "lint": "eslint --config frontend/.eslintrc.js --ignore-path frontend/.eslintignore frontend/",
- "lint-fix": "yarn lint --fix",
- "stylelint-linux": "stylelint $(find frontend -name '*.css') --config frontend/.stylelintrc",
- "stylelint-windows": "stylelint \"frontend/**/*.css\" --config frontend/.stylelintrc"
+ "preinstall": ""
},
"repository": {
"type": "git",
- "url": "git://github.com/Lidarr/Lidarr.git"
+ "url": "git://github.com/Sonarr/Sonarr.git"
},
- "author": "Team Lidarr",
- "license": "GPL-3.0",
+ "author": "",
+ "license": "BSD",
+ "gitHead": "9ff7aa1bf7fe38c4c5bdb92f56c8ad556916ed67",
"readmeFilename": "readme.md",
- "main": "index.ts",
- "browserslist": [
- "defaults"
- ],
"dependencies": {
- "@fortawesome/fontawesome-free": "6.7.1",
- "@fortawesome/fontawesome-svg-core": "6.7.1",
- "@fortawesome/free-regular-svg-icons": "6.7.1",
- "@fortawesome/free-solid-svg-icons": "6.7.1",
- "@fortawesome/react-fontawesome": "0.2.2",
- "@juggle/resize-observer": "3.4.0",
- "@microsoft/signalr": "6.0.25",
- "@sentry/browser": "7.119.1",
- "@sentry/integrations": "7.119.1",
- "@types/node": "20.16.11",
- "@types/react": "18.3.12",
- "@types/react-dom": "18.3.1",
- "classnames": "2.5.1",
- "clipboard": "2.0.11",
- "connected-react-router": "6.9.3",
- "element-class": "0.2.2",
- "filesize": "10.1.6",
- "fuse.js": "6.6.2",
- "history": "4.10.1",
- "jdu": "1.0.0",
- "jquery": "3.7.1",
- "lodash": "4.17.21",
- "mobile-detect": "1.4.5",
- "moment": "2.30.1",
- "mousetrap": "1.6.5",
- "normalize.css": "8.0.1",
- "prop-types": "15.8.1",
- "qs": "6.13.0",
- "react": "18.3.1",
- "react-addons-shallow-compare": "15.6.3",
- "react-async-script": "1.2.0",
- "react-autosuggest": "10.1.0",
- "react-custom-scrollbars-2": "4.5.0",
- "react-dnd": "14.0.4",
- "react-dnd-html5-backend": "14.0.2",
- "react-dnd-multi-backend": "6.0.2",
- "react-dnd-touch-backend": "14.1.1",
- "react-document-title": "2.0.3",
- "react-dom": "18.3.1",
- "react-focus-lock": "2.9.4",
- "react-google-recaptcha": "2.1.0",
- "react-lazyload": "3.2.0",
- "react-measure": "1.4.7",
- "react-middle-truncate": "1.0.3",
- "react-popper": "1.3.7",
- "react-redux": "7.2.4",
- "react-router": "5.2.0",
- "react-router-dom": "5.2.0",
- "react-slider": "1.1.4",
- "react-tabs": "4.3.0",
- "react-text-truncate": "0.19.0",
- "react-use-measure": "2.1.1",
- "react-virtualized": "9.21.1",
- "react-window": "1.8.10",
- "redux": "4.2.1",
- "redux-actions": "2.6.5",
- "redux-batched-actions": "0.5.0",
- "redux-localstorage": "0.4.1",
- "redux-thunk": "2.4.2",
- "reselect": "4.1.8",
- "stacktrace-js": "2.0.2",
- "typescript": "5.7.2"
- },
- "devDependencies": {
- "@babel/core": "7.26.0",
- "@babel/eslint-parser": "7.25.9",
- "@babel/plugin-proposal-export-default-from": "7.25.9",
- "@babel/plugin-syntax-dynamic-import": "7.8.3",
- "@babel/preset-env": "7.26.0",
- "@babel/preset-react": "7.26.3",
- "@babel/preset-typescript": "7.26.0",
- "@types/lodash": "4.14.195",
- "@types/react-lazyload": "3.2.3",
- "@types/react-router-dom": "5.3.3",
- "@types/react-text-truncate": "0.19.0",
- "@types/react-window": "1.8.8",
- "@types/redux-actions": "2.6.5",
- "@types/webpack-livereload-plugin": "2.3.6",
- "@typescript-eslint/eslint-plugin": "8.18.1",
- "@typescript-eslint/parser": "8.18.1",
- "autoprefixer": "10.4.20",
- "babel-loader": "9.2.1",
- "babel-plugin-inline-classnames": "2.0.1",
- "babel-plugin-transform-react-remove-prop-types": "0.4.24",
- "core-js": "3.41.0",
- "css-loader": "6.7.3",
- "css-modules-typescript-loader": "4.0.1",
- "eslint": "8.57.1",
- "eslint-config-prettier": "8.10.0",
- "eslint-plugin-filenames": "1.3.2",
- "eslint-plugin-import": "2.31.0",
- "eslint-plugin-prettier": "4.2.1",
- "eslint-plugin-react": "7.37.1",
- "eslint-plugin-react-hooks": "4.6.2",
- "eslint-plugin-simple-import-sort": "12.1.1",
- "file-loader": "6.2.0",
- "filemanager-webpack-plugin": "8.0.0",
- "fork-ts-checker-webpack-plugin": "8.0.0",
- "html-webpack-plugin": "5.6.0",
- "loader-utils": "^3.2.1",
- "mini-css-extract-plugin": "2.9.1",
- "postcss": "8.4.47",
- "postcss-color-function": "4.1.0",
- "postcss-loader": "7.3.0",
- "postcss-mixins": "9.0.4",
- "postcss-nested": "6.2.0",
- "postcss-simple-vars": "7.0.1",
- "postcss-url": "10.1.3",
- "prettier": "2.8.8",
- "require-nocache": "1.0.0",
- "rimraf": "6.0.1",
- "style-loader": "3.3.2",
- "stylelint": "15.6.1",
- "stylelint-order": "6.0.4",
- "terser-webpack-plugin": "5.3.10",
- "ts-loader": "9.5.1",
- "typescript-plugin-css-modules": "5.0.1",
- "url-loader": "4.1.1",
- "webpack": "5.95.0",
- "webpack-cli": "5.1.4",
- "webpack-livereload-plugin": "3.0.2",
- "worker-loader": "3.0.8"
- },
- "volta": {
- "node": "16.17.0",
- "yarn": "1.22.19"
+ "autoprefixer-core": "5.2.1",
+ "del": "1.2.0",
+ "gulp": "3.9.0",
+ "gulp-cached": "1.1.0",
+ "gulp-concat": "2.6.0",
+ "gulp-declare": "0.3.0",
+ "gulp-handlebars": "3.0.1",
+ "gulp-jshint": "1.11.2",
+ "gulp-less": "3.0.3",
+ "gulp-livereload": "3.8.0",
+ "gulp-postcss": "6.0.0",
+ "gulp-print": "1.1.0",
+ "gulp-replace": "0.5.3",
+ "gulp-run": "1.6.8",
+ "gulp-sourcemaps": "1.5.2",
+ "gulp-stripbom": "1.0.4",
+ "gulp-webpack": "1.5.0",
+ "gulp-wrap": "0.11.0",
+ "handlebars": "3.0.3",
+ "jshint-loader": "0.8.3",
+ "jshint-stylish": "2.0.1",
+ "run-sequence": "1.1.1",
+ "streamqueue": "1.1.0",
+ "tar.gz": "0.1.1",
+ "webpack": "1.12.0",
+ "webpack-stream": "2.1.0"
}
}
diff --git a/readme.md b/readme.md
new file mode 100644
index 000000000..327c05e86
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,55 @@
+# Sonarr #
+
+
+Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.
+
+## Major Features Include: ##
+
+* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
+* Automatically detects new episodes
+* Can scan your existing library and download any missing episodes
+* Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
+* Automatic failed download handling will try another release if one fails
+* Manual search so you can pick any release or to see why a release was not downloaded automatically
+* Fully configurable episode renaming
+* Full integration with SABNzbd and NzbGet
+* Full integration with XBMC, Plex (notification, library update, metadata)
+* Full support for specials and multi-episode releases
+* And a beautiful UI
+
+
+## Configuring Development Environment: ##
+
+### Requirements ###
+- Visual Studio 2013 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
+- [Git](http://git-scm.com/downloads)
+- [NodeJS](http://nodejs.org/download/)
+- [Gulp](http://gulpjs.com)
+
+### Setup ###
+
+- Make sure all the required software mentioned above are installed.
+- Clone the repository into your development machine. [*info*](https://help.github.com/articles/working-with-repositories)
+- Grab the submodules `git submodule init && git submodule update`
+- install the required Node Packages `npm install`
+- install gulp `npm install gulp -g`
+- start gulp to monitor your dev environment for any changes that need post processing using `gulp watch` command.
+
+*Please note gulp must be running at all times while you are working with Sonarr client source files.*
+
+
+### Development ###
+- Open `NzbDrone.sln` in Visual Studio
+- Make sure `NzbDrone.Console` is set as the startup project
+
+
+### License ###
+* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
+Copyright 2010-2015
+
+
+### Sponsors ###
+- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
+ - [ReSharper](http://www.jetbrains.com/resharper/)
+ - [WebStorm](http://www.jetbrains.com/webstorm/)
+ - [TeamCity](http://www.jetbrains.com/teamcity/)
diff --git a/rename.ps1 b/rename.ps1
new file mode 100644
index 000000000..c28c97a92
--- /dev/null
+++ b/rename.ps1
@@ -0,0 +1,17 @@
+Param(
+ [Parameter(Mandatory=$true, Position=0, HelpMessage="A branch name is #requires required")]
+ [string]$branch,
+ [Parameter(Mandatory=$true, Position=1, HelpMessage="A version is required")]
+ [string]$version
+)
+
+if ($branch -eq "")
+{
+ $branch = "teamcity";
+}
+
+Write-Host $branch;
+Write-Host $version;
+Write-Host "NzbDrone.$branch.$version.zip";
+
+Rename-Item "nzbdrone.zip" "NzbDrone.$branch.$version.zip"
\ No newline at end of file
diff --git a/schemas/torznab.xsd b/schemas/torznab.xsd
index 9c772c9da..810711ee6 100644
--- a/schemas/torznab.xsd
+++ b/schemas/torznab.xsd
@@ -75,8 +75,6 @@
-
-
diff --git a/setup/build.bat b/setup/build.bat
new file mode 100644
index 000000000..1821e5844
--- /dev/null
+++ b/setup/build.bat
@@ -0,0 +1,3 @@
+#SET BUILD_NUMBER=1
+#SET branch=develop
+inno\ISCC.exe nzbdrone.iss
\ No newline at end of file
diff --git a/setup/inno/Default.isl b/setup/inno/Default.isl
new file mode 100644
index 000000000..b417cf916
--- /dev/null
+++ b/setup/inno/Default.isl
@@ -0,0 +1,336 @@
+; *** Inno Setup version 5.5.3+ English messages ***
+;
+; To download user-contributed translations of this file, go to:
+; http://www.jrsoftware.org/files/istrans/
+;
+; Note: When translating this text, do not add periods (.) to the end of
+; messages that didn't have them already, because on those messages Inno
+; Setup adds the periods automatically (appending a period would result in
+; two periods being displayed).
+
+[LangOptions]
+; The following three entries are very important. Be sure to read and
+; understand the '[LangOptions] section' topic in the help file.
+LanguageName=English
+LanguageID=$0409
+LanguageCodePage=0
+; If the language you are translating to requires special font faces or
+; sizes, uncomment any of the following entries and change them accordingly.
+;DialogFontName=
+;DialogFontSize=8
+;WelcomeFontName=Verdana
+;WelcomeFontSize=12
+;TitleFontName=Arial
+;TitleFontSize=29
+;CopyrightFontName=Arial
+;CopyrightFontSize=8
+
+[Messages]
+
+; *** Application titles
+SetupAppTitle=Setup
+SetupWindowTitle=Setup - %1
+UninstallAppTitle=Uninstall
+UninstallAppFullTitle=%1 Uninstall
+
+; *** Misc. common
+InformationTitle=Information
+ConfirmTitle=Confirm
+ErrorTitle=Error
+
+; *** SetupLdr messages
+SetupLdrStartupMessage=This will install %1. Do you wish to continue?
+LdrCannotCreateTemp=Unable to create a temporary file. Setup aborted
+LdrCannotExecTemp=Unable to execute file in the temporary directory. Setup aborted
+
+; *** Startup error messages
+LastErrorMessage=%1.%n%nError %2: %3
+SetupFileMissing=The file %1 is missing from the installation directory. Please correct the problem or obtain a new copy of the program.
+SetupFileCorrupt=The setup files are corrupted. Please obtain a new copy of the program.
+SetupFileCorruptOrWrongVer=The setup files are corrupted, or are incompatible with this version of Setup. Please correct the problem or obtain a new copy of the program.
+InvalidParameter=An invalid parameter was passed on the command line:%n%n%1
+SetupAlreadyRunning=Setup is already running.
+WindowsVersionNotSupported=This program does not support the version of Windows your computer is running.
+WindowsServicePackRequired=This program requires %1 Service Pack %2 or later.
+NotOnThisPlatform=This program will not run on %1.
+OnlyOnThisPlatform=This program must be run on %1.
+OnlyOnTheseArchitectures=This program can only be installed on versions of Windows designed for the following processor architectures:%n%n%1
+MissingWOW64APIs=The version of Windows you are running does not include functionality required by Setup to perform a 64-bit installation. To correct this problem, please install Service Pack %1.
+WinVersionTooLowError=This program requires %1 version %2 or later.
+WinVersionTooHighError=This program cannot be installed on %1 version %2 or later.
+AdminPrivilegesRequired=You must be logged in as an administrator when installing this program.
+PowerUserPrivilegesRequired=You must be logged in as an administrator or as a member of the Power Users group when installing this program.
+SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
+UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit.
+
+; *** Misc. errors
+ErrorCreatingDir=Setup was unable to create the directory "%1"
+ErrorTooManyFilesInDir=Unable to create a file in the directory "%1" because it contains too many files
+
+; *** Setup common messages
+ExitSetupTitle=Exit Setup
+ExitSetupMessage=Setup is not complete. If you exit now, the program will not be installed.%n%nYou may run Setup again at another time to complete the installation.%n%nExit Setup?
+AboutSetupMenuItem=&About Setup...
+AboutSetupTitle=About Setup
+AboutSetupMessage=%1 version %2%n%3%n%n%1 home page:%n%4
+AboutSetupNote=
+TranslatorNote=
+
+; *** Buttons
+ButtonBack=< &Back
+ButtonNext=&Next >
+ButtonInstall=&Install
+ButtonOK=OK
+ButtonCancel=Cancel
+ButtonYes=&Yes
+ButtonYesToAll=Yes to &All
+ButtonNo=&No
+ButtonNoToAll=N&o to All
+ButtonFinish=&Finish
+ButtonBrowse=&Browse...
+ButtonWizardBrowse=B&rowse...
+ButtonNewFolder=&Make New Folder
+
+; *** "Select Language" dialog messages
+SelectLanguageTitle=Select Setup Language
+SelectLanguageLabel=Select the language to use during the installation:
+
+; *** Common wizard text
+ClickNext=Click Next to continue, or Cancel to exit Setup.
+BeveledLabel=
+BrowseDialogTitle=Browse For Folder
+BrowseDialogLabel=Select a folder in the list below, then click OK.
+NewFolderName=New Folder
+
+; *** "Welcome" wizard page
+WelcomeLabel1=Welcome to the [name] Setup Wizard
+WelcomeLabel2=This will install [name/ver] on your computer.%n%nIt is recommended that you close all other applications before continuing.
+
+; *** "Password" wizard page
+WizardPassword=Password
+PasswordLabel1=This installation is password protected.
+PasswordLabel3=Please provide the password, then click Next to continue. Passwords are case-sensitive.
+PasswordEditLabel=&Password:
+IncorrectPassword=The password you entered is not correct. Please try again.
+
+; *** "License Agreement" wizard page
+WizardLicense=License Agreement
+LicenseLabel=Please read the following important information before continuing.
+LicenseLabel3=Please read the following License Agreement. You must accept the terms of this agreement before continuing with the installation.
+LicenseAccepted=I &accept the agreement
+LicenseNotAccepted=I &do not accept the agreement
+
+; *** "Information" wizard pages
+WizardInfoBefore=Information
+InfoBeforeLabel=Please read the following important information before continuing.
+InfoBeforeClickLabel=When you are ready to continue with Setup, click Next.
+WizardInfoAfter=Information
+InfoAfterLabel=Please read the following important information before continuing.
+InfoAfterClickLabel=When you are ready to continue with Setup, click Next.
+
+; *** "User Information" wizard page
+WizardUserInfo=User Information
+UserInfoDesc=Please enter your information.
+UserInfoName=&User Name:
+UserInfoOrg=&Organization:
+UserInfoSerial=&Serial Number:
+UserInfoNameRequired=You must enter a name.
+
+; *** "Select Destination Location" wizard page
+WizardSelectDir=Select Destination Location
+SelectDirDesc=Where should [name] be installed?
+SelectDirLabel3=Setup will install [name] into the following folder.
+SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse.
+DiskSpaceMBLabel=At least [mb] MB of free disk space is required.
+CannotInstallToNetworkDrive=Setup cannot install to a network drive.
+CannotInstallToUNCPath=Setup cannot install to a UNC path.
+InvalidPath=You must enter a full path with drive letter; for example:%n%nC:\APP%n%nor a UNC path in the form:%n%n\\server\share
+InvalidDrive=The drive or UNC share you selected does not exist or is not accessible. Please select another.
+DiskSpaceWarningTitle=Not Enough Disk Space
+DiskSpaceWarning=Setup requires at least %1 KB of free space to install, but the selected drive only has %2 KB available.%n%nDo you want to continue anyway?
+DirNameTooLong=The folder name or path is too long.
+InvalidDirName=The folder name is not valid.
+BadDirName32=Folder names cannot include any of the following characters:%n%n%1
+DirExistsTitle=Folder Exists
+DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway?
+DirDoesntExistTitle=Folder Does Not Exist
+DirDoesntExist=The folder:%n%n%1%n%ndoes not exist. Would you like the folder to be created?
+
+; *** "Select Components" wizard page
+WizardSelectComponents=Select Components
+SelectComponentsDesc=Which components should be installed?
+SelectComponentsLabel2=Select the components you want to install; clear the components you do not want to install. Click Next when you are ready to continue.
+FullInstallation=Full installation
+; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language)
+CompactInstallation=Compact installation
+CustomInstallation=Custom installation
+NoUninstallWarningTitle=Components Exist
+NoUninstallWarning=Setup has detected that the following components are already installed on your computer:%n%n%1%n%nDeselecting these components will not uninstall them.%n%nWould you like to continue anyway?
+ComponentSize1=%1 KB
+ComponentSize2=%1 MB
+ComponentsDiskSpaceMBLabel=Current selection requires at least [mb] MB of disk space.
+
+; *** "Select Additional Tasks" wizard page
+WizardSelectTasks=Select Additional Tasks
+SelectTasksDesc=Which additional tasks should be performed?
+SelectTasksLabel2=Select the additional tasks you would like Setup to perform while installing [name], then click Next.
+
+; *** "Select Start Menu Folder" wizard page
+WizardSelectProgramGroup=Select Start Menu Folder
+SelectStartMenuFolderDesc=Where should Setup place the program's shortcuts?
+SelectStartMenuFolderLabel3=Setup will create the program's shortcuts in the following Start Menu folder.
+SelectStartMenuFolderBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse.
+MustEnterGroupName=You must enter a folder name.
+GroupNameTooLong=The folder name or path is too long.
+InvalidGroupName=The folder name is not valid.
+BadGroupName=The folder name cannot include any of the following characters:%n%n%1
+NoProgramGroupCheck2=&Don't create a Start Menu folder
+
+; *** "Ready to Install" wizard page
+WizardReady=Ready to Install
+ReadyLabel1=Setup is now ready to begin installing [name] on your computer.
+ReadyLabel2a=Click Install to continue with the installation, or click Back if you want to review or change any settings.
+ReadyLabel2b=Click Install to continue with the installation.
+ReadyMemoUserInfo=User information:
+ReadyMemoDir=Destination location:
+ReadyMemoType=Setup type:
+ReadyMemoComponents=Selected components:
+ReadyMemoGroup=Start Menu folder:
+ReadyMemoTasks=Additional tasks:
+
+; *** "Preparing to Install" wizard page
+WizardPreparing=Preparing to Install
+PreparingDesc=Setup is preparing to install [name] on your computer.
+PreviousInstallNotCompleted=The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.%n%nAfter restarting your computer, run Setup again to complete the installation of [name].
+CannotContinue=Setup cannot continue. Please click Cancel to exit.
+ApplicationsFound=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications.
+ApplicationsFound2=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. After the installation has completed, Setup will attempt to restart the applications.
+CloseApplications=&Automatically close the applications
+DontCloseApplications=&Do not close the applications
+ErrorCloseApplications=Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing.
+
+; *** "Installing" wizard page
+WizardInstalling=Installing
+InstallingLabel=Please wait while Setup installs [name] on your computer.
+
+; *** "Setup Completed" wizard page
+FinishedHeadingLabel=Completing the [name] Setup Wizard
+FinishedLabelNoIcons=Setup has finished installing [name] on your computer.
+FinishedLabel=Setup has finished installing [name] on your computer. The application may be launched by selecting the installed icons.
+ClickFinish=Click Finish to exit Setup.
+FinishedRestartLabel=To complete the installation of [name], Setup must restart your computer. Would you like to restart now?
+FinishedRestartMessage=To complete the installation of [name], Setup must restart your computer.%n%nWould you like to restart now?
+ShowReadmeCheck=Yes, I would like to view the README file
+YesRadio=&Yes, restart the computer now
+NoRadio=&No, I will restart the computer later
+; used for example as 'Run MyProg.exe'
+RunEntryExec=Run %1
+; used for example as 'View Readme.txt'
+RunEntryShellExec=View %1
+
+; *** "Setup Needs the Next Disk" stuff
+ChangeDiskTitle=Setup Needs the Next Disk
+SelectDiskLabel2=Please insert Disk %1 and click OK.%n%nIf the files on this disk can be found in a folder other than the one displayed below, enter the correct path or click Browse.
+PathLabel=&Path:
+FileNotInDir2=The file "%1" could not be located in "%2". Please insert the correct disk or select another folder.
+SelectDirectoryLabel=Please specify the location of the next disk.
+
+; *** Installation phase messages
+SetupAborted=Setup was not completed.%n%nPlease correct the problem and run Setup again.
+EntryAbortRetryIgnore=Click Retry to try again, Ignore to proceed anyway, or Abort to cancel installation.
+
+; *** Installation status messages
+StatusClosingApplications=Closing applications...
+StatusCreateDirs=Creating directories...
+StatusExtractFiles=Extracting files...
+StatusCreateIcons=Creating shortcuts...
+StatusCreateIniEntries=Creating INI entries...
+StatusCreateRegistryEntries=Creating registry entries...
+StatusRegisterFiles=Registering files...
+StatusSavingUninstall=Saving uninstall information...
+StatusRunProgram=Finishing installation...
+StatusRestartingApplications=Restarting applications...
+StatusRollback=Rolling back changes...
+
+; *** Misc. errors
+ErrorInternal2=Internal error: %1
+ErrorFunctionFailedNoCode=%1 failed
+ErrorFunctionFailed=%1 failed; code %2
+ErrorFunctionFailedWithMessage=%1 failed; code %2.%n%3
+ErrorExecutingProgram=Unable to execute file:%n%1
+
+; *** Registry errors
+ErrorRegOpenKey=Error opening registry key:%n%1\%2
+ErrorRegCreateKey=Error creating registry key:%n%1\%2
+ErrorRegWriteKey=Error writing to registry key:%n%1\%2
+
+; *** INI errors
+ErrorIniEntry=Error creating INI entry in file "%1".
+
+; *** File copying errors
+FileAbortRetryIgnore=Click Retry to try again, Ignore to skip this file (not recommended), or Abort to cancel installation.
+FileAbortRetryIgnore2=Click Retry to try again, Ignore to proceed anyway (not recommended), or Abort to cancel installation.
+SourceIsCorrupted=The source file is corrupted
+SourceDoesntExist=The source file "%1" does not exist
+ExistingFileReadOnly=The existing file is marked as read-only.%n%nClick Retry to remove the read-only attribute and try again, Ignore to skip this file, or Abort to cancel installation.
+ErrorReadingExistingDest=An error occurred while trying to read the existing file:
+FileExists=The file already exists.%n%nWould you like Setup to overwrite it?
+ExistingFileNewer=The existing file is newer than the one Setup is trying to install. It is recommended that you keep the existing file.%n%nDo you want to keep the existing file?
+ErrorChangingAttr=An error occurred while trying to change the attributes of the existing file:
+ErrorCreatingTemp=An error occurred while trying to create a file in the destination directory:
+ErrorReadingSource=An error occurred while trying to read the source file:
+ErrorCopying=An error occurred while trying to copy a file:
+ErrorReplacingExistingFile=An error occurred while trying to replace the existing file:
+ErrorRestartReplace=RestartReplace failed:
+ErrorRenamingTemp=An error occurred while trying to rename a file in the destination directory:
+ErrorRegisterServer=Unable to register the DLL/OCX: %1
+ErrorRegSvr32Failed=RegSvr32 failed with exit code %1
+ErrorRegisterTypeLib=Unable to register the type library: %1
+
+; *** Post-installation errors
+ErrorOpeningReadme=An error occurred while trying to open the README file.
+ErrorRestartingComputer=Setup was unable to restart the computer. Please do this manually.
+
+; *** Uninstaller messages
+UninstallNotFound=File "%1" does not exist. Cannot uninstall.
+UninstallOpenError=File "%1" could not be opened. Cannot uninstall
+UninstallUnsupportedVer=The uninstall log file "%1" is in a format not recognized by this version of the uninstaller. Cannot uninstall
+UninstallUnknownEntry=An unknown entry (%1) was encountered in the uninstall log
+ConfirmUninstall=Are you sure you want to completely remove %1 and all of its components?
+UninstallOnlyOnWin64=This installation can only be uninstalled on 64-bit Windows.
+OnlyAdminCanUninstall=This installation can only be uninstalled by a user with administrative privileges.
+UninstallStatusLabel=Please wait while %1 is removed from your computer.
+UninstalledAll=%1 was successfully removed from your computer.
+UninstalledMost=%1 uninstall complete.%n%nSome elements could not be removed. These can be removed manually.
+UninstalledAndNeedsRestart=To complete the uninstallation of %1, your computer must be restarted.%n%nWould you like to restart now?
+UninstallDataCorrupted="%1" file is corrupted. Cannot uninstall
+
+; *** Uninstallation phase messages
+ConfirmDeleteSharedFileTitle=Remove Shared File?
+ConfirmDeleteSharedFile2=The system indicates that the following shared file is no longer in use by any programs. Would you like for Uninstall to remove this shared file?%n%nIf any programs are still using this file and it is removed, those programs may not function properly. If you are unsure, choose No. Leaving the file on your system will not cause any harm.
+SharedFileNameLabel=File name:
+SharedFileLocationLabel=Location:
+WizardUninstalling=Uninstall Status
+StatusUninstalling=Uninstalling %1...
+
+; *** Shutdown block reasons
+ShutdownBlockReasonInstallingApp=Installing %1.
+ShutdownBlockReasonUninstallingApp=Uninstalling %1.
+
+; The custom messages below aren't used by Setup itself, but if you make
+; use of them in your scripts, you'll want to translate them.
+
+[CustomMessages]
+
+NameAndVersion=%1 version %2
+AdditionalIcons=Additional icons:
+CreateDesktopIcon=Create a &desktop icon
+CreateQuickLaunchIcon=Create a &Quick Launch icon
+ProgramOnTheWeb=%1 on the Web
+UninstallProgram=Uninstall %1
+LaunchProgram=Launch %1
+AssocFileExtension=&Associate %1 with the %2 file extension
+AssocingFileExtension=Associating %1 with the %2 file extension...
+AutoStartProgramGroupDescription=Startup:
+AutoStartProgram=Automatically start %1
+AddonHostProgramNotFound=%1 could not be located in the folder you selected.%n%nDo you want to continue anyway?
diff --git a/setup/inno/ISCC.exe b/setup/inno/ISCC.exe
new file mode 100644
index 000000000..8e54535ce
Binary files /dev/null and b/setup/inno/ISCC.exe differ
diff --git a/setup/inno/ISCmplr.dll b/setup/inno/ISCmplr.dll
new file mode 100644
index 000000000..39129a3d2
Binary files /dev/null and b/setup/inno/ISCmplr.dll differ
diff --git a/setup/inno/ISPP.dll b/setup/inno/ISPP.dll
new file mode 100644
index 000000000..87551fb89
Binary files /dev/null and b/setup/inno/ISPP.dll differ
diff --git a/setup/inno/Setup.e32 b/setup/inno/Setup.e32
new file mode 100644
index 000000000..09cc13598
Binary files /dev/null and b/setup/inno/Setup.e32 differ
diff --git a/setup/inno/SetupLdr.e32 b/setup/inno/SetupLdr.e32
new file mode 100644
index 000000000..956755065
Binary files /dev/null and b/setup/inno/SetupLdr.e32 differ
diff --git a/setup/inno/WizModernImage.bmp b/setup/inno/WizModernImage.bmp
new file mode 100644
index 000000000..cf844e093
Binary files /dev/null and b/setup/inno/WizModernImage.bmp differ
diff --git a/setup/inno/WizModernSmallImage.bmp b/setup/inno/WizModernSmallImage.bmp
new file mode 100644
index 000000000..1e8e49792
Binary files /dev/null and b/setup/inno/WizModernSmallImage.bmp differ
diff --git a/setup/inno/islzma.dll b/setup/inno/islzma.dll
new file mode 100644
index 000000000..49395ada5
Binary files /dev/null and b/setup/inno/islzma.dll differ
diff --git a/setup/nzbdrone.iss b/setup/nzbdrone.iss
new file mode 100644
index 000000000..e667c0d03
--- /dev/null
+++ b/setup/nzbdrone.iss
@@ -0,0 +1,60 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define AppName "Sonarr"
+#define AppPublisher "Team Sonarr"
+#define AppURL "https://sonarr.tv/"
+#define ForumsURL "https://forums.sonarr.tv/"
+#define AppExeName "NzbDrone.exe"
+#define BuildNumber "2.0"
+#define BuildNumber GetEnv('BUILD_NUMBER')
+#define BranchName GetEnv('branch')
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{56C1065D-3523-4025-B76D-6F73F67F7F71}
+AppName={#AppName}
+AppVersion=2.0
+AppPublisher={#AppPublisher}
+AppPublisherURL={#AppURL}
+AppSupportURL={#ForumsURL}
+AppUpdatesURL={#AppURL}
+DefaultDirName={commonappdata}\NzbDrone\bin
+DisableDirPage=yes
+DefaultGroupName={#AppName}
+DisableProgramGroupPage=yes
+OutputBaseFilename=NzbDrone.{#BranchName}.{#BuildNumber}
+SolidCompression=yes
+AppCopyright=Creative Commons 3.0 License
+AllowUNCPath=False
+UninstallDisplayIcon={app}\NzbDrone.exe
+DisableReadyPage=True
+CompressionThreads=2
+Compression=lzma2/normal
+AppContact={#ForumsURL}
+VersionInfoVersion={#BuildNumber}
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Tasks]
+;Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+Name: "windowsService"; Description: "Install as a Windows Service"
+
+[Files]
+Source: "..\_output\NzbDrone.exe"; DestDir: "{app}"; Flags: ignoreversion
+Source: "..\_output\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+[Icons]
+Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
+Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
+
+[Run]
+Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated;
+Filename: "{app}\nzbdrone.console.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
+
+[UninstallRun]
+Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
diff --git a/src/.globalconfig b/src/.globalconfig
deleted file mode 100644
index 6c8ed149b..000000000
--- a/src/.globalconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-is_global = true
-
-dotnet_diagnostic.CA1014.severity = none
diff --git a/src/.nuget/NuGet.Config b/src/.nuget/NuGet.Config
new file mode 100644
index 000000000..67f8ea046
--- /dev/null
+++ b/src/.nuget/NuGet.Config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/.nuget/NuGet.exe b/src/.nuget/NuGet.exe
new file mode 100644
index 000000000..81511ebc5
Binary files /dev/null and b/src/.nuget/NuGet.exe differ
diff --git a/src/.nuget/NuGet.targets b/src/.nuget/NuGet.targets
new file mode 100644
index 000000000..83fe90601
--- /dev/null
+++ b/src/.nuget/NuGet.targets
@@ -0,0 +1,136 @@
+
+
+
+ $(MSBuildProjectDirectory)\..\
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
+ $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
+
+
+
+
+ $(SolutionDir).nuget
+ packages.config
+
+
+
+
+ $(NuGetToolsPath)\NuGet.exe
+ @(PackageSource)
+
+ "$(NuGetExePath)"
+ mono --runtime=v4.0.30319 $(NuGetExePath)
+
+ $(TargetDir.Trim('\\'))
+
+ -RequireConsent
+ -NonInteractive
+
+ "$(SolutionDir) "
+ "$(SolutionDir)"
+
+
+ $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
+ $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
+
+
+
+ RestorePackages;
+ $(BuildDependsOn);
+
+
+
+
+ $(BuildDependsOn);
+ BuildPackage;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Common/CodeAnalysisDictionary.xml b/src/Common/CodeAnalysisDictionary.xml
new file mode 100644
index 000000000..857f46c4e
--- /dev/null
+++ b/src/Common/CodeAnalysisDictionary.xml
@@ -0,0 +1,22 @@
+
+
+
+
+ Ack
+ Minifier
+ Jsonp
+ Linktionary
+ Scaleout
+ Redis
+ Owin
+ Stringify
+ Unminify
+ Unminified
+ Stateful
+ SignalR
+ Hubservable
+ Sse
+ GitHub
+
+
+
\ No newline at end of file
diff --git a/src/Common/CommonAssemblyInfo.cs b/src/Common/CommonAssemblyInfo.cs
new file mode 100644
index 000000000..c245672c6
--- /dev/null
+++ b/src/Common/CommonAssemblyInfo.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyCompany("Microsoft Open Technologies, Inc.")]
+[assembly: AssemblyCopyright("© Microsoft Open Technologies, Inc. All rights reserved.")]
+
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: ComVisible(false)]
+[assembly: CLSCompliant(false)]
+
+[assembly: NeutralResourcesLanguage("en-US")]
\ No newline at end of file
diff --git a/src/Common/CommonVersionInfo.cs b/src/Common/CommonVersionInfo.cs
new file mode 100644
index 000000000..d674c376f
--- /dev/null
+++ b/src/Common/CommonVersionInfo.cs
@@ -0,0 +1,5 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+using System.Reflection;
+
+[assembly: AssemblyVersion("10.0.0.*")]
diff --git a/src/Common/GlobalSuppressions.cs b/src/Common/GlobalSuppressions.cs
new file mode 100644
index 000000000..ec9dfe318
--- /dev/null
+++ b/src/Common/GlobalSuppressions.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.md in the project root for license information.
+
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+//
+// To add a suppression to this file, right-click the message in the
+// Code Analysis results, point to "Suppress Message", and click
+// "In Suppression File".
+// You do not need to add suppressions to this file manually.
+
+using System.Diagnostics.CodeAnalysis;
+
+[assembly: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "Strong naming is done on the CI.")]
+[assembly: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", MessageId = "param", Scope = "resource", Target = "Microsoft.AspNet.SignalR.Resources.resources")]
+[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", Justification = "We use semver")]
+[assembly: SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations", Scope = "member", Target = "Microsoft.AspNet.SignalR.Messaging.ScaleoutTaskQueue.#.cctor()", Justification = "The task is cached")]
diff --git a/src/Common/Microsoft.AspNet.SignalR.ruleset b/src/Common/Microsoft.AspNet.SignalR.ruleset
new file mode 100644
index 000000000..38ad3e9ec
--- /dev/null
+++ b/src/Common/Microsoft.AspNet.SignalR.ruleset
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Common/Microsoft.AspNet.SignalR.targets b/src/Common/Microsoft.AspNet.SignalR.targets
new file mode 100644
index 000000000..291b985a8
--- /dev/null
+++ b/src/Common/Microsoft.AspNet.SignalR.targets
@@ -0,0 +1,40 @@
+
+
+
+ $(ArtifactsDir)\$(MSBuildProjectName)
+ $(ArtifactsDir)\$(MSBuildProjectName)\bin
+
+
+
+ $(MSBuildThisFileDirectory)Microsoft.AspNet.SignalR.ruleset
+ false
+ 1591
+ true
+
+
+
+ $(DefineConstants);CODE_ANALYSIS
+ 11.0
+
+
+
+ $(DefineConstants);MONO
+
+
+
+ $(DefineConstants);SIGNED
+ true
+ true
+ $(KeyFile)
+
+
+
+
+ GlobalSuppressions.cs
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
deleted file mode 100644
index f9853bdd5..000000000
--- a/src/Directory.Build.props
+++ /dev/null
@@ -1,227 +0,0 @@
-
-
-
- 6.0-all
- true
- true
- false
-
- AnyCPU
- true
- win-x64;win-x86;osx-x64;osx-arm64;linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64
-
- $(MSBuildThisFileDirectory)..\
-
-
- Library
- Test
- Exe
- Exe
- Exe
- Exe
- Update
-
-
- false
- true
- true
- true
-
-
- false
- true
-
-
- true
-
- $(NoWarn);CS1591
-
-
-
- Release
-
- $(LidarrRootDir)_temp\obj\$(MSBuildProjectName)\
- $(LidarrRootDir)_temp\obj\$(MSBuildProjectName)\$(Configuration)\
- $(LidarrRootDir)_temp\bin\$(Configuration)\$(MSBuildProjectName)\
-
-
- $(LidarrRootDir)_output\
- $(LidarrRootDir)_tests\
- $(LidarrRootDir)_output\Lidarr.Update\
-
-
- false
- $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$(BaseIntermediateOutputPath)'))
- $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$(IntermediateOutputPath)'))
- $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)', '$(OutputPath)'))
-
- true
-
-
-
-
- true
- true
- false
-
-
-
-
- Lidarr
- lidarr.audio
- Copyright 2017-$([System.DateTime]::Now.ToString('yyyy')) lidarr.audio (GNU General Public v3)
-
-
- 10.0.0.*
- $(Configuration)-dev
- en
-
- false
- false
- false
-
- False
-
- $(MSBuildProjectDirectory)=./$(MSBuildProjectName)/
-
-
-
-
-
- <_Parameter1>$(AssemblyConfiguration)
-
-
-
-
-
- $(MSBuildProjectName.Replace('Lidarr','NzbDrone'))
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- true
-
-
-
- true
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers
-
-
-
-
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
- true
-
-
-
-
-
-
-
-
- x64
-
-
-
-
- x86
-
-
-
-
- arm64
-
-
-
-
- arm
-
-
-
-
-
-
-
-
-
-
- <_UsingDefaultRuntimeIdentifier>true
- win-$(Architecture)
-
-
-
- <_UsingDefaultRuntimeIdentifier>true
- linux-$(Architecture)
-
-
-
- <_UsingDefaultRuntimeIdentifier>true
- osx-x64
-
-
-
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
deleted file mode 100644
index 4cf15bc72..000000000
--- a/src/Directory.Build.targets
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/src/ExternalModules/CurlSharp b/src/ExternalModules/CurlSharp
new file mode 160000
index 000000000..cfdbbbd9c
--- /dev/null
+++ b/src/ExternalModules/CurlSharp
@@ -0,0 +1 @@
+Subproject commit cfdbbbd9c6b9612c2756245049a8234ce87dc576
diff --git a/src/Libraries/Growl.Connector.dll b/src/Libraries/Growl.Connector.dll
new file mode 100644
index 000000000..ba848ae44
Binary files /dev/null and b/src/Libraries/Growl.Connector.dll differ
diff --git a/src/Libraries/Growl.CoreLibrary.dll b/src/Libraries/Growl.CoreLibrary.dll
new file mode 100644
index 000000000..5e67e08f4
Binary files /dev/null and b/src/Libraries/Growl.CoreLibrary.dll differ
diff --git a/src/Libraries/Interop.NetFwTypeLib.dll b/src/Libraries/Interop.NetFwTypeLib.dll
index 1a809435f..7eae191e5 100644
Binary files a/src/Libraries/Interop.NetFwTypeLib.dll and b/src/Libraries/Interop.NetFwTypeLib.dll differ
diff --git a/src/Libraries/Manifest Tool/mt.exe b/src/Libraries/Manifest Tool/mt.exe
new file mode 100644
index 000000000..a8bf42088
Binary files /dev/null and b/src/Libraries/Manifest Tool/mt.exe differ
diff --git a/src/Libraries/Manifest Tool/mt.exe.config b/src/Libraries/Manifest Tool/mt.exe.config
new file mode 100644
index 000000000..88376d847
--- /dev/null
+++ b/src/Libraries/Manifest Tool/mt.exe.config
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Libraries/MediaInfo/MediaInfo.dll b/src/Libraries/MediaInfo/MediaInfo.dll
new file mode 100644
index 000000000..e8d93a233
Binary files /dev/null and b/src/Libraries/MediaInfo/MediaInfo.dll differ
diff --git a/src/Libraries/MediaInfo/libmediainfo.0.dylib b/src/Libraries/MediaInfo/libmediainfo.0.dylib
new file mode 100644
index 000000000..f60a2644a
Binary files /dev/null and b/src/Libraries/MediaInfo/libmediainfo.0.dylib differ
diff --git a/src/Libraries/Mono.Posix.dll b/src/Libraries/Mono.Posix.dll
new file mode 100644
index 000000000..8e219445f
Binary files /dev/null and b/src/Libraries/Mono.Posix.dll differ
diff --git a/src/Libraries/Sqlite/System.Data.SQLite.dll b/src/Libraries/Sqlite/System.Data.SQLite.dll
new file mode 100644
index 000000000..1e7145a8d
Binary files /dev/null and b/src/Libraries/Sqlite/System.Data.SQLite.dll differ
diff --git a/src/Libraries/Sqlite/System.Data.SQLite.xml b/src/Libraries/Sqlite/System.Data.SQLite.xml
new file mode 100644
index 000000000..6e533f0a6
--- /dev/null
+++ b/src/Libraries/Sqlite/System.Data.SQLite.xml
@@ -0,0 +1,13539 @@
+
+
+
+ System.Data.SQLite
+
+
+
+
+ Defines a source code identifier custom attribute for an assembly
+ manifest.
+
+
+
+
+ Constructs an instance of this attribute class using the specified
+ source code identifier value.
+
+
+ The source code identifier value to use.
+
+
+
+
+ Gets the source code identifier value.
+
+
+
+
+ Defines a source code time-stamp custom attribute for an assembly
+ manifest.
+
+
+
+
+ Constructs an instance of this attribute class using the specified
+ source code time-stamp value.
+
+
+ The source code time-stamp value to use.
+
+
+
+
+ Gets the source code time-stamp value.
+
+
+
+
+ This is the method signature for the SQLite core library logging callback
+ function for use with sqlite3_log() and the SQLITE_CONFIG_LOG.
+
+ WARNING: This delegate is used more-or-less directly by native code, do
+ not modify its type signature.
+
+
+ The extra data associated with this message, if any.
+
+
+ The error code associated with this message.
+
+
+ The message string to be logged.
+
+
+
+
+ This class implements SQLiteBase completely, and is the guts of the code that interop's SQLite with .NET
+
+
+
+
+ This internal class provides the foundation of SQLite support. It defines all the abstract members needed to implement
+ a SQLite data provider, and inherits from SQLiteConvert which allows for simple translations of string to and from SQLite.
+
+
+
+
+ This base class provides datatype conversion services for the SQLite provider.
+
+
+
+
+ The fallback default database type when one cannot be obtained from an
+ existing connection instance.
+
+
+
+
+ The format string for DateTime values when using the InvariantCulture or CurrentCulture formats.
+
+
+
+
+ The fallback default database type name when one cannot be obtained from
+ an existing connection instance.
+
+
+
+
+ The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).
+
+
+
+
+ The value of the OLE Automation epoch represented as a Julian day.
+
+
+
+
+ An array of ISO-8601 DateTime formats that we support parsing.
+
+
+
+
+ The internal default format for UTC DateTime values when converting
+ to a string.
+
+
+
+
+ The internal default format for local DateTime values when converting
+ to a string.
+
+
+
+
+ An UTF-8 Encoding instance, so we can convert strings to and from UTF-8
+
+
+
+
+ The default DateTime format for this instance.
+
+
+
+
+ The default DateTimeKind for this instance.
+
+
+
+
+ The default DateTime format string for this instance.
+
+
+
+
+ Initializes the conversion class
+
+ The default date/time format to use for this instance
+ The DateTimeKind to use.
+ The DateTime format string to use.
+
+
+
+ Converts a string to a UTF-8 encoded byte array sized to include a null-terminating character.
+
+ The string to convert to UTF-8
+ A byte array containing the converted string plus an extra 0 terminating byte at the end of the array.
+
+
+
+ Convert a DateTime to a UTF-8 encoded, zero-terminated byte array.
+
+
+ This function is a convenience function, which first calls ToString() on the DateTime, and then calls ToUTF8() with the
+ string result.
+
+ The DateTime to convert.
+ The UTF-8 encoded string, including a 0 terminating byte at the end of the array.
+
+
+
+ Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
+
+ The pointer to the memory where the UTF-8 string is encoded
+ The number of bytes to decode
+ A string containing the translated character(s)
+
+
+
+ Converts a UTF-8 encoded IntPtr of the specified length into a .NET string
+
+ The pointer to the memory where the UTF-8 string is encoded
+ The number of bytes to decode
+ A string containing the translated character(s)
+
+
+
+ Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind,
+ and DateTimeFormatString specified for the connection when it was opened.
+
+
+ Acceptable ISO8601 DateTime formats are:
+
+ THHmmssK
+ THHmmK
+ HH:mm:ss.FFFFFFFK
+ HH:mm:ssK
+ HH:mmK
+ yyyy-MM-dd HH:mm:ss.FFFFFFFK
+ yyyy-MM-dd HH:mm:ssK
+ yyyy-MM-dd HH:mmK
+ yyyy-MM-ddTHH:mm:ss.FFFFFFFK
+ yyyy-MM-ddTHH:mmK
+ yyyy-MM-ddTHH:mm:ssK
+ yyyyMMddHHmmssK
+ yyyyMMddHHmmK
+ yyyyMMddTHHmmssFFFFFFFK
+ THHmmss
+ THHmm
+ HH:mm:ss.FFFFFFF
+ HH:mm:ss
+ HH:mm
+ yyyy-MM-dd HH:mm:ss.FFFFFFF
+ yyyy-MM-dd HH:mm:ss
+ yyyy-MM-dd HH:mm
+ yyyy-MM-ddTHH:mm:ss.FFFFFFF
+ yyyy-MM-ddTHH:mm
+ yyyy-MM-ddTHH:mm:ss
+ yyyyMMddHHmmss
+ yyyyMMddHHmm
+ yyyyMMddTHHmmssFFFFFFF
+ yyyy-MM-dd
+ yyyyMMdd
+ yy-MM-dd
+
+ If the string cannot be matched to one of the above formats -OR-
+ the DateTimeFormatString if one was provided, an exception will
+ be thrown.
+
+ The string containing either a long integer number of 100-nanosecond units since
+ System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
+ culture-independent formatted date and time string, a formatted date and time string in the current
+ culture, or an ISO8601-format string.
+ A DateTime value
+
+
+
+ Converts a string into a DateTime, using the specified DateTimeFormat,
+ DateTimeKind and DateTimeFormatString.
+
+
+ Acceptable ISO8601 DateTime formats are:
+
+ THHmmssK
+ THHmmK
+ HH:mm:ss.FFFFFFFK
+ HH:mm:ssK
+ HH:mmK
+ yyyy-MM-dd HH:mm:ss.FFFFFFFK
+ yyyy-MM-dd HH:mm:ssK
+ yyyy-MM-dd HH:mmK
+ yyyy-MM-ddTHH:mm:ss.FFFFFFFK
+ yyyy-MM-ddTHH:mmK
+ yyyy-MM-ddTHH:mm:ssK
+ yyyyMMddHHmmssK
+ yyyyMMddHHmmK
+ yyyyMMddTHHmmssFFFFFFFK
+ THHmmss
+ THHmm
+ HH:mm:ss.FFFFFFF
+ HH:mm:ss
+ HH:mm
+ yyyy-MM-dd HH:mm:ss.FFFFFFF
+ yyyy-MM-dd HH:mm:ss
+ yyyy-MM-dd HH:mm
+ yyyy-MM-ddTHH:mm:ss.FFFFFFF
+ yyyy-MM-ddTHH:mm
+ yyyy-MM-ddTHH:mm:ss
+ yyyyMMddHHmmss
+ yyyyMMddHHmm
+ yyyyMMddTHHmmssFFFFFFF
+ yyyy-MM-dd
+ yyyyMMdd
+ yy-MM-dd
+
+ If the string cannot be matched to one of the above formats -OR-
+ the DateTimeFormatString if one was provided, an exception will
+ be thrown.
+
+ The string containing either a long integer number of 100-nanosecond units since
+ System.DateTime.MinValue, a Julian day double, an integer number of seconds since the Unix epoch, a
+ culture-independent formatted date and time string, a formatted date and time string in the current
+ culture, or an ISO8601-format string.
+ The SQLiteDateFormats to use.
+ The DateTimeKind to use.
+ The DateTime format string to use.
+ A DateTime value
+
+
+
+ Converts a julianday value into a DateTime
+
+ The value to convert
+ A .NET DateTime
+
+
+
+ Converts a julianday value into a DateTime
+
+ The value to convert
+ The DateTimeKind to use.
+ A .NET DateTime
+
+
+
+ Converts the specified number of seconds from the Unix epoch into a
+ value.
+
+
+ The number of whole seconds since the Unix epoch.
+
+
+ Either Utc or Local time.
+
+
+ The new value.
+
+
+
+
+ Converts the specified number of ticks since the epoch into a
+ value.
+
+
+ The number of whole ticks since the epoch.
+
+
+ Either Utc or Local time.
+
+
+ The new value.
+
+
+
+
+ Converts a DateTime struct to a JulianDay double
+
+ The DateTime to convert
+ The JulianDay value the Datetime represents
+
+
+
+ Converts a DateTime struct to the whole number of seconds since the
+ Unix epoch.
+
+ The DateTime to convert
+ The whole number of seconds since the Unix epoch
+
+
+
+ Returns the DateTime format string to use for the specified DateTimeKind.
+ If is not null, it will be returned verbatim.
+
+ The DateTimeKind to use.
+ The DateTime format string to use.
+
+ The DateTime format string to use for the specified DateTimeKind.
+
+
+
+
+ Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind,
+ and DateTimeFormatString specified for the connection when it was opened.
+
+ The DateTime value to convert
+ Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
+ Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time
+ string, a formatted date and time string in the current culture, or an ISO8601-format date/time string.
+
+
+
+ Converts a string into a DateTime, using the DateTimeFormat, DateTimeKind,
+ and DateTimeFormatString specified for the connection when it was opened.
+
+ The DateTime value to convert
+ The SQLiteDateFormats to use.
+ The DateTimeKind to use.
+ The DateTime format string to use.
+ Either a string containing the long integer number of 100-nanosecond units since System.DateTime.MinValue, a
+ Julian day double, an integer number of seconds since the Unix epoch, a culture-independent formatted date and time
+ string, a formatted date and time string in the current culture, or an ISO8601-format date/time string.
+
+
+
+ Internal function to convert a UTF-8 encoded IntPtr of the specified length to a DateTime.
+
+
+ This is a convenience function, which first calls ToString() on the IntPtr to convert it to a string, then calls
+ ToDateTime() on the string to return a DateTime.
+
+ A pointer to the UTF-8 encoded string
+ The length in bytes of the string
+ The parsed DateTime value
+
+
+
+ Smart method of splitting a string. Skips quoted elements, removes the quotes.
+
+
+ This split function works somewhat like the String.Split() function in that it breaks apart a string into
+ pieces and returns the pieces as an array. The primary differences are:
+
+ Only one character can be provided as a separator character
+ Quoted text inside the string is skipped over when searching for the separator, and the quotes are removed.
+
+ Thus, if splitting the following string looking for a comma:
+ One,Two, "Three, Four", Five
+
+ The resulting array would contain
+ [0] One
+ [1] Two
+ [2] Three, Four
+ [3] Five
+
+ Note that the leading and trailing spaces were removed from each item during the split.
+
+ Source string to split apart
+ Separator character
+ A string array of the split up elements
+
+
+
+ Splits the specified string into multiple strings based on a separator
+ and returns the result as an array of strings.
+
+
+ The string to split into pieces based on the separator character. If
+ this string is null, null will always be returned. If this string is
+ empty, an array of zero strings will always be returned.
+
+
+ The character used to divide the original string into sub-strings.
+ This character cannot be a backslash or a double-quote; otherwise, no
+ work will be performed and null will be returned.
+
+
+ If this parameter is non-zero, all double-quote characters will be
+ retained in the returned list of strings; otherwise, they will be
+ dropped.
+
+
+ Upon failure, this parameter will be modified to contain an appropriate
+ error message.
+
+
+ The new array of strings or null if the input string is null -OR- the
+ separator character is a backslash or a double-quote -OR- the string
+ contains an unbalanced backslash or double-quote character.
+
+
+
+
+ Queries and returns the string representation for an object, using the
+ specified (or current) format provider.
+
+
+ The object instance to return the string representation for.
+
+
+ The format provider to use -OR- null if the current format provider for
+ the thread should be used instead.
+
+
+ The string representation for the object instance -OR- null if the
+ object instance is also null.
+
+
+
+
+ Attempts to convert an arbitrary object to the Boolean data type.
+ Null object values are converted to false. Throws an exception
+ upon failure.
+
+
+ The object value to convert.
+
+
+ The format provider to use.
+
+
+ If non-zero, a string value will be converted using the
+
+ method; otherwise, the
+ method will be used.
+
+
+ The converted boolean value.
+
+
+
+
+ Convert a value to true or false.
+
+ A string or number representing true or false
+
+
+
+
+ Convert a string to true or false.
+
+ A string representing true or false
+
+
+ "yes", "no", "y", "n", "0", "1", "on", "off" as well as Boolean.FalseString and Boolean.TrueString will all be
+ converted to a proper boolean value.
+
+
+
+
+ Converts a SQLiteType to a .NET Type object
+
+ The SQLiteType to convert
+ Returns a .NET Type object
+
+
+
+ For a given intrinsic type, return a DbType
+
+ The native type to convert
+ The corresponding (closest match) DbType
+
+
+
+ Returns the ColumnSize for the given DbType
+
+ The DbType to get the size of
+
+
+
+
+ Determines the default database type name to be used when a
+ per-connection value is not available.
+
+
+ The connection context for type mappings, if any.
+
+
+ The default database type name to use.
+
+
+
+
+ If applicable, issues a trace log message warning about falling back to
+ the default database type name.
+
+
+ The database value type.
+
+
+ The flags associated with the parent connection object.
+
+
+ The textual name of the database type.
+
+
+
+
+ If applicable, issues a trace log message warning about falling back to
+ the default database value type.
+
+
+ The textual name of the database type.
+
+
+ The flags associated with the parent connection object.
+
+
+ The database value type.
+
+
+
+
+ For a given database value type, return the "closest-match" textual database type name.
+
+ The connection context for custom type mappings, if any.
+ The database value type.
+ The flags associated with the parent connection object.
+ The type name or an empty string if it cannot be determined.
+
+
+
+ Convert a DbType to a Type
+
+ The DbType to convert from
+ The closest-match .NET type
+
+
+
+ For a given type, return the closest-match SQLite TypeAffinity, which only understands a very limited subset of types.
+
+ The type to evaluate
+ The SQLite type affinity for that type.
+
+
+
+ Builds and returns a map containing the database column types
+ recognized by this provider.
+
+
+ A map containing the database column types recognized by this
+ provider.
+
+
+
+
+ Determines if a database type is considered to be a string.
+
+
+ The database type to check.
+
+
+ Non-zero if the database type is considered to be a string, zero
+ otherwise.
+
+
+
+
+ Determines and returns the runtime configuration setting string that
+ should be used in place of the specified object value.
+
+
+ The object value to convert to a string.
+
+
+ Either the string to use in place of the object value -OR- null if it
+ cannot be determined.
+
+
+
+
+ Determines the default value to be used when a
+ per-connection value is not available.
+
+
+ The connection context for type mappings, if any.
+
+
+ The default value to use.
+
+
+
+
+ Determines if the specified textual value appears to be a
+ value.
+
+
+ The textual value to inspect.
+
+
+ Non-zero if the text looks like a value,
+ zero otherwise.
+
+
+
+
+ Determines if the specified textual value appears to be an
+ value.
+
+
+ The textual value to inspect.
+
+
+ Non-zero if the text looks like an value,
+ zero otherwise.
+
+
+
+
+ Determines if the specified textual value appears to be a
+ value.
+
+
+ The textual value to inspect.
+
+
+ Non-zero if the text looks like a value,
+ zero otherwise.
+
+
+
+
+ Determines if the specified textual value appears to be a
+ value.
+
+
+ The object instance configured with
+ the chosen format.
+
+
+ The textual value to inspect.
+
+
+ Non-zero if the text looks like a in the
+ configured format, zero otherwise.
+
+
+
+
+ For a given textual database type name, return the "closest-match" database type.
+ This method is called during query result processing; therefore, its performance
+ is critical.
+
+ The connection context for custom type mappings, if any.
+ The textual name of the database type to match.
+ The flags associated with the parent connection object.
+ The .NET DBType the text evaluates to.
+
+
+
+ The error code used for logging exceptions caught in user-provided
+ code.
+
+
+
+
+ Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled.
+ If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is
+ global to the process.
+
+ Non-zero to enable memory usage tracking, zero otherwise.
+ A standard SQLite return code (i.e. zero for success and non-zero for failure).
+
+
+
+ Attempts to free as much heap memory as possible for the database connection.
+
+ A standard SQLite return code (i.e. zero for success and non-zero for failure).
+
+
+
+ Shutdown the SQLite engine so that it can be restarted with different config options.
+ We depend on auto initialization to recover.
+
+
+
+
+ Determines if the associated native connection handle is open.
+
+
+ Non-zero if a database connection is open.
+
+
+
+
+ Opens a database.
+
+
+ Implementers should call SQLiteFunction.BindFunctions() and save the array after opening a connection
+ to bind all attributed user-defined functions and collating sequences to the new connection.
+
+ The filename of the database to open. SQLite automatically creates it if it doesn't exist.
+ The flags associated with the parent connection object
+ The open flags to use when creating the connection
+ The maximum size of the pool for the given filename
+ If true, the connection can be pulled from the connection pool
+
+
+
+ Closes the currently-open database.
+
+
+ After the database has been closed implemeters should call SQLiteFunction.UnbindFunctions() to deallocate all interop allocated
+ memory associated with the user-defined functions and collating sequences tied to the closed connection.
+
+ Non-zero if the operation is allowed to throw exceptions, zero otherwise.
+
+
+
+ Sets the busy timeout on the connection. SQLiteCommand will call this before executing any command.
+
+ The number of milliseconds to wait before returning SQLITE_BUSY
+
+
+
+ Returns the text of the last error issued by SQLite
+
+
+
+
+
+ Returns the text of the last error issued by SQLite -OR- the specified default error text if
+ none is available from the SQLite core library.
+
+
+ The error text to return in the event that one is not available from the SQLite core library.
+
+
+ The error text.
+
+
+
+
+ When pooling is enabled, force this connection to be disposed rather than returned to the pool
+
+
+
+
+ When pooling is enabled, returns the number of pool entries matching the current file name.
+
+ The number of pool entries matching the current file name.
+
+
+
+ Prepares a SQL statement for execution.
+
+ The source connection preparing the command. Can be null for any caller except LINQ
+ The SQL command text to prepare
+ The previous statement in a multi-statement command, or null if no previous statement exists
+ The timeout to wait before aborting the prepare
+ The remainder of the statement that was not processed. Each call to prepare parses the
+ SQL up to to either the end of the text or to the first semi-colon delimiter. The remaining text is returned
+ here for a subsequent call to Prepare() until all the text has been processed.
+ Returns an initialized SQLiteStatement.
+
+
+
+ Steps through a prepared statement.
+
+ The SQLiteStatement to step through
+ True if a row was returned, False if not.
+
+
+
+ Resets a prepared statement so it can be executed again. If the error returned is SQLITE_SCHEMA,
+ transparently attempt to rebuild the SQL statement and throw an error if that was not possible.
+
+ The statement to reset
+ Returns -1 if the schema changed while resetting, 0 if the reset was sucessful or 6 (SQLITE_LOCKED) if the reset failed due to a lock
+
+
+
+ Attempts to interrupt the query currently executing on the associated
+ native database connection.
+
+
+
+
+ This function binds a user-defined functions to the connection.
+
+
+ The object instance containing
+ the metadata for the function to be bound.
+
+
+ The object instance that implements the
+ function to be bound.
+
+
+ The flags associated with the parent connection object.
+
+
+
+
+ Calls the native SQLite core library in order to create a disposable
+ module containing the implementation of a virtual table.
+
+
+ The module object to be used when creating the native disposable module.
+
+
+ The flags for the associated object instance.
+
+
+
+
+ Calls the native SQLite core library in order to cleanup the resources
+ associated with a module containing the implementation of a virtual table.
+
+
+ The module object previously passed to the
+ method.
+
+
+ The flags for the associated object instance.
+
+
+
+
+ Calls the native SQLite core library in order to declare a virtual table
+ in response to a call into the
+ or virtual table methods.
+
+
+ The virtual table module that is to be responsible for the virtual table
+ being declared.
+
+
+ The string containing the SQL statement describing the virtual table to
+ be declared.
+
+
+ Upon success, the contents of this parameter are undefined. Upon failure,
+ it should contain an appropriate error message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Calls the native SQLite core library in order to declare a virtual table
+ function in response to a call into the
+ or virtual table methods.
+
+
+ The virtual table module that is to be responsible for the virtual table
+ function being declared.
+
+
+ The number of arguments to the function being declared.
+
+
+ The name of the function being declared.
+
+
+ Upon success, the contents of this parameter are undefined. Upon failure,
+ it should contain an appropriate error message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Enables or disabled extension loading by SQLite.
+
+
+ True to enable loading of extensions, false to disable.
+
+
+
+
+ Loads a SQLite extension library from the named file.
+
+
+ The name of the dynamic link library file containing the extension.
+
+
+ The name of the exported function used to initialize the extension.
+ If null, the default "sqlite3_extension_init" will be used.
+
+
+
+
+ Enables or disabled extened result codes returned by SQLite
+
+ true to enable extended result codes, false to disable.
+
+
+
+
+ Returns the numeric result code for the most recent failed SQLite API call
+ associated with the database connection.
+
+ Result code
+
+
+
+ Returns the extended numeric result code for the most recent failed SQLite API call
+ associated with the database connection.
+
+ Extended result code
+
+
+
+ Add a log message via the SQLite sqlite3_log interface.
+
+ Error code to be logged with the message.
+ String to be logged. Unlike the SQLite sqlite3_log()
+ interface, this should be pre-formatted. Consider using the
+ String.Format() function.
+
+
+
+
+ Checks if the SQLite core library has been initialized in the current process.
+
+
+ Non-zero if the SQLite core library has been initialized in the current process,
+ zero otherwise.
+
+
+
+
+ Creates a new SQLite backup object based on the provided destination
+ database connection. The source database connection is the one
+ associated with this object. The source and destination database
+ connections cannot be the same.
+
+ The destination database connection.
+ The destination database name.
+ The source database name.
+ The newly created backup object.
+
+
+
+ Copies up to N pages from the source database to the destination
+ database associated with the specified backup object.
+
+ The backup object to use.
+
+ The number of pages to copy or negative to copy all remaining pages.
+
+
+ Set to true if the operation needs to be retried due to database
+ locking issues.
+
+
+ True if there are more pages to be copied, false otherwise.
+
+
+
+
+ Returns the number of pages remaining to be copied from the source
+ database to the destination database associated with the specified
+ backup object.
+
+ The backup object to check.
+ The number of pages remaining to be copied.
+
+
+
+ Returns the total number of pages in the source database associated
+ with the specified backup object.
+
+ The backup object to check.
+ The total number of pages in the source database.
+
+
+
+ Destroys the backup object, rolling back any backup that may be in
+ progess.
+
+ The backup object to destroy.
+
+
+
+ Returns the error message for the specified SQLite return code using
+ the internal static lookup table.
+
+ The SQLite return code.
+ The error message or null if it cannot be found.
+
+
+
+ Returns the error message for the specified SQLite return code using
+ the sqlite3_errstr() function, falling back to the internal lookup
+ table if necessary.
+
+ The SQLite return code.
+ The error message or null if it cannot be found.
+
+
+
+ Returns a string representing the active version of SQLite
+
+
+
+
+ Returns an integer representing the active version of SQLite
+
+
+
+
+ Returns the rowid of the most recent successful INSERT into the database from this connection.
+
+
+
+
+ Returns the number of changes the last executing insert/update caused.
+
+
+
+
+ Returns the amount of memory (in bytes) currently in use by the SQLite core library. This is not really a per-connection
+ value, it is global to the process.
+
+
+
+
+ Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset.
+ This is not really a per-connection value, it is global to the process.
+
+
+
+
+ Returns non-zero if the underlying native connection handle is owned by this instance.
+
+
+
+
+ Returns non-zero if the given database connection is in autocommit mode.
+ Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN
+ statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK.
+
+
+
+
+ The opaque pointer returned to us by the sqlite provider
+
+
+
+
+ The user-defined functions registered on this connection
+
+
+
+
+ The modules created using this connection.
+
+
+
+
+ Constructs the object used to interact with the SQLite core library
+ using the UTF-8 text encoding.
+
+
+ The DateTime format to be used when converting string values to a
+ DateTime and binding DateTime parameters.
+
+
+ The to be used when creating DateTime
+ values.
+
+
+ The format string to be used when parsing and formatting DateTime
+ values.
+
+
+ The native handle to be associated with the database connection.
+
+
+ The fully qualified file name associated with .
+
+
+ Non-zero if the newly created object instance will need to dispose
+ of when it is no longer needed.
+
+
+
+
+ This method attempts to dispose of all the derived
+ object instances currently associated with the native database connection.
+
+
+
+
+ Attempts to interrupt the query currently executing on the associated
+ native database connection.
+
+
+
+
+ This function binds a user-defined function to the connection.
+
+
+ The object instance containing
+ the metadata for the function to be bound.
+
+
+ The object instance that implements the
+ function to be bound.
+
+
+ The flags associated with the parent connection object.
+
+
+
+
+ Attempts to free as much heap memory as possible for the database connection.
+
+ A standard SQLite return code (i.e. zero for success and non-zero for failure).
+
+
+
+ Attempts to free N bytes of heap memory by deallocating non-essential memory
+ allocations held by the database library. Memory used to cache database pages
+ to improve performance is an example of non-essential memory. This is a no-op
+ returning zero if the SQLite core library was not compiled with the compile-time
+ option SQLITE_ENABLE_MEMORY_MANAGEMENT. Optionally, attempts to reset and/or
+ compact the Win32 native heap, if applicable.
+
+
+ The requested number of bytes to free.
+
+
+ Non-zero to attempt a heap reset.
+
+
+ Non-zero to attempt heap compaction.
+
+
+ The number of bytes actually freed. This value may be zero.
+
+
+ This value will be non-zero if the heap reset was successful.
+
+
+ The size of the largest committed free block in the heap, in bytes.
+ This value will be zero unless heap compaction is enabled.
+
+
+ A standard SQLite return code (i.e. zero for success and non-zero
+ for failure).
+
+
+
+
+ Shutdown the SQLite engine so that it can be restarted with different
+ configuration options. We depend on auto initialization to recover.
+
+ Returns a standard SQLite result code.
+
+
+
+ Shutdown the SQLite engine so that it can be restarted with different
+ configuration options. We depend on auto initialization to recover.
+
+
+ Non-zero to reset the database and temporary directories to their
+ default values, which should be null for both. This parameter has no
+ effect on non-Windows operating systems.
+
+ Returns a standard SQLite result code.
+
+
+
+ Determines if the associated native connection handle is open.
+
+
+ Non-zero if the associated native connection handle is open.
+
+
+
+
+ Calls the native SQLite core library in order to create a disposable
+ module containing the implementation of a virtual table.
+
+
+ The module object to be used when creating the native disposable module.
+
+
+ The flags for the associated object instance.
+
+
+
+
+ Calls the native SQLite core library in order to cleanup the resources
+ associated with a module containing the implementation of a virtual table.
+
+
+ The module object previously passed to the
+ method.
+
+
+ The flags for the associated object instance.
+
+
+
+
+ Calls the native SQLite core library in order to declare a virtual table
+ in response to a call into the
+ or virtual table methods.
+
+
+ The virtual table module that is to be responsible for the virtual table
+ being declared.
+
+
+ The string containing the SQL statement describing the virtual table to
+ be declared.
+
+
+ Upon success, the contents of this parameter are undefined. Upon failure,
+ it should contain an appropriate error message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Calls the native SQLite core library in order to declare a virtual table
+ function in response to a call into the
+ or virtual table methods.
+
+
+ The virtual table module that is to be responsible for the virtual table
+ function being declared.
+
+
+ The number of arguments to the function being declared.
+
+
+ The name of the function being declared.
+
+
+ Upon success, the contents of this parameter are undefined. Upon failure,
+ it should contain an appropriate error message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Enables or disabled extension loading by SQLite.
+
+
+ True to enable loading of extensions, false to disable.
+
+
+
+
+ Loads a SQLite extension library from the named file.
+
+
+ The name of the dynamic link library file containing the extension.
+
+
+ The name of the exported function used to initialize the extension.
+ If null, the default "sqlite3_extension_init" will be used.
+
+
+
+ Enables or disabled extended result codes returned by SQLite
+
+
+ Gets the last SQLite error code
+
+
+ Gets the last SQLite extended error code
+
+
+ Add a log message via the SQLite sqlite3_log interface.
+
+
+ Add a log message via the SQLite sqlite3_log interface.
+
+
+
+ Allows the setting of a logging callback invoked by SQLite when a
+ log event occurs. Only one callback may be set. If NULL is passed,
+ the logging callback is unregistered.
+
+ The callback function to invoke.
+ Returns a result code
+
+
+
+ Creates a new SQLite backup object based on the provided destination
+ database connection. The source database connection is the one
+ associated with this object. The source and destination database
+ connections cannot be the same.
+
+ The destination database connection.
+ The destination database name.
+ The source database name.
+ The newly created backup object.
+
+
+
+ Copies up to N pages from the source database to the destination
+ database associated with the specified backup object.
+
+ The backup object to use.
+
+ The number of pages to copy, negative to copy all remaining pages.
+
+
+ Set to true if the operation needs to be retried due to database
+ locking issues; otherwise, set to false.
+
+
+ True if there are more pages to be copied, false otherwise.
+
+
+
+
+ Returns the number of pages remaining to be copied from the source
+ database to the destination database associated with the specified
+ backup object.
+
+ The backup object to check.
+ The number of pages remaining to be copied.
+
+
+
+ Returns the total number of pages in the source database associated
+ with the specified backup object.
+
+ The backup object to check.
+ The total number of pages in the source database.
+
+
+
+ Destroys the backup object, rolling back any backup that may be in
+ progess.
+
+ The backup object to destroy.
+
+
+
+ Determines if the SQLite core library has been initialized for the
+ current process.
+
+
+ A boolean indicating whether or not the SQLite core library has been
+ initialized for the current process.
+
+
+
+
+ Determines if the SQLite core library has been initialized for the
+ current process.
+
+
+ A boolean indicating whether or not the SQLite core library has been
+ initialized for the current process.
+
+
+
+
+ Helper function to retrieve a column of data from an active statement.
+
+ The statement being step()'d through
+ The flags associated with the connection.
+ The column index to retrieve
+ The type of data contained in the column. If Uninitialized, this function will retrieve the datatype information.
+ Returns the data in the column
+
+
+
+ Returns non-zero if the underlying native connection handle is owned
+ by this instance.
+
+
+
+
+ Alternate SQLite3 object, overriding many text behaviors to support UTF-16 (Unicode)
+
+
+
+
+ Constructs the object used to interact with the SQLite core library
+ using the UTF-8 text encoding.
+
+
+ The DateTime format to be used when converting string values to a
+ DateTime and binding DateTime parameters.
+
+
+ The to be used when creating DateTime
+ values.
+
+
+ The format string to be used when parsing and formatting DateTime
+ values.
+
+
+ The native handle to be associated with the database connection.
+
+
+ The fully qualified file name associated with .
+
+
+ Non-zero if the newly created object instance will need to dispose
+ of when it is no longer needed.
+
+
+
+
+ Overrides SQLiteConvert.ToString() to marshal UTF-16 strings instead of UTF-8
+
+ A pointer to a UTF-16 string
+ The length (IN BYTES) of the string
+ A .NET string
+
+
+
+ Represents a single SQL backup in SQLite.
+
+
+
+
+ The underlying SQLite object this backup is bound to.
+
+
+
+
+ The actual backup handle.
+
+
+
+
+ The destination database for the backup.
+
+
+
+
+ The destination database name for the backup.
+
+
+
+
+ The source database for the backup.
+
+
+
+
+ The source database name for the backup.
+
+
+
+
+ The last result from the StepBackup method of the SQLite3 class.
+ This is used to determine if the call to the FinishBackup method of
+ the SQLite3 class should throw an exception when it receives a non-Ok
+ return code from the core SQLite library.
+
+
+
+
+ Initializes the backup.
+
+ The base SQLite object.
+ The backup handle.
+ The destination database for the backup.
+ The destination database name for the backup.
+ The source database for the backup.
+ The source database name for the backup.
+
+
+
+ Disposes and finalizes the backup.
+
+
+
+
+
+
+
+
+
+ Creates temporary tables on the connection so schema information can be queried.
+
+
+ The connection upon which to build the schema tables.
+
+
+
+
+ The extra behavioral flags that can be applied to a connection.
+
+
+
+
+ No extra flags.
+
+
+
+
+ Enable logging of all SQL statements to be prepared.
+
+
+
+
+ Enable logging of all bound parameter types and raw values.
+
+
+
+
+ Enable logging of all bound parameter strongly typed values.
+
+
+
+
+ Enable logging of all exceptions caught from user-provided
+ managed code called from native code via delegates.
+
+
+
+
+ Enable logging of backup API errors.
+
+
+
+
+ Skip adding the extension functions provided by the native
+ interop assembly.
+
+
+
+
+ When binding parameter values with the
+ type, use the interop method that accepts an
+ value.
+
+
+
+
+ When binding parameter values, always bind them as though they were
+ plain text (i.e. no numeric, date/time, or other conversions should
+ be attempted).
+
+
+
+
+ When returning column values, always return them as though they were
+ plain text (i.e. no numeric, date/time, or other conversions should
+ be attempted).
+
+
+
+
+ Prevent this object instance from
+ loading extensions.
+
+
+
+
+ Prevent this object instance from
+ creating virtual table modules.
+
+
+
+
+ Skip binding any functions provided by other managed assemblies when
+ opening the connection.
+
+
+
+
+ Skip setting the logging related properties of the
+ object instance that was passed to
+ the method.
+
+
+
+
+ Enable logging of all virtual table module errors seen by the
+ method.
+
+
+
+
+ Enable logging of certain virtual table module exceptions that cannot
+ be easily discovered via other means.
+
+
+
+
+ Enable tracing of potentially important [non-fatal] error conditions
+ that cannot be easily reported through other means.
+
+
+
+
+ When binding parameter values, always use the invariant culture when
+ converting their values from strings.
+
+
+
+
+ When binding parameter values, always use the invariant culture when
+ converting their values to strings.
+
+
+
+
+ Disable using the connection pool by default. If the "Pooling"
+ connection string property is specified, its value will override
+ this flag. The precise outcome of combining this flag with the
+ flag is unspecified; however,
+ one of the flags will be in effect.
+
+
+
+
+ Enable using the connection pool by default. If the "Pooling"
+ connection string property is specified, its value will override
+ this flag. The precise outcome of combining this flag with the
+ flag is unspecified; however,
+ one of the flags will be in effect.
+
+
+
+
+ Enable using per-connection mappings between type names and
+ values. Also see the
+ ,
+ , and
+ methods. These
+ per-connection mappings, when present, override the corresponding
+ global mappings.
+
+
+
+
+ Disable using global mappings between type names and
+ values. This may be useful in some very narrow
+ cases; however, if there are no per-connection type mappings, the
+ fallback defaults will be used for both type names and their
+ associated values. Therefore, use of this flag
+ is not recommended.
+
+
+
+
+ When the property is used, it
+ should return non-zero if there were ever any rows in the associated
+ result sets.
+
+
+
+
+ Enable "strict" transaction enlistment semantics. Setting this flag
+ will cause an exception to be thrown if an attempt is made to enlist
+ in a transaction with an unavailable or unsupported isolation level.
+ In the future, more extensive checks may be enabled by this flag as
+ well.
+
+
+
+
+ Enable mapping of unsupported transaction isolation levels to the
+ closest supported transaction isolation level.
+
+
+
+
+ When returning column values, attempt to detect the affinity of
+ textual values by checking if they fully conform to those of the
+ ,
+ ,
+ ,
+ or types.
+
+
+
+
+ When returning column values, attempt to detect the type of
+ string values by checking if they fully conform to those of
+ the ,
+ ,
+ ,
+ or types.
+
+
+
+
+ Skip querying runtime configuration settings for use by the
+ class, including the default
+ value and default database type name.
+ NOTE: If the
+ and/or
+ properties are not set explicitly nor set via their connection
+ string properties and repeated calls to determine these runtime
+ configuration settings are seen to be a problem, this flag
+ should be set.
+
+
+
+
+ When binding parameter values or returning column values, always
+ treat them as though they were plain text (i.e. no numeric,
+ date/time, or other conversions should be attempted).
+
+
+
+
+ When binding parameter values, always use the invariant culture when
+ converting their values to strings or from strings.
+
+
+
+
+ When binding parameter values or returning column values, always
+ treat them as though they were plain text (i.e. no numeric,
+ date/time, or other conversions should be attempted) and always
+ use the invariant culture when converting their values to strings.
+
+
+
+
+ When binding parameter values or returning column values, always
+ treat them as though they were plain text (i.e. no numeric,
+ date/time, or other conversions should be attempted) and always
+ use the invariant culture when converting their values to strings
+ or from strings.
+
+
+
+
+ Enable all logging.
+
+
+
+
+ The default extra flags for new connections.
+
+
+
+
+ The default extra flags for new connections with all logging enabled.
+
+
+
+
+ SQLite implementation of DbCommand.
+
+
+
+
+ The default connection string to be used when creating a temporary
+ connection to execute a command via the static
+ or
+
+ methods.
+
+
+
+
+ The command text this command is based on
+
+
+
+
+ The connection the command is associated with
+
+
+
+
+ The version of the connection the command is associated with
+
+
+
+
+ Indicates whether or not a DataReader is active on the command.
+
+
+
+
+ The timeout for the command, kludged because SQLite doesn't support per-command timeout values
+
+
+
+
+ Designer support
+
+
+
+
+ Used by DbDataAdapter to determine updating behavior
+
+
+
+
+ The collection of parameters for the command
+
+
+
+
+ The SQL command text, broken into individual SQL statements as they are executed
+
+
+
+
+ Unprocessed SQL text that has not been executed
+
+
+
+
+ Transaction associated with this command
+
+
+
+
+ Constructs a new SQLiteCommand
+
+
+ Default constructor
+
+
+
+
+ Initializes the command with the given command text
+
+ The SQL command text
+
+
+
+ Initializes the command with the given SQL command text and attach the command to the specified
+ connection.
+
+ The SQL command text
+ The connection to associate with the command
+
+
+
+ Initializes the command and associates it with the specified connection.
+
+ The connection to associate with the command
+
+
+
+ Initializes a command with the given SQL, connection and transaction
+
+ The SQL command text
+ The connection to associate with the command
+ The transaction the command should be associated with
+
+
+
+ Disposes of the command and clears all member variables
+
+ Whether or not the class is being explicitly or implicitly disposed
+
+
+
+ This method attempts to query the flags associated with the database
+ connection in use. If the database connection is disposed, the default
+ flags will be returned.
+
+
+ The command containing the databse connection to query the flags from.
+
+
+ The connection flags value.
+
+
+
+
+ Clears and destroys all statements currently prepared
+
+
+
+
+ Builds an array of prepared statements for each complete SQL statement in the command text
+
+
+
+
+ Not implemented
+
+
+
+
+ Forwards to the local CreateParameter() function
+
+
+
+
+
+ Create a new parameter
+
+
+
+
+
+ This function ensures there are no active readers, that we have a valid connection,
+ that the connection is open, that all statements are prepared and all parameters are assigned
+ in preparation for allocating a data reader.
+
+
+
+
+ Creates a new SQLiteDataReader to execute/iterate the array of SQLite prepared statements
+
+ The behavior the data reader should adopt
+ Returns a SQLiteDataReader object
+
+
+
+ This method creates a new connection, executes the query using the given
+ execution type, closes the connection, and returns the results. If the
+ connection string is null, a temporary in-memory database connection will
+ be used.
+
+
+ The text of the command to be executed.
+
+
+ The execution type for the command. This is used to determine which method
+ of the command object to call, which then determines the type of results
+ returned, if any.
+
+
+ The connection string to the database to be opened, used, and closed. If
+ this parameter is null, a temporary in-memory databse will be used.
+
+
+ The SQL parameter values to be used when building the command object to be
+ executed, if any.
+
+
+ The results of the query -OR- null if no results were produced from the
+ given execution type.
+
+
+
+
+ This method creates a new connection, executes the query using the given
+ execution type and command behavior, closes the connection, and returns
+ the results. If the connection string is null, a temporary in-memory
+ database connection will be used.
+
+
+ The text of the command to be executed.
+
+
+ The execution type for the command. This is used to determine which method
+ of the command object to call, which then determines the type of results
+ returned, if any.
+
+
+ The command behavior flags for the command.
+
+
+ The connection string to the database to be opened, used, and closed. If
+ this parameter is null, a temporary in-memory databse will be used.
+
+
+ The SQL parameter values to be used when building the command object to be
+ executed, if any.
+
+
+ The results of the query -OR- null if no results were produced from the
+ given execution type.
+
+
+
+
+ Overrides the default behavior to return a SQLiteDataReader specialization class
+
+ The flags to be associated with the reader.
+ A SQLiteDataReader
+
+
+
+ Overrides the default behavior of DbDataReader to return a specialized SQLiteDataReader class
+
+ A SQLiteDataReader
+
+
+
+ Called by the SQLiteDataReader when the data reader is closed.
+
+
+
+
+ Execute the command and return the number of rows inserted/updated affected by it.
+
+ The number of rows inserted/updated affected by it.
+
+
+
+ Execute the command and return the number of rows inserted/updated affected by it.
+
+ The flags to be associated with the reader.
+ The number of rows inserted/updated affected by it.
+
+
+
+ Execute the command and return the first column of the first row of the resultset
+ (if present), or null if no resultset was returned.
+
+ The first column of the first row of the first resultset from the query.
+
+
+
+ Execute the command and return the first column of the first row of the resultset
+ (if present), or null if no resultset was returned.
+
+ The flags to be associated with the reader.
+ The first column of the first row of the first resultset from the query.
+
+
+
+ Does nothing. Commands are prepared as they are executed the first time, and kept in prepared state afterwards.
+
+
+
+
+ Clones a command, including all its parameters
+
+ A new SQLiteCommand with the same commandtext, connection and parameters
+
+
+
+ The SQL command text associated with the command
+
+
+
+
+ The amount of time to wait for the connection to become available before erroring out
+
+
+
+
+ The type of the command. SQLite only supports CommandType.Text
+
+
+
+
+ The connection associated with this command
+
+
+
+
+ Forwards to the local Connection property
+
+
+
+
+ Returns the SQLiteParameterCollection for the given command
+
+
+
+
+ Forwards to the local Parameters property
+
+
+
+
+ The transaction associated with this command. SQLite only supports one transaction per connection, so this property forwards to the
+ command's underlying connection.
+
+
+
+
+ Forwards to the local Transaction property
+
+
+
+
+ Sets the method the SQLiteCommandBuilder uses to determine how to update inserted or updated rows in a DataTable.
+
+
+
+
+ Determines if the command is visible at design time. Defaults to True.
+
+
+
+
+ SQLite implementation of DbCommandBuilder.
+
+
+
+
+ Default constructor
+
+
+
+
+ Initializes the command builder and associates it with the specified data adapter.
+
+
+
+
+
+ Minimal amount of parameter processing. Primarily sets the DbType for the parameter equal to the provider type in the schema
+
+ The parameter to use in applying custom behaviors to a row
+ The row to apply the parameter to
+ The type of statement
+ Whether the application of the parameter is part of a WHERE clause
+
+
+
+ Returns a valid named parameter
+
+ The name of the parameter
+ Error
+
+
+
+ Returns a named parameter for the given ordinal
+
+ The i of the parameter
+ Error
+
+
+
+ Returns a placeholder character for the specified parameter i.
+
+ The index of the parameter to provide a placeholder for
+ Returns a named parameter
+
+
+
+ Sets the handler for receiving row updating events. Used by the DbCommandBuilder to autogenerate SQL
+ statements that may not have previously been generated.
+
+ A data adapter to receive events on.
+
+
+
+ Returns the automatically-generated SQLite command to delete rows from the database
+
+
+
+
+
+ Returns the automatically-generated SQLite command to delete rows from the database
+
+
+
+
+
+
+ Returns the automatically-generated SQLite command to update rows in the database
+
+
+
+
+
+ Returns the automatically-generated SQLite command to update rows in the database
+
+
+
+
+
+
+ Returns the automatically-generated SQLite command to insert rows into the database
+
+
+
+
+
+ Returns the automatically-generated SQLite command to insert rows into the database
+
+
+
+
+
+
+ Places brackets around an identifier
+
+ The identifier to quote
+ The bracketed identifier
+
+
+
+ Removes brackets around an identifier
+
+ The quoted (bracketed) identifier
+ The undecorated identifier
+
+
+
+ Override helper, which can help the base command builder choose the right keys for the given query
+
+
+
+
+
+
+ Gets/sets the DataAdapter for this CommandBuilder
+
+
+
+
+ Overridden to hide its property from the designer
+
+
+
+
+ Overridden to hide its property from the designer
+
+
+
+
+ Overridden to hide its property from the designer
+
+
+
+
+ Overridden to hide its property from the designer
+
+
+
+
+ Overridden to hide its property from the designer
+
+
+
+
+ Event data for connection event handlers.
+
+
+
+
+ The type of event being raised.
+
+
+
+
+ The associated with this event, if any.
+
+
+
+
+ The transaction associated with this event, if any.
+
+
+
+
+ The command associated with this event, if any.
+
+
+
+
+ The data reader associated with this event, if any.
+
+
+
+
+ The critical handle associated with this event, if any.
+
+
+
+
+ Command or message text associated with this event, if any.
+
+
+
+
+ Extra data associated with this event, if any.
+
+
+
+
+ Constructs the object.
+
+ The type of event being raised.
+ The base associated
+ with this event, if any.
+ The transaction associated with this event, if any.
+ The command associated with this event, if any.
+ The data reader associated with this event, if any.
+ The critical handle associated with this event, if any.
+ The command or message text, if any.
+ The extra data, if any.
+
+
+
+ Raised when an event pertaining to a connection occurs.
+
+ The connection involved.
+ Extra information about the event.
+
+
+
+ SQLite implentation of DbConnection.
+
+
+ The property can contain the following parameter(s), delimited with a semi-colon:
+
+
+ Parameter
+ Values
+ Required
+ Default
+
+ -
+
Data Source
+
+ This may be a file name, the string ":memory:", or any supported URI (starting with SQLite 3.7.7).
+ Starting with release 1.0.86.0, in order to use more than one consecutive backslash (e.g. for a
+ UNC path), each of the adjoining backslash characters must be doubled (e.g. "\\Network\Share\test.db"
+ would become "\\\\Network\Share\test.db").
+
+ Y
+
+
+ -
+
Version
+ 3
+ N
+ 3
+
+ -
+
UseUTF16Encoding
+ True False
+ N
+ False
+
+ -
+
DateTimeFormat
+
+ Ticks - Use the value of DateTime.Ticks.
+ ISO8601 - Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC
+ DateTime values and "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+ JulianDay - The interval of time in days and fractions of a day since January 1, 4713 BC.
+ UnixEpoch - The whole number of seconds since the Unix epoch (January 1, 1970).
+ InvariantCulture - Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+ CurrentCulture - Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+ N
+ ISO8601
+
+ -
+
DateTimeKind
+ Unspecified - Not specified as either UTC or local time.Utc - The time represented is UTC.Local - The time represented is local time.
+ N
+ Unspecified
+
+ -
+
DateTimeFormatString
+ The exact DateTime format string to use for all formatting and parsing of all DateTime
+ values for this connection.
+ N
+ null
+
+ -
+
BaseSchemaName
+ Some base data classes in the framework (e.g. those that build SQL queries dynamically)
+ assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting
+ alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used
+ as a placeholder and removed prior to preparing any SQL statements that may contain it.
+ N
+ sqlite_default_schema
+
+ -
+
BinaryGUID
+ True - Store GUID columns in binary formFalse - Store GUID columns as text
+ N
+ True
+
+ -
+
Cache Size
+ {size in bytes}
+ N
+ 2000
+
+ -
+
Synchronous
+ Normal - Normal file flushing behaviorFull - Full flushing after all writesOff - Underlying OS flushes I/O's
+ N
+ Full
+
+ -
+
Page Size
+ {size in bytes}
+ N
+ 1024
+
+ -
+
Password
+ {password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.
+ N
+
+
+ -
+
HexPassword
+ {hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix. Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.
+ N
+
+
+ -
+
Enlist
+ Y - Automatically enlist in distributed transactionsN - No automatic enlistment
+ N
+ Y
+
+ -
+
Pooling
+
+ True - Use connection pooling.
+ False - Do not use connection pooling.
+ WARNING: When using the default connection pool implementation,
+ setting this property to True should be avoided by applications that make
+ use of COM (either directly or indirectly) due to possible deadlocks that
+ can occur during the finalization of some COM objects.
+
+ N
+ False
+
+ -
+
FailIfMissing
+ True - Don't create the database if it does not exist, throw an error insteadFalse - Automatically create the database if it does not exist
+ N
+ False
+
+ -
+
Max Page Count
+ {size in pages} - Limits the maximum number of pages (limits the size) of the database
+ N
+ 0
+
+ -
+
Legacy Format
+ True - Use the more compatible legacy 3.x database formatFalse - Use the newer 3.3x database format which compresses numbers more effectively
+ N
+ False
+
+ -
+
Default Timeout
+ {time in seconds} The default command timeout
+ N
+ 30
+
+ -
+
Journal Mode
+ Delete - Delete the journal file after a commitPersist - Zero out and leave the journal file on disk after a commitOff - Disable the rollback journal entirely
+ N
+ Delete
+
+ -
+
Read Only
+ True - Open the database for read only accessFalse - Open the database for normal read/write access
+ N
+ False
+
+ -
+
Max Pool Size
+ The maximum number of connections for the given connection string that can be in the connection pool
+ N
+ 100
+
+ -
+
Default IsolationLevel
+ The default transaciton isolation level
+ N
+ Serializable
+
+ -
+
Foreign Keys
+ Enable foreign key constraints
+ N
+ False
+
+ -
+
Flags
+ Extra behavioral flags for the connection. See the enumeration for possible values.
+ N
+ Default
+
+ -
+
SetDefaults
+
+ True - Apply the default connection settings to the opened database.
+ False - Skip applying the default connection settings to the opened database.
+
+ N
+ True
+
+ -
+
ToFullPath
+
+ True - Attempt to expand the data source file name to a fully qualified path before opening.
+ False - Skip attempting to expand the data source file name to a fully qualified path before opening.
+
+ N
+ True
+
+
+
+
+
+
+ The "invalid value" for the enumeration used
+ by the property. This constant is shared
+ by this class and the SQLiteConnectionStringBuilder class.
+
+
+
+
+ The default "stub" (i.e. placeholder) base schema name to use when
+ returning column schema information. Used as the initial value of
+ the BaseSchemaName property. This should start with "sqlite_*"
+ because those names are reserved for use by SQLite (i.e. they cannot
+ be confused with the names of user objects).
+
+
+
+
+ The managed assembly containing this type.
+
+
+
+
+ Object used to synchronize access to the static instance data
+ for this class.
+
+
+
+
+ The extra connection flags to be used for all opened connections.
+
+
+
+
+ Used to hold the active library version number of SQLite.
+
+
+
+
+ State of the current connection
+
+
+
+
+ The connection string
+
+
+
+
+ Nesting level of the transactions open on the connection
+
+
+
+
+ If set, then the connection is currently being disposed.
+
+
+
+
+ The default isolation level for new transactions
+
+
+
+
+ Whether or not the connection is enlisted in a distrubuted transaction
+
+
+
+
+ The per-connection mappings between type names and
+ values. These mappings override the corresponding global mappings.
+
+
+
+
+ The base SQLite object to interop with
+
+
+
+
+ The database filename minus path and extension
+
+
+
+
+ Temporary password storage, emptied after the database has been opened
+
+
+
+
+ The "stub" (i.e. placeholder) base schema name to use when returning
+ column schema information.
+
+
+
+
+ The extra behavioral flags for this connection, if any. See the
+ enumeration for a list of
+ possible values.
+
+
+
+
+ The cached values for all settings that have been fetched on behalf
+ of this connection. This cache may be cleared by calling the
+ method.
+
+
+
+
+ The default databse type for this connection. This value will only
+ be used if the
+ flag is set.
+
+
+
+
+ The default databse type name for this connection. This value will only
+ be used if the
+ flag is set.
+
+
+
+
+ Default command timeout
+
+
+
+
+ Non-zero if the built-in (i.e. framework provided) connection string
+ parser should be used when opening the connection.
+
+
+
+
+ Constructs a new SQLiteConnection object
+
+
+ Default constructor
+
+
+
+
+ Initializes the connection with the specified connection string.
+
+ The connection string to use.
+
+
+
+ Initializes the connection with a pre-existing native connection handle.
+ This constructor overload is intended to be used only by the private
+ method.
+
+
+ The native connection handle to use.
+
+
+ The file name corresponding to the native connection handle.
+
+
+ Non-zero if this instance owns the native connection handle and
+ should dispose of it when it is no longer needed.
+
+
+
+
+ Initializes the connection with the specified connection string.
+
+
+ The connection string to use.
+
+
+ Non-zero to parse the connection string using the built-in (i.e.
+ framework provided) parser when opening the connection.
+
+
+
+
+ Clones the settings and connection string from an existing connection. If the existing connection is already open, this
+ function will open its own connection, enumerate any attached databases of the original connection, and automatically
+ attach to them.
+
+ The connection to copy the settings from.
+
+
+
+ Raises the event.
+
+
+ The connection associated with this event. If this parameter is not
+ null and the specified connection cannot raise events, then the
+ registered event handlers will not be invoked.
+
+
+ A that contains the event data.
+
+
+
+
+ Creates and returns a new managed database connection handle. This
+ method is intended to be used by implementations of the
+ interface only. In theory, it
+ could be used by other classes; however, that usage is not supported.
+
+
+ This must be a native database connection handle returned by the
+ SQLite core library and it must remain valid and open during the
+ entire duration of the calling method.
+
+
+ The new managed database connection handle or null if it cannot be
+ created.
+
+
+
+
+ Backs up the database, using the specified database connection as the
+ destination.
+
+ The destination database connection.
+ The destination database name.
+ The source database name.
+
+ The number of pages to copy or negative to copy all remaining pages.
+
+
+ The method to invoke between each step of the backup process. This
+ parameter may be null (i.e. no callbacks will be performed).
+
+
+ The number of milliseconds to sleep after encountering a locking error
+ during the backup process. A value less than zero means that no sleep
+ should be performed.
+
+
+
+
+ Clears the per-connection cached settings.
+
+
+ The total number of per-connection settings cleared.
+
+
+
+
+ Queries and returns the value of the specified setting, using the
+ cached setting names and values for this connection, when available.
+
+
+ The name of the setting.
+
+
+ The value to be returned if the setting has not been set explicitly
+ or cannot be determined.
+
+
+ The value of the cached setting is stored here if found; otherwise,
+ the value of is stored here.
+
+
+ Non-zero if the cached setting was found; otherwise, zero.
+
+
+
+
+ Adds or sets the cached setting specified by
+ to the value specified by .
+
+
+ The name of the cached setting to add or replace.
+
+
+ The new value of the cached setting.
+
+
+
+
+ Clears the per-connection type mappings.
+
+
+ The total number of per-connection type mappings cleared.
+
+
+
+
+ Returns the per-connection type mappings.
+
+
+ The per-connection type mappings -OR- null if they are unavailable.
+
+
+
+
+ Adds a per-connection type mapping, possibly replacing one or more
+ that already exist.
+
+
+ The case-insensitive database type name (e.g. "MYDATE"). The value
+ of this parameter cannot be null. Using an empty string value (or
+ a string value consisting entirely of whitespace) for this parameter
+ is not recommended.
+
+
+ The value that should be associated with the
+ specified type name.
+
+
+ Non-zero if this mapping should be considered to be the primary one
+ for the specified .
+
+
+ A negative value if nothing was done. Zero if no per-connection type
+ mappings were replaced (i.e. it was a pure add operation). More than
+ zero if some per-connection type mappings were replaced.
+
+
+
+
+ Attempts to bind the specified object
+ instance to this connection.
+
+
+ The object instance containing
+ the metadata for the function to be bound.
+
+
+ The object instance that implements the
+ function to be bound.
+
+
+
+
+ Creates a clone of the connection. All attached databases and user-defined functions are cloned. If the existing connection is open, the cloned connection
+ will also be opened.
+
+
+
+
+
+ Creates a database file. This just creates a zero-byte file which SQLite
+ will turn into a database when the file is opened properly.
+
+ The file to create
+
+
+
+ Raises the state change event when the state of the connection changes
+
+ The new connection state. If this is different
+ from the previous state, the event is
+ raised.
+ The event data created for the raised event, if
+ it was actually raised.
+
+
+
+ Determines and returns the fallback default isolation level when one cannot be
+ obtained from an existing connection instance.
+
+
+ The fallback default isolation level for this connection instance -OR-
+ if it cannot be determined.
+
+
+
+
+ Determines and returns the default isolation level for this connection instance.
+
+
+ The default isolation level for this connection instance -OR-
+ if it cannot be determined.
+
+
+
+
+ OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection.
+
+ This parameter is ignored.
+ When TRUE, SQLite defers obtaining a write lock until a write operation is requested.
+ When FALSE, a writelock is obtained immediately. The default is TRUE, but in a multi-threaded multi-writer
+ environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock.
+ Returns a SQLiteTransaction object.
+
+
+
+ OBSOLETE. Creates a new SQLiteTransaction if one isn't already active on the connection.
+
+ When TRUE, SQLite defers obtaining a write lock until a write operation is requested.
+ When FALSE, a writelock is obtained immediately. The default is false, but in a multi-threaded multi-writer
+ environment, one may instead choose to lock the database immediately to avoid any possible writer deadlock.
+ Returns a SQLiteTransaction object.
+
+
+
+ Creates a new if one isn't already active on the connection.
+
+ Supported isolation levels are Serializable, ReadCommitted and Unspecified.
+
+ Unspecified will use the default isolation level specified in the connection string. If no isolation level is specified in the
+ connection string, Serializable is used.
+ Serializable transactions are the default. In this mode, the engine gets an immediate lock on the database, and no other threads
+ may begin a transaction. Other threads may read from the database, but not write.
+ With a ReadCommitted isolation level, locks are deferred and elevated as needed. It is possible for multiple threads to start
+ a transaction in ReadCommitted mode, but if a thread attempts to commit a transaction while another thread
+ has a ReadCommitted lock, it may timeout or cause a deadlock on both threads until both threads' CommandTimeout's are reached.
+
+ Returns a SQLiteTransaction object.
+
+
+
+ Creates a new if one isn't already
+ active on the connection.
+
+ Returns the new transaction object.
+
+
+
+ Forwards to the local function
+
+ Supported isolation levels are Unspecified, Serializable, and ReadCommitted
+
+
+
+
+ This method is not implemented; however, the
+ event will still be raised.
+
+
+
+
+
+ When the database connection is closed, all commands linked to this connection are automatically reset.
+
+
+
+
+ Clears the connection pool associated with the connection. Any other active connections using the same database file
+ will be discarded instead of returned to the pool when they are closed.
+
+
+
+
+
+ Clears all connection pools. Any active connections will be discarded instead of sent to the pool when they are closed.
+
+
+
+
+ Create a new and associate it with this connection.
+
+ Returns a new command object already assigned to this connection.
+
+
+
+ Forwards to the local function.
+
+
+
+
+
+ Parses the connection string into component parts using the custom
+ connection string parser.
+
+ The connection string to parse
+ An array of key-value pairs representing each parameter of the connection string
+
+
+
+ Parses a connection string using the built-in (i.e. framework provided)
+ connection string parser class and returns the key/value pairs. An
+ exception may be thrown if the connection string is invalid or cannot be
+ parsed. When compiled for the .NET Compact Framework, the custom
+ connection string parser is always used instead because the framework
+ provided one is unavailable there.
+
+
+ The connection string to parse.
+
+
+ Non-zero to throw an exception if any connection string values are not of
+ the type.
+
+ The list of key/value pairs.
+
+
+
+ Manual distributed transaction enlistment support
+
+ The distributed transaction to enlist in
+
+
+
+ Looks for a key in the array of key/values of the parameter string. If not found, return the specified default value
+
+ The list to look in
+ The key to find
+ The default value to return if the key is not found
+ The value corresponding to the specified key, or the default value if not found.
+
+
+
+ Attempts to convert the string value to an enumerated value of the specified type.
+
+ The enumerated type to convert the string value to.
+ The string value to be converted.
+ Non-zero to make the conversion case-insensitive.
+ The enumerated value upon success or null upon error.
+
+
+
+ Attempts to convert an input string into a byte value.
+
+
+ The string value to be converted.
+
+
+ The number styles to use for the conversion.
+
+
+ Upon sucess, this will contain the parsed byte value.
+ Upon failure, the value of this parameter is undefined.
+
+
+ Non-zero upon success; zero on failure.
+
+
+
+
+ Enables or disabled extension loading.
+
+
+ True to enable loading of extensions, false to disable.
+
+
+
+
+ Loads a SQLite extension library from the named dynamic link library file.
+
+
+ The name of the dynamic link library file containing the extension.
+
+
+
+
+ Loads a SQLite extension library from the named dynamic link library file.
+
+
+ The name of the dynamic link library file containing the extension.
+
+
+ The name of the exported function used to initialize the extension.
+ If null, the default "sqlite3_extension_init" will be used.
+
+
+
+
+ Creates a disposable module containing the implementation of a virtual
+ table.
+
+
+ The module object to be used when creating the disposable module.
+
+
+
+
+ Parses a string containing a sequence of zero or more hexadecimal
+ encoded byte values and returns the resulting byte array. The
+ "0x" prefix is not allowed on the input string.
+
+
+ The input string containing zero or more hexadecimal encoded byte
+ values.
+
+
+ A byte array containing the parsed byte values or null if an error
+ was encountered.
+
+
+
+
+ Creates and returns a string containing the hexadecimal encoded byte
+ values from the input array.
+
+
+ The input array of bytes.
+
+
+ The resulting string or null upon failure.
+
+
+
+
+ Parses a string containing a sequence of zero or more hexadecimal
+ encoded byte values and returns the resulting byte array. The
+ "0x" prefix is not allowed on the input string.
+
+
+ The input string containing zero or more hexadecimal encoded byte
+ values.
+
+
+ Upon failure, this will contain an appropriate error message.
+
+
+ A byte array containing the parsed byte values or null if an error
+ was encountered.
+
+
+
+
+ This method figures out what the default connection pool setting should
+ be based on the connection flags. When present, the "Pooling" connection
+ string property value always overrides the value returned by this method.
+
+
+ Non-zero if the connection pool should be enabled by default; otherwise,
+ zero.
+
+
+
+
+ Determines the transaction isolation level that should be used by
+ the caller, primarily based upon the one specified by the caller.
+ If mapping of transaction isolation levels is enabled, the returned
+ transaction isolation level may be significantly different than the
+ originally specified one.
+
+
+ The originally specified transaction isolation level.
+
+
+ The transaction isolation level that should be used.
+
+
+
+
+ Opens the connection using the parameters found in the .
+
+
+
+
+ Opens the connection using the parameters found in the and then returns it.
+
+ The current connection object.
+
+
+
+ This method causes any pending database operation to abort and return at
+ its earliest opportunity. This routine is typically called in response
+ to a user action such as pressing "Cancel" or Ctrl-C where the user wants
+ a long query operation to halt immediately. It is safe to call this
+ routine from any thread. However, it is not safe to call this routine
+ with a database connection that is closed or might close before this method
+ returns.
+
+
+
+
+ Returns various global memory statistics for the SQLite core library via
+ a dictionary of key/value pairs. Currently, only the "MemoryUsed" and
+ "MemoryHighwater" keys are returned and they have values that correspond
+ to the values that could be obtained via the
+ and connection properties.
+
+
+ This dictionary will be populated with the global memory statistics. It
+ will be created if necessary.
+
+
+
+
+ Attempts to free as much heap memory as possible for this database connection.
+
+
+
+
+ Attempts to free N bytes of heap memory by deallocating non-essential memory
+ allocations held by the database library. Memory used to cache database pages
+ to improve performance is an example of non-essential memory. This is a no-op
+ returning zero if the SQLite core library was not compiled with the compile-time
+ option SQLITE_ENABLE_MEMORY_MANAGEMENT. Optionally, attempts to reset and/or
+ compact the Win32 native heap, if applicable.
+
+
+ The requested number of bytes to free.
+
+
+ Non-zero to attempt a heap reset.
+
+
+ Non-zero to attempt heap compaction.
+
+
+ The number of bytes actually freed. This value may be zero.
+
+
+ This value will be non-zero if the heap reset was successful.
+
+
+ The size of the largest committed free block in the heap, in bytes.
+ This value will be zero unless heap compaction is enabled.
+
+
+ A standard SQLite return code (i.e. zero for success and non-zero
+ for failure).
+
+
+
+
+ Sets the status of the memory usage tracking subsystem in the SQLite core library. By default, this is enabled.
+ If this is disabled, memory usage tracking will not be performed. This is not really a per-connection value, it is
+ global to the process.
+
+ Non-zero to enable memory usage tracking, zero otherwise.
+ A standard SQLite return code (i.e. zero for success and non-zero for failure).
+
+
+
+ Passes a shutdown request to the SQLite core library. Does not throw
+ an exception if the shutdown request fails.
+
+
+ A standard SQLite return code (i.e. zero for success and non-zero for
+ failure).
+
+
+
+
+ Passes a shutdown request to the SQLite core library. Throws an
+ exception if the shutdown request fails and the no-throw parameter
+ is non-zero.
+
+
+ Non-zero to reset the database and temporary directories to their
+ default values, which should be null for both.
+
+
+ When non-zero, throw an exception if the shutdown request fails.
+
+
+
+ Enables or disabled extended result codes returned by SQLite
+
+
+ Enables or disabled extended result codes returned by SQLite
+
+
+ Enables or disabled extended result codes returned by SQLite
+
+
+ Add a log message via the SQLite sqlite3_log interface.
+
+
+ Add a log message via the SQLite sqlite3_log interface.
+
+
+
+ Change the password (or assign a password) to an open database.
+
+
+ No readers or writers may be active for this process. The database must already be open
+ and if it already was password protected, the existing password must already have been supplied.
+
+ The new password to assign to the database
+
+
+
+ Change the password (or assign a password) to an open database.
+
+
+ No readers or writers may be active for this process. The database must already be open
+ and if it already was password protected, the existing password must already have been supplied.
+
+ The new password to assign to the database
+
+
+
+ Sets the password for a password-protected database. A password-protected database is
+ unusable for any operation until the password has been set.
+
+ The password for the database
+
+
+
+ Sets the password for a password-protected database. A password-protected database is
+ unusable for any operation until the password has been set.
+
+ The password for the database
+
+
+
+ Queries or modifies the number of retries or the retry interval (in milliseconds) for
+ certain I/O operations that may fail due to anti-virus software.
+
+ The number of times to retry the I/O operation. A negative value
+ will cause the current count to be queried and replace that negative value.
+ The number of milliseconds to wait before retrying the I/O
+ operation. This number is multiplied by the number of retry attempts so far to come
+ up with the final number of milliseconds to wait. A negative value will cause the
+ current interval to be queried and replace that negative value.
+ Zero for success, non-zero for error.
+
+
+
+ Sets the chunk size for the primary file associated with this database
+ connection.
+
+
+ The new chunk size for the main database, in bytes.
+
+
+ Zero for success, non-zero for error.
+
+
+
+
+ Removes one set of surrounding single -OR- double quotes from the string
+ value and returns the resulting string value. If the string is null, empty,
+ or contains quotes that are not balanced, nothing is done and the original
+ string value will be returned.
+
+ The string value to process.
+
+ The string value, modified to remove one set of surrounding single -OR-
+ double quotes, if applicable.
+
+
+
+
+ Expand the filename of the data source, resolving the |DataDirectory|
+ macro as appropriate.
+
+ The database filename to expand
+
+ Non-zero if the returned file name should be converted to a full path
+ (except when using the .NET Compact Framework).
+
+ The expanded path and filename of the filename
+
+
+
+ The following commands are used to extract schema information out of the database. Valid schema types are:
+
+ -
+
MetaDataCollections
+
+ -
+
DataSourceInformation
+
+ -
+
Catalogs
+
+ -
+
Columns
+
+ -
+
ForeignKeys
+
+ -
+
Indexes
+
+ -
+
IndexColumns
+
+ -
+
Tables
+
+ -
+
Views
+
+ -
+
ViewColumns
+
+
+
+
+ Returns the MetaDataCollections schema
+
+ A DataTable of the MetaDataCollections schema
+
+
+
+ Returns schema information of the specified collection
+
+ The schema collection to retrieve
+ A DataTable of the specified collection
+
+
+
+ Retrieves schema information using the specified constraint(s) for the specified collection
+
+ The collection to retrieve
+ The restrictions to impose
+ A DataTable of the specified collection
+
+
+
+ Builds a MetaDataCollections schema datatable
+
+ DataTable
+
+
+
+ Builds a DataSourceInformation datatable
+
+ DataTable
+
+
+
+ Build a Columns schema
+
+ The catalog (attached database) to query, can be null
+ The table to retrieve schema information for, must not be null
+ The column to retrieve schema information for, can be null
+ DataTable
+
+
+
+ Returns index information for the given database and catalog
+
+ The catalog (attached database) to query, can be null
+ The name of the index to retrieve information for, can be null
+ The table to retrieve index information for, can be null
+ DataTable
+
+
+
+ Retrieves table schema information for the database and catalog
+
+ The catalog (attached database) to retrieve tables on
+ The table to retrieve, can be null
+ The table type, can be null
+ DataTable
+
+
+
+ Retrieves view schema information for the database
+
+ The catalog (attached database) to retrieve views on
+ The view name, can be null
+ DataTable
+
+
+
+ Retrieves catalog (attached databases) schema information for the database
+
+ The catalog to retrieve, can be null
+ DataTable
+
+
+
+ Returns the base column information for indexes in a database
+
+ The catalog to retrieve indexes for (can be null)
+ The table to restrict index information by (can be null)
+ The index to restrict index information by (can be null)
+ The source column to restrict index information by (can be null)
+ A DataTable containing the results
+
+
+
+ Returns detailed column information for a specified view
+
+ The catalog to retrieve columns for (can be null)
+ The view to restrict column information by (can be null)
+ The source column to restrict column information by (can be null)
+ A DataTable containing the results
+
+
+
+ Retrieves foreign key information from the specified set of filters
+
+ An optional catalog to restrict results on
+ An optional table to restrict results on
+ An optional foreign key name to restrict results on
+ A DataTable with the results of the query
+
+
+
+ Static variable to store the connection event handlers to call.
+
+
+
+
+ This event is raised whenever the database is opened or closed.
+
+
+
+
+ This event is raised when events related to the lifecycle of a
+ SQLiteConnection object occur.
+
+
+
+
+ This property is used to obtain or set the custom connection pool
+ implementation to use, if any. Setting this property to null will
+ cause the default connection pool implementation to be used.
+
+
+
+
+ Returns the number of pool entries for the file name associated with this connection.
+
+
+
+
+ The connection string containing the parameters for the connection
+
+
+
+
+ Parameter
+ Values
+ Required
+ Default
+
+ -
+
Data Source
+
+ This may be a file name, the string ":memory:", or any supported URI (starting with SQLite 3.7.7).
+ Starting with release 1.0.86.0, in order to use more than one consecutive backslash (e.g. for a
+ UNC path), each of the adjoining backslash characters must be doubled (e.g. "\\Network\Share\test.db"
+ would become "\\\\Network\Share\test.db").
+
+ Y
+
+
+ -
+
Version
+ 3
+ N
+ 3
+
+ -
+
UseUTF16Encoding
+ True False
+ N
+ False
+
+ -
+
DateTimeFormat
+
+ Ticks - Use the value of DateTime.Ticks.
+ ISO8601 - Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC
+ DateTime values and "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+ JulianDay - The interval of time in days and fractions of a day since January 1, 4713 BC.
+ UnixEpoch - The whole number of seconds since the Unix epoch (January 1, 1970).
+ InvariantCulture - Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+ CurrentCulture - Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+ N
+ ISO8601
+
+ -
+
DateTimeKind
+ Unspecified - Not specified as either UTC or local time.Utc - The time represented is UTC.Local - The time represented is local time.
+ N
+ Unspecified
+
+ -
+
DateTimeFormatString
+ The exact DateTime format string to use for all formatting and parsing of all DateTime
+ values for this connection.
+ N
+ null
+
+ -
+
BaseSchemaName
+ Some base data classes in the framework (e.g. those that build SQL queries dynamically)
+ assume that an ADO.NET provider cannot support an alternate catalog (i.e. database) without supporting
+ alternate schemas as well; however, SQLite does not fit into this model. Therefore, this value is used
+ as a placeholder and removed prior to preparing any SQL statements that may contain it.
+ N
+ sqlite_default_schema
+
+ -
+
BinaryGUID
+ True - Store GUID columns in binary formFalse - Store GUID columns as text
+ N
+ True
+
+ -
+
Cache Size
+ {size in bytes}
+ N
+ 2000
+
+ -
+
Synchronous
+ Normal - Normal file flushing behaviorFull - Full flushing after all writesOff - Underlying OS flushes I/O's
+ N
+ Full
+
+ -
+
Page Size
+ {size in bytes}
+ N
+ 1024
+
+ -
+
Password
+ {password} - Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.
+ N
+
+
+ -
+
HexPassword
+ {hexPassword} - Must contain a sequence of zero or more hexadecimal encoded byte values without a leading "0x" prefix. Using this parameter requires that the CryptoAPI based codec be enabled at compile-time for both the native interop assembly and the core managed assemblies; otherwise, using this parameter may result in an exception being thrown when attempting to open the connection.
+ N
+
+
+ -
+
Enlist
+ Y - Automatically enlist in distributed transactionsN - No automatic enlistment
+ N
+ Y
+
+ -
+
Pooling
+
+ True - Use connection pooling.
+ False - Do not use connection pooling.
+ WARNING: When using the default connection pool implementation,
+ setting this property to True should be avoided by applications that
+ make use of COM (either directly or indirectly) due to possible
+ deadlocks that can occur during the finalization of some COM objects.
+
+ N
+ False
+
+ -
+
FailIfMissing
+ True - Don't create the database if it does not exist, throw an error insteadFalse - Automatically create the database if it does not exist
+ N
+ False
+
+ -
+
Max Page Count
+ {size in pages} - Limits the maximum number of pages (limits the size) of the database
+ N
+ 0
+
+ -
+
Legacy Format
+ True - Use the more compatible legacy 3.x database formatFalse - Use the newer 3.3x database format which compresses numbers more effectively
+ N
+ False
+
+ -
+
Default Timeout
+ {time in seconds} The default command timeout
+ N
+ 30
+
+ -
+
Journal Mode
+ Delete - Delete the journal file after a commitPersist - Zero out and leave the journal file on disk after a commitOff - Disable the rollback journal entirely
+ N
+ Delete
+
+ -
+
Read Only
+ True - Open the database for read only accessFalse - Open the database for normal read/write access
+ N
+ False
+
+ -
+
Max Pool Size
+ The maximum number of connections for the given connection string that can be in the connection pool
+ N
+ 100
+
+ -
+
Default IsolationLevel
+ The default transaciton isolation level
+ N
+ Serializable
+
+ -
+
Foreign Keys
+ Enable foreign key constraints
+ N
+ False
+
+ -
+
Flags
+ Extra behavioral flags for the connection. See the enumeration for possible values.
+ N
+ Default
+
+ -
+
SetDefaults
+
+ True - Apply the default connection settings to the opened database.
+ False - Skip applying the default connection settings to the opened database.
+
+ N
+ True
+
+ -
+
ToFullPath
+
+ True - Attempt to expand the data source file name to a fully qualified path before opening.
+ False - Skip attempting to expand the data source file name to a fully qualified path before opening.
+
+ N
+ True
+
+
+
+
+
+
+ Returns the data source file name without extension or path.
+
+
+
+
+ Returns the string "main".
+
+
+
+
+ Gets/sets the default command timeout for newly-created commands. This is especially useful for
+ commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible.
+ This can also be set in the ConnectionString with "Default Timeout"
+
+
+
+
+ Non-zero if the built-in (i.e. framework provided) connection string
+ parser should be used when opening the connection.
+
+
+
+
+ Gets/sets the extra behavioral flags for this connection. See the
+ enumeration for a list of
+ possible values.
+
+
+
+
+ Gets/sets the default database type for this connection. This value
+ will only be used when not null.
+
+
+
+
+ Gets/sets the default database type name for this connection. This
+ value will only be used when not null.
+
+
+
+
+ Returns non-zero if the underlying native connection handle is
+ owned by this instance.
+
+
+
+
+ Returns the version of the underlying SQLite database engine
+
+
+
+
+ Returns the rowid of the most recent successful INSERT into the database from this connection.
+
+
+
+
+ Returns the number of rows changed by the last INSERT, UPDATE, or DELETE statement executed on
+ this connection.
+
+
+
+
+ Returns non-zero if the given database connection is in autocommit mode.
+ Autocommit mode is on by default. Autocommit mode is disabled by a BEGIN
+ statement. Autocommit mode is re-enabled by a COMMIT or ROLLBACK.
+
+
+
+
+ Returns the amount of memory (in bytes) currently in use by the SQLite core library.
+
+
+
+
+ Returns the maximum amount of memory (in bytes) used by the SQLite core library since the high-water mark was last reset.
+
+
+
+
+ Returns a string containing the define constants (i.e. compile-time
+ options) used to compile the core managed assembly, delimited with
+ spaces.
+
+
+
+
+ Returns the version of the underlying SQLite core library.
+
+
+
+
+ This method returns the string whose value is the same as the
+ SQLITE_SOURCE_ID C preprocessor macro used when compiling the
+ SQLite core library.
+
+
+
+
+ Returns a string containing the compile-time options used to
+ compile the SQLite core native library, delimited with spaces.
+
+
+
+
+ This method returns the version of the interop SQLite assembly
+ used. If the SQLite interop assembly is not in use or the
+ necessary information cannot be obtained for any reason, a null
+ value may be returned.
+
+
+
+
+ This method returns the string whose value contains the unique
+ identifier for the source checkout used to build the interop
+ assembly. If the SQLite interop assembly is not in use or the
+ necessary information cannot be obtained for any reason, a null
+ value may be returned.
+
+
+
+
+ Returns a string containing the compile-time options used to
+ compile the SQLite interop assembly, delimited with spaces.
+
+
+
+
+ This method returns the version of the managed components used
+ to interact with the SQLite core library. If the necessary
+ information cannot be obtained for any reason, a null value may
+ be returned.
+
+
+
+
+ This method returns the string whose value contains the unique
+ identifier for the source checkout used to build the managed
+ components currently executing. If the necessary information
+ cannot be obtained for any reason, a null value may be returned.
+
+
+
+
+ The extra connection flags to be used for all opened connections.
+
+
+
+
+ Returns the state of the connection.
+
+
+
+
+ This event is raised whenever SQLite encounters an action covered by the
+ authorizer during query preparation. Changing the value of the
+ property will determine if
+ the specific action will be allowed, ignored, or denied. For the entire
+ duration of the event, the associated connection and statement objects
+ must not be modified, either directly or indirectly, by the called code.
+
+
+
+
+ This event is raised whenever SQLite makes an update/delete/insert into the database on
+ this connection. It only applies to the given connection.
+
+
+
+
+ This event is raised whenever SQLite is committing a transaction.
+ Return non-zero to trigger a rollback.
+
+
+
+
+ This event is raised whenever SQLite statement first begins executing on
+ this connection. It only applies to the given connection.
+
+
+
+
+ This event is raised whenever SQLite is rolling back a transaction.
+
+
+
+
+ Returns the instance.
+
+
+
+
+ The I/O file cache flushing behavior for the connection
+
+
+
+
+ Normal file flushing at critical sections of the code
+
+
+
+
+ Full file flushing after every write operation
+
+
+
+
+ Use the default operating system's file flushing, SQLite does not explicitly flush the file buffers after writing
+
+
+
+
+ Raised when authorization is required to perform an action contained
+ within a SQL query.
+
+ The connection performing the action.
+ A that contains the
+ event data.
+
+
+
+ Raised when a transaction is about to be committed. To roll back a transaction, set the
+ rollbackTrans boolean value to true.
+
+ The connection committing the transaction
+ Event arguments on the transaction
+
+
+
+ Raised when data is inserted, updated and deleted on a given connection
+
+ The connection committing the transaction
+ The event parameters which triggered the event
+
+
+
+ Raised when a statement first begins executing on a given connection
+
+ The connection executing the statement
+ Event arguments of the trace
+
+
+
+ Raised between each backup step.
+
+
+ The source database connection.
+
+
+ The source database name.
+
+
+ The destination database connection.
+
+
+ The destination database name.
+
+
+ The number of pages copied with each step.
+
+
+ The number of pages remaining to be copied.
+
+
+ The total number of pages in the source database.
+
+
+ Set to true if the operation needs to be retried due to database
+ locking issues; otherwise, set to false.
+
+
+ True to continue with the backup process or false to halt the backup
+ process, rolling back any changes that have been made so far.
+
+
+
+
+ The data associated with a call into the authorizer.
+
+
+
+
+ The user-defined native data associated with this event. Currently,
+ this will always contain the value of .
+
+
+
+
+ The action code responsible for the current call into the authorizer.
+
+
+
+
+ The first string argument for the current call into the authorizer.
+ The exact value will vary based on the action code, see the
+ enumeration for possible
+ values.
+
+
+
+
+ The second string argument for the current call into the authorizer.
+ The exact value will vary based on the action code, see the
+ enumeration for possible
+ values.
+
+
+
+
+ The database name for the current call into the authorizer, if
+ applicable.
+
+
+
+
+ The name of the inner-most trigger or view that is responsible for
+ the access attempt or a null value if this access attempt is directly
+ from top-level SQL code.
+
+
+
+
+ The return code for the current call into the authorizer.
+
+
+
+
+ Constructs an instance of this class with default property values.
+
+
+
+
+ Constructs an instance of this class with specific property values.
+
+
+ The user-defined native data associated with this event.
+
+
+ The authorizer action code.
+
+
+ The first authorizer argument.
+
+
+ The second authorizer argument.
+
+
+ The database name, if applicable.
+
+
+ The name of the inner-most trigger or view that is responsible for
+ the access attempt or a null value if this access attempt is directly
+ from top-level SQL code.
+
+
+ The authorizer return code.
+
+
+
+
+ Whenever an update event is triggered on a connection, this enum will indicate
+ exactly what type of operation is being performed.
+
+
+
+
+ A row is being deleted from the given database and table
+
+
+
+
+ A row is being inserted into the table.
+
+
+
+
+ A row is being updated in the table.
+
+
+
+
+ Passed during an Update callback, these event arguments detail the type of update operation being performed
+ on the given connection.
+
+
+
+
+ The name of the database being updated (usually "main" but can be any attached or temporary database)
+
+
+
+
+ The name of the table being updated
+
+
+
+
+ The type of update being performed (insert/update/delete)
+
+
+
+
+ The RowId affected by this update.
+
+
+
+
+ Event arguments raised when a transaction is being committed
+
+
+
+
+ Set to true to abort the transaction and trigger a rollback
+
+
+
+
+ Passed during an Trace callback, these event arguments contain the UTF-8 rendering of the SQL statement text
+
+
+
+
+ SQL statement text as the statement first begins executing
+
+
+
+
+ This interface represents a custom connection pool implementation
+ usable by System.Data.SQLite.
+
+
+
+
+ Counts the number of pool entries matching the specified file name.
+
+
+ The file name to match or null to match all files.
+
+
+ The pool entry counts for each matching file.
+
+
+ The total number of connections successfully opened from any pool.
+
+
+ The total number of connections successfully closed from any pool.
+
+
+ The total number of pool entries for all matching files.
+
+
+
+
+ Disposes of all pooled connections associated with the specified
+ database file name.
+
+
+ The database file name.
+
+
+
+
+ Disposes of all pooled connections.
+
+
+
+
+ Adds a connection to the pool of those associated with the
+ specified database file name.
+
+
+ The database file name.
+
+
+ The database connection handle.
+
+
+ The connection pool version at the point the database connection
+ handle was received from the connection pool. This is also the
+ connection pool version that the database connection handle was
+ created under.
+
+
+
+
+ Removes a connection from the pool of those associated with the
+ specified database file name with the intent of using it to
+ interact with the database.
+
+
+ The database file name.
+
+
+ The new maximum size of the connection pool for the specified
+ database file name.
+
+
+ The connection pool version associated with the returned database
+ connection handle, if any.
+
+
+ The database connection handle associated with the specified
+ database file name or null if it cannot be obtained.
+
+
+
+
+ This default method implementations in this class should not be used by
+ applications that make use of COM (either directly or indirectly) due
+ to possible deadlocks that can occur during finalization of some COM
+ objects.
+
+
+
+
+ This field is used to synchronize access to the private static data
+ in this class.
+
+
+
+
+ When this field is non-null, it will be used to provide the
+ implementation of all the connection pool methods; otherwise,
+ the default method implementations will be used.
+
+
+
+
+ The dictionary of connection pools, based on the normalized file
+ name of the SQLite database.
+
+
+
+
+ The default version number new pools will get.
+
+
+
+
+ The number of connections successfully opened from any pool.
+ This value is incremented by the Remove method.
+
+
+
+
+ The number of connections successfully closed from any pool.
+ This value is incremented by the Add method.
+
+
+
+
+ Counts the number of pool entries matching the specified file name.
+
+
+ The file name to match or null to match all files.
+
+
+ The pool entry counts for each matching file.
+
+
+ The total number of connections successfully opened from any pool.
+
+
+ The total number of connections successfully closed from any pool.
+
+
+ The total number of pool entries for all matching files.
+
+
+
+
+ Disposes of all pooled connections associated with the specified
+ database file name.
+
+
+ The database file name.
+
+
+
+
+ Disposes of all pooled connections.
+
+
+
+
+ Adds a connection to the pool of those associated with the
+ specified database file name.
+
+
+ The database file name.
+
+
+ The database connection handle.
+
+
+ The connection pool version at the point the database connection
+ handle was received from the connection pool. This is also the
+ connection pool version that the database connection handle was
+ created under.
+
+
+
+
+ Removes a connection from the pool of those associated with the
+ specified database file name with the intent of using it to
+ interact with the database.
+
+
+ The database file name.
+
+
+ The new maximum size of the connection pool for the specified
+ database file name.
+
+
+ The connection pool version associated with the returned database
+ connection handle, if any.
+
+
+ The database connection handle associated with the specified
+ database file name or null if it cannot be obtained.
+
+
+
+
+ This method is used to obtain a reference to the custom connection
+ pool implementation currently in use, if any.
+
+
+ The custom connection pool implementation or null if the default
+ connection pool implementation should be used.
+
+
+
+
+ This method is used to set the reference to the custom connection
+ pool implementation to use, if any.
+
+
+ The custom connection pool implementation to use or null if the
+ default connection pool implementation should be used.
+
+
+
+
+ We do not have to thread-lock anything in this function, because it
+ is only called by other functions above which already take the lock.
+
+
+ The pool queue to resize.
+
+
+ If a function intends to add to the pool, this is true, which
+ forces the resize to take one more than it needs from the pool.
+
+
+
+
+ Keeps track of connections made on a specified file. The PoolVersion
+ dictates whether old objects get returned to the pool or discarded
+ when no longer in use.
+
+
+
+
+ The queue of weak references to the actual database connection
+ handles.
+
+
+
+
+ This pool version associated with the database connection
+ handles in this pool queue.
+
+
+
+
+ The maximum size of this pool queue.
+
+
+
+
+ Constructs a connection pool queue using the specified version
+ and maximum size. Normally, all the database connection
+ handles in this pool are associated with a single database file
+ name.
+
+
+ The initial pool version for this connection pool queue.
+
+
+ The initial maximum size for this connection pool queue.
+
+
+
+
+ SQLite implementation of DbConnectionStringBuilder.
+
+
+
+
+ Properties of this class
+
+
+
+
+ Constructs a new instance of the class
+
+
+ Default constructor
+
+
+
+
+ Constructs a new instance of the class using the specified connection string.
+
+ The connection string to parse
+
+
+
+ Private initializer, which assigns the connection string and resets the builder
+
+ The connection string to assign
+
+
+
+ Helper function for retrieving values from the connectionstring
+
+ The keyword to retrieve settings for
+ The resulting parameter value
+ Returns true if the value was found and returned
+
+
+
+ Fallback method for MONO, which doesn't implement DbConnectionStringBuilder.GetProperties()
+
+ The hashtable to fill with property descriptors
+
+
+
+ Gets/Sets the default version of the SQLite engine to instantiate. Currently the only valid value is 3, indicating version 3 of the sqlite library.
+
+
+
+
+ Gets/Sets the synchronization mode (file flushing) of the connection string. Default is "Normal".
+
+
+
+
+ Gets/Sets the encoding for the connection string. The default is "False" which indicates UTF-8 encoding.
+
+
+
+
+ Gets/Sets whether or not to use connection pooling. The default is "False"
+
+
+
+
+ Gets/Sets whethor not to store GUID's in binary format. The default is True
+ which saves space in the database.
+
+
+
+
+ Gets/Sets the filename to open on the connection string.
+
+
+
+
+ An alternate to the data source property
+
+
+
+
+ An alternate to the data source property that uses the SQLite URI syntax.
+
+
+
+
+ Gets/sets the default command timeout for newly-created commands. This is especially useful for
+ commands used internally such as inside a SQLiteTransaction, where setting the timeout is not possible.
+
+
+
+
+ Determines whether or not the connection will automatically participate
+ in the current distributed transaction (if one exists)
+
+
+
+
+ If set to true, will throw an exception if the database specified in the connection
+ string does not exist. If false, the database will be created automatically.
+
+
+
+
+ If enabled, uses the legacy 3.xx format for maximum compatibility, but results in larger
+ database sizes.
+
+
+
+
+ When enabled, the database will be opened for read-only access and writing will be disabled.
+
+
+
+
+ Gets/sets the database encryption password
+
+
+
+
+ Gets/sets the database encryption hexadecimal password
+
+
+
+
+ Gets/Sets the page size for the connection.
+
+
+
+
+ Gets/Sets the maximum number of pages the database may hold
+
+
+
+
+ Gets/Sets the cache size for the connection.
+
+
+
+
+ Gets/Sets the DateTime format for the connection.
+
+
+
+
+ Gets/Sets the DateTime kind for the connection.
+
+
+
+
+ Gets/sets the DateTime format string used for formatting
+ and parsing purposes.
+
+
+
+
+ Gets/Sets the placeholder base schema name used for
+ .NET Framework compatibility purposes.
+
+
+
+
+ Determines how SQLite handles the transaction journal file.
+
+
+
+
+ Sets the default isolation level for transactions on the connection.
+
+
+
+
+ Gets/sets the default database type for the connection.
+
+
+
+
+ Gets/sets the default type name for the connection.
+
+
+
+
+ If enabled, use foreign key constraints
+
+
+
+
+ Gets/Sets the extra behavioral flags.
+
+
+
+
+ If enabled, apply the default connection settings to opened databases.
+
+
+
+
+ If enabled, attempt to resolve the provided data source file name to a
+ full path before opening.
+
+
+
+
+ If enabled, skip using the configured shared connection flags.
+
+
+
+
+ SQLite has very limited types, and is inherently text-based. The first 5 types below represent the sum of all types SQLite
+ understands. The DateTime extension to the spec is for internal use only.
+
+
+
+
+ Not used
+
+
+
+
+ All integers in SQLite default to Int64
+
+
+
+
+ All floating point numbers in SQLite default to double
+
+
+
+
+ The default data type of SQLite is text
+
+
+
+
+ Typically blob types are only seen when returned from a function
+
+
+
+
+ Null types can be returned from functions
+
+
+
+
+ Used internally by this provider
+
+
+
+
+ Used internally by this provider
+
+
+
+
+ These are the event types associated with the
+
+ delegate (and its corresponding event) and the
+ class.
+
+
+
+
+ Not used.
+
+
+
+
+ Not used.
+
+
+
+
+ The connection is being opened.
+
+
+
+
+ The connection string has been parsed.
+
+
+
+
+ The connection was opened.
+
+
+
+
+ The method was called on the
+ connection.
+
+
+
+
+ A transaction was created using the connection.
+
+
+
+
+ The connection was enlisted into a transaction.
+
+
+
+
+ A command was created using the connection.
+
+
+
+
+ A data reader was created using the connection.
+
+
+
+
+ An instance of a derived class has
+ been created to wrap a native resource.
+
+
+
+
+ The connection is being closed.
+
+
+
+
+ The connection was closed.
+
+
+
+
+ A command is being disposed.
+
+
+
+
+ A data reader is being disposed.
+
+
+
+
+ A data reader is being closed.
+
+
+
+
+ This implementation of SQLite for ADO.NET can process date/time fields in
+ databases in one of six formats.
+
+
+ ISO8601 format is more compatible, readable, fully-processable, but less
+ accurate as it does not provide time down to fractions of a second.
+ JulianDay is the numeric format the SQLite uses internally and is arguably
+ the most compatible with 3rd party tools. It is not readable as text
+ without post-processing. Ticks less compatible with 3rd party tools that
+ query the database, and renders the DateTime field unreadable as text
+ without post-processing. UnixEpoch is more compatible with Unix systems.
+ InvariantCulture allows the configured format for the invariant culture
+ format to be used and is human readable. CurrentCulture allows the
+ configured format for the current culture to be used and is also human
+ readable.
+
+ The preferred order of choosing a DateTime format is JulianDay, ISO8601,
+ and then Ticks. Ticks is mainly present for legacy code support.
+
+
+
+
+ Use the value of DateTime.Ticks. This value is not recommended and is not well supported with LINQ.
+
+
+
+
+ Use the ISO-8601 format. Uses the "yyyy-MM-dd HH:mm:ss.FFFFFFFK" format for UTC DateTime values and
+ "yyyy-MM-dd HH:mm:ss.FFFFFFF" format for local DateTime values).
+
+
+
+
+ The interval of time in days and fractions of a day since January 1, 4713 BC.
+
+
+
+
+ The whole number of seconds since the Unix epoch (January 1, 1970).
+
+
+
+
+ Any culture-independent string value that the .NET Framework can interpret as a valid DateTime.
+
+
+
+
+ Any string value that the .NET Framework can interpret as a valid DateTime using the current culture.
+
+
+
+
+ The default format for this provider.
+
+
+
+
+ This enum determines how SQLite treats its journal file.
+
+
+ By default SQLite will create and delete the journal file when needed during a transaction.
+ However, for some computers running certain filesystem monitoring tools, the rapid
+ creation and deletion of the journal file can cause those programs to fail, or to interfere with SQLite.
+
+ If a program or virus scanner is interfering with SQLite's journal file, you may receive errors like "unable to open database file"
+ when starting a transaction. If this is happening, you may want to change the default journal mode to Persist.
+
+
+
+
+ The default mode, this causes SQLite to use the existing journaling mode for the database.
+
+
+
+
+ SQLite will create and destroy the journal file as-needed.
+
+
+
+
+ When this is set, SQLite will keep the journal file even after a transaction has completed. It's contents will be erased,
+ and the journal re-used as often as needed. If it is deleted, it will be recreated the next time it is needed.
+
+
+
+
+ This option disables the rollback journal entirely. Interrupted transactions or a program crash can cause database
+ corruption in this mode!
+
+
+
+
+ SQLite will truncate the journal file to zero-length instead of deleting it.
+
+
+
+
+ SQLite will store the journal in volatile RAM. This saves disk I/O but at the expense of database safety and integrity.
+ If the application using SQLite crashes in the middle of a transaction when the MEMORY journaling mode is set, then the
+ database file will very likely go corrupt.
+
+
+
+
+ SQLite uses a write-ahead log instead of a rollback journal to implement transactions. The WAL journaling mode is persistent;
+ after being set it stays in effect across multiple database connections and after closing and reopening the database. A database
+ in WAL journaling mode can only be accessed by SQLite version 3.7.0 or later.
+
+
+
+
+ Possible values for the "synchronous" database setting. This setting determines
+ how often the database engine calls the xSync method of the VFS.
+
+
+
+
+ Use the default "synchronous" database setting. Currently, this should be
+ the same as using the FULL mode.
+
+
+
+
+ The database engine continues without syncing as soon as it has handed
+ data off to the operating system. If the application running SQLite
+ crashes, the data will be safe, but the database might become corrupted
+ if the operating system crashes or the computer loses power before that
+ data has been written to the disk surface.
+
+
+
+
+ The database engine will still sync at the most critical moments, but
+ less often than in FULL mode. There is a very small (though non-zero)
+ chance that a power failure at just the wrong time could corrupt the
+ database in NORMAL mode.
+
+
+
+
+ The database engine will use the xSync method of the VFS to ensure that
+ all content is safely written to the disk surface prior to continuing.
+ This ensures that an operating system crash or power failure will not
+ corrupt the database. FULL synchronous is very safe, but it is also
+ slower.
+
+
+
+
+ The requested command execution type. This controls which method of the
+ object will be called.
+
+
+
+
+ Do nothing. No method will be called.
+
+
+
+
+ The command is not expected to return a result -OR- the result is not
+ needed. The or
+ method
+ will be called.
+
+
+
+
+ The command is expected to return a scalar result -OR- the result should
+ be limited to a scalar result. The
+ or method will
+ be called.
+
+
+
+
+ The command is expected to return result.
+ The or
+ method will
+ be called.
+
+
+
+
+ Use the default command execution type. Using this value is the same
+ as using the value.
+
+
+
+
+ The action code responsible for the current call into the authorizer.
+
+
+
+
+ No action is being performed. This value should not be used from
+ external code.
+
+
+
+
+ No longer used.
+
+
+
+
+ An index will be created. The action-specific arguments are the
+ index name and the table name.
+
+
+
+
+
+ A table will be created. The action-specific arguments are the
+ table name and a null value.
+
+
+
+
+ A temporary index will be created. The action-specific arguments
+ are the index name and the table name.
+
+
+
+
+ A temporary table will be created. The action-specific arguments
+ are the table name and a null value.
+
+
+
+
+ A temporary trigger will be created. The action-specific arguments
+ are the trigger name and the table name.
+
+
+
+
+ A temporary view will be created. The action-specific arguments are
+ the view name and a null value.
+
+
+
+
+ A trigger will be created. The action-specific arguments are the
+ trigger name and the table name.
+
+
+
+
+ A view will be created. The action-specific arguments are the view
+ name and a null value.
+
+
+
+
+ A DELETE statement will be executed. The action-specific arguments
+ are the table name and a null value.
+
+
+
+
+ An index will be dropped. The action-specific arguments are the
+ index name and the table name.
+
+
+
+
+ A table will be dropped. The action-specific arguments are the tables
+ name and a null value.
+
+
+
+
+ A temporary index will be dropped. The action-specific arguments are
+ the index name and the table name.
+
+
+
+
+ A temporary table will be dropped. The action-specific arguments are
+ the table name and a null value.
+
+
+
+
+ A temporary trigger will be dropped. The action-specific arguments
+ are the trigger name and the table name.
+
+
+
+
+ A temporary view will be dropped. The action-specific arguments are
+ the view name and a null value.
+
+
+
+
+ A trigger will be dropped. The action-specific arguments are the
+ trigger name and the table name.
+
+
+
+
+ A view will be dropped. The action-specific arguments are the view
+ name and a null value.
+
+
+
+
+ An INSERT statement will be executed. The action-specific arguments
+ are the table name and a null value.
+
+
+
+
+ A PRAGMA statement will be executed. The action-specific arguments
+ are the name of the PRAGMA and the new value or a null value.
+
+
+
+
+ A table column will be read. The action-specific arguments are the
+ table name and the column name.
+
+
+
+
+ A SELECT statement will be executed. The action-specific arguments
+ are both null values.
+
+
+
+
+ A transaction will be started, committed, or rolled back. The
+ action-specific arguments are the name of the operation (BEGIN,
+ COMMIT, or ROLLBACK) and a null value.
+
+
+
+
+ An UPDATE statement will be executed. The action-specific arguments
+ are the table name and the column name.
+
+
+
+
+ A database will be attached to the connection. The action-specific
+ arguments are the database file name and a null value.
+
+
+
+
+ A database will be detached from the connection. The action-specific
+ arguments are the database name and a null value.
+
+
+
+
+ The schema of a table will be altered. The action-specific arguments
+ are the database name and the table name.
+
+
+
+
+ An index will be deleted and then recreated. The action-specific
+ arguments are the index name and a null value.
+
+
+
+
+ A table will be analyzed to gathers statistics about it. The
+ action-specific arguments are the table name and a null value.
+
+
+
+
+ A virtual table will be created. The action-specific arguments are
+ the table name and the module name.
+
+
+
+
+ A virtual table will be dropped. The action-specific arguments are
+ the table name and the module name.
+
+
+
+
+ A SQL function will be called. The action-specific arguments are a
+ null value and the function name.
+
+
+
+
+ A savepoint will be created, released, or rolled back. The
+ action-specific arguments are the name of the operation (BEGIN,
+ RELEASE, or ROLLBACK) and the savepoint name.
+
+
+
+
+ A recursive query will be executed. The action-specific arguments
+ are two null values.
+
+
+
+
+ The return code for the current call into the authorizer.
+
+
+
+
+ The action will be allowed.
+
+
+
+
+ The overall action will be disallowed and an error message will be
+ returned from the query preparation method.
+
+
+
+
+ The specific action will be disallowed; however, the overall action
+ will continue. The exact effects of this return code vary depending
+ on the specific action, please refer to the SQLite core library
+ documentation for futher details.
+
+
+
+
+ Class used internally to determine the datatype of a column in a resultset
+
+
+
+
+ The DbType of the column, or DbType.Object if it cannot be determined
+
+
+
+
+ The affinity of a column, used for expressions or when Type is DbType.Object
+
+
+
+
+ Constructs a default instance of this type.
+
+
+
+
+ Constructs an instance of this type with the specified field values.
+
+
+ The type affinity to use for the new instance.
+
+
+ The database type to use for the new instance.
+
+
+
+
+ SQLite implementation of DbDataAdapter.
+
+
+
+
+ This class is just a shell around the DbDataAdapter. Nothing from
+ DbDataAdapter is overridden here, just a few constructors are defined.
+
+
+ Default constructor.
+
+
+
+
+ Constructs a data adapter using the specified select command.
+
+
+ The select command to associate with the adapter.
+
+
+
+
+ Constructs a data adapter with the supplied select command text and
+ associated with the specified connection.
+
+
+ The select command text to associate with the data adapter.
+
+
+ The connection to associate with the select command.
+
+
+
+
+ Constructs a data adapter with the specified select command text,
+ and using the specified database connection string.
+
+
+ The select command text to use to construct a select command.
+
+
+ A connection string suitable for passing to a new SQLiteConnection,
+ which is associated with the select command.
+
+
+
+
+ Constructs a data adapter with the specified select command text,
+ and using the specified database connection string.
+
+
+ The select command text to use to construct a select command.
+
+
+ A connection string suitable for passing to a new SQLiteConnection,
+ which is associated with the select command.
+
+
+ Non-zero to parse the connection string using the built-in (i.e.
+ framework provided) parser when opening the connection.
+
+
+
+
+ Raised by the underlying DbDataAdapter when a row is being updated
+
+ The event's specifics
+
+
+
+ Raised by DbDataAdapter after a row is updated
+
+ The event's specifics
+
+
+
+ Row updating event handler
+
+
+
+
+ Row updated event handler
+
+
+
+
+ Gets/sets the select command for this DataAdapter
+
+
+
+
+ Gets/sets the insert command for this DataAdapter
+
+
+
+
+ Gets/sets the update command for this DataAdapter
+
+
+
+
+ Gets/sets the delete command for this DataAdapter
+
+
+
+
+ SQLite implementation of DbDataReader.
+
+
+
+
+ Underlying command this reader is attached to
+
+
+
+
+ The flags pertaining to the associated connection (via the command).
+
+
+
+
+ Index of the current statement in the command being processed
+
+
+
+
+ Current statement being Read()
+
+
+
+
+ State of the current statement being processed.
+ -1 = First Step() executed, so the first Read() will be ignored
+ 0 = Actively reading
+ 1 = Finished reading
+ 2 = Non-row-returning statement, no records
+
+
+
+
+ Number of records affected by the insert/update statements executed on the command
+
+
+
+
+ Count of fields (columns) in the row-returning statement currently being processed
+
+
+
+
+ The number of calls to Step() that have returned true (i.e. the number of rows that
+ have been read in the current result set).
+
+
+
+
+ Maps the field (column) names to their corresponding indexes within the results.
+
+
+
+
+ Datatypes of active fields (columns) in the current statement, used for type-restricting data
+
+
+
+
+ The behavior of the datareader
+
+
+
+
+ If set, then dispose of the command object when the reader is finished
+
+
+
+
+ If set, then raise an exception when the object is accessed after being disposed.
+
+
+
+
+ An array of rowid's for the active statement if CommandBehavior.KeyInfo is specified
+
+
+
+
+ Matches the version of the connection.
+
+
+
+
+ The "stub" (i.e. placeholder) base schema name to use when returning
+ column schema information. Matches the base schema name used by the
+ associated connection.
+
+
+
+
+ Internal constructor, initializes the datareader and sets up to begin executing statements
+
+ The SQLiteCommand this data reader is for
+ The expected behavior of the data reader
+
+
+
+ Dispose of all resources used by this datareader.
+
+
+
+
+
+ Closes the datareader, potentially closing the connection as well if CommandBehavior.CloseConnection was specified.
+
+
+
+
+ Throw an error if the datareader is closed
+
+
+
+
+ Throw an error if a row is not loaded
+
+
+
+
+ Enumerator support
+
+ Returns a DbEnumerator object.
+
+
+
+ Forces the connection flags cached by this data reader to be refreshed
+ from the underlying connection.
+
+
+
+
+ SQLite is inherently un-typed. All datatypes in SQLite are natively strings. The definition of the columns of a table
+ and the affinity of returned types are all we have to go on to type-restrict data in the reader.
+
+ This function attempts to verify that the type of data being requested of a column matches the datatype of the column. In
+ the case of columns that are not backed into a table definition, we attempt to match up the affinity of a column (int, double, string or blob)
+ to a set of known types that closely match that affinity. It's not an exact science, but its the best we can do.
+
+
+ This function throws an InvalidTypeCast() exception if the requested type doesn't match the column's definition or affinity.
+
+ The index of the column to type-check
+ The type we want to get out of the column
+
+
+
+ Retrieves the column as a boolean value
+
+ The index of the column to retrieve
+ bool
+
+
+
+ Retrieves the column as a single byte value
+
+ The index of the column to retrieve
+ byte
+
+
+
+ Retrieves a column as an array of bytes (blob)
+
+ The index of the column to retrieve
+ The zero-based index of where to begin reading the data
+ The buffer to write the bytes into
+ The zero-based index of where to begin writing into the array
+ The number of bytes to retrieve
+ The actual number of bytes written into the array
+
+ To determine the number of bytes in the column, pass a null value for the buffer. The total length will be returned.
+
+
+
+
+ Returns the column as a single character
+
+ The index of the column to retrieve
+ char
+
+
+
+ Retrieves a column as an array of chars (blob)
+
+ The index of the column to retrieve
+ The zero-based index of where to begin reading the data
+ The buffer to write the characters into
+ The zero-based index of where to begin writing into the array
+ The number of bytes to retrieve
+ The actual number of characters written into the array
+
+ To determine the number of characters in the column, pass a null value for the buffer. The total length will be returned.
+
+
+
+
+ Retrieves the name of the back-end datatype of the column
+
+ The index of the column to retrieve
+ string
+
+
+
+ Retrieve the column as a date/time value
+
+ The index of the column to retrieve
+ DateTime
+
+
+
+ Retrieve the column as a decimal value
+
+ The index of the column to retrieve
+ decimal
+
+
+
+ Returns the column as a double
+
+ The index of the column to retrieve
+ double
+
+
+
+ Returns the .NET type of a given column
+
+ The index of the column to retrieve
+ Type
+
+
+
+ Returns a column as a float value
+
+ The index of the column to retrieve
+ float
+
+
+
+ Returns the column as a Guid
+
+ The index of the column to retrieve
+ Guid
+
+
+
+ Returns the column as a short
+
+ The index of the column to retrieve
+ Int16
+
+
+
+ Retrieves the column as an int
+
+ The index of the column to retrieve
+ Int32
+
+
+
+ Retrieves the column as a long
+
+ The index of the column to retrieve
+ Int64
+
+
+
+ Retrieves the name of the column
+
+ The index of the column to retrieve
+ string
+
+
+
+ Retrieves the i of a column, given its name
+
+ The name of the column to retrieve
+ The int i of the column
+
+
+
+ Schema information in SQLite is difficult to map into .NET conventions, so a lot of work must be done
+ to gather the necessary information so it can be represented in an ADO.NET manner.
+
+ Returns a DataTable containing the schema information for the active SELECT statement being processed.
+
+
+
+ Retrieves the column as a string
+
+ The index of the column to retrieve
+ string
+
+
+
+ Retrieves the column as an object corresponding to the underlying datatype of the column
+
+ The index of the column to retrieve
+ object
+
+
+
+ Retreives the values of multiple columns, up to the size of the supplied array
+
+ The array to fill with values from the columns in the current resultset
+ The number of columns retrieved
+
+
+
+ Returns a collection containing all the column names and values for the
+ current row of data in the current resultset, if any. If there is no
+ current row or no current resultset, an exception may be thrown.
+
+
+ The collection containing the column name and value information for the
+ current row of data in the current resultset or null if this information
+ cannot be obtained.
+
+
+
+
+ Returns True if the specified column is null
+
+ The index of the column to retrieve
+ True or False
+
+
+
+ Moves to the next resultset in multiple row-returning SQL command.
+
+ True if the command was successful and a new resultset is available, False otherwise.
+
+
+
+ This method attempts to query the database connection associated with
+ the data reader in use. If the underlying command or connection is
+ unavailable, a null value will be returned.
+
+
+ The connection object -OR- null if it is unavailable.
+
+
+
+
+ Retrieves the SQLiteType for a given column and row value.
+
+
+ The original SQLiteType structure, based only on the column.
+
+
+ The textual value of the column for a given row.
+
+
+ The SQLiteType structure.
+
+
+
+
+ Retrieves the SQLiteType for a given column, and caches it to avoid repetetive interop calls.
+
+ The flags associated with the parent connection object.
+ The index of the column to retrieve
+ A SQLiteType structure
+
+
+
+ Reads the next row from the resultset
+
+ True if a new row was successfully loaded and is ready for processing
+
+
+
+ Not implemented. Returns 0
+
+
+
+
+ Returns the number of columns in the current resultset
+
+
+
+
+ Returns the number of rows seen so far in the current result set.
+
+
+
+
+ Returns the number of visible fields in the current resultset
+
+
+
+
+ Returns True if the resultset has rows that can be fetched
+
+
+
+
+ Returns True if the data reader is closed
+
+
+
+
+ Retrieve the count of records affected by an update/insert command. Only valid once the data reader is closed!
+
+
+
+
+ Indexer to retrieve data from a column given its name
+
+ The name of the column to retrieve data for
+ The value contained in the column
+
+
+
+ Indexer to retrieve data from a column given its i
+
+ The index of the column to retrieve
+ The value contained in the column
+
+
+
+ SQLite exception class.
+
+
+
+
+ Private constructor for use with serialization.
+
+
+ Holds the serialized object data about the exception being thrown.
+
+
+ Contains contextual information about the source or destination.
+
+
+
+
+ Public constructor for generating a SQLite exception given the error
+ code and message.
+
+
+ The SQLite return code to report.
+
+
+ Message text to go along with the return code message text.
+
+
+
+
+ Public constructor that uses the base class constructor for the error
+ message.
+
+ Error message text.
+
+
+
+ Public constructor that uses the default base class constructor.
+
+
+
+
+ Public constructor that uses the base class constructor for the error
+ message and inner exception.
+
+ Error message text.
+ The original (inner) exception.
+
+
+
+ Adds extra information to the serialized object data specific to this
+ class type. This is only used for serialization.
+
+
+ Holds the serialized object data about the exception being thrown.
+
+
+ Contains contextual information about the source or destination.
+
+
+
+
+ Returns the error message for the specified SQLite return code.
+
+ The SQLite return code.
+ The error message or null if it cannot be found.
+
+
+
+ Returns the composite error message based on the SQLite return code
+ and the optional detailed error message.
+
+ The SQLite return code.
+ Optional detailed error message.
+ Error message text for the return code.
+
+
+
+ Gets the associated SQLite result code for this exception as a
+ . This property returns the same
+ underlying value as the property.
+
+
+
+
+ Gets the associated SQLite return code for this exception as an
+ . For desktop versions of the .NET Framework,
+ this property overrides the property of the same name within the
+
+ class. This property returns the same underlying value as the
+ property.
+
+
+
+
+ SQLite error codes. Actually, this enumeration represents a return code,
+ which may also indicate success in one of several ways (e.g. SQLITE_OK,
+ SQLITE_ROW, and SQLITE_DONE). Therefore, the name of this enumeration is
+ something of a misnomer.
+
+
+
+
+ The error code is unknown. This error code
+ is only used by the managed wrapper itself.
+
+
+
+
+ Successful result
+
+
+
+
+ SQL error or missing database
+
+
+
+
+ Internal logic error in SQLite
+
+
+
+
+ Access permission denied
+
+
+
+
+ Callback routine requested an abort
+
+
+
+
+ The database file is locked
+
+
+
+
+ A table in the database is locked
+
+
+
+
+ A malloc() failed
+
+
+
+
+ Attempt to write a readonly database
+
+
+
+
+ Operation terminated by sqlite3_interrupt()
+
+
+
+
+ Some kind of disk I/O error occurred
+
+
+
+
+ The database disk image is malformed
+
+
+
+
+ Unknown opcode in sqlite3_file_control()
+
+
+
+
+ Insertion failed because database is full
+
+
+
+
+ Unable to open the database file
+
+
+
+
+ Database lock protocol error
+
+
+
+
+ Database is empty
+
+
+
+
+ The database schema changed
+
+
+
+
+ String or BLOB exceeds size limit
+
+
+
+
+ Abort due to constraint violation
+
+
+
+
+ Data type mismatch
+
+
+
+
+ Library used incorrectly
+
+
+
+
+ Uses OS features not supported on host
+
+
+
+
+ Authorization denied
+
+
+
+
+ Auxiliary database format error
+
+
+
+
+ 2nd parameter to sqlite3_bind out of range
+
+
+
+
+ File opened that is not a database file
+
+
+
+
+ Notifications from sqlite3_log()
+
+
+
+
+ Warnings from sqlite3_log()
+
+
+
+
+ sqlite3_step() has another row ready
+
+
+
+
+ sqlite3_step() has finished executing
+
+
+
+
+ Used to mask off extended result codes
+
+
+
+
+ SQLite implementation of .
+
+
+ SQLite implementation of .
+
+
+
+
+ Constructs a new instance.
+
+
+
+
+ Static instance member which returns an instanced class.
+
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Creates and returns a new object.
+
+ The new object.
+
+
+
+ Will provide a object in .NET 3.5.
+
+ The class or interface type to query for.
+
+
+
+
+ This event is raised whenever SQLite raises a logging event.
+ Note that this should be set as one of the first things in the
+ application. This event is provided for backward compatibility only.
+ New code should use the class instead.
+
+
+
+
+ This abstract class is designed to handle user-defined functions easily. An instance of the derived class is made for each
+ connection to the database.
+
+
+ Although there is one instance of a class derived from SQLiteFunction per database connection, the derived class has no access
+ to the underlying connection. This is necessary to deter implementers from thinking it would be a good idea to make database
+ calls during processing.
+
+ It is important to distinguish between a per-connection instance, and a per-SQL statement context. One instance of this class
+ services all SQL statements being stepped through on that connection, and there can be many. One should never store per-statement
+ information in member variables of user-defined function classes.
+
+ For aggregate functions, always create and store your per-statement data in the contextData object on the 1st step. This data will
+ be automatically freed for you (and Dispose() called if the item supports IDisposable) when the statement completes.
+
+
+
+
+ The base connection this function is attached to
+
+
+
+
+ Internal array used to keep track of aggregate function context data
+
+
+
+
+ The connection flags associated with this object (this should be the
+ same value as the flags associated with the parent connection object).
+
+
+
+
+ Holds a reference to the callback function for user functions
+
+
+
+
+ Holds a reference to the callbakc function for stepping in an aggregate function
+
+
+
+
+ Holds a reference to the callback function for finalizing an aggregate function
+
+
+
+
+ Holds a reference to the callback function for collation sequences
+
+
+
+
+ Current context of the current callback. Only valid during a callback
+
+
+
+
+ This static list contains all the user-defined functions declared using the proper attributes.
+
+
+
+
+ Internal constructor, initializes the function's internal variables.
+
+
+
+
+ Constructs an instance of this class using the specified data-type
+ conversion parameters.
+
+
+ The DateTime format to be used when converting string values to a
+ DateTime and binding DateTime parameters.
+
+
+ The to be used when creating DateTime
+ values.
+
+
+ The format string to be used when parsing and formatting DateTime
+ values.
+
+
+ Non-zero to create a UTF-16 data-type conversion context; otherwise,
+ a UTF-8 data-type conversion context will be created.
+
+
+
+
+ Disposes of any active contextData variables that were not automatically cleaned up. Sometimes this can happen if
+ someone closes the connection while a DataReader is open.
+
+
+
+
+ Placeholder for a user-defined disposal routine
+
+ True if the object is being disposed explicitly
+
+
+
+ Scalar functions override this method to do their magic.
+
+
+ Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available
+ to force them into a certain type. Therefore the only types you will ever see as parameters are
+ DBNull.Value, Int64, Double, String or byte[] array.
+
+ The arguments for the command to process
+ You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or
+ you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error,
+ just return it!
+
+
+
+ Aggregate functions override this method to do their magic.
+
+
+ Typically you'll be updating whatever you've placed in the contextData field and returning as quickly as possible.
+
+ The arguments for the command to process
+ The 1-based step number. This is incrememted each time the step method is called.
+ A placeholder for implementers to store contextual data pertaining to the current context.
+
+
+
+ Aggregate functions override this method to finish their aggregate processing.
+
+
+ If you implemented your aggregate function properly,
+ you've been recording and keeping track of your data in the contextData object provided, and now at this stage you should have
+ all the information you need in there to figure out what to return.
+ NOTE: It is possible to arrive here without receiving a previous call to Step(), in which case the contextData will
+ be null. This can happen when no rows were returned. You can either return null, or 0 or some other custom return value
+ if that is the case.
+
+ Your own assigned contextData, provided for you so you can return your final results.
+ You may return most simple types as a return value, null or DBNull.Value to return null, DateTime, or
+ you may return an Exception-derived class if you wish to return an error to SQLite. Do not actually throw the error,
+ just return it!
+
+
+
+
+ User-defined collation sequences override this method to provide a custom string sorting algorithm.
+
+ The first string to compare
+ The second strnig to compare
+ 1 if param1 is greater than param2, 0 if they are equal, or -1 if param1 is less than param2
+
+
+
+ Converts an IntPtr array of context arguments to an object array containing the resolved parameters the pointers point to.
+
+
+ Parameters passed to functions have only an affinity for a certain data type, there is no underlying schema available
+ to force them into a certain type. Therefore the only types you will ever see as parameters are
+ DBNull.Value, Int64, Double, String or byte[] array.
+
+ The number of arguments
+ A pointer to the array of arguments
+ An object array of the arguments once they've been converted to .NET values
+
+
+
+ Takes the return value from Invoke() and Final() and figures out how to return it to SQLite's context.
+
+ The context the return value applies to
+ The parameter to return to SQLite
+
+
+
+ Internal scalar callback function, which wraps the raw context pointer and calls the virtual Invoke() method.
+ WARNING: Must not throw exceptions.
+
+ A raw context pointer
+ Number of arguments passed in
+ A pointer to the array of arguments
+
+
+
+ Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
+ WARNING: Must not throw exceptions.
+
+ Not used
+ Length of the string pv1
+ Pointer to the first string to compare
+ Length of the string pv2
+ Pointer to the second string to compare
+ Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
+ than the second. Returns 0 if an exception is caught.
+
+
+
+ Internal collation sequence function, which wraps up the raw string pointers and executes the Compare() virtual function.
+ WARNING: Must not throw exceptions.
+
+ Not used
+ Length of the string pv1
+ Pointer to the first string to compare
+ Length of the string pv2
+ Pointer to the second string to compare
+ Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
+ than the second. Returns 0 if an exception is caught.
+
+
+
+ The internal aggregate Step function callback, which wraps the raw context pointer and calls the virtual Step() method.
+ WARNING: Must not throw exceptions.
+
+
+ This function takes care of doing the lookups and getting the important information put together to call the Step() function.
+ That includes pulling out the user's contextData and updating it after the call is made. We use a sorted list for this so
+ binary searches can be done to find the data.
+
+ A raw context pointer
+ Number of arguments passed in
+ A pointer to the array of arguments
+
+
+
+ An internal aggregate Final function callback, which wraps the context pointer and calls the virtual Final() method.
+ WARNING: Must not throw exceptions.
+
+ A raw context pointer
+
+
+
+ Using reflection, enumerate all assemblies in the current appdomain looking for classes that
+ have a SQLiteFunctionAttribute attribute, and registering them accordingly.
+
+
+
+
+ Manual method of registering a function. The type must still have the SQLiteFunctionAttributes in order to work
+ properly, but this is a workaround for the Compact Framework where enumerating assemblies is not currently supported.
+
+ The type of the function to register
+
+
+
+ Called by SQLiteBase derived classes, this function binds all user-defined functions to a connection.
+ It is done this way so that all user-defined functions will access the database using the same encoding scheme
+ as the connection (UTF-8 or UTF-16).
+
+
+ The wrapper functions that interop with SQLite will create a unique cookie value, which internally is a pointer to
+ all the wrapped callback functions. The interop function uses it to map CDecl callbacks to StdCall callbacks.
+
+ The base object on which the functions are to bind
+ The flags associated with the parent connection object
+ Returns a logical list of functions which the connection should retain until it is closed.
+
+
+
+ This function binds a user-defined functions to a connection.
+
+
+ The object instance associated with the
+ that the function should be bound to.
+
+
+ The object instance containing
+ the metadata for the function to be bound.
+
+
+ The object instance that implements the
+ function to be bound.
+
+
+ The flags associated with the parent connection object.
+
+
+
+
+ Returns a reference to the underlying connection's SQLiteConvert class, which can be used to convert
+ strings and DateTime's into the current connection's encoding schema.
+
+
+
+
+ Extends SQLiteFunction and allows an inherited class to obtain the collating sequence associated with a function call.
+
+
+ User-defined functions can call the GetCollationSequence() method in this class and use it to compare strings and char arrays.
+
+
+
+
+ Obtains the collating sequence in effect for the given function.
+
+
+
+
+
+ The type of user-defined function to declare
+
+
+
+
+ Scalar functions are designed to be called and return a result immediately. Examples include ABS(), Upper(), Lower(), etc.
+
+
+
+
+ Aggregate functions are designed to accumulate data until the end of a call and then return a result gleaned from the accumulated data.
+ Examples include SUM(), COUNT(), AVG(), etc.
+
+
+
+
+ Collation sequences are used to sort textual data in a custom manner, and appear in an ORDER BY clause. Typically text in an ORDER BY is
+ sorted using a straight case-insensitive comparison function. Custom collating sequences can be used to alter the behavior of text sorting
+ in a user-defined manner.
+
+
+
+
+ An internal callback delegate declaration.
+
+ Raw native context pointer for the user function.
+ Total number of arguments to the user function.
+ Raw native pointer to the array of raw native argument pointers.
+
+
+
+ An internal final callback delegate declaration.
+
+ Raw context pointer for the user function
+
+
+
+ Internal callback delegate for implementing collation sequences
+
+ Not used
+ Length of the string pv1
+ Pointer to the first string to compare
+ Length of the string pv2
+ Pointer to the second string to compare
+ Returns -1 if the first string is less than the second. 0 if they are equal, or 1 if the first string is greater
+ than the second.
+
+
+
+ The type of collating sequence
+
+
+
+
+ The built-in BINARY collating sequence
+
+
+
+
+ The built-in NOCASE collating sequence
+
+
+
+
+ The built-in REVERSE collating sequence
+
+
+
+
+ A custom user-defined collating sequence
+
+
+
+
+ The encoding type the collation sequence uses
+
+
+
+
+ The collation sequence is UTF8
+
+
+
+
+ The collation sequence is UTF16 little-endian
+
+
+
+
+ The collation sequence is UTF16 big-endian
+
+
+
+
+ A struct describing the collating sequence a function is executing in
+
+
+
+
+ The name of the collating sequence
+
+
+
+
+ The type of collating sequence
+
+
+
+
+ The text encoding of the collation sequence
+
+
+
+
+ Context of the function that requested the collating sequence
+
+
+
+
+ Calls the base collating sequence to compare two strings
+
+ The first string to compare
+ The second string to compare
+ -1 if s1 is less than s2, 0 if s1 is equal to s2, and 1 if s1 is greater than s2
+
+
+
+ Calls the base collating sequence to compare two character arrays
+
+ The first array to compare
+ The second array to compare
+ -1 if c1 is less than c2, 0 if c1 is equal to c2, and 1 if c1 is greater than c2
+
+
+
+ A simple custom attribute to enable us to easily find user-defined functions in
+ the loaded assemblies and initialize them in SQLite as connections are made.
+
+
+
+
+ Default constructor, initializes the internal variables for the function.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the function, as seen by the SQLite core library.
+
+
+ The number of arguments that the function will accept.
+
+
+ The type of function being declared. This will either be Scalar,
+ Aggregate, or Collation.
+
+
+
+
+ The function's name as it will be used in SQLite command text.
+
+
+
+
+ The number of arguments this function expects. -1 if the number of arguments is variable.
+
+
+
+
+ The type of function this implementation will be.
+
+
+
+
+ The object instance that describes the class
+ containing the implementation for the associated function.
+
+
+
+
+ This class provides key info for a given SQLite statement.
+
+ Providing key information for a given statement is non-trivial :(
+
+
+
+
+
+ This function does all the nasty work at determining what keys need to be returned for
+ a given statement.
+
+
+
+
+
+
+
+ Make sure all the subqueries are open and ready and sync'd with the current rowid
+ of the table they're supporting
+
+
+
+
+ Release any readers on any subqueries
+
+
+
+
+ Append all the columns we've added to the original query to the schema
+
+
+
+
+
+ How many additional columns of keyinfo we're holding
+
+
+
+
+ Used to support CommandBehavior.KeyInfo
+
+
+
+
+ A single sub-query for a given table/database.
+
+
+
+
+ Event data for logging event handlers.
+
+
+
+
+ The error code. The type of this object value should be
+ or .
+
+
+
+
+ SQL statement text as the statement first begins executing
+
+
+
+
+ Extra data associated with this event, if any.
+
+
+
+
+ Constructs the object.
+
+ Should be null.
+
+ The error code. The type of this object value should be
+ or .
+
+ The error message, if any.
+ The extra data, if any.
+
+
+
+ Raised when a log event occurs.
+
+ The current connection
+ Event arguments of the trace
+
+
+
+ Manages the SQLite custom logging functionality and the associated
+ callback for the whole process.
+
+
+
+
+ Object used to synchronize access to the static instance data
+ for this class.
+
+
+
+
+ Member variable to store the AppDomain.DomainUnload event handler.
+
+
+
+
+ The default log event handler.
+
+
+
+
+ The log callback passed to native SQLite engine. This must live
+ as long as the SQLite library has a pointer to it.
+
+
+
+
+ The base SQLite object to interop with.
+
+
+
+
+ This will be non-zero if logging is currently enabled.
+
+
+
+
+ Initializes the SQLite logging facilities.
+
+
+
+
+ Handles the AppDomain being unloaded.
+
+ Should be null.
+ The data associated with this event.
+
+
+
+ Log a message to all the registered log event handlers without going
+ through the SQLite library.
+
+ The message to be logged.
+
+
+
+ Log a message to all the registered log event handlers without going
+ through the SQLite library.
+
+ The SQLite error code.
+ The message to be logged.
+
+
+
+ Log a message to all the registered log event handlers without going
+ through the SQLite library.
+
+ The integer error code.
+ The message to be logged.
+
+
+
+ Log a message to all the registered log event handlers without going
+ through the SQLite library.
+
+
+ The error code. The type of this object value should be
+ System.Int32 or SQLiteErrorCode.
+
+ The message to be logged.
+
+
+
+ Creates and initializes the default log event handler.
+
+
+
+
+ Adds the default log event handler to the list of handlers.
+
+
+
+
+ Removes the default log event handler from the list of handlers.
+
+
+
+
+ Internal proxy function that calls any registered application log
+ event handlers.
+
+ WARNING: This method is used more-or-less directly by native code,
+ do not modify its type signature.
+
+
+ The extra data associated with this message, if any.
+
+
+ The error code associated with this message.
+
+
+ The message string to be logged.
+
+
+
+
+ Default logger. Currently, uses the Trace class (i.e. sends events
+ to the current trace listeners, if any).
+
+ Should be null.
+ The data associated with this event.
+
+
+
+ Member variable to store the application log handler to call.
+
+
+
+
+ This event is raised whenever SQLite raises a logging event.
+ Note that this should be set as one of the first things in the
+ application.
+
+
+
+
+ If this property is true, logging is enabled; otherwise, logging is
+ disabled. When logging is disabled, no logging events will fire.
+
+
+
+
+ MetaDataCollections specific to SQLite
+
+
+
+
+ Returns a list of databases attached to the connection
+
+
+
+
+ Returns column information for the specified table
+
+
+
+
+ Returns index information for the optionally-specified table
+
+
+
+
+ Returns base columns for the given index
+
+
+
+
+ Returns the tables in the given catalog
+
+
+
+
+ Returns user-defined views in the given catalog
+
+
+
+
+ Returns underlying column information on the given view
+
+
+
+
+ Returns foreign key information for the given catalog
+
+
+
+
+ Returns the triggers on the database
+
+
+
+
+ SQLite implementation of DbParameter.
+
+
+
+
+ The data type of the parameter
+
+
+
+
+ The version information for mapping the parameter
+
+
+
+
+ The value of the data in the parameter
+
+
+
+
+ The source column for the parameter
+
+
+
+
+ The column name
+
+
+
+
+ The data size, unused by SQLite
+
+
+
+
+ Default constructor
+
+
+
+
+ Constructs a named parameter given the specified parameter name
+
+ The parameter name
+
+
+
+ Constructs a named parameter given the specified parameter name and initial value
+
+ The parameter name
+ The initial value of the parameter
+
+
+
+ Constructs a named parameter of the specified type
+
+ The parameter name
+ The datatype of the parameter
+
+
+
+ Constructs a named parameter of the specified type and source column reference
+
+ The parameter name
+ The data type
+ The source column
+
+
+
+ Constructs a named parameter of the specified type, source column and row version
+
+ The parameter name
+ The data type
+ The source column
+ The row version information
+
+
+
+ Constructs an unnamed parameter of the specified data type
+
+ The datatype of the parameter
+
+
+
+ Constructs an unnamed parameter of the specified data type and sets the initial value
+
+ The datatype of the parameter
+ The initial value of the parameter
+
+
+
+ Constructs an unnamed parameter of the specified data type and source column
+
+ The datatype of the parameter
+ The source column
+
+
+
+ Constructs an unnamed parameter of the specified data type, source column and row version
+
+ The data type
+ The source column
+ The row version information
+
+
+
+ Constructs a named parameter of the specified type and size
+
+ The parameter name
+ The data type
+ The size of the parameter
+
+
+
+ Constructs a named parameter of the specified type, size and source column
+
+ The name of the parameter
+ The data type
+ The size of the parameter
+ The source column
+
+
+
+ Constructs a named parameter of the specified type, size, source column and row version
+
+ The name of the parameter
+ The data type
+ The size of the parameter
+ The source column
+ The row version information
+
+
+
+ Constructs a named parameter of the specified type, size, source column and row version
+
+ The name of the parameter
+ The data type
+ The size of the parameter
+ Only input parameters are supported in SQLite
+ Ignored
+ Ignored
+ Ignored
+ The source column
+ The row version information
+ The initial value to assign the parameter
+
+
+
+ Constructs a named parameter, yet another flavor
+
+ The name of the parameter
+ The data type
+ The size of the parameter
+ Only input parameters are supported in SQLite
+ Ignored
+ Ignored
+ The source column
+ The row version information
+ Whether or not this parameter is for comparing NULL's
+ The intial value to assign the parameter
+
+
+
+ Constructs an unnamed parameter of the specified type and size
+
+ The data type
+ The size of the parameter
+
+
+
+ Constructs an unnamed parameter of the specified type, size, and source column
+
+ The data type
+ The size of the parameter
+ The source column
+
+
+
+ Constructs an unnamed parameter of the specified type, size, source column and row version
+
+ The data type
+ The size of the parameter
+ The source column
+ The row version information
+
+
+
+ Resets the DbType of the parameter so it can be inferred from the value
+
+
+
+
+ Clones a parameter
+
+ A new, unassociated SQLiteParameter
+
+
+
+ Whether or not the parameter can contain a null value
+
+
+
+
+ Returns the datatype of the parameter
+
+
+
+
+ Supports only input parameters
+
+
+
+
+ Returns the parameter name
+
+
+
+
+ Returns the size of the parameter
+
+
+
+
+ Gets/sets the source column
+
+
+
+
+ Used by DbCommandBuilder to determine the mapping for nullable fields
+
+
+
+
+ Gets and sets the row version
+
+
+
+
+ Gets and sets the parameter value. If no datatype was specified, the datatype will assume the type from the value given.
+
+
+
+
+ SQLite implementation of DbParameterCollection.
+
+
+
+
+ The underlying command to which this collection belongs
+
+
+
+
+ The internal array of parameters in this collection
+
+
+
+
+ Determines whether or not all parameters have been bound to their statement(s)
+
+
+
+
+ Initializes the collection
+
+ The command to which the collection belongs
+
+
+
+ Retrieves an enumerator for the collection
+
+ An enumerator for the underlying array
+
+
+
+ Adds a parameter to the collection
+
+ The parameter name
+ The data type
+ The size of the value
+ The source column
+ A SQLiteParameter object
+
+
+
+ Adds a parameter to the collection
+
+ The parameter name
+ The data type
+ The size of the value
+ A SQLiteParameter object
+
+
+
+ Adds a parameter to the collection
+
+ The parameter name
+ The data type
+ A SQLiteParameter object
+
+
+
+ Adds a parameter to the collection
+
+ The parameter to add
+ A zero-based index of where the parameter is located in the array
+
+
+
+ Adds a parameter to the collection
+
+ The parameter to add
+ A zero-based index of where the parameter is located in the array
+
+
+
+ Adds a named/unnamed parameter and its value to the parameter collection.
+
+ Name of the parameter, or null to indicate an unnamed parameter
+ The initial value of the parameter
+ Returns the SQLiteParameter object created during the call.
+
+
+
+ Adds an array of parameters to the collection
+
+ The array of parameters to add
+
+
+
+ Adds an array of parameters to the collection
+
+ The array of parameters to add
+
+
+
+ Clears the array and resets the collection
+
+
+
+
+ Determines if the named parameter exists in the collection
+
+ The name of the parameter to check
+ True if the parameter is in the collection
+
+
+
+ Determines if the parameter exists in the collection
+
+ The SQLiteParameter to check
+ True if the parameter is in the collection
+
+
+
+ Not implemented
+
+
+
+
+
+
+ Retrieve a parameter by name from the collection
+
+ The name of the parameter to fetch
+ A DbParameter object
+
+
+
+ Retrieves a parameter by its index in the collection
+
+ The index of the parameter to retrieve
+ A DbParameter object
+
+
+
+ Returns the index of a parameter given its name
+
+ The name of the parameter to find
+ -1 if not found, otherwise a zero-based index of the parameter
+
+
+
+ Returns the index of a parameter
+
+ The parameter to find
+ -1 if not found, otherwise a zero-based index of the parameter
+
+
+
+ Inserts a parameter into the array at the specified location
+
+ The zero-based index to insert the parameter at
+ The parameter to insert
+
+
+
+ Removes a parameter from the collection
+
+ The parameter to remove
+
+
+
+ Removes a parameter from the collection given its name
+
+ The name of the parameter to remove
+
+
+
+ Removes a parameter from the collection given its index
+
+ The zero-based parameter index to remove
+
+
+
+ Re-assign the named parameter to a new parameter object
+
+ The name of the parameter to replace
+ The new parameter
+
+
+
+ Re-assign a parameter at the specified index
+
+ The zero-based index of the parameter to replace
+ The new parameter
+
+
+
+ Un-binds all parameters from their statements
+
+
+
+
+ This function attempts to map all parameters in the collection to all statements in a Command.
+ Since named parameters may span multiple statements, this function makes sure all statements are bound
+ to the same named parameter. Unnamed parameters are bound in sequence.
+
+
+
+
+ Returns false
+
+
+
+
+ Returns false
+
+
+
+
+ Returns false
+
+
+
+
+ Returns null
+
+
+
+
+ Returns a count of parameters in the collection
+
+
+
+
+ Overloaded to specialize the return value of the default indexer
+
+ Name of the parameter to get/set
+ The specified named SQLite parameter
+
+
+
+ Overloaded to specialize the return value of the default indexer
+
+ The index of the parameter to get/set
+ The specified SQLite parameter
+
+
+
+ Represents a single SQL statement in SQLite.
+
+
+
+
+ The underlying SQLite object this statement is bound to
+
+
+
+
+ The command text of this SQL statement
+
+
+
+
+ The actual statement pointer
+
+
+
+
+ An index from which unnamed parameters begin
+
+
+
+
+ Names of the parameters as SQLite understands them to be
+
+
+
+
+ Parameters for this statement
+
+
+
+
+ Command this statement belongs to (if any)
+
+
+
+
+ The flags associated with the parent connection object.
+
+
+
+
+ Initializes the statement and attempts to get all information about parameters in the statement
+
+ The base SQLite object
+ The flags associated with the parent connection object
+ The statement
+ The command text for this statement
+ The previous command in a multi-statement command
+
+
+
+ Disposes and finalizes the statement
+
+
+
+
+ If the underlying database connection is open, fetches the number of changed rows
+ resulting from the most recent query; otherwise, does nothing.
+
+
+ The number of changes when true is returned.
+ Undefined if false is returned.
+
+ Non-zero if the number of changed rows was fetched.
+
+
+
+ Called by SQLiteParameterCollection, this function determines if the specified parameter name belongs to
+ this statement, and if so, keeps a reference to the parameter so it can be bound later.
+
+ The parameter name to map
+ The parameter to assign it
+
+
+
+ Bind all parameters, making sure the caller didn't miss any
+
+
+
+
+ Perform the bind operation for an individual parameter
+
+ The index of the parameter to bind
+ The parameter we're binding
+
+
+
+ SQLite implementation of DbTransaction.
+
+
+
+
+ The connection to which this transaction is bound
+
+
+
+
+ Constructs the transaction object, binding it to the supplied connection
+
+ The connection to open a transaction on
+ TRUE to defer the writelock, or FALSE to lock immediately
+
+
+
+ Disposes the transaction. If it is currently active, any changes are rolled back.
+
+
+
+
+ Commits the current transaction.
+
+
+
+
+ Rolls back the active transaction.
+
+
+
+
+ Returns the underlying connection to which this transaction applies.
+
+
+
+
+ Forwards to the local Connection property
+
+
+
+
+ Gets the isolation level of the transaction. SQLite only supports Serializable transactions.
+
+
+
+
+ The file extension used for dynamic link libraries.
+
+
+
+
+ The file extension used for the XML configuration file.
+
+
+
+
+ This is the name of the XML configuration file specific to the
+ System.Data.SQLite assembly.
+
+
+
+
+ This lock is used to protect the static _SQLiteNativeModuleFileName,
+ _SQLiteNativeModuleHandle, and processorArchitecturePlatforms fields.
+
+
+
+
+ This dictionary stores the mappings between processor architecture
+ names and platform names. These mappings are now used for two
+ purposes. First, they are used to determine if the assembly code
+ base should be used instead of the location, based upon whether one
+ or more of the named sub-directories exist within the assembly code
+ base. Second, they are used to assist in loading the appropriate
+ SQLite interop assembly into the current process.
+
+
+
+
+ For now, this method simply calls the Initialize method.
+
+
+
+
+ Attempts to initialize this class by pre-loading the native SQLite
+ library for the processor architecture of the current process.
+
+
+
+
+ Queries and returns the XML configuration file name for the assembly
+ containing the managed System.Data.SQLite components.
+
+
+ The XML configuration file name -OR- null if it cannot be determined
+ or does not exist.
+
+
+
+
+ Queries and returns the value of the specified setting, using the XML
+ configuration file and/or the environment variables for the current
+ process and/or the current system, when available.
+
+
+ The name of the setting.
+
+
+ The value to be returned if the setting has not been set explicitly
+ or cannot be determined.
+
+
+ The value of the setting -OR- the default value specified by
+ if it has not been set explicitly or
+ cannot be determined. By default, all references to existing
+ environment variables will be expanded to their corresponding values
+ within the value to be returned unless either the "No_Expand" or
+ "No_Expand_ " environment variable is set [to
+ anything].
+
+
+
+
+ Queries and returns the directory for the assembly currently being
+ executed.
+
+
+ The directory for the assembly currently being executed -OR- null if
+ it cannot be determined.
+
+
+
+
+ The name of the environment variable containing the processor
+ architecture of the current process.
+
+
+
+
+ This is the P/Invoke method that wraps the native Win32 LoadLibrary
+ function. See the MSDN documentation for full details on what it
+ does.
+
+
+ The name of the executable library.
+
+
+ The native module handle upon success -OR- IntPtr.Zero on failure.
+
+
+
+
+ The native module file name for the native SQLite library or null.
+
+
+
+
+ The native module handle for the native SQLite library or the value
+ IntPtr.Zero.
+
+
+
+
+ Searches for the native SQLite library in the directory containing
+ the assembly currently being executed as well as the base directory
+ for the current application domain.
+
+
+ Upon success, this parameter will be modified to refer to the base
+ directory containing the native SQLite library.
+
+
+ Upon success, this parameter will be modified to refer to the name
+ of the immediate directory (i.e. the offset from the base directory)
+ containing the native SQLite library.
+
+
+ Non-zero (success) if the native SQLite library was found; otherwise,
+ zero (failure).
+
+
+
+
+ Queries and returns the base directory of the current application
+ domain.
+
+
+ The base directory for the current application domain -OR- null if it
+ cannot be determined.
+
+
+
+
+ Determines if the dynamic link library file name requires a suffix
+ and adds it if necessary.
+
+
+ The original dynamic link library file name to inspect.
+
+
+ The dynamic link library file name, possibly modified to include an
+ extension.
+
+
+
+
+ Queries and returns the processor architecture of the current
+ process.
+
+
+ The processor architecture of the current process -OR- null if it
+ cannot be determined.
+
+
+
+
+ Given the processor architecture, returns the name of the platform.
+
+
+ The processor architecture to be translated to a platform name.
+
+
+ The platform name for the specified processor architecture -OR- null
+ if it cannot be determined.
+
+
+
+
+ Attempts to load the native SQLite library based on the specified
+ directory and processor architecture.
+
+
+ The base directory to use, null for default (the base directory of
+ the current application domain). This directory should contain the
+ processor architecture specific sub-directories.
+
+
+ The requested processor architecture, null for default (the
+ processor architecture of the current process). This caller should
+ almost always specify null for this parameter.
+
+
+ The candidate native module file name to load will be stored here,
+ if necessary.
+
+
+ The native module handle as returned by LoadLibrary will be stored
+ here, if necessary. This value will be IntPtr.Zero if the call to
+ LoadLibrary fails.
+
+
+ Non-zero if the native module was loaded successfully; otherwise,
+ zero.
+
+
+
+
+ A strongly-typed resource class, for looking up localized strings, etc.
+
+
+
+
+ Returns the cached ResourceManager instance used by this class.
+
+
+
+
+ Overrides the current thread's CurrentUICulture property for all
+ resource lookups using this strongly typed resource class.
+
+
+
+
+ Looks up a localized string similar to <?xml version="1.0" standalone="yes"?>
+ <DocumentElement>
+ <DataTypes>
+ <TypeName>smallint</TypeName>
+ <ProviderDbType>10</ProviderDbType>
+ <ColumnSize>5</ColumnSize>
+ <DataType>System.Int16</DataType>
+ <CreateFormat>smallint</CreateFormat>
+ <IsAutoIncrementable>false</IsAutoIncrementable>
+ <IsCaseSensitive>false</IsCaseSensitive>
+ <IsFixedLength>true</IsFixedLength>
+ <IsFixedPrecisionScale>true</IsFixedPrecisionScale>
+ <IsLong>false</IsLong>
+ <IsNullable>true</ [rest of string was truncated]";.
+
+
+
+
+ Looks up a localized string similar to ALL,ALTER,AND,AS,AUTOINCREMENT,BETWEEN,BY,CASE,CHECK,COLLATE,COMMIT,CONSTRAINT,CREATE,CROSS,DEFAULT,DEFERRABLE,DELETE,DISTINCT,DROP,ELSE,ESCAPE,EXCEPT,FOREIGN,FROM,FULL,GROUP,HAVING,IN,INDEX,INNER,INSERT,INTERSECT,INTO,IS,ISNULL,JOIN,LEFT,LIMIT,NATURAL,NOT,NOTNULL,NULL,ON,OR,ORDER,OUTER,PRIMARY,REFERENCES,RIGHT,ROLLBACK,SELECT,SET,TABLE,THEN,TO,TRANSACTION,UNION,UNIQUE,UPDATE,USING,VALUES,WHEN,WHERE.
+
+
+
+
+ Looks up a localized string similar to <?xml version="1.0" encoding="utf-8" ?>
+ <DocumentElement>
+ <MetaDataCollections>
+ <CollectionName>MetaDataCollections</CollectionName>
+ <NumberOfRestrictions>0</NumberOfRestrictions>
+ <NumberOfIdentifierParts>0</NumberOfIdentifierParts>
+ </MetaDataCollections>
+ <MetaDataCollections>
+ <CollectionName>DataSourceInformation</CollectionName>
+ <NumberOfRestrictions>0</NumberOfRestrictions>
+ <NumberOfIdentifierParts>0</NumberOfIdentifierParts>
+ </MetaDataCollections>
+ <MetaDataC [rest of string was truncated]";.
+
+
+
+
+ This class represents a context from the SQLite core library that can
+ be passed to the sqlite3_result_*() and associated functions.
+
+
+
+
+ This interface represents a native handle provided by the SQLite core
+ library.
+
+
+
+
+ The native handle value.
+
+
+
+
+ The native context handle.
+
+
+
+
+ Constructs an instance of this class using the specified native
+ context handle.
+
+
+ The native context handle to use.
+
+
+
+
+ Sets the context result to NULL.
+
+
+
+
+ Sets the context result to the specified
+ value.
+
+
+ The value to use.
+
+
+
+
+ Sets the context result to the specified
+ value.
+
+
+ The value to use.
+
+
+
+
+ Sets the context result to the specified
+ value.
+
+
+ The value to use.
+
+
+
+
+ Sets the context result to the specified
+ value.
+
+
+ The value to use. This value will be
+ converted to the UTF-8 encoding prior to being used.
+
+
+
+
+ Sets the context result to the specified
+ value containing an error message.
+
+
+ The value containing the error message text.
+ This value will be converted to the UTF-8 encoding prior to being
+ used.
+
+
+
+
+ Sets the context result to the specified
+ value.
+
+
+ The value to use.
+
+
+
+
+ Sets the context result to contain the error code SQLITE_TOOBIG.
+
+
+
+
+ Sets the context result to contain the error code SQLITE_NOMEM.
+
+
+
+
+ Sets the context result to the specified array
+ value.
+
+
+ The array value to use.
+
+
+
+
+ Sets the context result to a BLOB of zeros of the specified size.
+
+
+ The number of zero bytes to use for the BLOB context result.
+
+
+
+
+ Sets the context result to the specified .
+
+
+ The to use.
+
+
+
+
+ Returns the underlying SQLite native handle associated with this
+ object instance.
+
+
+
+
+ This class represents a value from the SQLite core library that can be
+ passed to the sqlite3_value_*() and associated functions.
+
+
+
+
+ The native value handle.
+
+
+
+
+ Constructs an instance of this class using the specified native
+ value handle.
+
+
+ The native value handle to use.
+
+
+
+
+ Invalidates the native value handle, thereby preventing further
+ access to it from this object instance.
+
+
+
+
+ Converts a logical array of native pointers to native sqlite3_value
+ structures into a managed array of
+ object instances.
+
+
+ The number of elements in the logical array of native sqlite3_value
+ structures.
+
+
+ The native pointer to the logical array of native sqlite3_value
+ structures to convert.
+
+
+ The managed array of object instances or
+ null upon failure.
+
+
+
+
+ Gets and returns the type affinity associated with this value.
+
+
+ The type affinity associated with this value.
+
+
+
+
+ Gets and returns the number of bytes associated with this value, if
+ it refers to a UTF-8 encoded string.
+
+
+ The number of bytes associated with this value. The returned value
+ may be zero.
+
+
+
+
+ Gets and returns the associated with this
+ value.
+
+
+ The associated with this value.
+
+
+
+
+ Gets and returns the associated with
+ this value.
+
+
+ The associated with this value.
+
+
+
+
+ Gets and returns the associated with this
+ value.
+
+
+ The associated with this value.
+
+
+
+
+ Gets and returns the associated with this
+ value.
+
+
+ The associated with this value. The value is
+ converted from the UTF-8 encoding prior to being returned.
+
+
+
+
+ Gets and returns the array associated with this
+ value.
+
+
+ The array associated with this value.
+
+
+
+
+ Uses the native value handle to obtain and store the managed value
+ for this object instance, thus saving it for later use. The type
+ of the managed value is determined by the type affinity of the
+ native value. If the type affinity is not recognized by this
+ method, no work is done and false is returned.
+
+
+ Non-zero if the native value was persisted successfully.
+
+
+
+
+ Returns the underlying SQLite native handle associated with this
+ object instance.
+
+
+
+
+ Returns non-zero if the native SQLite value has been successfully
+ persisted as a managed value within this object instance (i.e. the
+ property may then be read successfully).
+
+
+
+
+ If the managed value for this object instance is available (i.e. it
+ has been previously persisted via the ) method,
+ that value is returned; otherwise, an exception is thrown. The
+ returned value may be null.
+
+
+
+
+ These are the allowed values for the operators that are part of a
+ constraint term in the WHERE clause of a query that uses a virtual
+ table.
+
+
+
+
+ This value represents the equality operator.
+
+
+
+
+ This value represents the greater than operator.
+
+
+
+
+ This value represents the less than or equal to operator.
+
+
+
+
+ This value represents the less than operator.
+
+
+
+
+ This value represents the greater than or equal to operator.
+
+
+
+
+ This value represents the MATCH operator.
+
+
+
+
+ This class represents the native sqlite3_index_constraint structure
+ from the SQLite core library.
+
+
+
+
+ Constructs an instance of this class using the specified native
+ sqlite3_index_constraint structure.
+
+
+ The native sqlite3_index_constraint structure to use.
+
+
+
+
+ Constructs an instance of this class using the specified field
+ values.
+
+
+ Column on left-hand side of constraint.
+
+
+ Constraint operator ( ).
+
+
+ True if this constraint is usable.
+
+
+ Used internally -
+ should ignore.
+
+
+
+
+ Column on left-hand side of constraint.
+
+
+
+
+ Constraint operator ( ).
+
+
+
+
+ True if this constraint is usable.
+
+
+
+
+ Used internally -
+ should ignore.
+
+
+
+
+ This class represents the native sqlite3_index_orderby structure from
+ the SQLite core library.
+
+
+
+
+ Constructs an instance of this class using the specified native
+ sqlite3_index_orderby structure.
+
+
+ The native sqlite3_index_orderby structure to use.
+
+
+
+
+ Constructs an instance of this class using the specified field
+ values.
+
+
+ Column number.
+
+
+ True for DESC. False for ASC.
+
+
+
+
+ Column number.
+
+
+
+
+ True for DESC. False for ASC.
+
+
+
+
+ This class represents the native sqlite3_index_constraint_usage
+ structure from the SQLite core library.
+
+
+
+
+ Constructs an instance of this class using the specified native
+ sqlite3_index_constraint_usage structure.
+
+
+ The native sqlite3_index_constraint_usage structure to use.
+
+
+
+
+ Constructs an instance of this class using the specified field
+ values.
+
+
+ If greater than 0, constraint is part of argv to xFilter.
+
+
+ Do not code a test for this constraint.
+
+
+
+
+ If greater than 0, constraint is part of argv to xFilter.
+
+
+
+
+ Do not code a test for this constraint.
+
+
+
+
+ This class represents the various inputs provided by the SQLite core
+ library to the method.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The number of instances to
+ pre-allocate space for.
+
+
+ The number of instances to
+ pre-allocate space for.
+
+
+
+
+ An array of object instances,
+ each containing information supplied by the SQLite core library.
+
+
+
+
+ An array of object instances,
+ each containing information supplied by the SQLite core library.
+
+
+
+
+ This class represents the various outputs provided to the SQLite core
+ library by the method.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The number of instances
+ to pre-allocate space for.
+
+
+
+
+ Determines if the native estimatedRows field can be used, based on
+ the available version of the SQLite core library.
+
+
+ Non-zero if the property is supported
+ by the SQLite core library.
+
+
+
+
+ An array of object
+ instances, each containing information to be supplied to the SQLite
+ core library.
+
+
+
+
+ Number used to help identify the selected index. This value will
+ later be provided to the
+ method.
+
+
+
+
+ String used to help identify the selected index. This value will
+ later be provided to the
+ method.
+
+
+
+
+ Non-zero if the index string must be freed by the SQLite core
+ library.
+
+
+
+
+ True if output is already ordered.
+
+
+
+
+ Estimated cost of using this index. Using a null value here
+ indicates that a default estimated cost value should be used.
+
+
+
+
+ Estimated number of rows returned. Using a null value here
+ indicates that a default estimated rows value should be used.
+
+
+
+
+ This class represents the various inputs and outputs used with the
+ method.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The number of (and
+ ) instances to
+ pre-allocate space for.
+
+
+ The number of instances to
+ pre-allocate space for.
+
+
+
+
+ Converts a native pointer to a native sqlite3_index_info structure
+ into a new object instance.
+
+
+ The native pointer to the native sqlite3_index_info structure to
+ convert.
+
+
+ Upon success, this parameter will be modified to contain the newly
+ created object instance.
+
+
+
+
+ Populates the outputs of a pre-allocated native sqlite3_index_info
+ structure using an existing object
+ instance.
+
+
+ The existing object instance containing
+ the output data to use.
+
+
+ The native pointer to the pre-allocated native sqlite3_index_info
+ structure.
+
+
+
+
+ The object instance containing
+ the inputs to the
+ method.
+
+
+
+
+ The object instance containing
+ the outputs from the
+ method.
+
+
+
+
+ This class represents a managed virtual table implementation. It is
+ not sealed and should be used as the base class for any user-defined
+ virtual table classes implemented in managed code.
+
+
+
+
+ The index within the array of strings provided to the
+ and
+ methods containing the
+ name of the module implementing this virtual table.
+
+
+
+
+ The index within the array of strings provided to the
+ and
+ methods containing the
+ name of the database containing this virtual table.
+
+
+
+
+ The index within the array of strings provided to the
+ and
+ methods containing the
+ name of the virtual table.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The original array of strings provided to the
+ and
+ methods.
+
+
+
+
+ This method should normally be used by the
+ method in order to
+ perform index selection based on the constraints provided by the
+ SQLite core library.
+
+
+ The object instance containing all the
+ data for the inputs and outputs relating to index selection.
+
+
+ Non-zero upon success.
+
+
+
+
+ Attempts to record the renaming of the virtual table associated
+ with this object instance.
+
+
+ The new name for the virtual table.
+
+
+ Non-zero upon success.
+
+
+
+
+ Disposes of this object instance.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is being called
+ from the finalizer.
+
+
+
+
+ Finalizes this object instance.
+
+
+
+
+ The original array of strings provided to the
+ and
+ methods.
+
+
+
+
+ The name of the module implementing this virtual table.
+
+
+
+
+ The name of the database containing this virtual table.
+
+
+
+
+ The name of the virtual table.
+
+
+
+
+ The object instance containing all the
+ data for the inputs and outputs relating to the most recent index
+ selection.
+
+
+
+
+ Returns the underlying SQLite native handle associated with this
+ object instance.
+
+
+
+
+ This class represents a managed virtual table cursor implementation.
+ It is not sealed and should be used as the base class for any
+ user-defined virtual table cursor classes implemented in managed code.
+
+
+
+
+ This value represents an invalid integer row sequence number.
+
+
+
+
+ The field holds the integer row sequence number for the current row
+ pointed to by this cursor object instance.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The object instance associated
+ with this object instance.
+
+
+
+
+ Constructs an instance of this class.
+
+
+
+
+ Attempts to persist the specified object
+ instances in order to make them available after the
+ method returns.
+
+
+ The array of object instances to be
+ persisted.
+
+
+ The number of object instances that were
+ successfully persisted.
+
+
+
+
+ This method should normally be used by the
+ method in order to
+ perform filtering of the result rows and/or to record the filtering
+ criteria provided by the SQLite core library.
+
+
+ Number used to help identify the selected index.
+
+
+ String used to help identify the selected index.
+
+
+ The values corresponding to each column in the selected index.
+
+
+
+
+ Determines the integer row sequence number for the current row.
+
+
+ The integer row sequence number for the current row -OR- zero if
+ it cannot be determined.
+
+
+
+
+ Adjusts the integer row sequence number so that it refers to the
+ next row.
+
+
+
+
+ Disposes of this object instance.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is being called
+ from the finalizer.
+
+
+
+
+ Finalizes this object instance.
+
+
+
+
+ The object instance associated
+ with this object instance.
+
+
+
+
+ Number used to help identify the selected index. This value will
+ be set via the method.
+
+
+
+
+ String used to help identify the selected index. This value will
+ be set via the method.
+
+
+
+
+ The values used to filter the rows returned via this cursor object
+ instance. This value will be set via the
+ method.
+
+
+
+
+ Returns the underlying SQLite native handle associated with this
+ object instance.
+
+
+
+
+ This interface represents a virtual table implementation written in
+ native code.
+
+
+
+
+
+ This method is called to create a new instance of a virtual table
+ in response to a CREATE VIRTUAL TABLE statement. The db parameter
+ is a pointer to the SQLite database connection that is executing
+ the CREATE VIRTUAL TABLE statement. The pAux argument is the copy
+ of the client data pointer that was the fourth argument to the
+ sqlite3_create_module() or sqlite3_create_module_v2() call that
+ registered the virtual table module. The argv parameter is an
+ array of argc pointers to null terminated strings. The first
+ string, argv[0], is the name of the module being invoked. The
+ module name is the name provided as the second argument to
+ sqlite3_create_module() and as the argument to the USING clause of
+ the CREATE VIRTUAL TABLE statement that is running. The second,
+ argv[1], is the name of the database in which the new virtual table
+ is being created. The database name is "main" for the primary
+ database, or "temp" for TEMP database, or the name given at the
+ end of the ATTACH statement for attached databases. The third
+ element of the array, argv[2], is the name of the new virtual
+ table, as specified following the TABLE keyword in the CREATE
+ VIRTUAL TABLE statement. If present, the fourth and subsequent
+ strings in the argv[] array report the arguments to the module name
+ in the CREATE VIRTUAL TABLE statement.
+
+
+ The job of this method is to construct the new virtual table object
+ (an sqlite3_vtab object) and return a pointer to it in *ppVTab.
+
+
+ As part of the task of creating a new sqlite3_vtab structure, this
+ method must invoke sqlite3_declare_vtab() to tell the SQLite core
+ about the columns and datatypes in the virtual table. The
+ sqlite3_declare_vtab() API has the following prototype:
+
+
+
+ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable)
+
+
+
+ The first argument to sqlite3_declare_vtab() must be the same
+ database connection pointer as the first parameter to this method.
+ The second argument to sqlite3_declare_vtab() must a
+ zero-terminated UTF-8 string that contains a well-formed CREATE
+ TABLE statement that defines the columns in the virtual table and
+ their data types. The name of the table in this CREATE TABLE
+ statement is ignored, as are all constraints. Only the column names
+ and datatypes matter. The CREATE TABLE statement string need not to
+ be held in persistent memory. The string can be deallocated and/or
+ reused as soon as the sqlite3_declare_vtab() routine returns.
+
+
+
+ The native database connection handle.
+
+
+ The original native pointer value that was provided to the
+ sqlite3_create_module(), sqlite3_create_module_v2() or
+ sqlite3_create_disposable_module() functions.
+
+
+ The number of arguments from the CREATE VIRTUAL TABLE statement.
+
+
+ The array of string arguments from the CREATE VIRTUAL TABLE
+ statement.
+
+
+ Upon success, this parameter must be modified to point to the newly
+ created native sqlite3_vtab derived structure.
+
+
+ Upon failure, this parameter must be modified to point to the error
+ message, with the underlying memory having been obtained from the
+ sqlite3_malloc() function.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ The xConnect method is very similar to xCreate. It has the same
+ parameters and constructs a new sqlite3_vtab structure just like
+ xCreate. And it must also call sqlite3_declare_vtab() like xCreate.
+
+
+ The difference is that xConnect is called to establish a new
+ connection to an existing virtual table whereas xCreate is called
+ to create a new virtual table from scratch.
+
+
+ The xCreate and xConnect methods are only different when the
+ virtual table has some kind of backing store that must be
+ initialized the first time the virtual table is created. The
+ xCreate method creates and initializes the backing store. The
+ xConnect method just connects to an existing backing store.
+
+
+ As an example, consider a virtual table implementation that
+ provides read-only access to existing comma-separated-value (CSV)
+ files on disk. There is no backing store that needs to be created
+ or initialized for such a virtual table (since the CSV files
+ already exist on disk) so the xCreate and xConnect methods will be
+ identical for that module.
+
+
+ Another example is a virtual table that implements a full-text
+ index. The xCreate method must create and initialize data
+ structures to hold the dictionary and posting lists for that index.
+ The xConnect method, on the other hand, only has to locate and use
+ an existing dictionary and posting lists that were created by a
+ prior xCreate call.
+
+
+ The xConnect method must return SQLITE_OK if it is successful in
+ creating the new virtual table, or SQLITE_ERROR if it is not
+ successful. If not successful, the sqlite3_vtab structure must not
+ be allocated. An error message may optionally be returned in *pzErr
+ if unsuccessful. Space to hold the error message string must be
+ allocated using an SQLite memory allocation function like
+ sqlite3_malloc() or sqlite3_mprintf() as the SQLite core will
+ attempt to free the space using sqlite3_free() after the error has
+ been reported up to the application.
+
+
+ The xConnect method is required for every virtual table
+ implementation, though the xCreate and xConnect pointers of the
+ sqlite3_module object may point to the same function the virtual
+ table does not need to initialize backing store.
+
+
+
+ The native database connection handle.
+
+
+ The original native pointer value that was provided to the
+ sqlite3_create_module(), sqlite3_create_module_v2() or
+ sqlite3_create_disposable_module() functions.
+
+
+ The number of arguments from the CREATE VIRTUAL TABLE statement.
+
+
+ The array of string arguments from the CREATE VIRTUAL TABLE
+ statement.
+
+
+ Upon success, this parameter must be modified to point to the newly
+ created native sqlite3_vtab derived structure.
+
+
+ Upon failure, this parameter must be modified to point to the error
+ message, with the underlying memory having been obtained from the
+ sqlite3_malloc() function.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ SQLite uses the xBestIndex method of a virtual table module to
+ determine the best way to access the virtual table. The xBestIndex
+ method has a prototype like this:
+
+
+ int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
+
+
+ The SQLite core communicates with the xBestIndex method by filling
+ in certain fields of the sqlite3_index_info structure and passing a
+ pointer to that structure into xBestIndex as the second parameter.
+ The xBestIndex method fills out other fields of this structure
+ which forms the reply. The sqlite3_index_info structure looks like
+ this:
+
+
+ struct sqlite3_index_info {
+ /* Inputs */
+ const int nConstraint; /* Number of entries in aConstraint */
+ const struct sqlite3_index_constraint {
+ int iColumn; /* Column on left-hand side of
+ * constraint */
+ unsigned char op; /* Constraint operator */
+ unsigned char usable; /* True if this constraint is usable */
+ int iTermOffset; /* Used internally - xBestIndex should
+ * ignore */
+ } *const aConstraint; /* Table of WHERE clause constraints */
+ const int nOrderBy; /* Number of terms in the ORDER BY
+ * clause */
+ const struct sqlite3_index_orderby {
+ int iColumn; /* Column number */
+ unsigned char desc; /* True for DESC. False for ASC. */
+ } *const aOrderBy; /* The ORDER BY clause */
+ /* Outputs */
+ struct sqlite3_index_constraint_usage {
+ int argvIndex; /* if greater than zero, constraint is
+ * part of argv to xFilter */
+ unsigned char omit; /* Do not code a test for this
+ * constraint */
+ } *const aConstraintUsage;
+ int idxNum; /* Number used to identify the index */
+ char *idxStr; /* String, possibly obtained from
+ * sqlite3_malloc() */
+ int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if
+ * true */
+ int orderByConsumed; /* True if output is already ordered */
+ double estimatedCost; /* Estimated cost of using this index */
+ };
+
+
+ In addition, there are some defined constants:
+
+
+ #define SQLITE_INDEX_CONSTRAINT_EQ 2
+ #define SQLITE_INDEX_CONSTRAINT_GT 4
+ #define SQLITE_INDEX_CONSTRAINT_LE 8
+ #define SQLITE_INDEX_CONSTRAINT_LT 16
+ #define SQLITE_INDEX_CONSTRAINT_GE 32
+ #define SQLITE_INDEX_CONSTRAINT_MATCH 64
+
+
+ The SQLite core calls the xBestIndex method when it is compiling a
+ query that involves a virtual table. In other words, SQLite calls
+ this method when it is running sqlite3_prepare() or the equivalent.
+ By calling this method, the SQLite core is saying to the virtual
+ table that it needs to access some subset of the rows in the
+ virtual table and it wants to know the most efficient way to do
+ that access. The xBestIndex method replies with information that
+ the SQLite core can then use to conduct an efficient search of the
+ virtual table.
+
+
+ While compiling a single SQL query, the SQLite core might call
+ xBestIndex multiple times with different settings in
+ sqlite3_index_info. The SQLite core will then select the
+ combination that appears to give the best performance.
+
+
+ Before calling this method, the SQLite core initializes an instance
+ of the sqlite3_index_info structure with information about the
+ query that it is currently trying to process. This information
+ derives mainly from the WHERE clause and ORDER BY or GROUP BY
+ clauses of the query, but also from any ON or USING clauses if the
+ query is a join. The information that the SQLite core provides to
+ the xBestIndex method is held in the part of the structure that is
+ marked as "Inputs". The "Outputs" section is initialized to zero.
+
+
+ The information in the sqlite3_index_info structure is ephemeral
+ and may be overwritten or deallocated as soon as the xBestIndex
+ method returns. If the xBestIndex method needs to remember any part
+ of the sqlite3_index_info structure, it should make a copy. Care
+ must be take to store the copy in a place where it will be
+ deallocated, such as in the idxStr field with needToFreeIdxStr set
+ to 1.
+
+
+ Note that xBestIndex will always be called before xFilter, since
+ the idxNum and idxStr outputs from xBestIndex are required inputs
+ to xFilter. However, there is no guarantee that xFilter will be
+ called following a successful xBestIndex.
+
+
+ The xBestIndex method is required for every virtual table
+ implementation.
+
+
+ 2.3.1 Inputs
+
+
+ The main thing that the SQLite core is trying to communicate to the
+ virtual table is the constraints that are available to limit the
+ number of rows that need to be searched. The aConstraint[] array
+ contains one entry for each constraint. There will be exactly
+ nConstraint entries in that array.
+
+
+ Each constraint will correspond to a term in the WHERE clause or in
+ a USING or ON clause that is of the form
+
+
+ column OP EXPR
+
+
+ Where "column" is a column in the virtual table, OP is an operator
+ like "=" or "<", and EXPR is an arbitrary expression. So, for
+ example, if the WHERE clause contained a term like this:
+
+
+ a = 5
+
+
+ Then one of the constraints would be on the "a" column with
+ operator "=" and an expression of "5". Constraints need not have a
+ literal representation of the WHERE clause. The query optimizer
+ might make transformations to the WHERE clause in order to extract
+ as many constraints as it can. So, for example, if the WHERE clause
+ contained something like this:
+
+
+ x BETWEEN 10 AND 100 AND 999>y
+
+
+ The query optimizer might translate this into three separate
+ constraints:
+
+
+ x >= 10
+ x <= 100
+ y < 999
+
+
+ For each constraint, the aConstraint[].iColumn field indicates
+ which column appears on the left-hand side of the constraint. The
+ first column of the virtual table is column 0. The rowid of the
+ virtual table is column -1. The aConstraint[].op field indicates
+ which operator is used. The SQLITE_INDEX_CONSTRAINT_* constants map
+ integer constants into operator values. Columns occur in the order
+ they were defined by the call to sqlite3_declare_vtab() in the
+ xCreate or xConnect method. Hidden columns are counted when
+ determining the column index.
+
+
+ The aConstraint[] array contains information about all constraints
+ that apply to the virtual table. But some of the constraints might
+ not be usable because of the way tables are ordered in a join. The
+ xBestIndex method must therefore only consider constraints that
+ have an aConstraint[].usable flag which is true.
+
+
+ In addition to WHERE clause constraints, the SQLite core also tells
+ the xBestIndex method about the ORDER BY clause. (In an aggregate
+ query, the SQLite core might put in GROUP BY clause information in
+ place of the ORDER BY clause information, but this fact should not
+ make any difference to the xBestIndex method.) If all terms of the
+ ORDER BY clause are columns in the virtual table, then nOrderBy
+ will be the number of terms in the ORDER BY clause and the
+ aOrderBy[] array will identify the column for each term in the
+ order by clause and whether or not that column is ASC or DESC.
+
+
+ 2.3.2 Outputs
+
+
+ Given all of the information above, the job of the xBestIndex
+ method it to figure out the best way to search the virtual table.
+
+
+ The xBestIndex method fills the idxNum and idxStr fields with
+ information that communicates an indexing strategy to the xFilter
+ method. The information in idxNum and idxStr is arbitrary as far as
+ the SQLite core is concerned. The SQLite core just copies the
+ information through to the xFilter method. Any desired meaning can
+ be assigned to idxNum and idxStr as long as xBestIndex and xFilter
+ agree on what that meaning is.
+
+
+ The idxStr value may be a string obtained from an SQLite memory
+ allocation function such as sqlite3_mprintf(). If this is the case,
+ then the needToFreeIdxStr flag must be set to true so that the
+ SQLite core will know to call sqlite3_free() on that string when it
+ has finished with it, and thus avoid a memory leak.
+
+
+ If the virtual table will output rows in the order specified by the
+ ORDER BY clause, then the orderByConsumed flag may be set to true.
+ If the output is not automatically in the correct order then
+ orderByConsumed must be left in its default false setting. This
+ will indicate to the SQLite core that it will need to do a separate
+ sorting pass over the data after it comes out of the virtual table.
+
+
+ The estimatedCost field should be set to the estimated number of
+ disk access operations required to execute this query against the
+ virtual table. The SQLite core will often call xBestIndex multiple
+ times with different constraints, obtain multiple cost estimates,
+ then choose the query plan that gives the lowest estimate.
+
+
+ The aConstraintUsage[] array contains one element for each of the
+ nConstraint constraints in the inputs section of the
+ sqlite3_index_info structure. The aConstraintUsage[] array is used
+ by xBestIndex to tell the core how it is using the constraints.
+
+
+ The xBestIndex method may set aConstraintUsage[].argvIndex entries
+ to values greater than one. Exactly one entry should be set to 1,
+ another to 2, another to 3, and so forth up to as many or as few as
+ the xBestIndex method wants. The EXPR of the corresponding
+ constraints will then be passed in as the argv[] parameters to
+ xFilter.
+
+
+ For example, if the aConstraint[3].argvIndex is set to 1, then when
+ xFilter is called, the argv[0] passed to xFilter will have the EXPR
+ value of the aConstraint[3] constraint.
+
+
+ By default, the SQLite core double checks all constraints on each
+ row of the virtual table that it receives. If such a check is
+ redundant, the xBestFilter method can suppress that double-check by
+ setting aConstraintUsage[].omit.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The native pointer to the sqlite3_index_info structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method releases a connection to a virtual table. Only the
+ sqlite3_vtab object is destroyed. The virtual table is not
+ destroyed and any backing store associated with the virtual table
+ persists. This method undoes the work of xConnect.
+
+
+ This method is a destructor for a connection to the virtual table.
+ Contrast this method with xDestroy. The xDestroy is a destructor
+ for the entire virtual table.
+
+
+ The xDisconnect method is required for every virtual table
+ implementation, though it is acceptable for the xDisconnect and
+ xDestroy methods to be the same function if that makes sense for
+ the particular virtual table.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method releases a connection to a virtual table, just like the
+ xDisconnect method, and it also destroys the underlying table
+ implementation. This method undoes the work of xCreate.
+
+
+ The xDisconnect method is called whenever a database connection
+ that uses a virtual table is closed. The xDestroy method is only
+ called when a DROP TABLE statement is executed against the virtual
+ table.
+
+
+ The xDestroy method is required for every virtual table
+ implementation, though it is acceptable for the xDisconnect and
+ xDestroy methods to be the same function if that makes sense for
+ the particular virtual table.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ The xOpen method creates a new cursor used for accessing (read
+ and/or writing) a virtual table. A successful invocation of this
+ method will allocate the memory for the sqlite3_vtab_cursor (or a
+ subclass), initialize the new object, and make *ppCursor point to
+ the new object. The successful call then returns SQLITE_OK.
+
+
+ For every successful call to this method, the SQLite core will
+ later invoke the xClose method to destroy the allocated cursor.
+
+
+ The xOpen method need not initialize the pVtab field of the
+ sqlite3_vtab_cursor structure. The SQLite core will take care of
+ that chore automatically.
+
+
+ A virtual table implementation must be able to support an arbitrary
+ number of simultaneously open cursors.
+
+
+ When initially opened, the cursor is in an undefined state. The
+ SQLite core will invoke the xFilter method on the cursor prior to
+ any attempt to position or read from the cursor.
+
+
+ The xOpen method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ Upon success, this parameter must be modified to point to the newly
+ created native sqlite3_vtab_cursor derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ The xClose method closes a cursor previously opened by xOpen. The
+ SQLite core will always call xClose once for each cursor opened
+ using xOpen.
+
+
+ This method must release all resources allocated by the
+ corresponding xOpen call. The routine will not be called again even
+ if it returns an error. The SQLite core will not use the
+ sqlite3_vtab_cursor again after it has been closed.
+
+
+ The xClose method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method begins a search of a virtual table. The first argument
+ is a cursor opened by xOpen. The next two argument define a
+ particular search index previously chosen by xBestIndex. The
+ specific meanings of idxNum and idxStr are unimportant as long as
+ xFilter and xBestIndex agree on what that meaning is.
+
+
+ The xBestIndex function may have requested the values of certain
+ expressions using the aConstraintUsage[].argvIndex values of the
+ sqlite3_index_info structure. Those values are passed to xFilter
+ using the argc and argv parameters.
+
+
+ If the virtual table contains one or more rows that match the
+ search criteria, then the cursor must be left point at the first
+ row. Subsequent calls to xEof must return false (zero). If there
+ are no rows match, then the cursor must be left in a state that
+ will cause the xEof to return true (non-zero). The SQLite engine
+ will use the xColumn and xRowid methods to access that row content.
+ The xNext method will be used to advance to the next row.
+
+
+ This method must return SQLITE_OK if successful, or an sqlite error
+ code if an error occurs.
+
+
+ The xFilter method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ Number used to help identify the selected index.
+
+
+ The native pointer to the UTF-8 encoded string containing the
+ string used to help identify the selected index.
+
+
+ The number of native pointers to sqlite3_value structures specified
+ in .
+
+
+ An array of native pointers to sqlite3_value structures containing
+ filtering criteria for the selected index.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ The xNext method advances a virtual table cursor to the next row of
+ a result set initiated by xFilter. If the cursor is already
+ pointing at the last row when this routine is called, then the
+ cursor no longer points to valid data and a subsequent call to the
+ xEof method must return true (non-zero). If the cursor is
+ successfully advanced to another row of content, then subsequent
+ calls to xEof must return false (zero).
+
+
+ This method must return SQLITE_OK if successful, or an sqlite error
+ code if an error occurs.
+
+
+ The xNext method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ The xEof method must return false (zero) if the specified cursor
+ currently points to a valid row of data, or true (non-zero)
+ otherwise. This method is called by the SQL engine immediately
+ after each xFilter and xNext invocation.
+
+
+ The xEof method is required for every virtual table implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ Non-zero if no more rows are available; zero otherwise.
+
+
+
+
+
+ The SQLite core invokes this method in order to find the value for
+ the N-th column of the current row. N is zero-based so the first
+ column is numbered 0. The xColumn method may return its result back
+ to SQLite using one of the following interface:
+
+
+ sqlite3_result_blob()
+ sqlite3_result_double()
+ sqlite3_result_int()
+ sqlite3_result_int64()
+ sqlite3_result_null()
+ sqlite3_result_text()
+ sqlite3_result_text16()
+ sqlite3_result_text16le()
+ sqlite3_result_text16be()
+ sqlite3_result_zeroblob()
+
+
+ If the xColumn method implementation calls none of the functions
+ above, then the value of the column defaults to an SQL NULL.
+
+
+ To raise an error, the xColumn method should use one of the
+ result_text() methods to set the error message text, then return an
+ appropriate error code. The xColumn method must return SQLITE_OK on
+ success.
+
+
+ The xColumn method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ The native pointer to the sqlite3_context structure to be used
+ for returning the specified column value to the SQLite core
+ library.
+
+
+ The zero-based index corresponding to the column containing the
+ value to be returned.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ A successful invocation of this method will cause *pRowid to be
+ filled with the rowid of row that the virtual table cursor pCur is
+ currently pointing at. This method returns SQLITE_OK on success. It
+ returns an appropriate error code on failure.
+
+
+ The xRowid method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the current row for the specified cursor.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ All changes to a virtual table are made using the xUpdate method.
+ This one method can be used to insert, delete, or update.
+
+
+ The argc parameter specifies the number of entries in the argv
+ array. The value of argc will be 1 for a pure delete operation or
+ N+2 for an insert or replace or update where N is the number of
+ columns in the table. In the previous sentence, N includes any
+ hidden columns.
+
+
+ Every argv entry will have a non-NULL value in C but may contain
+ the SQL value NULL. In other words, it is always true that
+ argv[i]!=0 for i between 0 and argc-1. However, it might be the
+ case that sqlite3_value_type(argv[i])==SQLITE_NULL.
+
+
+ The argv[0] parameter is the rowid of a row in the virtual table
+ to be deleted. If argv[0] is an SQL NULL, then no deletion occurs.
+
+
+ The argv[1] parameter is the rowid of a new row to be inserted into
+ the virtual table. If argv[1] is an SQL NULL, then the
+ implementation must choose a rowid for the newly inserted row.
+ Subsequent argv[] entries contain values of the columns of the
+ virtual table, in the order that the columns were declared. The
+ number of columns will match the table declaration that the
+ xConnect or xCreate method made using the sqlite3_declare_vtab()
+ call. All hidden columns are included.
+
+
+ When doing an insert without a rowid (argc>1, argv[1] is an SQL
+ NULL), the implementation must set *pRowid to the rowid of the
+ newly inserted row; this will become the value returned by the
+ sqlite3_last_insert_rowid() function. Setting this value in all the
+ other cases is a harmless no-op; the SQLite engine ignores the
+ *pRowid return value if argc==1 or argv[1] is not an SQL NULL.
+
+
+ Each call to xUpdate will fall into one of cases shown below. Note
+ that references to argv[i] mean the SQL value held within the
+ argv[i] object, not the argv[i] object itself.
+
+
+ argc = 1
+
+
+ The single row with rowid equal to argv[0] is deleted. No
+ insert occurs.
+
+
+ argc > 1
+ argv[0] = NULL
+
+
+ A new row is inserted with a rowid argv[1] and column
+ values in argv[2] and following. If argv[1] is an SQL NULL,
+ the a new unique rowid is generated automatically.
+
+
+ argc > 1
+ argv[0] ? NULL
+ argv[0] = argv[1]
+
+
+ The row with rowid argv[0] is updated with new values in
+ argv[2] and following parameters.
+
+
+ argc > 1
+ argv[0] ? NULL
+ argv[0] ? argv[1]
+
+
+ The row with rowid argv[0] is updated with rowid argv[1]
+ and new values in argv[2] and following parameters. This
+ will occur when an SQL statement updates a rowid, as in
+ the statement:
+
+
+ UPDATE table SET rowid=rowid+1 WHERE ...;
+
+
+ The xUpdate method must return SQLITE_OK if and only if it is
+ successful. If a failure occurs, the xUpdate must return an
+ appropriate error code. On a failure, the pVTab->zErrMsg element
+ may optionally be replaced with error message text stored in memory
+ allocated from SQLite using functions such as sqlite3_mprintf() or
+ sqlite3_malloc().
+
+
+ If the xUpdate method violates some constraint of the virtual table
+ (including, but not limited to, attempting to store a value of the
+ wrong datatype, attempting to store a value that is too large or
+ too small, or attempting to change a read-only value) then the
+ xUpdate must fail with an appropriate error code.
+
+
+ There might be one or more sqlite3_vtab_cursor objects open and in
+ use on the virtual table instance and perhaps even on the row of
+ the virtual table when the xUpdate method is invoked. The
+ implementation of xUpdate must be prepared for attempts to delete
+ or modify rows of the table out from other existing cursors. If the
+ virtual table cannot accommodate such changes, the xUpdate method
+ must return an error code.
+
+
+ The xUpdate method is optional. If the xUpdate pointer in the
+ sqlite3_module for a virtual table is a NULL pointer, then the
+ virtual table is read-only.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The number of new or modified column values contained in
+ .
+
+
+ The array of native pointers to sqlite3_value structures containing
+ the new or modified column values, if any.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the row that was inserted, if any.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method begins a transaction on a virtual table. This is method
+ is optional. The xBegin pointer of sqlite3_module may be NULL.
+
+
+ This method is always followed by one call to either the xCommit or
+ xRollback method. Virtual table transactions do not nest, so the
+ xBegin method will not be invoked more than once on a single
+ virtual table without an intervening call to either xCommit or
+ xRollback. Multiple calls to other methods can and likely will
+ occur in between the xBegin and the corresponding xCommit or
+ xRollback.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method signals the start of a two-phase commit on a virtual
+ table. This is method is optional. The xSync pointer of
+ sqlite3_module may be NULL.
+
+
+ This method is only invoked after call to the xBegin method and
+ prior to an xCommit or xRollback. In order to implement two-phase
+ commit, the xSync method on all virtual tables is invoked prior to
+ invoking the xCommit method on any virtual table. If any of the
+ xSync methods fail, the entire transaction is rolled back.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method causes a virtual table transaction to commit. This is
+ method is optional. The xCommit pointer of sqlite3_module may be
+ NULL.
+
+
+ A call to this method always follows a prior call to xBegin and
+ xSync.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method causes a virtual table transaction to rollback. This is
+ method is optional. The xRollback pointer of sqlite3_module may be
+ NULL.
+
+
+ A call to this method always follows a prior call to xBegin.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ This method provides notification that the virtual table
+ implementation that the virtual table will be given a new name. If
+ this method returns SQLITE_OK then SQLite renames the table. If
+ this method returns an error code then the renaming is prevented.
+
+
+ The xRename method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The number of arguments to the function being sought.
+
+
+ The name of the function being sought.
+
+
+ Upon success, this parameter must be modified to contain the
+ delegate responsible for implementing the specified function.
+
+
+ Upon success, this parameter must be modified to contain the
+ native user-data pointer associated with
+ .
+
+
+ Non-zero if the specified function was found; zero otherwise.
+
+
+
+
+
+ This method provides notification that the virtual table
+ implementation that the virtual table will be given a new name. If
+ this method returns SQLITE_OK then SQLite renames the table. If
+ this method returns an error code then the renaming is prevented.
+
+
+ The xRename method is required for every virtual table
+ implementation.
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The native pointer to the UTF-8 encoded string containing the new
+ name for the virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ These methods provide the virtual table implementation an
+ opportunity to implement nested transactions. They are always
+ optional and will only be called in SQLite version 3.7.7 and later.
+
+
+ When xSavepoint(X,N) is invoked, that is a signal to the virtual
+ table X that it should save its current state as savepoint N. A
+ subsequent call to xRollbackTo(X,R) means that the state of the
+ virtual table should return to what it was when xSavepoint(X,R) was
+ last called. The call to xRollbackTo(X,R) will invalidate all
+ savepoints with N>R; none of the invalided savepoints will be
+ rolled back or released without first being reinitialized by a call
+ to xSavepoint(). A call to xRelease(X,M) invalidates all savepoints
+ where N>=M.
+
+
+ None of the xSavepoint(), xRelease(), or xRollbackTo() methods will
+ ever be called except in between calls to xBegin() and either
+ xCommit() or xRollback().
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ This is an integer identifier under which the the current state of
+ the virtual table should be saved.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ These methods provide the virtual table implementation an
+ opportunity to implement nested transactions. They are always
+ optional and will only be called in SQLite version 3.7.7 and later.
+
+
+ When xSavepoint(X,N) is invoked, that is a signal to the virtual
+ table X that it should save its current state as savepoint N. A
+ subsequent call to xRollbackTo(X,R) means that the state of the
+ virtual table should return to what it was when xSavepoint(X,R) was
+ last called. The call to xRollbackTo(X,R) will invalidate all
+ savepoints with N>R; none of the invalided savepoints will be
+ rolled back or released without first being reinitialized by a call
+ to xSavepoint(). A call to xRelease(X,M) invalidates all savepoints
+ where N>=M.
+
+
+ None of the xSavepoint(), xRelease(), or xRollbackTo() methods will
+ ever be called except in between calls to xBegin() and either
+ xCommit() or xRollback().
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ This is an integer used to indicate that any saved states with an
+ identifier greater than or equal to this should be deleted by the
+ virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+
+ These methods provide the virtual table implementation an
+ opportunity to implement nested transactions. They are always
+ optional and will only be called in SQLite version 3.7.7 and later.
+
+
+ When xSavepoint(X,N) is invoked, that is a signal to the virtual
+ table X that it should save its current state as savepoint N. A
+ subsequent call to xRollbackTo(X,R) means that the state of the
+ virtual table should return to what it was when xSavepoint(X,R) was
+ last called. The call to xRollbackTo(X,R) will invalidate all
+ savepoints with N>R; none of the invalided savepoints will be
+ rolled back or released without first being reinitialized by a call
+ to xSavepoint(). A call to xRelease(X,M) invalidates all savepoints
+ where N>=M.
+
+
+ None of the xSavepoint(), xRelease(), or xRollbackTo() methods will
+ ever be called except in between calls to xBegin() and either
+ xCommit() or xRollback().
+
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ This is an integer identifier used to specify a specific saved
+ state for the virtual table for it to restore itself back to, which
+ should also have the effect of deleting all saved states with an
+ integer identifier greater than this one.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This interface represents a virtual table implementation written in
+ managed code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated with
+ the virtual table.
+
+
+ The native user-data pointer associated with this module, as it was
+ provided to the SQLite core library when the native module instance
+ was created.
+
+
+ The module name, database name, virtual table name, and all other
+ arguments passed to the CREATE VIRTUAL TABLE statement.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated with
+ the virtual table.
+
+
+ Upon failure, this parameter must be modified to contain an error
+ message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated with
+ the virtual table.
+
+
+ The native user-data pointer associated with this module, as it was
+ provided to the SQLite core library when the native module instance
+ was created.
+
+
+ The module name, database name, virtual table name, and all other
+ arguments passed to the CREATE VIRTUAL TABLE statement.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated with
+ the virtual table.
+
+
+ Upon failure, this parameter must be modified to contain an error
+ message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The object instance containing all the
+ data for the inputs and outputs relating to index selection.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated
+ with the newly opened virtual table cursor.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Number used to help identify the selected index.
+
+
+ String used to help identify the selected index.
+
+
+ The values corresponding to each column in the selected index.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Non-zero if no more rows are available; zero otherwise.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ The object instance to be used for
+ returning the specified column value to the SQLite core library.
+
+
+ The zero-based index corresponding to the column containing the
+ value to be returned.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the current row for the specified cursor.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The array of object instances containing
+ the new or modified column values, if any.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the row that was inserted, if any.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The number of arguments to the function being sought.
+
+
+ The name of the function being sought.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance responsible for
+ implementing the specified function.
+
+
+ Upon success, this parameter must be modified to contain the
+ native user-data pointer associated with
+ .
+
+
+ Non-zero if the specified function was found; zero otherwise.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The new name for the virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer identifier under which the the current state of
+ the virtual table should be saved.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer used to indicate that any saved states with an
+ identifier greater than or equal to this should be deleted by the
+ virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer identifier used to specify a specific saved
+ state for the virtual table for it to restore itself back to, which
+ should also have the effect of deleting all saved states with an
+ integer identifier greater than this one.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Returns non-zero if the schema for the virtual table has been
+ declared.
+
+
+
+
+ Returns the name of the module as it was registered with the SQLite
+ core library.
+
+
+
+
+ This class contains static methods that are used to allocate,
+ manipulate, and free native memory provided by the SQLite core library.
+
+
+
+
+ Allocates at least the specified number of bytes of native memory
+ via the SQLite core library sqlite3_malloc() function and returns
+ the resulting native pointer.
+
+
+ The number of bytes to allocate.
+
+
+ The native pointer that points to a block of memory of at least the
+ specified size -OR- if the memory could
+ not be allocated.
+
+
+
+
+ Gets and returns the actual size of the specified memory block that
+ was previously obtained from the method.
+
+
+ The native pointer to the memory block previously obtained from the
+ method.
+
+
+ The actual size, in bytes, of the memory block specified via the
+ native pointer.
+
+
+
+
+ Frees a memory block previously obtained from the
+ method.
+
+
+ The native pointer to the memory block previously obtained from the
+ method.
+
+
+
+
+ This class contains static methods that are used to deal with native
+ UTF-8 string pointers to be used with the SQLite core library.
+
+
+
+
+ This is the maximum possible length for the native UTF-8 encoded
+ strings used with the SQLite core library.
+
+
+
+
+ This is the object instance used to handle
+ conversions from/to UTF-8.
+
+
+
+
+ Converts the specified managed string into the UTF-8 encoding and
+ returns the array of bytes containing its representation in that
+ encoding.
+
+
+ The managed string to convert.
+
+
+ The array of bytes containing the representation of the managed
+ string in the UTF-8 encoding or null upon failure.
+
+
+
+
+ Converts the specified array of bytes representing a string in the
+ UTF-8 encoding and returns a managed string.
+
+
+ The array of bytes to convert.
+
+
+ The managed string or null upon failure.
+
+
+
+
+ Probes a native pointer to a string in the UTF-8 encoding for its
+ terminating NUL character, within the specified length limit.
+
+
+ The native NUL-terminated string pointer.
+
+
+ The maximum length of the native string, in bytes.
+
+
+ The length of the native string, in bytes -OR- zero if the length
+ could not be determined.
+
+
+
+
+ Converts the specified native NUL-terminated UTF-8 string pointer
+ into a managed string.
+
+
+ The native NUL-terminated UTF-8 string pointer.
+
+
+ The managed string or null upon failure.
+
+
+
+
+ Converts the specified native UTF-8 string pointer of the specified
+ length into a managed string.
+
+
+ The native UTF-8 string pointer.
+
+
+ The length of the native string, in bytes.
+
+
+ The managed string or null upon failure.
+
+
+
+
+ Converts the specified managed string into a native NUL-terminated
+ UTF-8 string pointer using memory obtained from the SQLite core
+ library.
+
+
+ The managed string to convert.
+
+
+ The native NUL-terminated UTF-8 string pointer or
+ upon failure.
+
+
+
+
+ Converts a logical array of native NUL-terminated UTF-8 string
+ pointers into an array of managed strings.
+
+
+ The number of elements in the logical array of native
+ NUL-terminated UTF-8 string pointers.
+
+
+ The native pointer to the logical array of native NUL-terminated
+ UTF-8 string pointers to convert.
+
+
+ The array of managed strings or null upon failure.
+
+
+
+
+ Converts an array of managed strings into an array of native
+ NUL-terminated UTF-8 string pointers.
+
+
+ The array of managed strings to convert.
+
+
+ The array of native NUL-terminated UTF-8 string pointers or null
+ upon failure.
+
+
+
+
+ This class contains static methods that are used to deal with native
+ pointers to memory blocks that logically contain arrays of bytes to be
+ used with the SQLite core library.
+
+
+
+
+ Converts a native pointer to a logical array of bytes of the
+ specified length into a managed byte array.
+
+
+ The native pointer to the logical array of bytes to convert.
+
+
+ The length, in bytes, of the logical array of bytes to convert.
+
+
+ The managed byte array or null upon failure.
+
+
+
+
+ Converts a managed byte array into a native pointer to a logical
+ array of bytes.
+
+
+ The managed byte array to convert.
+
+
+ The native pointer to a logical byte array or null upon failure.
+
+
+
+
+ This class contains static methods that are used to perform several
+ low-level data marshalling tasks between native and managed code.
+
+
+
+
+ Returns a new object instance based on the
+ specified object instance and an integer
+ offset.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location that the new
+ object instance should point to.
+
+
+ The new object instance.
+
+
+
+
+ Rounds up an integer size to the next multiple of the alignment.
+
+
+ The size, in bytes, to be rounded up.
+
+
+ The required alignment for the return value.
+
+
+ The size, in bytes, rounded up to the next multiple of the
+ alignment. This value may end up being the same as the original
+ size.
+
+
+
+
+ Determines the offset, in bytes, of the next structure member.
+
+
+ The offset, in bytes, of the current structure member.
+
+
+ The size, in bytes, of the current structure member.
+
+
+ The alignment, in bytes, of the next structure member.
+
+
+ The offset, in bytes, of the next structure member.
+
+
+
+
+ Reads a value from the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be read is located.
+
+
+ The value at the specified memory location.
+
+
+
+
+ Reads a value from the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ to be read is located.
+
+
+ The value at the specified memory location.
+
+
+
+
+ Reads an value from the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be read is located.
+
+
+ The value at the specified memory location.
+
+
+
+
+ Writes an value to the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be written is located.
+
+
+ The value to write.
+
+
+
+
+ Writes an value to the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be written is located.
+
+
+ The value to write.
+
+
+
+
+ Writes a value to the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be written is located.
+
+
+ The value to write.
+
+
+
+
+ Writes a value to the specified memory
+ location.
+
+
+ The object instance representing the base
+ memory location.
+
+
+ The integer offset from the base memory location where the
+ value to be written is located.
+
+
+ The value to write.
+
+
+
+
+ Generates a hash code value for the object.
+
+
+ The object instance used to calculate the hash code.
+
+
+ Non-zero if different object instances with the same value should
+ generate different hash codes, where applicable. This parameter
+ has no effect on the .NET Compact Framework.
+
+
+ The hash code value -OR- zero if the object is null.
+
+
+
+
+ This class represents a managed virtual table module implementation.
+ It is not sealed and must be used as the base class for any
+ user-defined virtual table module classes implemented in managed code.
+
+
+
+
+ The default version of the native sqlite3_module structure in use.
+
+
+
+
+ This field is used to store the native sqlite3_module structure
+ associated with this object instance.
+
+
+
+
+ This field is used to store the destructor delegate to be passed to
+ the SQLite core library via the sqlite3_create_disposable_module()
+ function.
+
+
+
+
+ This field is used to store a pointer to the native sqlite3_module
+ structure returned by the sqlite3_create_disposable_module
+ function.
+
+
+
+
+ This field is used to store the virtual table instances associated
+ with this module. The native pointer to the sqlite3_vtab derived
+ structure is used to key into this collection.
+
+
+
+
+ This field is used to store the virtual table cursor instances
+ associated with this module. The native pointer to the
+ sqlite3_vtab_cursor derived structure is used to key into this
+ collection.
+
+
+
+
+ This field is used to store the virtual table function instances
+ associated with this module. The case-insensitive function name
+ and the number of arguments (with -1 meaning "any") are used to
+ construct the string that is used to key into this collection.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the module. This parameter cannot be null.
+
+
+
+
+ Calls the native SQLite core library in order to create a new
+ disposable module containing the implementation of a virtual table.
+
+
+ The native database connection pointer to use.
+
+
+ Non-zero upon success.
+
+
+
+
+ This method is called by the SQLite core library when the native
+ module associated with this object instance is being destroyed due
+ to its parent connection being closed. It may also be called by
+ the "vtshim" module if/when the sqlite3_dispose_module() function
+ is called.
+
+
+ The native user-data pointer associated with this module, as it was
+ provided to the SQLite core library when the native module instance
+ was created.
+
+
+
+
+ Creates and returns the native sqlite_module structure using the
+ configured (or default)
+ interface implementation.
+
+
+ The native sqlite_module structure using the configured (or
+ default) interface
+ implementation.
+
+
+
+
+ Creates and returns the native sqlite_module structure using the
+ specified interface
+ implementation.
+
+
+ The interface implementation to
+ use.
+
+
+ The native sqlite_module structure using the specified
+ interface implementation.
+
+
+
+
+ Creates a copy of the specified
+ object instance,
+ using default implementations for the contained delegates when
+ necessary.
+
+
+ The object
+ instance to copy.
+
+
+ The new object
+ instance.
+
+
+
+
+ Calls one of the virtual table initialization methods.
+
+
+ Non-zero to call the
+ method; otherwise, the
+ method will be called.
+
+
+ The native database connection handle.
+
+
+ The original native pointer value that was provided to the
+ sqlite3_create_module(), sqlite3_create_module_v2() or
+ sqlite3_create_disposable_module() functions.
+
+
+ The number of arguments from the CREATE VIRTUAL TABLE statement.
+
+
+ The array of string arguments from the CREATE VIRTUAL TABLE
+ statement.
+
+
+ Upon success, this parameter must be modified to point to the newly
+ created native sqlite3_vtab derived structure.
+
+
+ Upon failure, this parameter must be modified to point to the error
+ message, with the underlying memory having been obtained from the
+ sqlite3_malloc() function.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Calls one of the virtual table finalization methods.
+
+
+ Non-zero to call the
+ method; otherwise, the
+ method will be
+ called.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance to be used.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ Non-zero if this error message should also be logged using the
+ class.
+
+
+ Non-zero if caught exceptions should be logged using the
+ class.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance to be used.
+
+
+ The object instance used to
+ lookup the native pointer to the sqlite3_vtab derived structure.
+
+
+ Non-zero if this error message should also be logged using the
+ class.
+
+
+ Non-zero if caught exceptions should be logged using the
+ class.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance to be used.
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure
+ used to get the native pointer to the sqlite3_vtab derived
+ structure.
+
+
+ Non-zero if this error message should also be logged using the
+ class.
+
+
+ Non-zero if caught exceptions should be logged using the
+ class.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance to be used.
+
+
+ The object instance used to
+ lookup the native pointer to the sqlite3_vtab derived structure.
+
+
+ Non-zero if this error message should also be logged using the
+ class.
+
+
+ Non-zero if caught exceptions should be logged using the
+ class.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Gets and returns the interface
+ implementation to be used when creating the native sqlite3_module
+ structure. Derived classes may override this method to supply an
+ alternate implementation for the
+ interface.
+
+
+ The interface implementation to
+ be used when populating the native sqlite3_module structure. If
+ the returned value is null, the private methods provided by the
+ class and relating to the
+ interface will be used to
+ create the necessary delegates.
+
+
+
+
+ Creates and returns the
+ interface implementation corresponding to the current
+ object instance.
+
+
+ The interface implementation
+ corresponding to the current object
+ instance.
+
+
+
+
+ Allocates a native sqlite3_vtab derived structure and returns a
+ native pointer to it.
+
+
+ A native pointer to a native sqlite3_vtab derived structure.
+
+
+
+
+ Zeros out the fields of a native sqlite3_vtab derived structure.
+
+
+ The native pointer to the native sqlite3_vtab derived structure to
+ zero.
+
+
+
+
+ Frees a native sqlite3_vtab structure using the provided native
+ pointer to it.
+
+
+ A native pointer to a native sqlite3_vtab derived structure.
+
+
+
+
+ Allocates a native sqlite3_vtab_cursor derived structure and
+ returns a native pointer to it.
+
+
+ A native pointer to a native sqlite3_vtab_cursor derived structure.
+
+
+
+
+ Frees a native sqlite3_vtab_cursor structure using the provided
+ native pointer to it.
+
+
+ A native pointer to a native sqlite3_vtab_cursor derived structure.
+
+
+
+
+ Reads and returns the native pointer to the sqlite3_vtab derived
+ structure based on the native pointer to the sqlite3_vtab_cursor
+ derived structure.
+
+
+ The object instance to be used.
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure
+ from which to read the native pointer to the sqlite3_vtab derived
+ structure.
+
+
+ The native pointer to the sqlite3_vtab derived structure -OR-
+ if it cannot be determined.
+
+
+
+
+ Reads and returns the native pointer to the sqlite3_vtab derived
+ structure based on the native pointer to the sqlite3_vtab_cursor
+ derived structure.
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure
+ from which to read the native pointer to the sqlite3_vtab derived
+ structure.
+
+
+ The native pointer to the sqlite3_vtab derived structure -OR-
+ if it cannot be determined.
+
+
+
+
+ Looks up and returns the object
+ instance based on the native pointer to the sqlite3_vtab derived
+ structure.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The object instance or null if
+ the corresponding one cannot be found.
+
+
+
+
+ Allocates and returns a native pointer to a sqlite3_vtab derived
+ structure and creates an association between it and the specified
+ object instance.
+
+
+ The object instance to be used
+ when creating the association.
+
+
+ The native pointer to a sqlite3_vtab derived structure or
+ if the method fails for any reason.
+
+
+
+
+ Looks up and returns the
+ object instance based on the native pointer to the
+ sqlite3_vtab_cursor derived structure.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The native pointer to the sqlite3_vtab_cursor derived structure.
+
+
+ The object instance or null
+ if the corresponding one cannot be found.
+
+
+
+
+ Allocates and returns a native pointer to a sqlite3_vtab_cursor
+ derived structure and creates an association between it and the
+ specified object instance.
+
+
+ The object instance to be
+ used when creating the association.
+
+
+ The native pointer to a sqlite3_vtab_cursor derived structure or
+ if the method fails for any reason.
+
+
+
+
+ Deterimines the key that should be used to identify and store the
+ object instance for the virtual table
+ (i.e. to be returned via the
+ method).
+
+
+ The number of arguments to the virtual table function.
+
+
+ The name of the virtual table function.
+
+
+ The object instance associated with
+ this virtual table function.
+
+
+ The string that should be used to identify and store the virtual
+ table function instance. This method cannot return null. If null
+ is returned from this method, the behavior is undefined.
+
+
+
+
+ Attempts to declare the schema for the virtual table using the
+ specified database connection.
+
+
+ The object instance to use when
+ declaring the schema of the virtual table. This parameter may not
+ be null.
+
+
+ The string containing the CREATE TABLE statement that completely
+ describes the schema for the virtual table. This parameter may not
+ be null.
+
+
+ Upon failure, this parameter must be modified to contain an error
+ message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Calls the native SQLite core library in order to declare a virtual
+ table function in response to a call into the
+
+ or virtual table
+ methods.
+
+
+ The object instance to use when
+ declaring the schema of the virtual table.
+
+
+ The number of arguments to the function being declared.
+
+
+ The name of the function being declared.
+
+
+ Upon success, the contents of this parameter are undefined. Upon
+ failure, it should contain an appropriate error message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance used to
+ lookup the native pointer to the sqlite3_vtab derived structure.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Arranges for the specified error message to be placed into the
+ zErrMsg field of a sqlite3_vtab derived structure, freeing the
+ existing error message, if any.
+
+
+ The object instance used to
+ lookup the native pointer to the sqlite3_vtab derived structure.
+
+
+ The error message.
+
+
+ Non-zero upon success.
+
+
+
+
+ Modifies the specified object instance
+ to contain the specified estimated cost.
+
+
+ The object instance to modify.
+
+
+ The estimated cost value to use. Using a null value means that the
+ default value provided by the SQLite core library should be used.
+
+
+ Non-zero upon success.
+
+
+
+
+ Modifies the specified object instance
+ to contain the default estimated cost.
+
+
+ The object instance to modify.
+
+
+ Non-zero upon success.
+
+
+
+
+ Modifies the specified object instance
+ to contain the specified estimated rows.
+
+
+ The object instance to modify.
+
+
+ The estimated rows value to use. Using a null value means that the
+ default value provided by the SQLite core library should be used.
+
+
+ Non-zero upon success.
+
+
+
+
+ Modifies the specified object instance
+ to contain the default estimated rows.
+
+
+ The object instance to modify.
+
+
+ Non-zero upon success.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated with
+ the virtual table.
+
+
+ The native user-data pointer associated with this module, as it was
+ provided to the SQLite core library when the native module instance
+ was created.
+
+
+ The module name, database name, virtual table name, and all other
+ arguments passed to the CREATE VIRTUAL TABLE statement.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated with
+ the virtual table.
+
+
+ Upon failure, this parameter must be modified to contain an error
+ message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated with
+ the virtual table.
+
+
+ The native user-data pointer associated with this module, as it was
+ provided to the SQLite core library when the native module instance
+ was created.
+
+
+ The module name, database name, virtual table name, and all other
+ arguments passed to the CREATE VIRTUAL TABLE statement.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated with
+ the virtual table.
+
+
+ Upon failure, this parameter must be modified to contain an error
+ message.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The object instance containing all the
+ data for the inputs and outputs relating to index selection.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance associated
+ with the newly opened virtual table cursor.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Number used to help identify the selected index.
+
+
+ String used to help identify the selected index.
+
+
+ The values corresponding to each column in the selected index.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Non-zero if no more rows are available; zero otherwise.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ The object instance to be used for
+ returning the specified column value to the SQLite core library.
+
+
+ The zero-based index corresponding to the column containing the
+ value to be returned.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the current row for the specified cursor.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The array of object instances containing
+ the new or modified column values, if any.
+
+
+ Upon success, this parameter must be modified to contain the unique
+ integer row identifier for the row that was inserted, if any.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The number of arguments to the function being sought.
+
+
+ The name of the function being sought.
+
+
+ Upon success, this parameter must be modified to contain the
+ object instance responsible for
+ implementing the specified function.
+
+
+ Upon success, this parameter must be modified to contain the
+ native user-data pointer associated with
+ .
+
+
+ Non-zero if the specified function was found; zero otherwise.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ The new name for the virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer identifier under which the the current state of
+ the virtual table should be saved.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer used to indicate that any saved states with an
+ identifier greater than or equal to this should be deleted by the
+ virtual table.
+
+
+ A standard SQLite return code.
+
+
+
+
+ This method is called in response to the
+ method.
+
+
+ The object instance associated
+ with this virtual table.
+
+
+ This is an integer identifier used to specify a specific saved
+ state for the virtual table for it to restore itself back to, which
+ should also have the effect of deleting all saved states with an
+ integer identifier greater than this one.
+
+
+ A standard SQLite return code.
+
+
+
+
+ Disposes of this object instance.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is being
+ called from the finalizer.
+
+
+
+
+ Finalizes this object instance.
+
+
+
+
+ Returns or sets a boolean value indicating whether virtual table
+ errors should be logged using the class.
+
+
+
+
+ Returns or sets a boolean value indicating whether exceptions
+ caught in the
+ method,
+ the method,
+ the method,
+ the method,
+ and the method should be logged using the
+ class.
+
+
+
+
+ Returns or sets a boolean value indicating whether virtual table
+ errors should be logged using the class.
+
+
+
+
+ Returns or sets a boolean value indicating whether exceptions
+ caught in the
+ method,
+ method, and the
+ method should be logged using the
+ class.
+
+
+
+
+ Returns non-zero if the schema for the virtual table has been
+ declared.
+
+
+
+
+ Returns the name of the module as it was registered with the SQLite
+ core library.
+
+
+
+
+ This class implements the
+ interface by forwarding those method calls to the
+ object instance it contains. If the
+ contained object instance is null, all
+ the methods simply generate an
+ error.
+
+
+
+
+ This is the value that is always used for the "logErrors"
+ parameter to the various static error handling methods provided
+ by the class.
+
+
+
+
+ This is the value that is always used for the "logExceptions"
+ parameter to the various static error handling methods provided
+ by the class.
+
+
+
+
+ This is the error message text used when the contained
+ object instance is not available
+ for any reason.
+
+
+
+
+ The object instance used to provide
+ an implementation of the
+ interface.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The object instance used to provide
+ an implementation of the
+ interface.
+
+
+
+
+ Sets the table error message to one that indicates the native
+ module implementation is not available.
+
+
+ The native pointer to the sqlite3_vtab derived structure.
+
+
+ The value of .
+
+
+
+
+ Sets the table error message to one that indicates the native
+ module implementation is not available.
+
+
+ The native pointer to the sqlite3_vtab_cursor derived
+ structure.
+
+
+ The value of .
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ Disposes of this object instance.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is being
+ called from the finalizer.
+
+
+
+
+ Finalizes this object instance.
+
+
+
+
+ This class represents a virtual table cursor to be used with the
+ class. It is not sealed and may
+ be used as the base class for any user-defined virtual table cursor
+ class that wraps an object instance.
+
+
+
+
+ The instance provided when this cursor
+ was created.
+
+
+
+
+ This value will be non-zero if false has been returned from the
+ method.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The object instance associated
+ with this object instance.
+
+
+ The instance to expose as a virtual
+ table cursor.
+
+
+
+
+ Advances to the next row of the virtual table cursor using the
+ method of the
+ object instance.
+
+
+ Non-zero if the current row is valid; zero otherwise. If zero is
+ returned, no further rows are available.
+
+
+
+
+ Resets the virtual table cursor position, also invalidating the
+ current row, using the method of
+ the object instance.
+
+
+
+
+ Closes the virtual table cursor. This method must not throw any
+ exceptions.
+
+
+
+
+ Throws an if the virtual
+ table cursor has been closed.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is
+ being called from the finalizer.
+
+
+
+
+ Returns the value for the current row of the virtual table cursor
+ using the property of the
+ object instance.
+
+
+
+
+ Returns non-zero if the end of the virtual table cursor has been
+ seen (i.e. no more rows are available, including the current one).
+
+
+
+
+ Returns non-zero if the virtual table cursor is open.
+
+
+
+
+ This class implements a virtual table module that exposes an
+ object instance as a read-only virtual
+ table. It is not sealed and may be used as the base class for any
+ user-defined virtual table class that wraps an
+ object instance. The following short
+ example shows it being used to treat an array of strings as a table
+ data source:
+
+ public static class Sample
+ {
+ public static void Main()
+ {
+ using (SQLiteConnection connection = new SQLiteConnection(
+ "Data Source=:memory:;"))
+ {
+ connection.Open();
+
+ connection.CreateModule(new SQLiteModuleEnumerable(
+ "sampleModule", new string[] { "one", "two", "three" }));
+
+ using (SQLiteCommand command = connection.CreateCommand())
+ {
+ command.CommandText =
+ "CREATE VIRTUAL TABLE t1 USING sampleModule;";
+
+ command.ExecuteNonQuery();
+ }
+
+ using (SQLiteCommand command = connection.CreateCommand())
+ {
+ command.CommandText = "SELECT * FROM t1;";
+
+ using (SQLiteDataReader dataReader = command.ExecuteReader())
+ {
+ while (dataReader.Read())
+ Console.WriteLine(dataReader[0].ToString());
+ }
+ }
+
+ connection.Close();
+ }
+ }
+ }
+
+
+
+
+
+ This class implements a virtual table module that does nothing by
+ providing "empty" implementations for all of the
+ interface methods. The result
+ codes returned by these "empty" method implementations may be
+ controlled on a per-method basis by using and/or overriding the
+ ,
+ ,
+ ,
+ , and
+ methods from within derived classes.
+
+
+
+
+ This field is used to store the
+ values to return, on a per-method basis, for all methods that are
+ part of the interface.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the module. This parameter cannot be null.
+
+
+
+
+ Determines the default value to be
+ returned by methods of the
+ interface that lack an overridden implementation in all classes
+ derived from the class.
+
+
+ The value that should be returned
+ by all interface methods unless
+ a more specific result code has been set for that interface method.
+
+
+
+
+ Converts a value into a boolean
+ return value for use with the
+ method.
+
+
+ The value to convert.
+
+
+ The value.
+
+
+
+
+ Converts a value into a boolean
+ return value for use with the
+ method.
+
+
+ The value to convert.
+
+
+ The value.
+
+
+
+
+ Determines the value that should be
+ returned by the specified
+ interface method if it lack an overridden implementation. If no
+ specific value is available (or set)
+ for the specified method, the value
+ returned by the method will be
+ returned instead.
+
+
+ The name of the method. Currently, this method must be part of
+ the interface.
+
+
+ The value that should be returned
+ by the interface method.
+
+
+
+
+ Sets the value that should be
+ returned by the specified
+ interface method if it lack an overridden implementation.
+
+
+ The name of the method. Currently, this method must be part of
+ the interface.
+
+
+ The value that should be returned
+ by the interface method.
+
+
+ Non-zero upon success.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is
+ being called from the finalizer.
+
+
+
+
+ The CREATE TABLE statement used to declare the schema for the
+ virtual table.
+
+
+
+
+ The instance containing the backing data
+ for the virtual table.
+
+
+
+
+ Non-zero if different object instances with the same value should
+ generate different row identifiers, where applicable. This has no
+ effect on the .NET Compact Framework.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the module. This parameter cannot be null.
+
+
+ The instance to expose as a virtual
+ table. This parameter cannot be null.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the module. This parameter cannot be null.
+
+
+ The instance to expose as a virtual
+ table. This parameter cannot be null.
+
+
+ Non-zero if different object instances with the same value should
+ generate different row identifiers, where applicable. This
+ parameter has no effect on the .NET Compact Framework.
+
+
+
+
+ Determines the SQL statement used to declare the virtual table.
+ This method should be overridden in derived classes if they require
+ a custom virtual table schema.
+
+
+ The SQL statement used to declare the virtual table -OR- null if it
+ cannot be determined.
+
+
+
+
+ Sets the table error message to one that indicates the virtual
+ table cursor is of the wrong type.
+
+
+ The object instance.
+
+
+ The value of .
+
+
+
+
+ Sets the table error message to one that indicates the virtual
+ table cursor has no current row.
+
+
+ The object instance.
+
+
+ The value of .
+
+
+
+
+ Determines the string to return as the column value for the object
+ instance value.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ The object instance to return a string representation for.
+
+
+ The string representation of the specified object instance or null
+ upon failure.
+
+
+
+
+ Constructs an unique row identifier from two
+ values. The first value
+ must contain the row sequence number for the current row and the
+ second value must contain the hash code of the enumerator value
+ for the current row.
+
+
+ The integer row sequence number for the current row.
+
+
+ The hash code of the enumerator value for the current row.
+
+
+ The unique row identifier or zero upon failure.
+
+
+
+
+ Determines the unique row identifier for the current row.
+
+
+ The object instance
+ associated with the previously opened virtual table cursor to be
+ used.
+
+
+ The object instance to return a unique row identifier for.
+
+
+ The unique row identifier or zero upon failure.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is
+ being called from the finalizer.
+
+
+
+
+ This class represents a virtual table cursor to be used with the
+ class. It is not sealed and may
+ be used as the base class for any user-defined virtual table cursor
+ class that wraps an object instance.
+
+
+
+
+ The instance provided when this
+ cursor was created.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The object instance associated
+ with this object instance.
+
+
+ The instance to expose as a virtual
+ table cursor.
+
+
+
+
+ Closes the virtual table cursor. This method must not throw any
+ exceptions.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is
+ being called from the finalizer.
+
+
+
+
+ Returns the value for the current row of the virtual table cursor
+ using the property of the
+ object instance.
+
+
+
+
+ This class implements a virtual table module that exposes an
+ object instance as a read-only virtual
+ table. It is not sealed and may be used as the base class for any
+ user-defined virtual table class that wraps an
+ object instance.
+
+
+
+
+ The instance containing the backing
+ data for the virtual table.
+
+
+
+
+ Constructs an instance of this class.
+
+
+ The name of the module. This parameter cannot be null.
+
+
+ The instance to expose as a virtual
+ table. This parameter cannot be null.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+ See the method.
+
+
+
+
+ Throws an if this object
+ instance has been disposed.
+
+
+
+
+ Disposes of this object instance.
+
+
+ Non-zero if this method is being called from the
+ method. Zero if this method is
+ being called from the finalizer.
+
+
+
+
diff --git a/src/Libraries/Sqlite/libsqlite3.0.dylib b/src/Libraries/Sqlite/libsqlite3.0.dylib
new file mode 100644
index 000000000..364b585e7
Binary files /dev/null and b/src/Libraries/Sqlite/libsqlite3.0.dylib differ
diff --git a/src/Libraries/Sqlite/libsqlite3.dylib b/src/Libraries/Sqlite/libsqlite3.dylib
new file mode 120000
index 000000000..3a850bc81
--- /dev/null
+++ b/src/Libraries/Sqlite/libsqlite3.dylib
@@ -0,0 +1 @@
+libsqlite3.0.dylib
\ No newline at end of file
diff --git a/src/Libraries/Sqlite/sqlite3.dll b/src/Libraries/Sqlite/sqlite3.dll
new file mode 100644
index 000000000..a65d21493
Binary files /dev/null and b/src/Libraries/Sqlite/sqlite3.dll differ
diff --git a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioArtistResource.cs b/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioArtistResource.cs
deleted file mode 100644
index 653ed1df0..000000000
--- a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioArtistResource.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-using Lidarr.Api.V1.Albums;
-
-namespace Lidarr.Api.V1.AlbumStudio
-{
- public class AlbumStudioArtistResource
- {
- public int Id { get; set; }
- public bool? Monitored { get; set; }
- public List Albums { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioController.cs b/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioController.cs
deleted file mode 100644
index 57d640cd7..000000000
--- a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioController.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System.Linq;
-using Lidarr.Http;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.AlbumStudio
-{
- [V1ApiController]
- public class AlbumStudioController : Controller
- {
- private readonly IArtistService _artistService;
- private readonly IAlbumMonitoredService _albumMonitoredService;
-
- public AlbumStudioController(IArtistService artistService, IAlbumMonitoredService albumMonitoredService)
- {
- _artistService = artistService;
- _albumMonitoredService = albumMonitoredService;
- }
-
- [HttpPost]
- [Consumes("application/json")]
- public IActionResult UpdateAll([FromBody] AlbumStudioResource resource)
- {
- var artistToUpdate = _artistService.GetArtists(resource.Artist.Select(s => s.Id));
-
- foreach (var s in resource.Artist)
- {
- var artist = artistToUpdate.Single(c => c.Id == s.Id);
-
- if (s.Monitored.HasValue)
- {
- artist.Monitored = s.Monitored.Value;
- }
-
- if (resource.MonitoringOptions is { Monitor: MonitorTypes.None })
- {
- artist.Monitored = false;
- }
-
- if (resource.MonitorNewItems.HasValue)
- {
- artist.MonitorNewItems = resource.MonitorNewItems.Value;
- }
-
- _albumMonitoredService.SetAlbumMonitoredStatus(artist, resource.MonitoringOptions);
- }
-
- return Accepted(new object());
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioResource.cs b/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioResource.cs
deleted file mode 100644
index 97dbbc81f..000000000
--- a/src/Lidarr.Api.V1/AlbumStudio/AlbumStudioResource.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System.Collections.Generic;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.AlbumStudio
-{
- public class AlbumStudioResource
- {
- public List Artist { get; set; }
- public MonitoringOptions MonitoringOptions { get; set; }
- public NewItemMonitorTypes? MonitorNewItems { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumController.cs b/src/Lidarr.Api.V1/Albums/AlbumController.cs
deleted file mode 100644
index 149ca51fd..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumController.cs
+++ /dev/null
@@ -1,234 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using FluentValidation;
-using Lidarr.Http;
-using Lidarr.Http.REST.Attributes;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.ArtistStats;
-using NzbDrone.Core.Datastore.Events;
-using NzbDrone.Core.DecisionEngine.Specifications;
-using NzbDrone.Core.Download;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.MediaFiles;
-using NzbDrone.Core.MediaFiles.Events;
-using NzbDrone.Core.Messaging.Events;
-using NzbDrone.Core.Music;
-using NzbDrone.Core.Music.Events;
-using NzbDrone.Core.Validation;
-using NzbDrone.Core.Validation.Paths;
-using NzbDrone.SignalR;
-
-namespace Lidarr.Api.V1.Albums
-{
- [V1ApiController]
- public class AlbumController : AlbumControllerWithSignalR,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle
- {
- protected readonly IArtistService _artistService;
- protected readonly IReleaseService _releaseService;
- protected readonly IAddAlbumService _addAlbumService;
-
- public AlbumController(IArtistService artistService,
- IAlbumService albumService,
- IAddAlbumService addAlbumService,
- IReleaseService releaseService,
- IArtistStatisticsService artistStatisticsService,
- IMapCoversToLocal coverMapper,
- IUpgradableSpecification upgradableSpecification,
- IBroadcastSignalRMessage signalRBroadcaster,
- RootFolderValidator rootFolderValidator,
- MappedNetworkDriveValidator mappedNetworkDriveValidator,
- ArtistAncestorValidator artistAncestorValidator,
- RecycleBinValidator recycleBinValidator,
- SystemFolderValidator systemFolderValidator,
- AlbumExistsValidator albumExistsValidator,
- RootFolderExistsValidator rootFolderExistsValidator,
- QualityProfileExistsValidator qualityProfileExistsValidator,
- MetadataProfileExistsValidator metadataProfileExistsValidator)
-
- : base(albumService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
- {
- _artistService = artistService;
- _releaseService = releaseService;
- _addAlbumService = addAlbumService;
-
- PostValidator.RuleFor(s => s.ForeignAlbumId).NotEmpty().SetValidator(albumExistsValidator);
- PostValidator.RuleFor(s => s.Artist).NotNull();
- PostValidator.RuleFor(s => s.Artist.ForeignArtistId).NotEmpty().When(s => s.Artist != null);
-
- PostValidator.RuleFor(s => s.Artist.QualityProfileId).Cascade(CascadeMode.Stop)
- .ValidId()
- .SetValidator(qualityProfileExistsValidator)
- .When(s => s.Artist != null);
-
- PostValidator.RuleFor(s => s.Artist.MetadataProfileId).Cascade(CascadeMode.Stop)
- .ValidId()
- .SetValidator(metadataProfileExistsValidator)
- .When(s => s.Artist != null);
-
- PostValidator.RuleFor(s => s.Artist.Path).Cascade(CascadeMode.Stop)
- .IsValidPath()
- .SetValidator(rootFolderValidator)
- .SetValidator(mappedNetworkDriveValidator)
- .SetValidator(artistAncestorValidator)
- .SetValidator(recycleBinValidator)
- .SetValidator(systemFolderValidator)
- .When(s => s.Artist != null && s.Artist.Path.IsNotNullOrWhiteSpace());
-
- PostValidator.RuleFor(s => s.Artist.RootFolderPath)
- .IsValidPath()
- .SetValidator(rootFolderExistsValidator)
- .When(s => s.Artist != null && s.Artist.Path.IsNullOrWhiteSpace());
- }
-
- [HttpGet]
- public List GetAlbums([FromQuery]int? artistId,
- [FromQuery] List albumIds,
- [FromQuery]string foreignAlbumId,
- [FromQuery]bool includeAllArtistAlbums = false)
- {
- if (!artistId.HasValue && !albumIds.Any() && foreignAlbumId.IsNullOrWhiteSpace())
- {
- var albums = _albumService.GetAllAlbums();
-
- var artists = _artistService.GetAllArtists().ToDictionary(x => x.ArtistMetadataId);
- var releases = _releaseService.GetAllReleases().GroupBy(x => x.AlbumId).ToDictionary(x => x.Key, y => y.ToList());
-
- foreach (var album in albums)
- {
- if (!artists.TryGetValue(album.ArtistMetadataId, out var albumArtist))
- {
- continue;
- }
-
- album.Artist = albumArtist;
- album.AlbumReleases = releases.TryGetValue(album.Id, out var albumReleases) ? albumReleases : new List();
- }
-
- return MapToResource(albums, false);
- }
-
- if (artistId.HasValue)
- {
- return MapToResource(_albumService.GetAlbumsByArtist(artistId.Value), false);
- }
-
- if (foreignAlbumId.IsNotNullOrWhiteSpace())
- {
- var album = _albumService.FindById(foreignAlbumId);
-
- if (album == null)
- {
- return MapToResource(new List(), false);
- }
-
- if (includeAllArtistAlbums)
- {
- return MapToResource(_albumService.GetAlbumsByArtist(album.ArtistId), false);
- }
- else
- {
- return MapToResource(new List { album }, false);
- }
- }
-
- return MapToResource(_albumService.GetAlbums(albumIds), false);
- }
-
- [RestPostById]
- public ActionResult AddAlbum(AlbumResource albumResource)
- {
- var album = _addAlbumService.AddAlbum(albumResource.ToModel());
-
- return Created(album.Id);
- }
-
- [RestPutById]
- public ActionResult UpdateAlbum(AlbumResource albumResource)
- {
- var album = _albumService.GetAlbum(albumResource.Id);
-
- var model = albumResource.ToModel(album);
-
- _albumService.UpdateAlbum(model);
- _releaseService.UpdateMany(model.AlbumReleases.Value);
-
- BroadcastResourceChange(ModelAction.Updated, model.Id);
-
- return Accepted(model.Id);
- }
-
- [RestDeleteById]
- public void DeleteAlbum(int id, bool deleteFiles = false, bool addImportListExclusion = false)
- {
- _albumService.DeleteAlbum(id, deleteFiles, addImportListExclusion);
- }
-
- [HttpPut("monitor")]
- public IActionResult SetAlbumsMonitored([FromBody]AlbumsMonitoredResource resource)
- {
- _albumService.SetMonitored(resource.AlbumIds, resource.Monitored);
-
- return Accepted(MapToResource(_albumService.GetAlbums(resource.AlbumIds), false));
- }
-
- [NonAction]
- public void Handle(AlbumGrabbedEvent message)
- {
- foreach (var album in message.Album.Albums)
- {
- var resource = album.ToResource();
- resource.Grabbed = true;
-
- BroadcastResourceChange(ModelAction.Updated, resource);
- }
- }
-
- [NonAction]
- public void Handle(AlbumEditedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Album, true));
- }
-
- [NonAction]
- public void Handle(AlbumUpdatedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Album, true));
- }
-
- [NonAction]
- public void Handle(AlbumDeletedEvent message)
- {
- BroadcastResourceChange(ModelAction.Deleted, message.Album.ToResource());
- }
-
- [NonAction]
- public void Handle(AlbumImportedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, MapToResource(message.Album, true));
- }
-
- [NonAction]
- public void Handle(TrackImportedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, message.TrackInfo.Album.ToResource());
- }
-
- [NonAction]
- public void Handle(TrackFileDeletedEvent message)
- {
- if (message.Reason == DeleteMediaFileReason.Upgrade)
- {
- return;
- }
-
- BroadcastResourceChange(ModelAction.Updated, MapToResource(message.TrackFile.Album.Value, true));
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumControllerWithSignalR.cs b/src/Lidarr.Api.V1/Albums/AlbumControllerWithSignalR.cs
deleted file mode 100644
index 5a7d33b2d..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumControllerWithSignalR.cs
+++ /dev/null
@@ -1,114 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Lidarr.Api.V1.Artist;
-using Lidarr.Http.REST;
-using NzbDrone.Core.ArtistStats;
-using NzbDrone.Core.DecisionEngine.Specifications;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.Music;
-using NzbDrone.SignalR;
-
-namespace Lidarr.Api.V1.Albums
-{
- public abstract class AlbumControllerWithSignalR : RestControllerWithSignalR
- {
- protected readonly IAlbumService _albumService;
- protected readonly IArtistStatisticsService _artistStatisticsService;
- protected readonly IUpgradableSpecification _qualityUpgradableSpecification;
- protected readonly IMapCoversToLocal _coverMapper;
-
- protected AlbumControllerWithSignalR(IAlbumService albumService,
- IArtistStatisticsService artistStatisticsService,
- IMapCoversToLocal coverMapper,
- IUpgradableSpecification qualityUpgradableSpecification,
- IBroadcastSignalRMessage signalRBroadcaster)
- : base(signalRBroadcaster)
- {
- _albumService = albumService;
- _artistStatisticsService = artistStatisticsService;
- _coverMapper = coverMapper;
- _qualityUpgradableSpecification = qualityUpgradableSpecification;
- }
-
- public override AlbumResource GetResourceById(int id)
- {
- var album = _albumService.GetAlbum(id);
- var resource = MapToResource(album, true);
- return resource;
- }
-
- protected AlbumResource MapToResource(Album album, bool includeArtist)
- {
- var resource = album.ToResource();
-
- if (includeArtist)
- {
- var artist = album.Artist.Value;
-
- resource.Artist = artist.ToResource();
- }
-
- FetchAndLinkAlbumStatistics(resource);
- MapCoversToLocal(resource);
-
- return resource;
- }
-
- protected List MapToResource(List albums, bool includeArtist)
- {
- var result = albums.ToResource();
-
- if (includeArtist)
- {
- var artistDict = new Dictionary();
- for (var i = 0; i < albums.Count; i++)
- {
- var album = albums[i];
- var resource = result[i];
- var artist = artistDict.GetValueOrDefault(albums[i].ArtistMetadataId) ?? album.Artist?.Value;
- artistDict[artist.ArtistMetadataId] = artist;
-
- resource.Artist = artist.ToResource();
- }
- }
-
- var artistStats = _artistStatisticsService.ArtistStatistics();
- LinkArtistStatistics(result, artistStats);
- MapCoversToLocal(result.ToArray());
-
- return result;
- }
-
- private void FetchAndLinkAlbumStatistics(AlbumResource resource)
- {
- LinkArtistStatistics(resource, _artistStatisticsService.ArtistStatistics(resource.ArtistId));
- }
-
- private void LinkArtistStatistics(List resources, List artistStatistics)
- {
- foreach (var album in resources)
- {
- var stats = artistStatistics.SingleOrDefault(ss => ss.ArtistId == album.ArtistId);
- LinkArtistStatistics(album, stats);
- }
- }
-
- private void LinkArtistStatistics(AlbumResource resource, ArtistStatistics artistStatistics)
- {
- if (artistStatistics?.AlbumStatistics != null)
- {
- var dictAlbumStats = artistStatistics.AlbumStatistics.ToDictionary(v => v.AlbumId);
-
- resource.Statistics = dictAlbumStats.GetValueOrDefault(resource.Id).ToResource();
- }
- }
-
- private void MapCoversToLocal(params AlbumResource[] albums)
- {
- foreach (var albumResource in albums)
- {
- _coverMapper.ConvertToLocalUrls(albumResource.Id, MediaCoverEntity.Album, albumResource.Images);
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumLookupController.cs b/src/Lidarr.Api.V1/Albums/AlbumLookupController.cs
deleted file mode 100644
index e8853f611..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumLookupController.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Lidarr.Http;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.MetadataSource;
-
-namespace Lidarr.Api.V1.Albums
-{
- [V1ApiController("album/lookup")]
- public class AlbumLookupController : Controller
- {
- private readonly ISearchForNewAlbum _searchProxy;
- private readonly IMapCoversToLocal _coverMapper;
-
- public AlbumLookupController(ISearchForNewAlbum searchProxy, IMapCoversToLocal coverMapper)
- {
- _searchProxy = searchProxy;
- _coverMapper = coverMapper;
- }
-
- [HttpGet]
- [Produces("application/json")]
- public IEnumerable Search(string term)
- {
- var searchResults = _searchProxy.SearchForNewAlbum(term, null);
- return MapToResource(searchResults).ToList();
- }
-
- private IEnumerable MapToResource(IEnumerable albums)
- {
- foreach (var currentAlbum in albums)
- {
- var resource = currentAlbum.ToResource();
-
- _coverMapper.ConvertToLocalUrls(resource.Id, MediaCoverEntity.Album, resource.Images);
-
- var cover = currentAlbum.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Cover);
- if (cover != null)
- {
- resource.RemoteCover = cover.RemoteUrl;
- }
-
- yield return resource;
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumReleaseResource.cs b/src/Lidarr.Api.V1/Albums/AlbumReleaseResource.cs
deleted file mode 100644
index ce94efd5a..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumReleaseResource.cs
+++ /dev/null
@@ -1,107 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.Albums
-{
- public class AlbumReleaseResource
- {
- public int Id { get; set; }
- public int AlbumId { get; set; }
- public string ForeignReleaseId { get; set; }
- public string Title { get; set; }
- public string Status { get; set; }
- public int Duration { get; set; }
- public int TrackCount { get; set; }
- public List Media { get; set; }
- public int MediumCount
- {
- get
- {
- if (Media == null)
- {
- return 0;
- }
-
- return Media.Where(s => s.MediumNumber > 0).Count();
- }
- }
-
- public string Disambiguation { get; set; }
- public List Country { get; set; }
- public List Label { get; set; }
- public string Format { get; set; }
- public bool Monitored { get; set; }
- }
-
- public static class AlbumReleaseResourceMapper
- {
- public static AlbumReleaseResource ToResource(this AlbumRelease model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new AlbumReleaseResource
- {
- Id = model.Id,
- AlbumId = model.AlbumId,
- ForeignReleaseId = model.ForeignReleaseId,
- Title = model.Title,
- Status = model.Status,
- Duration = model.Duration,
- TrackCount = model.TrackCount,
- Media = model.Media.ToResource(),
- Disambiguation = model.Disambiguation,
- Country = model.Country,
- Label = model.Label,
- Monitored = model.Monitored,
- Format = string.Join(", ",
- model.Media.OrderBy(x => x.Number)
- .GroupBy(x => x.Format)
- .Select(g => MediaFormatHelper(g.Key, g.Count()))
- .ToList())
- };
- }
-
- public static AlbumRelease ToModel(this AlbumReleaseResource resource)
- {
- if (resource == null)
- {
- return null;
- }
-
- return new AlbumRelease
- {
- Id = resource.Id,
- AlbumId = resource.AlbumId,
- ForeignReleaseId = resource.ForeignReleaseId,
- Title = resource.Title,
- Status = resource.Status,
- Duration = resource.Duration,
- Label = resource.Label,
- Disambiguation = resource.Disambiguation,
- Country = resource.Country,
- Media = resource.Media.ToModel(),
- TrackCount = resource.TrackCount,
- Monitored = resource.Monitored
- };
- }
-
- private static string MediaFormatHelper(string name, int count)
- {
- return count == 1 ? name : string.Join("x", new List { count.ToString(), name });
- }
-
- public static List ToResource(this IEnumerable models)
- {
- return models.Select(ToResource).ToList();
- }
-
- public static List ToModel(this IEnumerable resources)
- {
- return resources.Select(ToModel).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumResource.cs b/src/Lidarr.Api.V1/Albums/AlbumResource.cs
deleted file mode 100644
index 24715e653..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumResource.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json.Serialization;
-using Lidarr.Api.V1.Artist;
-using Lidarr.Http.REST;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.Music;
-using Swashbuckle.AspNetCore.Annotations;
-
-namespace Lidarr.Api.V1.Albums
-{
- public class AlbumResource : RestResource
- {
- public string Title { get; set; }
- public string Disambiguation { get; set; }
- public string Overview { get; set; }
- public int ArtistId { get; set; }
- public string ForeignAlbumId { get; set; }
- public bool Monitored { get; set; }
- public bool AnyReleaseOk { get; set; }
- public int ProfileId { get; set; }
- public int Duration { get; set; }
- public string AlbumType { get; set; }
- public List SecondaryTypes { get; set; }
- public int MediumCount
- {
- get
- {
- if (Media == null)
- {
- return 0;
- }
-
- return Media.Where(s => s.MediumNumber > 0).Count();
- }
- }
-
- public Ratings Ratings { get; set; }
- public DateTime? ReleaseDate { get; set; }
- public List Releases { get; set; }
- public List Genres { get; set; }
- public List Media { get; set; }
- public ArtistResource Artist { get; set; }
- public List Images { get; set; }
- public List Links { get; set; }
- public DateTime? LastSearchTime { get; set; }
- public AlbumStatisticsResource Statistics { get; set; }
- public AddAlbumOptions AddOptions { get; set; }
- public string RemoteCover { get; set; }
-
- // Hiding this so people don't think its usable (only used to set the initial state)
- [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
- [SwaggerIgnore]
- public bool Grabbed { get; set; }
- }
-
- public static class AlbumResourceMapper
- {
- public static AlbumResource ToResource(this Album model)
- {
- if (model == null)
- {
- return null;
- }
-
- var selectedRelease = model.AlbumReleases?.Value.Where(x => x.Monitored).SingleOrDefault();
-
- return new AlbumResource
- {
- Id = model.Id,
- ArtistId = model.ArtistId,
- ForeignAlbumId = model.ForeignAlbumId,
- ProfileId = model.ProfileId,
- Monitored = model.Monitored,
- AnyReleaseOk = model.AnyReleaseOk,
- ReleaseDate = model.ReleaseDate,
- Genres = model.Genres,
- Title = model.Title,
- Disambiguation = model.Disambiguation,
- Overview = model.Overview,
- Images = model.Images,
- Links = model.Links,
- Ratings = model.Ratings,
- Duration = selectedRelease?.Duration ?? 0,
- AlbumType = model.AlbumType,
- SecondaryTypes = model.SecondaryTypes.Select(s => s.Name).ToList(),
- Releases = model.AlbumReleases?.Value.ToResource() ?? new List(),
- Media = selectedRelease?.Media.ToResource() ?? new List(),
- Artist = model.Artist?.Value.ToResource(),
- LastSearchTime = model.LastSearchTime
- };
- }
-
- public static Album ToModel(this AlbumResource resource)
- {
- if (resource == null)
- {
- return null;
- }
-
- var artist = resource.Artist?.ToModel() ?? new NzbDrone.Core.Music.Artist();
-
- return new Album
- {
- Id = resource.Id,
- ForeignAlbumId = resource.ForeignAlbumId,
- Title = resource.Title,
- Disambiguation = resource.Disambiguation,
- Overview = resource.Overview,
- Images = resource.Images,
- AlbumType = resource.AlbumType,
- Monitored = resource.Monitored,
- AnyReleaseOk = resource.AnyReleaseOk,
- AlbumReleases = resource.Releases?.ToModel() ?? new List(),
- AddOptions = resource.AddOptions ?? new AddAlbumOptions(),
- Artist = artist,
- ArtistMetadata = artist.Metadata.Value
- };
- }
-
- public static Album ToModel(this AlbumResource resource, Album album)
- {
- var updatedAlbum = resource.ToModel();
-
- album.ApplyChanges(updatedAlbum);
- album.AlbumReleases = updatedAlbum.AlbumReleases;
-
- return album;
- }
-
- public static List ToResource(this IEnumerable models)
- {
- return models?.Select(ToResource).ToList();
- }
-
- public static List ToModel(this IEnumerable resources)
- {
- return resources.Select(ToModel).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumStatisticsResource.cs b/src/Lidarr.Api.V1/Albums/AlbumStatisticsResource.cs
deleted file mode 100644
index a6173fabe..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumStatisticsResource.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using NzbDrone.Core.ArtistStats;
-
-namespace Lidarr.Api.V1.Albums
-{
- public class AlbumStatisticsResource
- {
- public int TrackFileCount { get; set; }
- public int TrackCount { get; set; }
- public int TotalTrackCount { get; set; }
- public long SizeOnDisk { get; set; }
-
- public decimal PercentOfTracks
- {
- get
- {
- if (TrackCount == 0)
- {
- return 0;
- }
-
- return TrackFileCount / (decimal)TrackCount * 100;
- }
- }
- }
-
- public static class AlbumStatisticsResourceMapper
- {
- public static AlbumStatisticsResource ToResource(this AlbumStatistics model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new AlbumStatisticsResource
- {
- TrackFileCount = model.TrackFileCount,
- TrackCount = model.TrackCount,
- TotalTrackCount = model.TotalTrackCount,
- SizeOnDisk = model.SizeOnDisk
- };
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/AlbumsMonitoredResource.cs b/src/Lidarr.Api.V1/Albums/AlbumsMonitoredResource.cs
deleted file mode 100644
index bfefef856..000000000
--- a/src/Lidarr.Api.V1/Albums/AlbumsMonitoredResource.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections.Generic;
-
-namespace Lidarr.Api.V1.Albums
-{
- public class AlbumsMonitoredResource
- {
- public List AlbumIds { get; set; }
- public bool Monitored { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Albums/MediumResource.cs b/src/Lidarr.Api.V1/Albums/MediumResource.cs
deleted file mode 100644
index 239cf02b1..000000000
--- a/src/Lidarr.Api.V1/Albums/MediumResource.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.Albums
-{
- public class MediumResource
- {
- public int MediumNumber { get; set; }
- public string MediumName { get; set; }
- public string MediumFormat { get; set; }
- }
-
- public static class MediumResourceMapper
- {
- public static MediumResource ToResource(this Medium model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new MediumResource
- {
- MediumNumber = model.Number,
- MediumName = model.Name,
- MediumFormat = model.Format
- };
- }
-
- public static Medium ToModel(this MediumResource resource)
- {
- if (resource == null)
- {
- return null;
- }
-
- return new Medium
- {
- Number = resource.MediumNumber,
- Name = resource.MediumName,
- Format = resource.MediumFormat
- };
- }
-
- public static List ToResource(this IEnumerable models)
- {
- return models.Select(ToResource).ToList();
- }
-
- public static List ToModel(this IEnumerable resources)
- {
- return resources.Select(ToModel).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/ApplyTags.cs b/src/Lidarr.Api.V1/ApplyTags.cs
deleted file mode 100644
index 0c4ab5a5c..000000000
--- a/src/Lidarr.Api.V1/ApplyTags.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Lidarr.Api.V1
-{
- public enum ApplyTags
- {
- Add,
- Remove,
- Replace
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/AlternateTitleResource.cs b/src/Lidarr.Api.V1/Artist/AlternateTitleResource.cs
deleted file mode 100644
index 0cecb77fb..000000000
--- a/src/Lidarr.Api.V1/Artist/AlternateTitleResource.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace Lidarr.Api.V1.Artist
-{
- public class AlternateTitleResource
- {
- public string Title { get; set; }
- public int? SeasonNumber { get; set; }
- public int? SceneSeasonNumber { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistController.cs b/src/Lidarr.Api.V1/Artist/ArtistController.cs
deleted file mode 100644
index 60f7f61fc..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistController.cs
+++ /dev/null
@@ -1,335 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using FluentValidation;
-using Lidarr.Api.V1.Albums;
-using Lidarr.Http;
-using Lidarr.Http.REST;
-using Lidarr.Http.REST.Attributes;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.ArtistStats;
-using NzbDrone.Core.Datastore.Events;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.MediaFiles;
-using NzbDrone.Core.MediaFiles.Events;
-using NzbDrone.Core.Messaging.Commands;
-using NzbDrone.Core.Messaging.Events;
-using NzbDrone.Core.Music;
-using NzbDrone.Core.Music.Commands;
-using NzbDrone.Core.Music.Events;
-using NzbDrone.Core.RootFolders;
-using NzbDrone.Core.Validation;
-using NzbDrone.Core.Validation.Paths;
-using NzbDrone.SignalR;
-
-namespace Lidarr.Api.V1.Artist
-{
- [V1ApiController]
- public class ArtistController : RestControllerWithSignalR,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle,
- IHandle
- {
- private readonly IArtistService _artistService;
- private readonly IAlbumService _albumService;
- private readonly IAddArtistService _addArtistService;
- private readonly IArtistStatisticsService _artistStatisticsService;
- private readonly IMapCoversToLocal _coverMapper;
- private readonly IManageCommandQueue _commandQueueManager;
- private readonly IRootFolderService _rootFolderService;
-
- public ArtistController(IBroadcastSignalRMessage signalRBroadcaster,
- IArtistService artistService,
- IAlbumService albumService,
- IAddArtistService addArtistService,
- IArtistStatisticsService artistStatisticsService,
- IMapCoversToLocal coverMapper,
- IManageCommandQueue commandQueueManager,
- IRootFolderService rootFolderService,
- RecycleBinValidator recycleBinValidator,
- RootFolderValidator rootFolderValidator,
- MappedNetworkDriveValidator mappedNetworkDriveValidator,
- ArtistPathValidator artistPathValidator,
- ArtistExistsValidator artistExistsValidator,
- ArtistAncestorValidator artistAncestorValidator,
- SystemFolderValidator systemFolderValidator,
- QualityProfileExistsValidator qualityProfileExistsValidator,
- MetadataProfileExistsValidator metadataProfileExistsValidator,
- RootFolderExistsValidator rootFolderExistsValidator,
- ArtistFolderAsRootFolderValidator artistFolderAsRootFolderValidator)
- : base(signalRBroadcaster)
- {
- _artistService = artistService;
- _albumService = albumService;
- _addArtistService = addArtistService;
- _artistStatisticsService = artistStatisticsService;
-
- _coverMapper = coverMapper;
- _commandQueueManager = commandQueueManager;
- _rootFolderService = rootFolderService;
-
- Http.Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.QualityProfileId));
- Http.Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.MetadataProfileId));
-
- SharedValidator.RuleFor(s => s.Path)
- .Cascade(CascadeMode.Stop)
- .IsValidPath()
- .SetValidator(rootFolderValidator)
- .SetValidator(mappedNetworkDriveValidator)
- .SetValidator(artistPathValidator)
- .SetValidator(artistAncestorValidator)
- .SetValidator(recycleBinValidator)
- .SetValidator(systemFolderValidator)
- .When(s => !s.Path.IsNullOrWhiteSpace());
-
- SharedValidator.RuleFor(s => s.QualityProfileId).SetValidator(qualityProfileExistsValidator);
- SharedValidator.RuleFor(s => s.MetadataProfileId).SetValidator(metadataProfileExistsValidator);
-
- PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
- PostValidator.RuleFor(s => s.RootFolderPath)
- .IsValidPath()
- .SetValidator(rootFolderExistsValidator)
- .SetValidator(artistFolderAsRootFolderValidator)
- .When(s => s.Path.IsNullOrWhiteSpace());
- PostValidator.RuleFor(s => s.ArtistName).NotEmpty();
- PostValidator.RuleFor(s => s.ForeignArtistId).NotEmpty().SetValidator(artistExistsValidator);
-
- PutValidator.RuleFor(s => s.Path).IsValidPath();
- }
-
- public override ArtistResource GetResourceById(int id)
- {
- var artist = _artistService.GetArtist(id);
- return GetArtistResource(artist);
- }
-
- private ArtistResource GetArtistResource(NzbDrone.Core.Music.Artist artist)
- {
- if (artist == null)
- {
- return null;
- }
-
- var resource = artist.ToResource();
- MapCoversToLocal(resource);
- FetchAndLinkArtistStatistics(resource);
- LinkNextPreviousAlbums(resource);
-
- // PopulateAlternateTitles(resource);
- LinkRootFolderPath(resource);
-
- return resource;
- }
-
- [HttpGet]
- [Produces("application/json")]
- public List AllArtists(Guid? mbId)
- {
- var artistStats = _artistStatisticsService.ArtistStatistics();
- var artistsResources = new List();
-
- if (mbId.HasValue)
- {
- artistsResources.AddIfNotNull(_artistService.FindById(mbId.Value.ToString()).ToResource());
- }
- else
- {
- artistsResources.AddRange(_artistService.GetAllArtists().ToResource());
- }
-
- MapCoversToLocal(artistsResources.ToArray());
- LinkNextPreviousAlbums(artistsResources.ToArray());
- LinkArtistStatistics(artistsResources, artistStats.ToDictionary(x => x.ArtistId));
- artistsResources.ForEach(LinkRootFolderPath);
-
- // PopulateAlternateTitles(seriesResources);
- return artistsResources;
- }
-
- [RestPostById]
- [Consumes("application/json")]
- [Produces("application/json")]
- public ActionResult AddArtist(ArtistResource artistResource)
- {
- var artist = _addArtistService.AddArtist(artistResource.ToModel());
-
- return Created(artist.Id);
- }
-
- [RestPutById]
- [Consumes("application/json")]
- [Produces("application/json")]
- public ActionResult UpdateArtist(ArtistResource artistResource, bool moveFiles = false)
- {
- var artist = _artistService.GetArtist(artistResource.Id);
-
- var sourcePath = artist.Path;
- var destinationPath = artistResource.Path;
-
- _commandQueueManager.Push(new MoveArtistCommand
- {
- ArtistId = artist.Id,
- SourcePath = sourcePath,
- DestinationPath = destinationPath,
- MoveFiles = moveFiles
- }, trigger: CommandTrigger.Manual);
-
- var model = artistResource.ToModel(artist);
-
- _artistService.UpdateArtist(model);
-
- BroadcastResourceChange(ModelAction.Updated, artistResource);
-
- return Accepted(artistResource.Id);
- }
-
- [RestDeleteById]
- public void DeleteArtist(int id, bool deleteFiles = false, bool addImportListExclusion = false)
- {
- _artistService.DeleteArtist(id, deleteFiles, addImportListExclusion);
- }
-
- private void MapCoversToLocal(params ArtistResource[] artists)
- {
- foreach (var artistResource in artists)
- {
- _coverMapper.ConvertToLocalUrls(artistResource.Id, MediaCoverEntity.Artist, artistResource.Images);
- }
- }
-
- private void LinkNextPreviousAlbums(params ArtistResource[] artists)
- {
- var artistMetadataIds = artists.Select(x => x.ArtistMetadataId).Distinct().ToList();
-
- var nextAlbums = _albumService.GetNextAlbumsByArtistMetadataId(artistMetadataIds);
- var lastAlbums = _albumService.GetLastAlbumsByArtistMetadataId(artistMetadataIds);
-
- foreach (var artistResource in artists)
- {
- artistResource.NextAlbum = nextAlbums.FirstOrDefault(x => x.ArtistMetadataId == artistResource.ArtistMetadataId).ToResource();
- artistResource.LastAlbum = lastAlbums.FirstOrDefault(x => x.ArtistMetadataId == artistResource.ArtistMetadataId).ToResource();
- }
- }
-
- private void FetchAndLinkArtistStatistics(ArtistResource resource)
- {
- LinkArtistStatistics(resource, _artistStatisticsService.ArtistStatistics(resource.Id));
- }
-
- private void LinkArtistStatistics(List resources, Dictionary artistStatistics)
- {
- foreach (var artist in resources)
- {
- if (artistStatistics.TryGetValue(artist.Id, out var stats))
- {
- LinkArtistStatistics(artist, stats);
- }
- }
- }
-
- private void LinkArtistStatistics(ArtistResource resource, ArtistStatistics artistStatistics)
- {
- resource.Statistics = artistStatistics.ToResource();
- }
-
- // private void PopulateAlternateTitles(List resources)
- // {
- // foreach (var resource in resources)
- // {
- // PopulateAlternateTitles(resource);
- // }
- // }
-
- // private void PopulateAlternateTitles(ArtistResource resource)
- // {
- // var mappings = _sceneMappingService.FindByTvdbId(resource.TvdbId);
-
- // if (mappings == null) return;
-
- // resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
- // }
- private void LinkRootFolderPath(ArtistResource resource)
- {
- resource.RootFolderPath = _rootFolderService.GetBestRootFolderPath(resource.Path);
- }
-
- [NonAction]
- public void Handle(AlbumImportedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Artist));
- }
-
- [NonAction]
- public void Handle(AlbumEditedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Album.Artist.Value));
- }
-
- [NonAction]
- public void Handle(AlbumDeletedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Album.Artist.Value));
- }
-
- [NonAction]
- public void Handle(TrackFileDeletedEvent message)
- {
- if (message.Reason == DeleteMediaFileReason.Upgrade)
- {
- return;
- }
-
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.TrackFile.Artist.Value));
- }
-
- [NonAction]
- public void Handle(ArtistAddedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Artist));
- }
-
- [NonAction]
- public void Handle(ArtistUpdatedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Artist));
- }
-
- [NonAction]
- public void Handle(ArtistEditedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Artist));
- }
-
- [NonAction]
- public void Handle(ArtistsDeletedEvent message)
- {
- foreach (var artist in message.Artists)
- {
- BroadcastResourceChange(ModelAction.Deleted, artist.ToResource());
- }
- }
-
- [NonAction]
- public void Handle(ArtistRenamedEvent message)
- {
- BroadcastResourceChange(ModelAction.Updated, message.Artist.Id);
- }
-
- [NonAction]
- public void Handle(MediaCoversUpdatedEvent message)
- {
- if (message.Updated)
- {
- BroadcastResourceChange(ModelAction.Updated, GetArtistResource(message.Artist));
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistEditorController.cs b/src/Lidarr.Api.V1/Artist/ArtistEditorController.cs
deleted file mode 100644
index c4eedb3d4..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistEditorController.cs
+++ /dev/null
@@ -1,134 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using FluentValidation;
-using Lidarr.Api.V1.Albums;
-using Lidarr.Http;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.Messaging.Commands;
-using NzbDrone.Core.Music;
-using NzbDrone.Core.Music.Commands;
-
-namespace Lidarr.Api.V1.Artist
-{
- [V1ApiController("artist/editor")]
- public class ArtistEditorController : Controller
- {
- private readonly IArtistService _artistService;
- private readonly IAlbumService _albumService;
- private readonly IManageCommandQueue _commandQueueManager;
- private readonly ArtistEditorValidator _artistEditorValidator;
-
- public ArtistEditorController(IArtistService artistService, IAlbumService albumService, IManageCommandQueue commandQueueManager, ArtistEditorValidator artistEditorValidator)
- {
- _artistService = artistService;
- _albumService = albumService;
- _commandQueueManager = commandQueueManager;
- _artistEditorValidator = artistEditorValidator;
- }
-
- [HttpPut]
- public IActionResult SaveAll([FromBody] ArtistEditorResource resource)
- {
- var artistToUpdate = _artistService.GetArtists(resource.ArtistIds);
- var artistToMove = new List();
-
- foreach (var artist in artistToUpdate)
- {
- if (resource.Monitored.HasValue)
- {
- artist.Monitored = resource.Monitored.Value;
- }
-
- if (resource.MonitorNewItems.HasValue)
- {
- artist.MonitorNewItems = resource.MonitorNewItems.Value;
- }
-
- if (resource.QualityProfileId.HasValue)
- {
- artist.QualityProfileId = resource.QualityProfileId.Value;
- }
-
- if (resource.MetadataProfileId.HasValue)
- {
- artist.MetadataProfileId = resource.MetadataProfileId.Value;
- }
-
- if (resource.RootFolderPath.IsNotNullOrWhiteSpace())
- {
- artist.RootFolderPath = resource.RootFolderPath;
- artistToMove.Add(new BulkMoveArtist
- {
- ArtistId = artist.Id,
- SourcePath = artist.Path
- });
- }
-
- if (resource.Tags != null)
- {
- var newTags = resource.Tags;
- var applyTags = resource.ApplyTags;
-
- switch (applyTags)
- {
- case ApplyTags.Add:
- newTags.ForEach(t => artist.Tags.Add(t));
- break;
- case ApplyTags.Remove:
- newTags.ForEach(t => artist.Tags.Remove(t));
- break;
- case ApplyTags.Replace:
- artist.Tags = new HashSet(newTags);
- break;
- }
- }
-
- var validationResult = _artistEditorValidator.Validate(artist);
-
- if (!validationResult.IsValid)
- {
- throw new ValidationException(validationResult.Errors);
- }
- }
-
- if (artistToMove.Any())
- {
- _commandQueueManager.Push(new BulkMoveArtistCommand
- {
- DestinationRootFolder = resource.RootFolderPath,
- Artist = artistToMove,
- MoveFiles = resource.MoveFiles
- });
- }
-
- var resources = _artistService.UpdateArtists(artistToUpdate, !resource.MoveFiles).ToResource();
-
- LinkNextPreviousAlbums(resources.ToArray());
-
- return Accepted(resources);
- }
-
- [HttpDelete]
- public object DeleteArtist([FromBody] ArtistEditorResource resource)
- {
- _artistService.DeleteArtists(resource.ArtistIds, resource.DeleteFiles, resource.AddImportListExclusion);
-
- return new { };
- }
-
- private void LinkNextPreviousAlbums(params ArtistResource[] artists)
- {
- var artistMetadataIds = artists.Select(x => x.ArtistMetadataId).Distinct().ToList();
-
- var nextAlbums = _albumService.GetNextAlbumsByArtistMetadataId(artistMetadataIds);
- var lastAlbums = _albumService.GetLastAlbumsByArtistMetadataId(artistMetadataIds);
-
- foreach (var artistResource in artists)
- {
- artistResource.NextAlbum = nextAlbums.FirstOrDefault(x => x.ArtistMetadataId == artistResource.ArtistMetadataId).ToResource();
- artistResource.LastAlbum = lastAlbums.FirstOrDefault(x => x.ArtistMetadataId == artistResource.ArtistMetadataId).ToResource();
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistEditorDeleteResource.cs b/src/Lidarr.Api.V1/Artist/ArtistEditorDeleteResource.cs
deleted file mode 100644
index cd719149e..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistEditorDeleteResource.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Collections.Generic;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistEditorDeleteResource
- {
- public List ArtistIds { get; set; }
- public bool DeleteFiles { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistEditorResource.cs b/src/Lidarr.Api.V1/Artist/ArtistEditorResource.cs
deleted file mode 100644
index 0b8bd7703..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistEditorResource.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using System.Collections.Generic;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistEditorResource
- {
- public List ArtistIds { get; set; }
- public bool? Monitored { get; set; }
- public NewItemMonitorTypes? MonitorNewItems { get; set; }
- public int? QualityProfileId { get; set; }
- public int? MetadataProfileId { get; set; }
- public string RootFolderPath { get; set; }
- public List Tags { get; set; }
- public ApplyTags ApplyTags { get; set; }
- public bool MoveFiles { get; set; }
- public bool DeleteFiles { get; set; }
- public bool AddImportListExclusion { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistEditorValidator.cs b/src/Lidarr.Api.V1/Artist/ArtistEditorValidator.cs
deleted file mode 100644
index 05677a5c9..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistEditorValidator.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using FluentValidation;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.Validation;
-using NzbDrone.Core.Validation.Paths;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistEditorValidator : AbstractValidator
- {
- public ArtistEditorValidator(RootFolderExistsValidator rootFolderExistsValidator, QualityProfileExistsValidator qualityProfileExistsValidator, MetadataProfileExistsValidator metadataProfileExistsValidator)
- {
- RuleFor(a => a.RootFolderPath).Cascade(CascadeMode.Stop)
- .IsValidPath()
- .SetValidator(rootFolderExistsValidator)
- .When(a => a.RootFolderPath.IsNotNullOrWhiteSpace());
-
- RuleFor(c => c.QualityProfileId).Cascade(CascadeMode.Stop)
- .ValidId()
- .SetValidator(qualityProfileExistsValidator);
-
- RuleFor(c => c.MetadataProfileId).Cascade(CascadeMode.Stop)
- .ValidId()
- .SetValidator(metadataProfileExistsValidator);
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistFolderAsRootFolderValidator.cs b/src/Lidarr.Api.V1/Artist/ArtistFolderAsRootFolderValidator.cs
deleted file mode 100644
index d58ae235e..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistFolderAsRootFolderValidator.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using System;
-using System.IO;
-using FluentValidation.Validators;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.Organizer;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistFolderAsRootFolderValidator : PropertyValidator
- {
- private readonly IBuildFileNames _fileNameBuilder;
-
- public ArtistFolderAsRootFolderValidator(IBuildFileNames fileNameBuilder)
- {
- _fileNameBuilder = fileNameBuilder;
- }
-
- protected override string GetDefaultMessageTemplate() => "Root folder path '{rootFolderPath}' contains artist folder '{artistFolder}'";
-
- protected override bool IsValid(PropertyValidatorContext context)
- {
- if (context.PropertyValue == null)
- {
- return true;
- }
-
- if (context.InstanceToValidate is not ArtistResource artistResource)
- {
- return true;
- }
-
- var rootFolderPath = context.PropertyValue.ToString();
-
- if (rootFolderPath.IsNullOrWhiteSpace())
- {
- return true;
- }
-
- var rootFolder = new DirectoryInfo(rootFolderPath!).Name;
- var artist = artistResource.ToModel();
- var artistFolder = _fileNameBuilder.GetArtistFolder(artist);
-
- context.MessageFormatter.AppendArgument("rootFolderPath", rootFolderPath);
- context.MessageFormatter.AppendArgument("artistFolder", artistFolder);
-
- if (artistFolder == rootFolder)
- {
- return false;
- }
-
- var distance = artistFolder.LevenshteinDistance(rootFolder);
-
- return distance >= Math.Max(1, artistFolder.Length * 0.2);
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistLookupController.cs b/src/Lidarr.Api.V1/Artist/ArtistLookupController.cs
deleted file mode 100644
index 19a18a0ba..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistLookupController.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using Lidarr.Http;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.MetadataSource;
-using NzbDrone.Core.Organizer;
-
-namespace Lidarr.Api.V1.Artist
-{
- [V1ApiController("artist/lookup")]
- public class ArtistLookupController : Controller
- {
- private readonly ISearchForNewArtist _searchProxy;
- private readonly IBuildFileNames _fileNameBuilder;
- private readonly IMapCoversToLocal _coverMapper;
-
- public ArtistLookupController(ISearchForNewArtist searchProxy, IBuildFileNames fileNameBuilder, IMapCoversToLocal coverMapper)
- {
- _searchProxy = searchProxy;
- _fileNameBuilder = fileNameBuilder;
- _coverMapper = coverMapper;
- }
-
- [HttpGet]
- [Produces("application/json")]
- public IEnumerable Search([FromQuery] string term)
- {
- var searchResults = _searchProxy.SearchForNewArtist(term);
- return MapToResource(searchResults).ToList();
- }
-
- private IEnumerable MapToResource(IEnumerable artist)
- {
- foreach (var currentArtist in artist)
- {
- var resource = currentArtist.ToResource();
-
- _coverMapper.ConvertToLocalUrls(resource.Id, MediaCoverEntity.Artist, resource.Images);
-
- var poster = currentArtist.Metadata.Value.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
-
- if (poster != null)
- {
- resource.RemotePoster = poster.RemoteUrl;
- }
-
- resource.Folder = _fileNameBuilder.GetArtistFolder(currentArtist);
-
- yield return resource;
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistResource.cs b/src/Lidarr.Api.V1/Artist/ArtistResource.cs
deleted file mode 100644
index dc6b32343..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistResource.cs
+++ /dev/null
@@ -1,176 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json.Serialization;
-using Lidarr.Api.V1.Albums;
-using Lidarr.Http.REST;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.Music;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistResource : RestResource
- {
- // Todo: Sorters should be done completely on the client
- // Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
- // Todo: We should get the entire Profile instead of ID and Name separately
- [JsonIgnore]
- public int ArtistMetadataId { get; set; }
- public ArtistStatusType Status { get; set; }
-
- public bool Ended => Status == ArtistStatusType.Ended;
-
- public string ArtistName { get; set; }
- public string ForeignArtistId { get; set; }
- public string MBId { get; set; }
- public int TADBId { get; set; }
- public int DiscogsId { get; set; }
- public string AllMusicId { get; set; }
- public string Overview { get; set; }
- public string ArtistType { get; set; }
- public string Disambiguation { get; set; }
- public List Links { get; set; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
- public AlbumResource NextAlbum { get; set; }
-
- [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
- public AlbumResource LastAlbum { get; set; }
-
- public List Images { get; set; }
- public List Members { get; set; }
-
- public string RemotePoster { get; set; }
-
- // View & Edit
- public string Path { get; set; }
- public int QualityProfileId { get; set; }
- public int MetadataProfileId { get; set; }
-
- // Editing Only
- public bool Monitored { get; set; }
- public NewItemMonitorTypes MonitorNewItems { get; set; }
-
- public string RootFolderPath { get; set; }
- public string Folder { get; set; }
- public List Genres { get; set; }
- public string CleanName { get; set; }
- public string SortName { get; set; }
- public HashSet Tags { get; set; }
- public DateTime Added { get; set; }
- public AddArtistOptions AddOptions { get; set; }
- public Ratings Ratings { get; set; }
-
- public ArtistStatisticsResource Statistics { get; set; }
- }
-
- public static class ArtistResourceMapper
- {
- public static ArtistResource ToResource(this NzbDrone.Core.Music.Artist model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new ArtistResource
- {
- Id = model.Id,
- ArtistMetadataId = model.ArtistMetadataId,
-
- ArtistName = model.Name,
-
- // AlternateTitles
- SortName = model.SortName,
-
- Status = model.Metadata.Value.Status,
- Overview = model.Metadata.Value.Overview,
- ArtistType = model.Metadata.Value.Type,
- Disambiguation = model.Metadata.Value.Disambiguation,
-
- Images = model.Metadata.Value.Images.JsonClone(),
-
- Path = model.Path,
- QualityProfileId = model.QualityProfileId,
- MetadataProfileId = model.MetadataProfileId,
- Links = model.Metadata.Value.Links,
-
- Monitored = model.Monitored,
- MonitorNewItems = model.MonitorNewItems,
-
- CleanName = model.CleanName,
- ForeignArtistId = model.Metadata.Value.ForeignArtistId,
-
- // Root folder path is now calculated from the artist path
- // RootFolderPath = model.RootFolderPath,
- Genres = model.Metadata.Value.Genres,
- Tags = model.Tags,
- Added = model.Added,
- AddOptions = model.AddOptions,
- Ratings = model.Metadata.Value.Ratings
- };
- }
-
- public static NzbDrone.Core.Music.Artist ToModel(this ArtistResource resource)
- {
- if (resource == null)
- {
- return null;
- }
-
- return new NzbDrone.Core.Music.Artist
- {
- Id = resource.Id,
-
- Metadata = new NzbDrone.Core.Music.ArtistMetadata
- {
- ForeignArtistId = resource.ForeignArtistId,
- Name = resource.ArtistName,
- Status = resource.Status,
- Overview = resource.Overview,
- Links = resource.Links,
- Images = resource.Images,
- Genres = resource.Genres,
- Ratings = resource.Ratings,
- Type = resource.ArtistType
- },
-
- // AlternateTitles
- SortName = resource.SortName,
- Path = resource.Path,
- QualityProfileId = resource.QualityProfileId,
- MetadataProfileId = resource.MetadataProfileId,
-
- Monitored = resource.Monitored,
- MonitorNewItems = resource.MonitorNewItems,
-
- CleanName = resource.CleanName,
- RootFolderPath = resource.RootFolderPath,
-
- Tags = resource.Tags,
- Added = resource.Added,
- AddOptions = resource.AddOptions,
- };
- }
-
- public static NzbDrone.Core.Music.Artist ToModel(this ArtistResource resource, NzbDrone.Core.Music.Artist artist)
- {
- var updatedArtist = resource.ToModel();
-
- artist.ApplyChanges(updatedArtist);
-
- return artist;
- }
-
- public static List ToResource(this IEnumerable artist)
- {
- return artist.Select(ToResource).ToList();
- }
-
- public static List ToModel(this IEnumerable resources)
- {
- return resources.Select(ToModel).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Artist/ArtistStatisticsResource.cs b/src/Lidarr.Api.V1/Artist/ArtistStatisticsResource.cs
deleted file mode 100644
index b514f1d29..000000000
--- a/src/Lidarr.Api.V1/Artist/ArtistStatisticsResource.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using NzbDrone.Core.ArtistStats;
-
-namespace Lidarr.Api.V1.Artist
-{
- public class ArtistStatisticsResource
- {
- public int AlbumCount { get; set; }
- public int TrackFileCount { get; set; }
- public int TrackCount { get; set; }
- public int TotalTrackCount { get; set; }
- public long SizeOnDisk { get; set; }
-
- public decimal PercentOfTracks
- {
- get
- {
- if (TrackCount == 0)
- {
- return 0;
- }
-
- return TrackFileCount / (decimal)TrackCount * 100;
- }
- }
- }
-
- public static class ArtistStatisticsResourceMapper
- {
- public static ArtistStatisticsResource ToResource(this ArtistStatistics model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new ArtistStatisticsResource
- {
- AlbumCount = model.AlbumCount,
- TrackFileCount = model.TrackFileCount,
- TrackCount = model.TrackCount,
- TotalTrackCount = model.TotalTrackCount,
- SizeOnDisk = model.SizeOnDisk
- };
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingController.cs b/src/Lidarr.Api.V1/AutoTagging/AutoTaggingController.cs
deleted file mode 100644
index 6a3e670eb..000000000
--- a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingController.cs
+++ /dev/null
@@ -1,115 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using FluentValidation;
-using FluentValidation.Results;
-using Lidarr.Http;
-using Lidarr.Http.REST;
-using Lidarr.Http.REST.Attributes;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.AutoTagging;
-using NzbDrone.Core.AutoTagging.Specifications;
-using NzbDrone.Core.Validation;
-
-namespace Lidarr.Api.V1.AutoTagging
-{
- [V1ApiController]
- public class AutoTaggingController : RestController
- {
- private readonly IAutoTaggingService _autoTaggingService;
- private readonly List _specifications;
-
- public AutoTaggingController(IAutoTaggingService autoTaggingService,
- List specifications)
- {
- _autoTaggingService = autoTaggingService;
- _specifications = specifications;
-
- SharedValidator.RuleFor(c => c.Name).NotEmpty();
- SharedValidator.RuleFor(c => c.Name)
- .Must((v, c) => !_autoTaggingService.All().Any(f => f.Name == c && f.Id != v.Id)).WithMessage("Must be unique.");
- SharedValidator.RuleFor(c => c.Tags).NotEmpty();
- SharedValidator.RuleFor(c => c.Specifications).NotEmpty();
- SharedValidator.RuleFor(c => c).Custom((autoTag, context) =>
- {
- if (!autoTag.Specifications.Any())
- {
- context.AddFailure("Must contain at least one Condition");
- }
-
- if (autoTag.Specifications.Any(s => s.Name.IsNullOrWhiteSpace()))
- {
- context.AddFailure("Condition name(s) cannot be empty or consist of only spaces");
- }
- });
- }
-
- public override AutoTaggingResource GetResourceById(int id)
- {
- return _autoTaggingService.GetById(id).ToResource();
- }
-
- [RestPostById]
- [Consumes("application/json")]
- public ActionResult Create(AutoTaggingResource autoTagResource)
- {
- var model = autoTagResource.ToModel(_specifications);
-
- Validate(model);
-
- return Created(_autoTaggingService.Insert(model).Id);
- }
-
- [RestPutById]
- [Consumes("application/json")]
- public ActionResult Update(AutoTaggingResource resource)
- {
- var model = resource.ToModel(_specifications);
-
- Validate(model);
-
- _autoTaggingService.Update(model);
-
- return Accepted(model.Id);
- }
-
- [HttpGet]
- [Produces("application/json")]
- public List GetAll()
- {
- return _autoTaggingService.All().ToResource();
- }
-
- [RestDeleteById]
- public void DeleteFormat(int id)
- {
- _autoTaggingService.Delete(id);
- }
-
- [HttpGet("schema")]
- public object GetTemplates()
- {
- var schema = _specifications.OrderBy(x => x.Order).Select(x => x.ToSchema()).ToList();
-
- return schema;
- }
-
- private void Validate(AutoTag definition)
- {
- foreach (var validationResult in definition.Specifications.Select(spec => spec.Validate()))
- {
- VerifyValidationResult(validationResult);
- }
- }
-
- private void VerifyValidationResult(ValidationResult validationResult)
- {
- var result = new NzbDroneValidationResult(validationResult.Errors);
-
- if (!result.IsValid)
- {
- throw new ValidationException(result.Errors);
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingResource.cs b/src/Lidarr.Api.V1/AutoTagging/AutoTaggingResource.cs
deleted file mode 100644
index 2a91d9044..000000000
--- a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingResource.cs
+++ /dev/null
@@ -1,76 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json.Serialization;
-using Lidarr.Http.ClientSchema;
-using Lidarr.Http.REST;
-using NzbDrone.Core.AutoTagging;
-using NzbDrone.Core.AutoTagging.Specifications;
-
-namespace Lidarr.Api.V1.AutoTagging
-{
- public class AutoTaggingResource : RestResource
- {
- [JsonIgnore(Condition = JsonIgnoreCondition.Never)]
- public override int Id { get; set; }
- public string Name { get; set; }
- public bool RemoveTagsAutomatically { get; set; }
- public HashSet Tags { get; set; }
- public List Specifications { get; set; }
- }
-
- public static class AutoTaggingResourceMapper
- {
- public static AutoTaggingResource ToResource(this AutoTag model)
- {
- return new AutoTaggingResource
- {
- Id = model.Id,
- Name = model.Name,
- RemoveTagsAutomatically = model.RemoveTagsAutomatically,
- Tags = model.Tags,
- Specifications = model.Specifications.Select(x => x.ToSchema()).ToList()
- };
- }
-
- public static List ToResource(this IEnumerable models)
- {
- return models.Select(m => m.ToResource()).ToList();
- }
-
- public static AutoTag ToModel(this AutoTaggingResource resource, List specifications)
- {
- return new AutoTag
- {
- Id = resource.Id,
- Name = resource.Name,
- RemoveTagsAutomatically = resource.RemoveTagsAutomatically,
- Tags = resource.Tags,
- Specifications = resource.Specifications.Select(x => MapSpecification(x, specifications)).ToList()
- };
- }
-
- private static IAutoTaggingSpecification MapSpecification(AutoTaggingSpecificationSchema resource, List specifications)
- {
- var matchingSpec =
- specifications.SingleOrDefault(x => x.GetType().Name == resource.Implementation);
-
- if (matchingSpec is null)
- {
- throw new ArgumentException(
- $"{resource.Implementation} is not a valid specification implementation");
- }
-
- var type = matchingSpec.GetType();
-
- // Finding the exact current specification isn't possible given the dynamic nature of them and the possibility that multiple
- // of the same type exist within the same format. Passing in null is safe as long as there never exists a specification that
- // relies on additional privacy.
- var spec = (IAutoTaggingSpecification)SchemaBuilder.ReadFromSchema(resource.Fields, type, null);
- spec.Name = resource.Name;
- spec.Negate = resource.Negate;
- spec.Required = resource.Required;
- return spec;
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingSpecificationSchema.cs b/src/Lidarr.Api.V1/AutoTagging/AutoTaggingSpecificationSchema.cs
deleted file mode 100644
index 6baca55ff..000000000
--- a/src/Lidarr.Api.V1/AutoTagging/AutoTaggingSpecificationSchema.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System.Collections.Generic;
-using Lidarr.Http.ClientSchema;
-using Lidarr.Http.REST;
-using NzbDrone.Core.AutoTagging.Specifications;
-
-namespace Lidarr.Api.V1.AutoTagging
-{
- public class AutoTaggingSpecificationSchema : RestResource
- {
- public string Name { get; set; }
- public string Implementation { get; set; }
- public string ImplementationName { get; set; }
- public bool Negate { get; set; }
- public bool Required { get; set; }
- public List Fields { get; set; }
- }
-
- public static class AutoTaggingSpecificationSchemaMapper
- {
- public static AutoTaggingSpecificationSchema ToSchema(this IAutoTaggingSpecification model)
- {
- return new AutoTaggingSpecificationSchema
- {
- Name = model.Name,
- Implementation = model.GetType().Name,
- ImplementationName = model.ImplementationName,
- Negate = model.Negate,
- Required = model.Required,
- Fields = SchemaBuilder.ToSchema(model)
- };
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Blocklist/BlocklistBulkResource.cs b/src/Lidarr.Api.V1/Blocklist/BlocklistBulkResource.cs
deleted file mode 100644
index 2dd6f6ff9..000000000
--- a/src/Lidarr.Api.V1/Blocklist/BlocklistBulkResource.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-using System.Collections.Generic;
-
-namespace Lidarr.Api.V1.Blocklist
-{
- public class BlocklistBulkResource
- {
- public List Ids { get; set; }
- }
-}
diff --git a/src/Lidarr.Api.V1/Blocklist/BlocklistController.cs b/src/Lidarr.Api.V1/Blocklist/BlocklistController.cs
deleted file mode 100644
index 0d9627062..000000000
--- a/src/Lidarr.Api.V1/Blocklist/BlocklistController.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using Lidarr.Http;
-using Lidarr.Http.Extensions;
-using Lidarr.Http.REST.Attributes;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Core.Blocklisting;
-using NzbDrone.Core.CustomFormats;
-using NzbDrone.Core.Datastore;
-
-namespace Lidarr.Api.V1.Blocklist
-{
- [V1ApiController]
- public class BlocklistController : Controller
- {
- private readonly IBlocklistService _blocklistService;
- private readonly ICustomFormatCalculationService _formatCalculator;
-
- public BlocklistController(IBlocklistService blocklistService,
- ICustomFormatCalculationService formatCalculator)
- {
- _blocklistService = blocklistService;
- _formatCalculator = formatCalculator;
- }
-
- [HttpGet]
- [Produces("application/json")]
- public PagingResource GetBlocklist([FromQuery] PagingRequestResource paging)
- {
- var pagingResource = new PagingResource(paging);
- var pagingSpec = pagingResource.MapToPagingSpec("date", SortDirection.Descending);
-
- return pagingSpec.ApplyToPage(_blocklistService.Paged, model => BlocklistResourceMapper.MapToResource(model, _formatCalculator));
- }
-
- [RestDeleteById]
- public void DeleteBlocklist(int id)
- {
- _blocklistService.Delete(id);
- }
-
- [HttpDelete("bulk")]
- [Produces("application/json")]
- public object Remove([FromBody] BlocklistBulkResource resource)
- {
- _blocklistService.Delete(resource.Ids);
-
- return new { };
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Blocklist/BlocklistResource.cs b/src/Lidarr.Api.V1/Blocklist/BlocklistResource.cs
deleted file mode 100644
index ac906b701..000000000
--- a/src/Lidarr.Api.V1/Blocklist/BlocklistResource.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Lidarr.Api.V1.Artist;
-using Lidarr.Api.V1.CustomFormats;
-using Lidarr.Http.REST;
-using NzbDrone.Core.CustomFormats;
-using NzbDrone.Core.Indexers;
-using NzbDrone.Core.Qualities;
-
-namespace Lidarr.Api.V1.Blocklist
-{
- public class BlocklistResource : RestResource
- {
- public int ArtistId { get; set; }
- public List AlbumIds { get; set; }
- public string SourceTitle { get; set; }
- public QualityModel Quality { get; set; }
- public List CustomFormats { get; set; }
- public DateTime Date { get; set; }
- public DownloadProtocol Protocol { get; set; }
- public string Indexer { get; set; }
- public string Message { get; set; }
-
- public ArtistResource Artist { get; set; }
- }
-
- public static class BlocklistResourceMapper
- {
- public static BlocklistResource MapToResource(this NzbDrone.Core.Blocklisting.Blocklist model, ICustomFormatCalculationService formatCalculator)
- {
- if (model == null)
- {
- return null;
- }
-
- return new BlocklistResource
- {
- Id = model.Id,
-
- ArtistId = model.ArtistId,
- AlbumIds = model.AlbumIds,
- SourceTitle = model.SourceTitle,
- Quality = model.Quality,
- CustomFormats = formatCalculator.ParseCustomFormat(model, model.Artist).ToResource(false),
- Date = model.Date,
- Protocol = model.Protocol,
- Indexer = model.Indexer,
- Message = model.Message,
-
- Artist = model.Artist.ToResource()
- };
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Calendar/CalendarController.cs b/src/Lidarr.Api.V1/Calendar/CalendarController.cs
deleted file mode 100644
index ee88c5285..000000000
--- a/src/Lidarr.Api.V1/Calendar/CalendarController.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Lidarr.Api.V1.Albums;
-using Lidarr.Http;
-using Lidarr.Http.Extensions;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.ArtistStats;
-using NzbDrone.Core.DecisionEngine.Specifications;
-using NzbDrone.Core.MediaCover;
-using NzbDrone.Core.Music;
-using NzbDrone.Core.Tags;
-using NzbDrone.SignalR;
-
-namespace Lidarr.Api.V1.Calendar
-{
- [V1ApiController]
- public class CalendarController : AlbumControllerWithSignalR
- {
- private readonly IArtistService _artistService;
- private readonly ITagService _tagService;
-
- public CalendarController(IAlbumService albumService,
- IArtistService artistService,
- IArtistStatisticsService artistStatisticsService,
- IMapCoversToLocal coverMapper,
- IUpgradableSpecification upgradableSpecification,
- ITagService tagService,
- IBroadcastSignalRMessage signalRBroadcaster)
- : base(albumService, artistStatisticsService, coverMapper, upgradableSpecification, signalRBroadcaster)
- {
- _artistService = artistService;
- _tagService = tagService;
- }
-
- [HttpGet]
- [Produces("application/json")]
- public List GetCalendar(DateTime? start, DateTime? end, bool unmonitored = false, bool includeArtist = false, string tags = "")
- {
- // TODO: Add Album Image support to AlbumControllerWithSignalR
- var includeAlbumImages = Request.GetBooleanQueryParameter("includeAlbumImages");
-
- var startUse = start ?? DateTime.Today;
- var endUse = end ?? DateTime.Today.AddDays(2);
- var albums = _albumService.AlbumsBetweenDates(startUse, endUse, unmonitored);
- var allArtists = _artistService.GetAllArtists();
- var parsedTags = new List();
- var result = new List();
-
- if (tags.IsNotNullOrWhiteSpace())
- {
- parsedTags.AddRange(tags.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
- }
-
- foreach (var album in albums)
- {
- var artist = allArtists.SingleOrDefault(s => s.Id == album.ArtistId);
-
- if (artist == null)
- {
- continue;
- }
-
- if (parsedTags.Any() && parsedTags.None(artist.Tags.Contains))
- {
- continue;
- }
-
- result.Add(album);
- }
-
- var resources = MapToResource(result, includeArtist);
-
- return resources.OrderBy(e => e.ReleaseDate).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Calendar/CalendarFeedController.cs b/src/Lidarr.Api.V1/Calendar/CalendarFeedController.cs
deleted file mode 100644
index d779ecc51..000000000
--- a/src/Lidarr.Api.V1/Calendar/CalendarFeedController.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using Ical.Net;
-using Ical.Net.CalendarComponents;
-using Ical.Net.DataTypes;
-using Ical.Net.Serialization;
-using Lidarr.Http;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Core.Music;
-using NzbDrone.Core.Tags;
-
-namespace Lidarr.Api.V1.Calendar
-{
- [V1FeedController("calendar")]
- public class CalendarFeedController : Controller
- {
- private readonly IAlbumService _albumService;
- private readonly IArtistService _artistService;
- private readonly ITagService _tagService;
-
- public CalendarFeedController(IAlbumService albumService, IArtistService artistService, ITagService tagService)
- {
- _albumService = albumService;
- _artistService = artistService;
- _tagService = tagService;
- }
-
- [HttpGet("Lidarr.ics")]
- public IActionResult GetCalendarFeed(int pastDays = 7, int futureDays = 28, string tags = "", bool unmonitored = false)
- {
- var start = DateTime.Today.AddDays(-pastDays);
- var end = DateTime.Today.AddDays(futureDays);
- var parsedTags = new List();
-
- if (tags.IsNotNullOrWhiteSpace())
- {
- parsedTags.AddRange(tags.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
- }
-
- var albums = _albumService.AlbumsBetweenDates(start, end, unmonitored);
- var calendar = new Ical.Net.Calendar
- {
- ProductId = "-//lidarr.audio//Lidarr//EN"
- };
-
- var calendarName = "Lidarr Music Schedule";
- calendar.AddProperty(new CalendarProperty("NAME", calendarName));
- calendar.AddProperty(new CalendarProperty("X-WR-CALNAME", calendarName));
-
- foreach (var album in albums.OrderBy(v => v.ReleaseDate.Value))
- {
- var artist = _artistService.GetArtist(album.ArtistId); // Temp fix TODO: Figure out why Album.Artist is not populated during AlbumsBetweenDates Query
-
- if (parsedTags.Any() && parsedTags.None(artist.Tags.Contains))
- {
- continue;
- }
-
- var occurrence = calendar.Create();
- occurrence.Uid = "Lidarr_album_" + album.Id;
-
- // occurrence.Status = album.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
- occurrence.Description = album.Overview;
- occurrence.Categories = album.Genres;
-
- occurrence.Start = new CalDateTime(album.ReleaseDate.Value.ToLocalTime()) { HasTime = false };
- occurrence.End = occurrence.Start;
- occurrence.IsAllDay = true;
-
- occurrence.Summary = $"{artist.Name} - {album.Title}";
- }
-
- var serializer = (IStringSerializer)new SerializerFactory().Build(calendar.GetType(), new SerializationContext());
- var icalendar = serializer.SerializeToString(calendar);
-
- return Content(icalendar, "text/calendar");
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Commands/CommandController.cs b/src/Lidarr.Api.V1/Commands/CommandController.cs
deleted file mode 100644
index 1f008e5e4..000000000
--- a/src/Lidarr.Api.V1/Commands/CommandController.cs
+++ /dev/null
@@ -1,131 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Lidarr.Http;
-using Lidarr.Http.REST;
-using Lidarr.Http.REST.Attributes;
-using Lidarr.Http.Validation;
-using Microsoft.AspNetCore.Mvc;
-using NzbDrone.Common.Composition;
-using NzbDrone.Common.Serializer;
-using NzbDrone.Common.TPL;
-using NzbDrone.Core.Datastore.Events;
-using NzbDrone.Core.MediaFiles.TrackImport.Manual;
-using NzbDrone.Core.Messaging.Commands;
-using NzbDrone.Core.Messaging.Events;
-using NzbDrone.Core.ProgressMessaging;
-using NzbDrone.SignalR;
-
-namespace Lidarr.Api.V1.Commands
-{
- [V1ApiController]
- public class CommandController : RestControllerWithSignalR, IHandle
- {
- private readonly IManageCommandQueue _commandQueueManager;
- private readonly KnownTypes _knownTypes;
- private readonly Debouncer _debouncer;
- private readonly Dictionary _pendingUpdates;
-
- private readonly CommandPriorityComparer _commandPriorityComparer = new CommandPriorityComparer();
-
- public CommandController(IManageCommandQueue commandQueueManager,
- IBroadcastSignalRMessage signalRBroadcaster,
- KnownTypes knownTypes)
- : base(signalRBroadcaster)
- {
- _commandQueueManager = commandQueueManager;
- _knownTypes = knownTypes;
-
- _debouncer = new Debouncer(SendUpdates, TimeSpan.FromSeconds(0.1));
- _pendingUpdates = new Dictionary();
-
- PostValidator.RuleFor(c => c.Name).NotBlank();
- }
-
- public override CommandResource GetResourceById(int id)
- {
- return _commandQueueManager.Get(id).ToResource();
- }
-
- [RestPostById]
- [Consumes("application/json")]
- [Produces("application/json")]
- public ActionResult StartCommand(CommandResource commandResource)
- {
- var commandType =
- _knownTypes.GetImplementations(typeof(Command))
- .Single(c => c.Name.Replace("Command", "")
- .Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
-
- Request.Body.Seek(0, SeekOrigin.Begin);
- using (var reader = new StreamReader(Request.Body))
- {
- var body = reader.ReadToEnd();
- var priority = commandType == typeof(ManualImportCommand)
- ? CommandPriority.High
- : CommandPriority.Normal;
-
- var command = STJson.Deserialize(body, commandType) as Command;
-
- command.SuppressMessages = !command.SendUpdatesToClient;
- command.SendUpdatesToClient = true;
- command.ClientUserAgent = Request.Headers["UserAgent"];
-
- var trackedCommand = _commandQueueManager.Push(command, priority, CommandTrigger.Manual);
-
- return Created(trackedCommand.Id);
- }
- }
-
- [HttpGet]
- [Produces("application/json")]
- public List GetStartedCommands()
- {
- return _commandQueueManager.All()
- .OrderBy(c => c.Status, _commandPriorityComparer)
- .ThenByDescending(c => c.Priority)
- .ToResource();
- }
-
- [RestDeleteById]
- public void CancelCommand(int id)
- {
- _commandQueueManager.Cancel(id);
- }
-
- [NonAction]
- public void Handle(CommandUpdatedEvent message)
- {
- if (message.Command.Body.SendUpdatesToClient)
- {
- lock (_pendingUpdates)
- {
- _pendingUpdates[message.Command.Id] = message.Command.ToResource();
- }
-
- _debouncer.Execute();
- }
- }
-
- private void SendUpdates()
- {
- lock (_pendingUpdates)
- {
- var pendingUpdates = _pendingUpdates.Values.ToArray();
- _pendingUpdates.Clear();
-
- foreach (var pendingUpdate in pendingUpdates)
- {
- BroadcastResourceChange(ModelAction.Updated, pendingUpdate);
-
- if (pendingUpdate.Name == typeof(MessagingCleanupCommand).Name.Replace("Command", "") &&
- pendingUpdate.Status == CommandStatus.Completed)
- {
- BroadcastResourceChange(ModelAction.Sync);
- }
- }
- }
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Commands/CommandResource.cs b/src/Lidarr.Api.V1/Commands/CommandResource.cs
deleted file mode 100644
index 95d7fb306..000000000
--- a/src/Lidarr.Api.V1/Commands/CommandResource.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json.Serialization;
-using Lidarr.Http.REST;
-using NzbDrone.Common.Extensions;
-using NzbDrone.Common.Http;
-using NzbDrone.Core.Messaging.Commands;
-
-namespace Lidarr.Api.V1.Commands
-{
- public class CommandResource : RestResource
- {
- public string Name { get; set; }
- public string CommandName { get; set; }
- public string Message { get; set; }
- public Command Body { get; set; }
- public CommandPriority Priority { get; set; }
- public CommandStatus Status { get; set; }
- public CommandResult Result { get; set; }
- public DateTime Queued { get; set; }
- public DateTime? Started { get; set; }
- public DateTime? Ended { get; set; }
- public TimeSpan? Duration { get; set; }
- public string Exception { get; set; }
- public CommandTrigger Trigger { get; set; }
-
- public string ClientUserAgent { get; set; }
-
- [JsonIgnore]
- public string CompletionMessage { get; set; }
-
- public DateTime? StateChangeTime
- {
- get
- {
- if (Started.HasValue)
- {
- return Started.Value;
- }
-
- return Ended;
- }
-
- set
- {
- }
- }
-
- public bool SendUpdatesToClient
- {
- get
- {
- if (Body != null)
- {
- return Body.SendUpdatesToClient;
- }
-
- return false;
- }
-
- set
- {
- }
- }
-
- public bool UpdateScheduledTask
- {
- get
- {
- if (Body != null)
- {
- return Body.UpdateScheduledTask;
- }
-
- return false;
- }
-
- set
- {
- }
- }
-
- public DateTime? LastExecutionTime { get; set; }
- }
-
- public static class CommandResourceMapper
- {
- public static CommandResource ToResource(this CommandModel model)
- {
- if (model == null)
- {
- return null;
- }
-
- return new CommandResource
- {
- Id = model.Id,
-
- Name = model.Name,
- CommandName = model.Name.SplitCamelCase(),
- Message = model.Message,
- Body = model.Body,
- Priority = model.Priority,
- Status = model.Status,
- Result = model.Result,
- Queued = model.QueuedAt,
- Started = model.StartedAt,
- Ended = model.EndedAt,
- Duration = model.Duration,
- Exception = model.Exception,
- Trigger = model.Trigger,
-
- ClientUserAgent = UserAgentParser.SimplifyUserAgent(model.Body.ClientUserAgent),
-
- CompletionMessage = model.Body.CompletionMessage,
- LastExecutionTime = model.Body.LastExecutionTime
- };
- }
-
- public static List ToResource(this IEnumerable models)
- {
- return models.Select(ToResource).ToList();
- }
- }
-}
diff --git a/src/Lidarr.Api.V1/Config/CertificateValidator.cs b/src/Lidarr.Api.V1/Config/CertificateValidator.cs
deleted file mode 100644
index 5dee51e89..000000000
--- a/src/Lidarr.Api.V1/Config/CertificateValidator.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System.Security.Cryptography;
-using System.Security.Cryptography.X509Certificates;
-using FluentValidation;
-using FluentValidation.Validators;
-using NLog;
-using NzbDrone.Common.Instrumentation;
-
-namespace Lidarr.Api.V1.Config
-{
- public static class CertificateValidation
- {
- public static IRuleBuilderOptions IsValidCertificate(this IRuleBuilder