New: Ability to test all Indexers, Lists, Clients

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
pull/528/head
Qstick 6 years ago
parent 6103afcc09
commit 029a0e4e20

@ -268,7 +268,7 @@
"react/jsx-no-bind": [2, { "allowArrowFunctions": true }], "react/jsx-no-bind": [2, { "allowArrowFunctions": true }],
"react/jsx-no-duplicate-props": [2, { "ignoreCase": true }], "react/jsx-no-duplicate-props": [2, { "ignoreCase": true }],
"react/jsx-max-props-per-line": [2, { "maximum": 2 }], "react/jsx-max-props-per-line": [2, { "maximum": 2 }],
"react/jsx-handler-names": [2, { "eventHandlerPrefix": "on", "eventHandlerPropPrefix": "on" }], "react/jsx-handler-names": [2, { "eventHandlerPrefix": "(on|dispatch)", "eventHandlerPropPrefix": "on" }],
"react/jsx-no-undef": 2, "react/jsx-no-undef": 2,
"react/jsx-pascal-case": 2, "react/jsx-pascal-case": 2,
"react/jsx-uses-react": 2, "react/jsx-uses-react": 2,

@ -21,9 +21,9 @@ import Settings from 'Settings/Settings';
import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector'; import MediaManagementConnector from 'Settings/MediaManagement/MediaManagementConnector';
import Profiles from 'Settings/Profiles/Profiles'; import Profiles from 'Settings/Profiles/Profiles';
import Quality from 'Settings/Quality/Quality'; import Quality from 'Settings/Quality/Quality';
import IndexerSettings from 'Settings/Indexers/IndexerSettings'; import IndexerSettingsConnector from 'Settings/Indexers/IndexerSettingsConnector';
import ImportListSettings from 'Settings/ImportLists/ImportListSettings'; import ImportListSettingsConnector from 'Settings/ImportLists/ImportListSettingsConnector';
import DownloadClientSettings from 'Settings/DownloadClients/DownloadClientSettings'; import DownloadClientSettingsConnector from 'Settings/DownloadClients/DownloadClientSettingsConnector';
import NotificationSettings from 'Settings/Notifications/NotificationSettings'; import NotificationSettings from 'Settings/Notifications/NotificationSettings';
import MetadataSettings from 'Settings/Metadata/MetadataSettings'; import MetadataSettings from 'Settings/Metadata/MetadataSettings';
import TagSettings from 'Settings/Tags/TagSettings'; import TagSettings from 'Settings/Tags/TagSettings';
@ -169,17 +169,17 @@ function AppRoutes(props) {
<Route <Route
path="/settings/indexers" path="/settings/indexers"
component={IndexerSettings} component={IndexerSettingsConnector}
/> />
<Route <Route
path="/settings/downloadclients" path="/settings/downloadclients"
component={DownloadClientSettings} component={DownloadClientSettingsConnector}
/> />
<Route <Route
path="/settings/importlists" path="/settings/importlists"
component={ImportListSettings} component={ImportListSettingsConnector}
/> />
<Route <Route

@ -1,6 +1,7 @@
.button { .button {
composes: link from 'Components/Link/Link.css'; composes: link from 'Components/Link/Link.css';
display: inline-block;
margin: 0 2px; margin: 0 2px;
width: 22px; width: 22px;
border-radius: 4px; border-radius: 4px;

@ -29,6 +29,7 @@ import {
faBars as fasBars, faBars as fasBars,
faBolt as fasBolt, faBolt as fasBolt,
faBookmark as fasBookmark, faBookmark as fasBookmark,
faBookReader as fasBookReader,
faBug as fasBug, faBug as fasBug,
faCalendarAlt as fasCalendarAlt, faCalendarAlt as fasCalendarAlt,
faCaretDown as fasCaretDown, faCaretDown as fasCaretDown,
@ -92,6 +93,7 @@ import {
faTimes as fasTimes, faTimes as fasTimes,
faTimesCircle as fasTimesCircle, faTimesCircle as fasTimesCircle,
faUser as fasUser, faUser as fasUser,
faVial as fasVial,
faWrench as fasWrench faWrench as fasWrench
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
@ -188,6 +190,7 @@ export const SUBTRACT = fasMinus;
export const SYSTEM = fasLaptop; export const SYSTEM = fasLaptop;
export const TAGS = fasTags; export const TAGS = fasTags;
export const TBA = fasQuestionCircle; export const TBA = fasQuestionCircle;
export const TEST = fasVial;
export const UNGROUP = farObjectUngroup; export const UNGROUP = farObjectUngroup;
export const UNKNOWN = fasQuestion; export const UNKNOWN = fasQuestion;
export const UNMONITORED = farBookmark; export const UNMONITORED = farBookmark;
@ -195,3 +198,4 @@ export const UPDATE = fasRetweet;
export const UNSAVED_SETTING = farDotCircle; export const UNSAVED_SETTING = farDotCircle;
export const VIEW = fasEye; export const VIEW = fasEye;
export const WARNING = fasExclamationTriangle; export const WARNING = fasExclamationTriangle;
export const WIKI = fasBookReader;

@ -1,6 +1,10 @@
import React, { Component } from 'react'; import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import { icons } from 'Helpers/Props';
import PageContent from 'Components/Page/PageContent'; import PageContent from 'Components/Page/PageContent';
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
import DownloadClientsConnector from './DownloadClients/DownloadClientsConnector'; import DownloadClientsConnector from './DownloadClients/DownloadClientsConnector';
import DownloadClientOptionsConnector from './Options/DownloadClientOptionsConnector'; import DownloadClientOptionsConnector from './Options/DownloadClientOptionsConnector';
@ -43,6 +47,11 @@ class DownloadClientSettings extends Component {
// Render // Render
render() { render() {
const {
isTestingAll,
dispatchTestAllDownloadClients
} = this.props;
const { const {
isSaving, isSaving,
hasPendingChanges hasPendingChanges
@ -53,6 +62,18 @@ class DownloadClientSettings extends Component {
<SettingsToolbarConnector <SettingsToolbarConnector
isSaving={isSaving} isSaving={isSaving}
hasPendingChanges={hasPendingChanges} hasPendingChanges={hasPendingChanges}
additionalButtons={
<Fragment>
<PageToolbarSeparator />
<PageToolbarButton
label="Test All Clients"
iconName={icons.TEST}
isSpinning={isTestingAll}
onPress={dispatchTestAllDownloadClients}
/>
</Fragment>
}
onSavePress={this.onSavePress} onSavePress={this.onSavePress}
/> />
@ -71,4 +92,9 @@ class DownloadClientSettings extends Component {
} }
} }
DownloadClientSettings.propTypes = {
isTestingAll: PropTypes.bool.isRequired,
dispatchTestAllDownloadClients: PropTypes.func.isRequired
};
export default DownloadClientSettings; export default DownloadClientSettings;

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { testAllDownloadClients } from 'Store/Actions/settingsActions';
import DownloadClientSettings from './DownloadClientSettings';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.downloadClients.isTestingAll,
(isTestingAll) => {
return {
isTestingAll
};
}
);
}
const mapDispatchToProps = {
dispatchTestAllDownloadClients: testAllDownloadClients
};
export default connect(createMapStateToProps, mapDispatchToProps)(DownloadClientSettings);

@ -1,6 +1,10 @@
import React, { Component } from 'react'; import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import { icons } from 'Helpers/Props';
import PageContent from 'Components/Page/PageContent'; import PageContent from 'Components/Page/PageContent';
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
import ImportListsConnector from './ImportLists/ImportListsConnector'; import ImportListsConnector from './ImportLists/ImportListsConnector';
@ -38,10 +42,33 @@ class ImportListSettings extends Component {
// Render // Render
render() { render() {
const {
isTestingAll,
dispatchTestAllImportLists
} = this.props;
const {
isSaving,
hasPendingChanges
} = this.state;
return ( return (
<PageContent title="Import List Settings"> <PageContent title="Import List Settings">
<SettingsToolbarConnector <SettingsToolbarConnector
hasPendingChanges={this.state.hasPendingChanges} isSaving={isSaving}
hasPendingChanges={hasPendingChanges}
additionalButtons={
<Fragment>
<PageToolbarSeparator />
<PageToolbarButton
label="Test All Lists"
iconName={icons.TEST}
isSpinning={isTestingAll}
onPress={dispatchTestAllImportLists}
/>
</Fragment>
}
onSavePress={this.onSavePress} onSavePress={this.onSavePress}
/> />
@ -53,4 +80,9 @@ class ImportListSettings extends Component {
} }
} }
ImportListSettings.propTypes = {
isTestingAll: PropTypes.bool.isRequired,
dispatchTestAllImportLists: PropTypes.func.isRequired
};
export default ImportListSettings; export default ImportListSettings;

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { testAllImportLists } from 'Store/Actions/settingsActions';
import ImportListSettings from './ImportListSettings';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.importLists.isTestingAll,
(isTestingAll) => {
return {
isTestingAll
};
}
);
}
const mapDispatchToProps = {
dispatchTestAllImportLists: testAllImportLists
};
export default connect(createMapStateToProps, mapDispatchToProps)(ImportListSettings);

@ -1,6 +1,10 @@
import React, { Component } from 'react'; import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import { icons } from 'Helpers/Props';
import PageContent from 'Components/Page/PageContent'; import PageContent from 'Components/Page/PageContent';
import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector'; import PageContentBodyConnector from 'Components/Page/PageContentBodyConnector';
import PageToolbarButton from 'Components/Page/Toolbar/PageToolbarButton';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector'; import SettingsToolbarConnector from 'Settings/SettingsToolbarConnector';
import IndexersConnector from './Indexers/IndexersConnector'; import IndexersConnector from './Indexers/IndexersConnector';
import IndexerOptionsConnector from './Options/IndexerOptionsConnector'; import IndexerOptionsConnector from './Options/IndexerOptionsConnector';
@ -43,6 +47,11 @@ class IndexerSettings extends Component {
// Render // Render
render() { render() {
const {
isTestingAll,
dispatchTestAllIndexers
} = this.props;
const { const {
isSaving, isSaving,
hasPendingChanges hasPendingChanges
@ -53,6 +62,18 @@ class IndexerSettings extends Component {
<SettingsToolbarConnector <SettingsToolbarConnector
isSaving={isSaving} isSaving={isSaving}
hasPendingChanges={hasPendingChanges} hasPendingChanges={hasPendingChanges}
additionalButtons={
<Fragment>
<PageToolbarSeparator />
<PageToolbarButton
label="Test All Indexers"
iconName={icons.TEST}
isSpinning={isTestingAll}
onPress={dispatchTestAllIndexers}
/>
</Fragment>
}
onSavePress={this.onSavePress} onSavePress={this.onSavePress}
/> />
@ -71,4 +92,9 @@ class IndexerSettings extends Component {
} }
} }
IndexerSettings.propTypes = {
isTestingAll: PropTypes.bool.isRequired,
dispatchTestAllIndexers: PropTypes.func.isRequired
};
export default IndexerSettings; export default IndexerSettings;

@ -0,0 +1,21 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { testAllIndexers } from 'Store/Actions/settingsActions';
import IndexerSettings from './IndexerSettings';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.indexers.isTestingAll,
(isTestingAll) => {
return {
isTestingAll
};
}
);
}
const mapDispatchToProps = {
dispatchTestAllIndexers: testAllIndexers
};
export default connect(createMapStateToProps, mapDispatchToProps)(IndexerSettings);

@ -42,6 +42,7 @@ class SettingsToolbar extends Component {
showSave, showSave,
isSaving, isSaving,
hasPendingChanges, hasPendingChanges,
additionalButtons,
hasPendingLocation, hasPendingLocation,
onSavePress, onSavePress,
onConfirmNavigation, onConfirmNavigation,
@ -67,7 +68,12 @@ class SettingsToolbar extends Component {
onPress={onSavePress} onPress={onSavePress}
/> />
} }
{
additionalButtons
}
</PageToolbarSection> </PageToolbarSection>
<PendingChangesModal <PendingChangesModal
isOpen={hasPendingLocation} isOpen={hasPendingLocation}
onConfirm={onConfirmNavigation} onConfirm={onConfirmNavigation}
@ -84,6 +90,7 @@ SettingsToolbar.propTypes = {
isSaving: PropTypes.bool, isSaving: PropTypes.bool,
hasPendingLocation: PropTypes.bool.isRequired, hasPendingLocation: PropTypes.bool.isRequired,
hasPendingChanges: PropTypes.bool, hasPendingChanges: PropTypes.bool,
additionalButtons: PropTypes.node,
onSavePress: PropTypes.func, onSavePress: PropTypes.func,
onAdvancedSettingsPress: PropTypes.func.isRequired, onAdvancedSettingsPress: PropTypes.func.isRequired,
onConfirmNavigation: PropTypes.func.isRequired, onConfirmNavigation: PropTypes.func.isRequired,

@ -0,0 +1,34 @@
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;

@ -7,6 +7,7 @@ import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
// //
@ -27,6 +28,7 @@ export const CANCEL_SAVE_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelSaveD
export const DELETE_DOWNLOAD_CLIENT = 'settings/downloadClients/deleteDownloadClient'; export const DELETE_DOWNLOAD_CLIENT = 'settings/downloadClients/deleteDownloadClient';
export const TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/testDownloadClient'; export const TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/testDownloadClient';
export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestDownloadClient'; export const CANCEL_TEST_DOWNLOAD_CLIENT = 'settings/downloadClients/cancelTestDownloadClient';
export const TEST_ALL_DOWNLOAD_CLIENTS = 'settings/downloadClients/testAllDownloadClients';
// //
// Action Creators // Action Creators
@ -40,6 +42,7 @@ export const cancelSaveDownloadClient = createThunk(CANCEL_SAVE_DOWNLOAD_CLIENT)
export const deleteDownloadClient = createThunk(DELETE_DOWNLOAD_CLIENT); export const deleteDownloadClient = createThunk(DELETE_DOWNLOAD_CLIENT);
export const testDownloadClient = createThunk(TEST_DOWNLOAD_CLIENT); export const testDownloadClient = createThunk(TEST_DOWNLOAD_CLIENT);
export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT); export const cancelTestDownloadClient = createThunk(CANCEL_TEST_DOWNLOAD_CLIENT);
export const testAllDownloadClients = createThunk(TEST_ALL_DOWNLOAD_CLIENTS);
export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => { export const setDownloadClientValue = createAction(SET_DOWNLOAD_CLIENT_VALUE, (payload) => {
return { return {
@ -75,6 +78,7 @@ export default {
isSaving: false, isSaving: false,
saveError: null, saveError: null,
isTesting: false, isTesting: false,
isTestingAll: false,
items: [], items: [],
pendingChanges: {} pendingChanges: {}
}, },
@ -90,7 +94,8 @@ export default {
[CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section), [CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section),
[DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'), [DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'),
[TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'), [TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'),
[CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section) [CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section),
[TEST_ALL_DOWNLOAD_CLIENTS]: createTestAllProvidersHandler(section, '/downloadclient')
}, },
// //

@ -7,6 +7,7 @@ import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
// //
@ -27,6 +28,7 @@ export const CANCEL_SAVE_IMPORT_LIST = 'settings/importlists/cancelSaveImportLis
export const DELETE_IMPORT_LIST = 'settings/importlists/deleteImportList'; export const DELETE_IMPORT_LIST = 'settings/importlists/deleteImportList';
export const TEST_IMPORT_LIST = 'settings/importlists/testImportList'; export const TEST_IMPORT_LIST = 'settings/importlists/testImportList';
export const CANCEL_TEST_IMPORT_LIST = 'settings/importlists/cancelTestImportList'; export const CANCEL_TEST_IMPORT_LIST = 'settings/importlists/cancelTestImportList';
export const TEST_ALL_IMPORT_LISTS = 'settings/importlists/testAllImportLists';
// //
// Action Creators // Action Creators
@ -40,6 +42,7 @@ export const cancelSaveImportList = createThunk(CANCEL_SAVE_IMPORT_LIST);
export const deleteImportList = createThunk(DELETE_IMPORT_LIST); export const deleteImportList = createThunk(DELETE_IMPORT_LIST);
export const testImportList = createThunk(TEST_IMPORT_LIST); export const testImportList = createThunk(TEST_IMPORT_LIST);
export const cancelTestImportList = createThunk(CANCEL_TEST_IMPORT_LIST); export const cancelTestImportList = createThunk(CANCEL_TEST_IMPORT_LIST);
export const testAllImportLists = createThunk(TEST_ALL_IMPORT_LISTS);
export const setImportListValue = createAction(SET_IMPORT_LIST_VALUE, (payload) => { export const setImportListValue = createAction(SET_IMPORT_LIST_VALUE, (payload) => {
return { return {
@ -75,6 +78,7 @@ export default {
isSaving: false, isSaving: false,
saveError: null, saveError: null,
isTesting: false, isTesting: false,
isTestingAll: false,
items: [], items: [],
pendingChanges: {} pendingChanges: {}
}, },
@ -90,7 +94,8 @@ export default {
[CANCEL_SAVE_IMPORT_LIST]: createCancelSaveProviderHandler(section), [CANCEL_SAVE_IMPORT_LIST]: createCancelSaveProviderHandler(section),
[DELETE_IMPORT_LIST]: createRemoveItemHandler(section, '/importlist'), [DELETE_IMPORT_LIST]: createRemoveItemHandler(section, '/importlist'),
[TEST_IMPORT_LIST]: createTestProviderHandler(section, '/importlist'), [TEST_IMPORT_LIST]: createTestProviderHandler(section, '/importlist'),
[CANCEL_TEST_IMPORT_LIST]: createCancelTestProviderHandler(section) [CANCEL_TEST_IMPORT_LIST]: createCancelTestProviderHandler(section),
[TEST_ALL_IMPORT_LISTS]: createTestAllProvidersHandler(section, '/importlist')
}, },
// //

@ -7,6 +7,7 @@ import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler'; import createFetchSchemaHandler from 'Store/Actions/Creators/createFetchSchemaHandler';
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler'; import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler'; import createTestProviderHandler, { createCancelTestProviderHandler } from 'Store/Actions/Creators/createTestProviderHandler';
import createTestAllProvidersHandler from 'Store/Actions/Creators/createTestAllProvidersHandler';
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler'; import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
// //
@ -27,6 +28,7 @@ export const CANCEL_SAVE_INDEXER = 'settings/indexers/cancelSaveIndexer';
export const DELETE_INDEXER = 'settings/indexers/deleteIndexer'; export const DELETE_INDEXER = 'settings/indexers/deleteIndexer';
export const TEST_INDEXER = 'settings/indexers/testIndexer'; export const TEST_INDEXER = 'settings/indexers/testIndexer';
export const CANCEL_TEST_INDEXER = 'settings/indexers/cancelTestIndexer'; export const CANCEL_TEST_INDEXER = 'settings/indexers/cancelTestIndexer';
export const TEST_ALL_INDEXERS = 'settings/indexers/testAllIndexers';
// //
// Action Creators // Action Creators
@ -40,6 +42,7 @@ export const cancelSaveIndexer = createThunk(CANCEL_SAVE_INDEXER);
export const deleteIndexer = createThunk(DELETE_INDEXER); export const deleteIndexer = createThunk(DELETE_INDEXER);
export const testIndexer = createThunk(TEST_INDEXER); export const testIndexer = createThunk(TEST_INDEXER);
export const cancelTestIndexer = createThunk(CANCEL_TEST_INDEXER); export const cancelTestIndexer = createThunk(CANCEL_TEST_INDEXER);
export const testAllIndexers = createThunk(TEST_ALL_INDEXERS);
export const setIndexerValue = createAction(SET_INDEXER_VALUE, (payload) => { export const setIndexerValue = createAction(SET_INDEXER_VALUE, (payload) => {
return { return {
@ -75,6 +78,7 @@ export default {
isSaving: false, isSaving: false,
saveError: null, saveError: null,
isTesting: false, isTesting: false,
isTestingAll: false,
items: [], items: [],
pendingChanges: {} pendingChanges: {}
}, },
@ -90,7 +94,8 @@ export default {
[CANCEL_SAVE_INDEXER]: createCancelSaveProviderHandler(section), [CANCEL_SAVE_INDEXER]: createCancelSaveProviderHandler(section),
[DELETE_INDEXER]: createRemoveItemHandler(section, '/indexer'), [DELETE_INDEXER]: createRemoveItemHandler(section, '/indexer'),
[TEST_INDEXER]: createTestProviderHandler(section, '/indexer'), [TEST_INDEXER]: createTestProviderHandler(section, '/indexer'),
[CANCEL_TEST_INDEXER]: createCancelTestProviderHandler(section) [CANCEL_TEST_INDEXER]: createCancelTestProviderHandler(section),
[TEST_ALL_INDEXERS]: createTestAllProvidersHandler(section, '/indexer')
}, },
// //

@ -3,7 +3,8 @@ import React, { Component } from 'react';
import titleCase from 'Utilities/String/titleCase'; import titleCase from 'Utilities/String/titleCase';
import { icons, kinds } from 'Helpers/Props'; import { icons, kinds } from 'Helpers/Props';
import Icon from 'Components/Icon'; import Icon from 'Components/Icon';
import Link from 'Components/Link/Link'; import IconButton from 'Components/Link/IconButton';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import FieldSet from 'Components/FieldSet'; import FieldSet from 'Components/FieldSet';
import Table from 'Components/Table/Table'; import Table from 'Components/Table/Table';
@ -18,36 +19,68 @@ function getInternalLink(source) {
case 'IndexerSearchCheck': case 'IndexerSearchCheck':
case 'IndexerStatusCheck': case 'IndexerStatusCheck':
return ( return (
<Link to="/settings/indexers"> <IconButton
Settings name={icons.SETTINGS}
</Link> title="Settings"
to="/settings/indexers"
/>
); );
case 'DownloadClientCheck': case 'DownloadClientCheck':
case 'ImportMechanismCheck': case 'ImportMechanismCheck':
return ( return (
<Link to="/settings/downloadclients"> <IconButton
Settings name={icons.SETTINGS}
</Link> title="Settings"
to="/settings/downloadclients"
/>
); );
case 'RootFolderCheck': case 'RootFolderCheck':
return ( return (
<div> <IconButton
<Link to="/artisteditor"> name={icons.ARTIST}
Artist Editor title="Artist Editor"
</Link> to="/artisteditor"
</div> />
); );
case 'UpdateCheck': case 'UpdateCheck':
return ( return (
<Link to="/system/updates"> <IconButton
Updates name={icons.UPDATE}
</Link> title="Updates"
to="/system/updates"
/>
); );
default: default:
return; return;
} }
} }
function getTestLink(source, props) {
switch (source) {
case 'IndexerStatusCheck':
return (
<SpinnerIconButton
name={icons.TEST}
title="Test All"
isSpinning={props.isTestingAllIndexers}
onPress={props.dispatchTestAllIndexers}
/>
);
case 'DownloadClientCheck':
return (
<SpinnerIconButton
name={icons.TEST}
title="Test All"
isSpinning={props.isTestingAllDownloadClients}
onPress={props.dispatchTestAllDownloadClients}
/>
);
default:
break;
}
}
const columns = [ const columns = [
{ {
className: styles.status, className: styles.status,
@ -60,12 +93,8 @@ const columns = [
isVisible: true isVisible: true
}, },
{ {
name: 'wikiLink', name: 'actions',
label: 'Wiki', label: 'Actions',
isVisible: true
},
{
name: 'internalLink',
isVisible: true isVisible: true
} }
]; ];
@ -121,6 +150,7 @@ class Health extends Component {
{ {
items.map((item) => { items.map((item) => {
const internalLink = getInternalLink(item.source); const internalLink = getInternalLink(item.source);
const testLink = getTestLink(item.source, this.props);
return ( return (
<TableRow key={`health${item.message}`}> <TableRow key={`health${item.message}`}>
@ -135,18 +165,20 @@ class Health extends Component {
<TableRowCell>{item.message}</TableRowCell> <TableRowCell>{item.message}</TableRowCell>
<TableRowCell> <TableRowCell>
<Link <IconButton
name={icons.WIKI}
to={item.wikiUrl} to={item.wikiUrl}
title="Read the Wiki for more information" title="Read the Wiki for more information"
> />
Wiki
</Link>
</TableRowCell>
<TableRowCell>
{ {
internalLink internalLink
} }
{
!!testLink &&
testLink
}
</TableRowCell> </TableRowCell>
</TableRow> </TableRow>
); );
@ -164,7 +196,11 @@ class Health extends Component {
Health.propTypes = { Health.propTypes = {
isFetching: PropTypes.bool.isRequired, isFetching: PropTypes.bool.isRequired,
isPopulated: PropTypes.bool.isRequired, isPopulated: PropTypes.bool.isRequired,
items: PropTypes.array.isRequired items: PropTypes.array.isRequired,
isTestingAllDownloadClients: PropTypes.bool.isRequired,
isTestingAllIndexers: PropTypes.bool.isRequired,
dispatchTestAllDownloadClients: PropTypes.func.isRequired,
dispatchTestAllIndexers: PropTypes.func.isRequired
}; };
export default Health; export default Health;

@ -3,12 +3,15 @@ import React, { Component } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { fetchHealth } from 'Store/Actions/systemActions'; import { fetchHealth } from 'Store/Actions/systemActions';
import { testAllDownloadClients, testAllIndexers } from 'Store/Actions/settingsActions';
import Health from './Health'; import Health from './Health';
function createMapStateToProps() { function createMapStateToProps() {
return createSelector( return createSelector(
(state) => state.system.health, (state) => state.system.health,
(health) => { (state) => state.settings.downloadClients.isTestingAll,
(state) => state.settings.indexers.isTestingAll,
(health, isTestingAllDownloadClients, isTestingAllIndexers) => {
const { const {
isFetching, isFetching,
isPopulated, isPopulated,
@ -18,14 +21,18 @@ function createMapStateToProps() {
return { return {
isFetching, isFetching,
isPopulated, isPopulated,
items items,
isTestingAllDownloadClients,
isTestingAllIndexers
}; };
} }
); );
} }
const mapDispatchToProps = { const mapDispatchToProps = {
fetchHealth dispatchFetchHealth: fetchHealth,
dispatchTestAllDownloadClients: testAllDownloadClients,
dispatchTestAllIndexers: testAllIndexers
}; };
class HealthConnector extends Component { class HealthConnector extends Component {
@ -34,23 +41,28 @@ class HealthConnector extends Component {
// Lifecycle // Lifecycle
componentDidMount() { componentDidMount() {
this.props.fetchHealth(); this.props.dispatchFetchHealth();
} }
// //
// Render // Render
render() { render() {
const {
dispatchFetchHealth,
...otherProps
} = this.props;
return ( return (
<Health <Health
{...this.props} {...otherProps}
/> />
); );
} }
} }
HealthConnector.propTypes = { HealthConnector.propTypes = {
fetchHealth: PropTypes.func.isRequired dispatchFetchHealth: PropTypes.func.isRequired
}; };
export default connect(createMapStateToProps, mapDispatchToProps)(HealthConnector); export default connect(createMapStateToProps, mapDispatchToProps)(HealthConnector);

Loading…
Cancel
Save