mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-04-24 13:57:11 -04:00
New: Category filter for Indexers
This commit is contained in:
parent
ebb66e9086
commit
a20a81f424
6 changed files with 82 additions and 2 deletions
|
@ -3,6 +3,7 @@ import AppSectionState, {
|
||||||
AppSectionItemState,
|
AppSectionItemState,
|
||||||
AppSectionSaveState,
|
AppSectionSaveState,
|
||||||
} from 'App/State/AppSectionState';
|
} from 'App/State/AppSectionState';
|
||||||
|
import { IndexerCategory } from 'Indexer/Indexer';
|
||||||
import Application from 'typings/Application';
|
import Application from 'typings/Application';
|
||||||
import DownloadClient from 'typings/DownloadClient';
|
import DownloadClient from 'typings/DownloadClient';
|
||||||
import Notification from 'typings/Notification';
|
import Notification from 'typings/Notification';
|
||||||
|
@ -25,6 +26,11 @@ export interface DownloadClientAppState
|
||||||
AppSectionDeleteState,
|
AppSectionDeleteState,
|
||||||
AppSectionSaveState {}
|
AppSectionSaveState {}
|
||||||
|
|
||||||
|
export interface IndexerCategoryAppState
|
||||||
|
extends AppSectionState<IndexerCategory>,
|
||||||
|
AppSectionDeleteState,
|
||||||
|
AppSectionSaveState {}
|
||||||
|
|
||||||
export interface NotificationAppState
|
export interface NotificationAppState
|
||||||
extends AppSectionState<Notification>,
|
extends AppSectionState<Notification>,
|
||||||
AppSectionDeleteState {}
|
AppSectionDeleteState {}
|
||||||
|
@ -35,6 +41,7 @@ interface SettingsAppState {
|
||||||
appProfiles: AppProfileAppState;
|
appProfiles: AppProfileAppState;
|
||||||
applications: ApplicationAppState;
|
applications: ApplicationAppState;
|
||||||
downloadClients: DownloadClientAppState;
|
downloadClients: DownloadClientAppState;
|
||||||
|
indexerCategories: IndexerCategoryAppState;
|
||||||
notifications: NotificationAppState;
|
notifications: NotificationAppState;
|
||||||
ui: UiSettingsAppState;
|
ui: UiSettingsAppState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import AppState from 'App/State/AppState';
|
||||||
|
import { IndexerCategory } from 'Indexer/Indexer';
|
||||||
|
import FilterBuilderRowValue from './FilterBuilderRowValue';
|
||||||
|
import FilterBuilderRowValueProps from './FilterBuilderRowValueProps';
|
||||||
|
|
||||||
|
const indexerCategoriesSelector = createSelector(
|
||||||
|
(state: AppState) => state.settings.indexerCategories,
|
||||||
|
(categories) => categories.items
|
||||||
|
);
|
||||||
|
|
||||||
|
function CategoryFilterBuilderRowValue(props: FilterBuilderRowValueProps) {
|
||||||
|
const categories: IndexerCategory[] = useSelector(indexerCategoriesSelector);
|
||||||
|
|
||||||
|
const tagList = categories.reduce(
|
||||||
|
(acc: { id: number; name: string }[], element) => {
|
||||||
|
acc.push({
|
||||||
|
id: element.id,
|
||||||
|
name: `${element.name} (${element.id})`,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (element.subCategories && element.subCategories.length > 0) {
|
||||||
|
element.subCategories.forEach((subCat) => {
|
||||||
|
acc.push({
|
||||||
|
id: subCat.id,
|
||||||
|
name: `${subCat.name} (${subCat.id})`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
return <FilterBuilderRowValue {...props} tagList={tagList} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CategoryFilterBuilderRowValue;
|
|
@ -5,6 +5,7 @@ import IconButton from 'Components/Link/IconButton';
|
||||||
import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Props';
|
import { filterBuilderTypes, filterBuilderValueTypes, icons } from 'Helpers/Props';
|
||||||
import AppProfileFilterBuilderRowValueConnector from './AppProfileFilterBuilderRowValueConnector';
|
import AppProfileFilterBuilderRowValueConnector from './AppProfileFilterBuilderRowValueConnector';
|
||||||
import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
|
import BoolFilterBuilderRowValue from './BoolFilterBuilderRowValue';
|
||||||
|
import CategoryFilterBuilderRowValue from './CategoryFilterBuilderRowValue';
|
||||||
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
|
import DateFilterBuilderRowValue from './DateFilterBuilderRowValue';
|
||||||
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
|
import FilterBuilderRowValueConnector from './FilterBuilderRowValueConnector';
|
||||||
import HistoryEventTypeFilterBuilderRowValue from './HistoryEventTypeFilterBuilderRowValue';
|
import HistoryEventTypeFilterBuilderRowValue from './HistoryEventTypeFilterBuilderRowValue';
|
||||||
|
@ -56,6 +57,9 @@ function getRowValueConnector(selectedFilterBuilderProp) {
|
||||||
case filterBuilderValueTypes.BOOL:
|
case filterBuilderValueTypes.BOOL:
|
||||||
return BoolFilterBuilderRowValue;
|
return BoolFilterBuilderRowValue;
|
||||||
|
|
||||||
|
case filterBuilderValueTypes.CATEGORY:
|
||||||
|
return CategoryFilterBuilderRowValue;
|
||||||
|
|
||||||
case filterBuilderValueTypes.DATE:
|
case filterBuilderValueTypes.DATE:
|
||||||
return DateFilterBuilderRowValue;
|
return DateFilterBuilderRowValue;
|
||||||
|
|
||||||
|
|
|
@ -7,5 +7,5 @@ export const INDEXER = 'indexer';
|
||||||
export const PROTOCOL = 'protocol';
|
export const PROTOCOL = 'protocol';
|
||||||
export const PRIVACY = 'privacy';
|
export const PRIVACY = 'privacy';
|
||||||
export const APP_PROFILE = 'appProfile';
|
export const APP_PROFILE = 'appProfile';
|
||||||
export const MOVIE_STATUS = 'movieStatus';
|
export const CATEGORY = 'category';
|
||||||
export const TAG = 'tag';
|
export const TAG = 'tag';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { createAction } from 'redux-actions';
|
import { createAction } from 'redux-actions';
|
||||||
import { sortDirections } from 'Helpers/Props';
|
import { filterTypePredicates, sortDirections } from 'Helpers/Props';
|
||||||
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
import createFetchHandler from 'Store/Actions/Creators/createFetchHandler';
|
||||||
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
import createRemoveItemHandler from 'Store/Actions/Creators/createRemoveItemHandler';
|
||||||
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
import createSaveProviderHandler, { createCancelSaveProviderHandler } from 'Store/Actions/Creators/createSaveProviderHandler';
|
||||||
|
@ -69,6 +69,28 @@ export const filterPredicates = {
|
||||||
item.fields.find((field) => field.name === 'vipExpiration')?.value ?? null;
|
item.fields.find((field) => field.name === 'vipExpiration')?.value ?? null;
|
||||||
|
|
||||||
return dateFilterPredicate(vipExpiration, filterValue, type);
|
return dateFilterPredicate(vipExpiration, filterValue, type);
|
||||||
|
},
|
||||||
|
|
||||||
|
categories: function(item, filterValue, type) {
|
||||||
|
const predicate = filterTypePredicates[type];
|
||||||
|
|
||||||
|
const { categories = [] } = item.capabilities || {};
|
||||||
|
|
||||||
|
const categoryList = categories
|
||||||
|
.filter((category) => category.id < 100000)
|
||||||
|
.reduce((acc, element) => {
|
||||||
|
acc.push(element.id);
|
||||||
|
|
||||||
|
if (element.subCategories && element.subCategories.length > 0) {
|
||||||
|
element.subCategories.forEach((subCat) => {
|
||||||
|
acc.push(subCat.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return predicate(categoryList, filterValue);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,12 @@ export const defaultState = {
|
||||||
type: filterBuilderTypes.EXACT,
|
type: filterBuilderTypes.EXACT,
|
||||||
valueType: filterBuilderValueTypes.APP_PROFILE
|
valueType: filterBuilderValueTypes.APP_PROFILE
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'categories',
|
||||||
|
label: () => translate('Categories'),
|
||||||
|
type: filterBuilderTypes.ARRAY,
|
||||||
|
valueType: filterBuilderValueTypes.CATEGORY
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'tags',
|
name: 'tags',
|
||||||
label: () => translate('Tags'),
|
label: () => translate('Tags'),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue