diff --git a/src/core/router/index.tsx b/src/core/router/index.tsx index 9ab6742a4..31cc70131 100644 --- a/src/core/router/index.tsx +++ b/src/core/router/index.tsx @@ -30,6 +30,7 @@ import MainPage from '@/pages/main/MainPage'; import SettingsPage from '@/pages/settings/SettingsPage'; import AniDBSettings from '@/pages/settings/tabs/AniDBSettings'; import ApiKey from '@/pages/settings/tabs/ApiKeys'; +import CollectionSettings from '@/pages/settings/tabs/CollectionSettings'; import GeneralSettings from '@/pages/settings/tabs/GeneralSettings'; import ImportSettings from '@/pages/settings/tabs/ImportSettings'; import MetadataSitesSettings from '@/pages/settings/tabs/MetadataSitesSettings'; @@ -110,6 +111,7 @@ const router = sentryCreateBrowserRouter( } /> } /> } /> + } /> } /> } /> diff --git a/src/css/common.css b/src/css/common.css index 270aa51ff..90085ddac 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -150,6 +150,11 @@ body { font-family: Sora, sans, serif, mono !important; } +/* stylelint-disable-next-line selector-class-pattern */ +.Toastify__progress-bar { + height: 10% !important; +} + /* stylelint-disable-next-line selector-class-pattern */ .Toastify__progress-bar--success { background: theme('colors.panel-text-important') !important; diff --git a/src/pages/settings/SettingsPage.tsx b/src/pages/settings/SettingsPage.tsx index 1ea5da408..14d5ed65f 100644 --- a/src/pages/settings/SettingsPage.tsx +++ b/src/pages/settings/SettingsPage.tsx @@ -18,6 +18,7 @@ const items = [ { name: 'Import', path: 'import' }, { name: 'AniDB', path: 'anidb' }, { name: 'Metadata Sites', path: 'metadata-sites' }, + { name: 'Collection', path: 'collection' }, // { name: 'Display', path: 'display' }, { name: 'User Management', path: 'user-management' }, // { name: 'Themes', path: 'themes' }, diff --git a/src/pages/settings/tabs/AniDBSettings.tsx b/src/pages/settings/tabs/AniDBSettings.tsx index 09f6ae472..48b4a592e 100644 --- a/src/pages/settings/tabs/AniDBSettings.tsx +++ b/src/pages/settings/tabs/AniDBSettings.tsx @@ -1,13 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import React, { useState } from 'react'; -import { mdiMinusCircleOutline, mdiPlusCircleOutline } from '@mdi/js'; -import { Icon } from '@mdi/react'; +import React from 'react'; import cx from 'classnames'; -import { remove } from 'lodash'; -import LanguagesModal from '@/components/Dialogs/LanguagesModal'; -import { languageDescription } from '@/components/Dialogs/constants'; -import DnDList from '@/components/DnDList/DnDList'; import Button from '@/components/Input/Button'; import Checkbox from '@/components/Input/Checkbox'; import InputSmall from '@/components/Input/InputSmall'; @@ -16,8 +10,6 @@ import toast from '@/components/Toast'; import { useAniDBTestLoginMutation } from '@/core/react-query/settings/mutations'; import useSettingsContext from '@/hooks/useSettingsContext'; -import type { DropResult } from '@hello-pangea/dnd'; - const UpdateFrequencyValues = () => ( <> @@ -30,12 +22,9 @@ const UpdateFrequencyValues = () => ( ); function AniDBSettings() { - const { newSettings, setNewSettings, updateSetting } = useSettingsContext(); - + const { newSettings, updateSetting } = useSettingsContext(); const { isPending: isAnidbLoginPending, mutate: testAniDbLogin } = useAniDBTestLoginMutation(); - const [showLanguagesModal, setShowLanguagesModal] = useState<'Series' | 'Episode' | null>(null); - const { AVDumpClientPort, AVDumpKey, @@ -61,34 +50,6 @@ function AniDBSettings() { Username, } = newSettings.AniDb; - const onDragEnd = (result: DropResult, episodePreference = false) => { - if (!result.destination || result.destination.index === result.source.index) { - return; - } - - const items = Array.from( - episodePreference ? newSettings.EpisodeLanguagePreference : newSettings.LanguagePreference, - ); - const [removed] = items.splice(result.source.index, 1); - items.splice(result.destination.index, 0, removed); - - setNewSettings({ - ...newSettings, - [episodePreference ? 'EpisodeLanguagePreference' : 'LanguagePreference']: items, - }); - }; - - const removeLanguage = (language: string, episodePreference = false) => { - const items = Array.from( - episodePreference ? newSettings.EpisodeLanguagePreference : newSettings.LanguagePreference, - ); - remove(items, item => item === language); - setNewSettings({ - ...newSettings, - [episodePreference ? 'EpisodeLanguagePreference' : 'LanguagePreference']: items, - }); - }; - const testLogin = () => { testAniDbLogin({ Username, Password }, { onSuccess: () => toast.success('AniDB Login Successful!'), @@ -345,67 +306,6 @@ function AniDBSettings() { - -
-
Language Options
-
- setNewSettings({ ...newSettings, LanguageUseSynonyms: event.target.checked })} - justify - /> -
- Series Title (Drag to Reorder) - -
-
- onDragEnd(result)}> - {newSettings.LanguagePreference.map(language => ( - { - key: language, - item: ( -
- {languageDescription[language]} - -
- ), - } - ))} -
-
-
- Episode Title (Drag to Reorder) - -
-
- onDragEnd(result, true)}> - {newSettings.EpisodeLanguagePreference.map(language => ( - { - key: language, - item: ( -
- {languageDescription[language]} - -
- ), - } - ))} -
-
-
-
- - setShowLanguagesModal(null)} /> ); } diff --git a/src/pages/settings/tabs/CollectionSettings.tsx b/src/pages/settings/tabs/CollectionSettings.tsx new file mode 100644 index 000000000..836f729fc --- /dev/null +++ b/src/pages/settings/tabs/CollectionSettings.tsx @@ -0,0 +1,236 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import React, { type ChangeEvent, useState } from 'react'; +import { mdiMinusCircleOutline, mdiPlusCircleOutline } from '@mdi/js'; +import { Icon } from '@mdi/react'; +import { keys, remove } from 'lodash'; + +import LanguagesModal from '@/components/Dialogs/LanguagesModal'; +import { languageDescription } from '@/components/Dialogs/constants'; +import DnDList from '@/components/DnDList/DnDList'; +import Button from '@/components/Input/Button'; +import Checkbox from '@/components/Input/Checkbox'; +import useSettingsContext from '@/hooks/useSettingsContext'; + +import type { DropResult } from '@hello-pangea/dnd'; + +const CollectionSettings = () => { + const { newSettings, setNewSettings } = useSettingsContext(); + const [showLanguagesModal, setShowLanguagesModal] = useState<'Series' | 'Episode' | null>(null); + + const { + AutoGroupSeries, + AutoGroupSeriesRelationExclusions, + AutoGroupSeriesUseScoreAlgorithm, + } = newSettings; + + const onDragEnd = (result: DropResult, episodePreference = false) => { + if (!result.destination || result.destination.index === result.source.index) { + return; + } + + const items = Array.from( + episodePreference ? newSettings.EpisodeLanguagePreference : newSettings.LanguagePreference, + ); + const [removed] = items.splice(result.source.index, 1); + items.splice(result.destination.index, 0, removed); + + setNewSettings({ + ...newSettings, + [episodePreference ? 'EpisodeLanguagePreference' : 'LanguagePreference']: items, + }); + }; + + const removeLanguage = (language: string, episodePreference = false) => { + const items = Array.from( + episodePreference ? newSettings.EpisodeLanguagePreference : newSettings.LanguagePreference, + ); + remove(items, item => item === language); + setNewSettings({ + ...newSettings, + [episodePreference ? 'EpisodeLanguagePreference' : 'LanguagePreference']: items, + }); + }; + + const exclusionMapping = { + dissimilarTitles: { + id: 'AllowDissimilarTitleExclusion', + name: 'Dissimilar Titles', + }, + prequel: { + id: 'prequel', + name: 'Prequel', + }, + sequel: { + id: 'sequel', + name: 'Sequel', + }, + ova: { + id: 'ova', + name: 'OVA', + }, + movie: { + id: 'movie', + name: 'Movie', + }, + sameSetting: { + id: 'same setting', + name: 'Same Setting', + }, + altSetting: { + id: 'alternative setting', + name: 'Alternative Setting', + }, + altVersion: { + id: 'alternative version', + name: 'Alternative Version', + }, + parentStory: { + id: 'parent story', + name: 'Parent Story', + }, + sideStory: { + id: 'side story', + name: 'Side Story', + }, + fullStory: { + id: 'full story', + name: 'Full Story', + }, + summary: { + id: 'summary', + name: 'Summary', + }, + character: { + id: 'character', + name: 'Character', + }, + other: { + id: 'other', + name: 'Other', + }, + }; + + function isExclusionKey(id: string): id is keyof typeof exclusionMapping { + return id in exclusionMapping; + } + + const handleExclusionChange = (event: ChangeEvent) => { + if (!(event.target.id in exclusionMapping)) return; + const { checked, id } = event.target; + + if (isExclusionKey(id)) { + if (checked) { + const tempExclusions = [...AutoGroupSeriesRelationExclusions, exclusionMapping[id].id]; + setNewSettings({ ...newSettings, AutoGroupSeriesRelationExclusions: tempExclusions }); + } else { + const tempExclusions = AutoGroupSeriesRelationExclusions.filter( + exclusion => exclusion !== exclusionMapping[id].id, + ); + setNewSettings({ ...newSettings, AutoGroupSeriesRelationExclusions: tempExclusions }); + } + } + }; + + return ( + <> +
Collection
+ {/* Language Settings */} +
+
Language Options
+
+ setNewSettings({ ...newSettings, LanguageUseSynonyms: event.target.checked })} + justify + /> +
+ Series Title (Drag to Reorder) + +
+
+ onDragEnd(result)}> + {newSettings.LanguagePreference.map(language => ( + { + key: language, + item: ( +
+ {languageDescription[language]} + +
+ ), + } + ))} +
+
+
+ Episode Title (Drag to Reorder) + +
+
+ onDragEnd(result, true)}> + {newSettings.EpisodeLanguagePreference.map(language => ( + { + key: language, + item: ( +
+ {languageDescription[language]} + +
+ ), + } + ))} +
+
+
+
+ setShowLanguagesModal(null)} /> + + {/* Relation Settings */} +
+
Relation Options
+
+ setNewSettings({ ...newSettings, AutoGroupSeries: event.target.checked })} + /> + + setNewSettings({ ...newSettings, AutoGroupSeriesUseScoreAlgorithm: event.target.checked })} + /> + Exclude following relations +
+ {keys(exclusionMapping).map((item: keyof typeof exclusionMapping) => ( + + ))} +
+
+
+ + ); +}; + +export default CollectionSettings; diff --git a/src/pages/settings/tabs/GeneralSettings.tsx b/src/pages/settings/tabs/GeneralSettings.tsx index a3ab6593f..8ff3a8b7d 100644 --- a/src/pages/settings/tabs/GeneralSettings.tsx +++ b/src/pages/settings/tabs/GeneralSettings.tsx @@ -1,10 +1,8 @@ /* eslint-disable @typescript-eslint/naming-convention */ import React, { useMemo } from 'react'; -import type { ChangeEvent } from 'react'; import { mdiOpenInNew, mdiRefresh } from '@mdi/js'; import { Icon } from '@mdi/react'; import cx from 'classnames'; -import { keys } from 'lodash'; import Button from '@/components/Input/Button'; import Checkbox from '@/components/Input/Checkbox'; @@ -16,76 +14,10 @@ import useSettingsContext from '@/hooks/useSettingsContext'; const UI_VERSION = uiVersion(); -const exclusionMapping = { - dissimilarTitles: { - id: 'AllowDissimilarTitleExclusion', - name: 'Dissimilar Titles', - }, - prequel: { - id: 'prequel', - name: 'Prequel', - }, - sequel: { - id: 'sequel', - name: 'Sequel', - }, - ova: { - id: 'ova', - name: 'OVA', - }, - movie: { - id: 'movie', - name: 'Movie', - }, - sameSetting: { - id: 'same setting', - name: 'Same Setting', - }, - altSetting: { - id: 'alternative setting', - name: 'Alternative Setting', - }, - altVersion: { - id: 'alternative version', - name: 'Alternative Version', - }, - parentStory: { - id: 'parent story', - name: 'Parent Story', - }, - sideStory: { - id: 'side story', - name: 'Side Story', - }, - fullStory: { - id: 'full story', - name: 'Full Story', - }, - summary: { - id: 'summary', - name: 'Summary', - }, - character: { - id: 'character', - name: 'Character', - }, - other: { - id: 'other', - name: 'Other', - }, -}; - -function isExclusionKey(id: string): id is keyof typeof exclusionMapping { - return id in exclusionMapping; -} - function GeneralSettings() { const { newSettings, setNewSettings, updateSetting } = useSettingsContext(); const { - AutoGroupSeries, - AutoGroupSeriesRelationExclusions, - AutoGroupSeriesUseScoreAlgorithm, LogRotator, TraceLog, WebUI_Settings, @@ -102,23 +34,6 @@ function GeneralSettings() { themesQuery.data?.find(theme => `theme-${theme.ID}` === WebUI_Settings.theme) ), [themesQuery.data, WebUI_Settings.theme]); - const handleExclusionChange = (event: ChangeEvent) => { - if (!(event.target.id in exclusionMapping)) return; - const { checked, id } = event.target; - - if (isExclusionKey(id)) { - if (checked) { - const tempExclusions = [...AutoGroupSeriesRelationExclusions, exclusionMapping[id].id]; - setNewSettings({ ...newSettings, AutoGroupSeriesRelationExclusions: tempExclusions }); - } else { - const tempExclusions = AutoGroupSeriesRelationExclusions.filter( - exclusion => exclusion !== exclusionMapping[id].id, - ); - setNewSettings({ ...newSettings, AutoGroupSeriesRelationExclusions: tempExclusions }); - } - } - }; - return ( <>
General
@@ -304,40 +219,6 @@ function GeneralSettings() { /> - -
-
Relation Options
-
- setNewSettings({ ...newSettings, AutoGroupSeries: event.target.checked })} - /> - - setNewSettings({ ...newSettings, AutoGroupSeriesUseScoreAlgorithm: event.target.checked })} - /> - Exclude following relations -
- {keys(exclusionMapping).map((item: keyof typeof exclusionMapping) => ( - - ))} -
-
-
); }