diff --git a/src/apps/dashboard/features/plugins/constants/pluginStatusOption.ts b/src/apps/dashboard/features/plugins/constants/pluginStatusOption.ts new file mode 100644 index 0000000000..e301087bee --- /dev/null +++ b/src/apps/dashboard/features/plugins/constants/pluginStatusOption.ts @@ -0,0 +1,6 @@ +/** Options for filtering plugins based on the installation status. */ +export enum PluginStatusOption { + All = 'All', + Available = 'Available', + Installed = 'Installed' +} diff --git a/src/apps/dashboard/routes/plugins/index.tsx b/src/apps/dashboard/routes/plugins/index.tsx index 8429345379..fdcc179633 100644 --- a/src/apps/dashboard/routes/plugins/index.tsx +++ b/src/apps/dashboard/routes/plugins/index.tsx @@ -16,6 +16,7 @@ import NoPluginResults from 'apps/dashboard/features/plugins/components/NoPlugin import PluginCard from 'apps/dashboard/features/plugins/components/PluginCard'; import { CATEGORY_LABELS } from 'apps/dashboard/features/plugins/constants/categoryLabels'; import { PluginCategory } from 'apps/dashboard/features/plugins/constants/pluginCategory'; +import { PluginStatusOption } from 'apps/dashboard/features/plugins/constants/pluginStatusOption'; import Loading from 'components/loading/LoadingComponent'; import Page from 'components/Page'; import globalize from 'lib/globalize'; @@ -35,9 +36,6 @@ const MAIN_CATEGORIES = [ PluginCategory.Subtitles.toLowerCase() ]; -/** The installed meta category. */ -const INSTALLED_CATEGORY = 'installed'; - export const Component = () => { const { data: pluginDetails, @@ -46,6 +44,7 @@ export const Component = () => { } = usePluginDetails(); const [ category, setCategory ] = useState(); const [ searchQuery, setSearchQuery ] = useState(''); + const [ status, setStatus ] = useState(PluginStatusOption.Installed); const onSearchChange = useCallback((event: React.ChangeEvent) => { setSearchQuery(event.target.value); @@ -55,11 +54,14 @@ export const Component = () => { if (pluginDetails) { let filtered = pluginDetails; + if (status === PluginStatusOption.Installed) { + filtered = filtered.filter(p => p.status); + } else if (status === PluginStatusOption.Available) { + filtered = filtered.filter(p => !p.status); + } + if (category) { - if (category === INSTALLED_CATEGORY) { - // Installed plugins will have a status - filtered = filtered.filter(p => p.status); - } else if (category === PluginCategory.Other.toLowerCase()) { + if (category === PluginCategory.Other.toLowerCase()) { filtered = filtered.filter(p => ( p.category && !MAIN_CATEGORIES.includes(p.category.toLowerCase()) )); @@ -72,7 +74,7 @@ export const Component = () => { } else { return []; } - }, [ category, pluginDetails, searchQuery ]); + }, [ category, pluginDetails, searchQuery, status ]); if (isPending) { return ; @@ -149,6 +151,29 @@ export const Component = () => { overflowX: 'auto' }} > + setStatus(PluginStatusOption.All)} + label={globalize.translate('All')} + /> + + setStatus(PluginStatusOption.Available)} + label={globalize.translate('LabelAvailable')} + /> + + setStatus(PluginStatusOption.Installed)} + label={globalize.translate('LabelInstalled')} + /> + + + { label={globalize.translate('All')} /> - setCategory(INSTALLED_CATEGORY)} - label={globalize.translate('LabelInstalled')} - /> - - - {Object.values(PluginCategory).map(c => ( { setCategory(undefined)} + onViewAll={() => { + setCategory(undefined); + setStatus(PluginStatusOption.All); + }} query={searchQuery} /> )} diff --git a/src/strings/en-us.json b/src/strings/en-us.json index 9977905ca6..fe3c153e8c 100644 --- a/src/strings/en-us.json +++ b/src/strings/en-us.json @@ -626,6 +626,7 @@ "LabelAutomaticallyRefreshInternetMetadataEvery": "Automatically refresh metadata from the internet", "LabelAutomaticDiscovery": "Enable Auto Discovery", "LabelAutomaticDiscoveryHelp": "Allow applications to automatically detect Jellyfin by using UDP port 7359.", + "LabelAvailable": "Available", "LabelBackupsUnavailable": "No backups available", "LabelBaseUrl": "Base URL", "LabelBaseUrlHelp": "Add a custom subdirectory to the server URL. For example: http://example.com/<baseurl>",