feat(blacklist): hide blacklisted items from discover pages for admins (#1601)
* feat(blacklist): add 'Hide Blacklisted Items' setting to general settings and UI * feat(migration): add HideBlacklistedItems migration for PostgreSQL and SQLite * feat(settings): add hideBlacklisted option to application settings * feat(settings): add tooltips for hideAvailable and hideBlacklisted options in settings * chore(migration): remove HideBlacklistedItems migration files for PostgreSQL and SQLite * docs(settings): clarify description of 'Hide Blacklisted Items' setting to specify it affects all users * docs(settings): update tooltip and description for 'Hide Blacklisted Items' to clarify it applies to all users, including administrators * docs(settings): clarify 'Hide Blacklisted Items' functionality to specify it applies only to administrators with the "Manage Blacklist" permission * fix(hooks): update permission check for 'Hide Blacklisted Items' to include 'Manage Blacklist' * fix(settings): update tooltip for 'Hide Blacklisted Items' to clarify it applies to all users with the "Manage Blacklist" permission * feat(settings): add experimental badge to settings tooltip for 'Hide Available' option
This commit is contained in:
@@ -34,7 +34,7 @@ const Search = () => {
|
||||
{
|
||||
query: router.query.query,
|
||||
},
|
||||
{ hideAvailable: false }
|
||||
{ hideAvailable: false, hideBlacklisted: false }
|
||||
);
|
||||
|
||||
if (error) {
|
||||
|
||||
@@ -45,11 +45,16 @@ const messages = defineMessages('components.Settings.SettingsMain', {
|
||||
'The "Process Blacklisted Tags" job will blacklist this many pages into each sort. Larger numbers will create a more accurate blacklist, but use more space.',
|
||||
streamingRegion: 'Streaming Region',
|
||||
streamingRegionTip: 'Show streaming sites by regional availability',
|
||||
hideBlacklisted: 'Hide Blacklisted Items',
|
||||
hideBlacklistedTip:
|
||||
'Hide blacklisted items from discover pages for all users with the "Manage Blacklist" permission',
|
||||
toastApiKeySuccess: 'New API key generated successfully!',
|
||||
toastApiKeyFailure: 'Something went wrong while generating a new API key.',
|
||||
toastSettingsSuccess: 'Settings saved successfully!',
|
||||
toastSettingsFailure: 'Something went wrong while saving settings.',
|
||||
hideAvailable: 'Hide Available Media',
|
||||
hideAvailableTip:
|
||||
'Hide available media from the discover pages but not search results',
|
||||
cacheImages: 'Enable Image Caching',
|
||||
cacheImagesTip:
|
||||
'Cache externally sourced images (requires a significant amount of disk space)',
|
||||
@@ -145,6 +150,7 @@ const SettingsMain = () => {
|
||||
applicationTitle: data?.applicationTitle,
|
||||
applicationUrl: data?.applicationUrl,
|
||||
hideAvailable: data?.hideAvailable,
|
||||
hideBlacklisted: data?.hideBlacklisted,
|
||||
locale: data?.locale ?? 'en',
|
||||
discoverRegion: data?.discoverRegion,
|
||||
originalLanguage: data?.originalLanguage,
|
||||
@@ -163,6 +169,7 @@ const SettingsMain = () => {
|
||||
applicationTitle: values.applicationTitle,
|
||||
applicationUrl: values.applicationUrl,
|
||||
hideAvailable: values.hideAvailable,
|
||||
hideBlacklisted: values.hideBlacklisted,
|
||||
locale: values.locale,
|
||||
discoverRegion: values.discoverRegion,
|
||||
streamingRegion: values.streamingRegion,
|
||||
@@ -428,6 +435,9 @@ const SettingsMain = () => {
|
||||
{intl.formatMessage(messages.hideAvailable)}
|
||||
</span>
|
||||
<SettingsBadge badgeType="experimental" />
|
||||
<span className="label-tip">
|
||||
{intl.formatMessage(messages.hideAvailableTip)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<Field
|
||||
@@ -440,6 +450,29 @@ const SettingsMain = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label htmlFor="hideBlacklisted" className="checkbox-label">
|
||||
<span className="mr-2">
|
||||
{intl.formatMessage(messages.hideBlacklisted)}
|
||||
</span>
|
||||
<span className="label-tip">
|
||||
{intl.formatMessage(messages.hideBlacklistedTip)}
|
||||
</span>
|
||||
</label>
|
||||
<div className="form-input-area">
|
||||
<Field
|
||||
type="checkbox"
|
||||
id="hideBlacklisted"
|
||||
name="hideBlacklisted"
|
||||
onChange={() => {
|
||||
setFieldValue(
|
||||
'hideBlacklisted',
|
||||
!values.hideBlacklisted
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<label
|
||||
htmlFor="partialRequestsEnabled"
|
||||
|
||||
@@ -13,6 +13,7 @@ const defaultSettings = {
|
||||
applicationTitle: 'Jellyseerr',
|
||||
applicationUrl: '',
|
||||
hideAvailable: false,
|
||||
hideBlacklisted: false,
|
||||
localLogin: true,
|
||||
mediaServerLogin: true,
|
||||
movie4kEnabled: false,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { MediaStatus } from '@server/constants/media';
|
||||
import useSWRInfinite from 'swr/infinite';
|
||||
import useSettings from './useSettings';
|
||||
import { Permission, useUser } from './useUser';
|
||||
|
||||
export interface BaseSearchResult<T> {
|
||||
page: number;
|
||||
@@ -53,9 +54,10 @@ const useDiscover = <
|
||||
>(
|
||||
endpoint: string,
|
||||
options?: O,
|
||||
{ hideAvailable = true } = {}
|
||||
{ hideAvailable = true, hideBlacklisted = true } = {}
|
||||
): DiscoverResult<T, S> => {
|
||||
const settings = useSettings();
|
||||
const { hasPermission } = useUser();
|
||||
const { data, error, size, setSize, isValidating, mutate } = useSWRInfinite<
|
||||
BaseSearchResult<T> & S
|
||||
>(
|
||||
@@ -120,6 +122,18 @@ const useDiscover = <
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
settings.currentSettings.hideBlacklisted &&
|
||||
hideBlacklisted &&
|
||||
hasPermission(Permission.MANAGE_BLACKLIST)
|
||||
) {
|
||||
titles = titles.filter(
|
||||
(i) =>
|
||||
(i.mediaType === 'movie' || i.mediaType === 'tv') &&
|
||||
i.mediaInfo?.status !== MediaStatus.BLACKLISTED
|
||||
);
|
||||
}
|
||||
|
||||
const isEmpty = !isLoadingInitialData && titles?.length === 0;
|
||||
const isReachingEnd =
|
||||
isEmpty ||
|
||||
|
||||
@@ -959,6 +959,9 @@
|
||||
"components.Settings.SettingsMain.generalsettings": "General Settings",
|
||||
"components.Settings.SettingsMain.generalsettingsDescription": "Configure global and default settings for Jellyseerr.",
|
||||
"components.Settings.SettingsMain.hideAvailable": "Hide Available Media",
|
||||
"components.Settings.SettingsMain.hideAvailableTip": "Hide available media from the discover pages but not search results",
|
||||
"components.Settings.SettingsMain.hideBlacklisted": "Hide Blacklisted Items",
|
||||
"components.Settings.SettingsMain.hideBlacklistedTip": "Hide blacklisted items from discover pages for all users with the \"Manage Blacklist\" permission",
|
||||
"components.Settings.SettingsMain.locale": "Display Language",
|
||||
"components.Settings.SettingsMain.originallanguage": "Discover Language",
|
||||
"components.Settings.SettingsMain.originallanguageTip": "Filter content by original language",
|
||||
|
||||
@@ -231,6 +231,7 @@ CoreApp.getInitialProps = async (initialProps) => {
|
||||
applicationTitle: '',
|
||||
applicationUrl: '',
|
||||
hideAvailable: false,
|
||||
hideBlacklisted: false,
|
||||
movie4kEnabled: false,
|
||||
series4kEnabled: false,
|
||||
localLogin: true,
|
||||
|
||||
Reference in New Issue
Block a user