diff --git a/ui/v2.5/src/components/FrontPage/FrontPageConfig.tsx b/ui/v2.5/src/components/FrontPage/FrontPageConfig.tsx index eee1342ff..71c1c2395 100644 --- a/ui/v2.5/src/components/FrontPage/FrontPageConfig.tsx +++ b/ui/v2.5/src/components/FrontPage/FrontPageConfig.tsx @@ -3,11 +3,7 @@ import { FormattedMessage, IntlShape, useIntl } from "react-intl"; import { useFindSavedFilters } from "src/core/StashService"; import { LoadingIndicator } from "../Shared/LoadingIndicator"; import { Button, Form, Modal } from "react-bootstrap"; -import { - FilterMode, - FindSavedFiltersQuery, - SavedFilter, -} from "src/core/generated-graphql"; +import * as GQL from "src/core/generated-graphql"; import { ConfigurationContext } from "src/hooks/Config"; import { IUIConfig, @@ -21,24 +17,25 @@ import { interface IAddSavedFilterModalProps { onClose: (content?: FrontPageContent) => void; existingSavedFilterIDs: string[]; - candidates: FindSavedFiltersQuery; + candidates: GQL.FindSavedFiltersQuery; } const FilterModeToMessageID = { - [FilterMode.Galleries]: "galleries", - [FilterMode.Images]: "images", - [FilterMode.Movies]: "movies", - [FilterMode.Performers]: "performers", - [FilterMode.SceneMarkers]: "markers", - [FilterMode.Scenes]: "scenes", - [FilterMode.Studios]: "studios", - [FilterMode.Tags]: "tags", + [GQL.FilterMode.Galleries]: "galleries", + [GQL.FilterMode.Images]: "images", + [GQL.FilterMode.Movies]: "movies", + [GQL.FilterMode.Performers]: "performers", + [GQL.FilterMode.SceneMarkers]: "markers", + [GQL.FilterMode.Scenes]: "scenes", + [GQL.FilterMode.Studios]: "studios", + [GQL.FilterMode.Tags]: "tags", }; -function filterTitle(intl: IntlShape, f: Pick) { - return `${intl.formatMessage({ id: FilterModeToMessageID[f.mode] })}: ${ - f.name - }`; +type SavedFilter = Pick; + +function filterTitle(intl: IntlShape, f: SavedFilter) { + const typeMessage = intl.formatMessage({ id: FilterModeToMessageID[f.mode] }); + return `${typeMessage}: ${f.name}`; } const AddContentModal: React.FC = ({ @@ -98,7 +95,7 @@ const AddContentModal: React.FC = ({ .filter((f) => { // markers not currently supported return ( - f.mode !== FilterMode.SceneMarkers && + f.mode !== GQL.FilterMode.SceneMarkers && !existingSavedFilterIDs.includes(f.id) ); }) @@ -232,7 +229,7 @@ const AddContentModal: React.FC = ({ interface IFilterRowProps { content: FrontPageContent; - allSavedFilters: Pick[]; + allSavedFilters: SavedFilter[]; onDelete: () => void; } @@ -242,10 +239,9 @@ const ContentRow: React.FC = (props: IFilterRowProps) => { function title() { switch (props.content.__typename) { case "SavedFilter": + const savedFilterId = String(props.content.savedFilterId); const savedFilter = props.allSavedFilters.find( - (f) => - f.id === - (props.content as ISavedFilterRow).savedFilterId?.toString() + (f) => f.id === savedFilterId ); if (!savedFilter) return ""; return filterTitle(intl, savedFilter); @@ -302,7 +298,18 @@ export const FrontPageConfig: React.FC = ({ const frontPageContent = getFrontPageContent(ui); if (frontPageContent) { - setCurrentContent(frontPageContent); + setCurrentContent( + // filter out rows where the saved filter no longer exists + frontPageContent.filter((r) => { + if (r.__typename === "SavedFilter") { + const savedFilterId = String(r.savedFilterId); + return allFilters.findSavedFilters.some( + (f) => f.id === savedFilterId + ); + } + return true; + }) + ); } }, [allFilters, ui]); diff --git a/ui/v2.5/src/components/List/Filters/PhashFilter.tsx b/ui/v2.5/src/components/List/Filters/PhashFilter.tsx index 988f813b9..68eda8002 100644 --- a/ui/v2.5/src/components/List/Filters/PhashFilter.tsx +++ b/ui/v2.5/src/components/List/Filters/PhashFilter.tsx @@ -43,7 +43,7 @@ export const PhashFilter: React.FC = ({ className="btn-secondary" onChange={valueChanged} value={value ? value.value : ""} - placeholder={intl.formatMessage({ id: "phash" })} + placeholder={intl.formatMessage({ id: "media_info.phash" })} /> {criterion.modifier !== CriterionModifier.IsNull && diff --git a/ui/v2.5/src/components/List/SavedFilterList.tsx b/ui/v2.5/src/components/List/SavedFilterList.tsx index 7d0b1233a..f46a28c84 100644 --- a/ui/v2.5/src/components/List/SavedFilterList.tsx +++ b/ui/v2.5/src/components/List/SavedFilterList.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react"; +import React, { useState } from "react"; import { Button, ButtonGroup, @@ -39,7 +39,6 @@ export const SavedFilterList: React.FC = ({ const intl = useIntl(); const { data, error, loading, refetch } = useFindSavedFilters(filter.mode); - const oldError = useRef(error); const [filterName, setFilterName] = useState(""); const [saving, setSaving] = useState(false); @@ -56,14 +55,6 @@ export const SavedFilterList: React.FC = ({ const savedFilters = data?.findSavedFilters ?? []; - useEffect(() => { - if (error && error !== oldError.current) { - Toast.error(error); - } - - oldError.current = error; - }, [error, Toast, oldError]); - async function onSaveFilter(name: string, id?: string) { const filterCopy = filter.clone(); @@ -285,6 +276,8 @@ export const SavedFilterList: React.FC = ({ } function renderSavedFilters() { + if (error) return
{error.message}
; + if (loading || saving) { return (
@@ -311,20 +304,22 @@ export const SavedFilterList: React.FC = ({ function maybeRenderSetDefaultButton() { if (persistState === PersistanceLevel.ALL) { return ( - +
+ +
); } } return ( -
+ <> {maybeRenderDeleteAlert()} {maybeRenderOverwriteAlert()} @@ -359,6 +354,6 @@ export const SavedFilterList: React.FC = ({ {renderSavedFilters()} {maybeRenderSetDefaultButton()} -
+ ); }; diff --git a/ui/v2.5/src/components/List/styles.scss b/ui/v2.5/src/components/List/styles.scss index 1c6a390f4..2b193cad3 100644 --- a/ui/v2.5/src/components/List/styles.scss +++ b/ui/v2.5/src/components/List/styles.scss @@ -65,8 +65,14 @@ input[type="range"].zoom-slider { .saved-filter-list-menu { width: 300px; + &.dropdown-menu.show { + display: flex; + flex-direction: column; + } + .set-as-default-button { float: right; + margin-right: 0.5rem; } .LoadingIndicator { @@ -94,12 +100,17 @@ input[type="range"].zoom-slider { align-items: center; display: inline; overflow-x: hidden; + padding-left: 1.25rem; padding-right: 0.25rem; text-overflow: ellipsis; } .btn-group { margin-left: auto; + + .btn { + border-radius: 0; + } } .delete-button { diff --git a/ui/v2.5/src/index.scss b/ui/v2.5/src/index.scss index ec11409c3..877e31f02 100755 --- a/ui/v2.5/src/index.scss +++ b/ui/v2.5/src/index.scss @@ -660,7 +660,6 @@ div.react-select__menu, div.dropdown-menu { background-color: $secondary; color: $text-color; - z-index: 1600; .react-select__option, .dropdown-item { diff --git a/ui/v2.5/src/locales/en-GB.json b/ui/v2.5/src/locales/en-GB.json index 8332ed3f7..bb2d5ca0a 100644 --- a/ui/v2.5/src/locales/en-GB.json +++ b/ui/v2.5/src/locales/en-GB.json @@ -921,6 +921,7 @@ "unknown": "Unknown", "wall": "Wall" }, + "distance": "Distance", "donate": "Donate", "dupe_check": { "description": "Levels below 'Exact' can take longer to calculate. False positives might also be returned on lower accuracy levels.",