diff --git a/ui/v2.5/src/components/Galleries/EditGalleriesDialog.tsx b/ui/v2.5/src/components/Galleries/EditGalleriesDialog.tsx index 9e0d98f28..88e2bd0be 100644 --- a/ui/v2.5/src/components/Galleries/EditGalleriesDialog.tsx +++ b/ui/v2.5/src/components/Galleries/EditGalleriesDialog.tsx @@ -27,10 +27,12 @@ export const EditGalleriesDialog: React.FC = ( setPerformerMode, ] = React.useState(GQL.BulkUpdateIdMode.Add); const [performerIds, setPerformerIds] = useState(); + const [existingPerformerIds, setExistingPerformerIds] = useState(); const [tagMode, setTagMode] = React.useState( GQL.BulkUpdateIdMode.Add ); const [tagIds, setTagIds] = useState(); + const [existingTagIds, setExistingTagIds] = useState(); const [organized, setOrganized] = useState(); const [updateGalleries] = useBulkGalleryUpdate(); @@ -279,16 +281,11 @@ export const EditGalleriesDialog: React.FC = ( setRating(updateRating); setStudioId(updateStudioID); - if (performerMode === GQL.BulkUpdateIdMode.Set) { - setPerformerIds(updatePerformerIds); - } - - if (tagMode === GQL.BulkUpdateIdMode.Set) { - setTagIds(updateTagIds); - } + setExistingPerformerIds(updatePerformerIds); + setExistingTagIds(updateTagIds); setOrganized(updateOrganized); - }, [props.selected, performerMode, tagMode]); + }, [props.selected]); useEffect(() => { if (checkboxRef.current) { @@ -301,12 +298,15 @@ export const EditGalleriesDialog: React.FC = ( ids: string[] | undefined ) { let mode = GQL.BulkUpdateIdMode.Add; + let existingIds: string[] | undefined = []; switch (type) { case "performers": mode = performerMode; + existingIds = existingPerformerIds; break; case "tags": mode = tagMode; + existingIds = existingTagIds; break; } @@ -314,8 +314,7 @@ export const EditGalleriesDialog: React.FC = ( { - const itemIDs = items.map((i) => i.id); + onUpdate={(itemIDs) => { switch (type) { case "performers": setPerformerIds(itemIDs); @@ -335,6 +334,7 @@ export const EditGalleriesDialog: React.FC = ( break; } }} + existingIds={existingIds ?? []} ids={ids ?? []} mode={mode} /> diff --git a/ui/v2.5/src/components/Galleries/GalleryCard.tsx b/ui/v2.5/src/components/Galleries/GalleryCard.tsx index 6d1d1dec9..857ca7f0c 100644 --- a/ui/v2.5/src/components/Galleries/GalleryCard.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryCard.tsx @@ -7,6 +7,7 @@ import { useConfiguration } from "src/core/StashService"; import { GridCard, HoverPopover, Icon, TagLink } from "src/components/Shared"; import { TextUtils } from "src/utils"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; +import { RatingBanner } from "../Shared/RatingBanner"; interface IProps { gallery: GQL.SlimGalleryDataFragment; @@ -114,21 +115,6 @@ export const GalleryCard: React.FC = (props) => { } } - function maybeRenderRatingBanner() { - if (!props.gallery.rating) { - return; - } - return ( -
- RATING: {props.gallery.rating} -
- ); - } - return ( = (props) => { src={`${props.gallery.cover.paths.thumbnail}`} /> ) : undefined} - {maybeRenderRatingBanner()} + } overlays={maybeRenderSceneStudioOverlay()} diff --git a/ui/v2.5/src/components/Images/EditImagesDialog.tsx b/ui/v2.5/src/components/Images/EditImagesDialog.tsx index 8bb78d337..237f8f0fc 100644 --- a/ui/v2.5/src/components/Images/EditImagesDialog.tsx +++ b/ui/v2.5/src/components/Images/EditImagesDialog.tsx @@ -27,10 +27,12 @@ export const EditImagesDialog: React.FC = ( setPerformerMode, ] = React.useState(GQL.BulkUpdateIdMode.Add); const [performerIds, setPerformerIds] = useState(); + const [existingPerformerIds, setExistingPerformerIds] = useState(); const [tagMode, setTagMode] = React.useState( GQL.BulkUpdateIdMode.Add ); const [tagIds, setTagIds] = useState(); + const [existingTagIds, setExistingTagIds] = useState(); const [organized, setOrganized] = useState(); const [updateImages] = useBulkImageUpdate(); @@ -275,13 +277,8 @@ export const EditImagesDialog: React.FC = ( setRating(updateRating); setStudioId(updateStudioID); - if (performerMode === GQL.BulkUpdateIdMode.Set) { - setPerformerIds(updatePerformerIds); - } - - if (tagMode === GQL.BulkUpdateIdMode.Set) { - setTagIds(updateTagIds); - } + setExistingPerformerIds(updatePerformerIds); + setExistingTagIds(updateTagIds); setOrganized(updateOrganized); }, [props.selected, performerMode, tagMode]); @@ -296,12 +293,15 @@ export const EditImagesDialog: React.FC = ( ids: string[] | undefined ) { let mode = GQL.BulkUpdateIdMode.Add; + let existingIds: string[] | undefined = []; switch (type) { case "performers": mode = performerMode; + existingIds = existingPerformerIds; break; case "tags": mode = tagMode; + existingIds = existingTagIds; break; } @@ -309,8 +309,7 @@ export const EditImagesDialog: React.FC = ( { - const itemIDs = items.map((i) => i.id); + onUpdate={(itemIDs) => { switch (type) { case "performers": setPerformerIds(itemIDs); @@ -330,6 +329,7 @@ export const EditImagesDialog: React.FC = ( break; } }} + existingIds={existingIds ?? []} ids={ids ?? []} mode={mode} /> diff --git a/ui/v2.5/src/components/Images/ImageCard.tsx b/ui/v2.5/src/components/Images/ImageCard.tsx index 7a82b79d8..670d11fb1 100644 --- a/ui/v2.5/src/components/Images/ImageCard.tsx +++ b/ui/v2.5/src/components/Images/ImageCard.tsx @@ -6,6 +6,7 @@ import { Icon, TagLink, HoverPopover, SweatDrops } from "src/components/Shared"; import { TextUtils } from "src/utils"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; import { GridCard } from "../Shared/GridCard"; +import { RatingBanner } from "../Shared/RatingBanner"; interface IImageCardProps { image: GQL.SlimImageDataFragment; @@ -18,21 +19,6 @@ interface IImageCardProps { export const ImageCard: React.FC = ( props: IImageCardProps ) => { - function maybeRenderRatingBanner() { - if (!props.image.rating) { - return; - } - return ( -
- RATING: {props.image.rating} -
- ); - } - function maybeRenderTagPopoverButton() { if (props.image.tags.length <= 0) return; @@ -130,7 +116,7 @@ export const ImageCard: React.FC = ( src={props.image.paths.thumbnail ?? ""} /> - {maybeRenderRatingBanner()} + } popovers={maybeRenderPopoverButtonGroup()} diff --git a/ui/v2.5/src/components/Movies/MovieCard.tsx b/ui/v2.5/src/components/Movies/MovieCard.tsx index 919da36da..96f6c69a5 100644 --- a/ui/v2.5/src/components/Movies/MovieCard.tsx +++ b/ui/v2.5/src/components/Movies/MovieCard.tsx @@ -2,6 +2,7 @@ import React, { FunctionComponent } from "react"; import { FormattedPlural } from "react-intl"; import * as GQL from "src/core/generated-graphql"; import { GridCard } from "src/components/Shared"; +import { RatingBanner } from "../Shared/RatingBanner"; interface IProps { movie: GQL.MovieDataFragment; @@ -12,21 +13,6 @@ interface IProps { } export const MovieCard: FunctionComponent = (props: IProps) => { - function maybeRenderRatingBanner() { - if (!props.movie.rating) { - return; - } - return ( -
- RATING: {props.movie.rating} -
- ); - } - function maybeRenderSceneNumber() { if (!props.sceneIndex) { return ( @@ -57,7 +43,7 @@ export const MovieCard: FunctionComponent = (props: IProps) => { alt={props.movie.name ?? ""} src={props.movie.front_image_path ?? ""} /> - {maybeRenderRatingBanner()} + } details={maybeRenderSceneNumber()} diff --git a/ui/v2.5/src/components/Performers/EditPerformersDialog.tsx b/ui/v2.5/src/components/Performers/EditPerformersDialog.tsx index e00f94ad9..99e7f6196 100644 --- a/ui/v2.5/src/components/Performers/EditPerformersDialog.tsx +++ b/ui/v2.5/src/components/Performers/EditPerformersDialog.tsx @@ -25,6 +25,7 @@ export const EditPerformersDialog: React.FC = ( GQL.BulkUpdateIdMode.Add ); const [tagIds, setTagIds] = useState(); + const [existingTagIds, setExistingTagIds] = useState(); const [favorite, setFavorite] = useState(); const [updatePerformers] = useBulkPerformerUpdate(getPerformerInput()); @@ -178,9 +179,7 @@ export const EditPerformersDialog: React.FC = ( } }); - if (tagMode === GQL.BulkUpdateIdMode.Set) { - setTagIds(updateTagIds); - } + setExistingTagIds(updateTagIds); setFavorite(updateFavorite); setRating(updateRating); }, [props.selected, tagMode]); @@ -191,42 +190,6 @@ export const EditPerformersDialog: React.FC = ( } }, [favorite, checkboxRef]); - function renderMultiSelect( - type: "performers" | "tags", - ids: string[] | undefined - ) { - let mode = GQL.BulkUpdateIdMode.Add; - switch (type) { - case "tags": - mode = tagMode; - break; - } - - return ( - { - const itemIDs = items.map((i) => i.id); - switch (type) { - case "tags": - setTagIds(itemIDs); - break; - } - }} - onSetMode={(newMode) => { - switch (type) { - case "tags": - setTagMode(newMode); - break; - } - }} - ids={ids ?? []} - mode={mode} - /> - ); - } - function cycleFavorite() { if (favorite) { setFavorite(undefined); @@ -271,7 +234,15 @@ export const EditPerformersDialog: React.FC = ( - {renderMultiSelect("tags", tagIds)} + setTagIds(itemIDs)} + onSetMode={(newMode) => setTagMode(newMode)} + existingIds={existingTagIds ?? []} + ids={tagIds ?? []} + mode={tagMode} + /> diff --git a/ui/v2.5/src/components/Scenes/EditScenesDialog.tsx b/ui/v2.5/src/components/Scenes/EditScenesDialog.tsx index b6029e348..71e18e641 100644 --- a/ui/v2.5/src/components/Scenes/EditScenesDialog.tsx +++ b/ui/v2.5/src/components/Scenes/EditScenesDialog.tsx @@ -27,10 +27,12 @@ export const EditScenesDialog: React.FC = ( setPerformerMode, ] = React.useState(GQL.BulkUpdateIdMode.Add); const [performerIds, setPerformerIds] = useState(); + const [existingPerformerIds, setExistingPerformerIds] = useState(); const [tagMode, setTagMode] = React.useState( GQL.BulkUpdateIdMode.Add ); const [tagIds, setTagIds] = useState(); + const [existingTagIds, setExistingTagIds] = useState(); const [organized, setOrganized] = useState(); const [updateScenes] = useBulkSceneUpdate(getSceneInput()); @@ -271,13 +273,8 @@ export const EditScenesDialog: React.FC = ( setRating(updateRating); setStudioId(updateStudioID); - if (performerMode === GQL.BulkUpdateIdMode.Set) { - setPerformerIds(updatePerformerIds); - } - - if (tagMode === GQL.BulkUpdateIdMode.Set) { - setTagIds(updateTagIds); - } + setExistingPerformerIds(updatePerformerIds); + setExistingTagIds(updateTagIds); setOrganized(updateOrganized); }, [props.selected, performerMode, tagMode]); @@ -292,12 +289,15 @@ export const EditScenesDialog: React.FC = ( ids: string[] | undefined ) { let mode = GQL.BulkUpdateIdMode.Add; + let existingIds: string[] | undefined = []; switch (type) { case "performers": mode = performerMode; + existingIds = existingPerformerIds; break; case "tags": mode = tagMode; + existingIds = existingTagIds; break; } @@ -305,8 +305,7 @@ export const EditScenesDialog: React.FC = ( { - const itemIDs = items.map((i) => i.id); + onUpdate={(itemIDs) => { switch (type) { case "performers": setPerformerIds(itemIDs); @@ -327,6 +326,7 @@ export const EditScenesDialog: React.FC = ( } }} ids={ids ?? []} + existingIds={existingIds ?? []} mode={mode} /> ); @@ -404,7 +404,7 @@ export const EditScenesDialog: React.FC = ( - + {renderMultiSelect("tags", tagIds)} diff --git a/ui/v2.5/src/components/Scenes/SceneCard.tsx b/ui/v2.5/src/components/Scenes/SceneCard.tsx index 21b9104b9..a96f02d13 100644 --- a/ui/v2.5/src/components/Scenes/SceneCard.tsx +++ b/ui/v2.5/src/components/Scenes/SceneCard.tsx @@ -15,6 +15,7 @@ import { TextUtils } from "src/utils"; import { SceneQueue } from "src/models/sceneQueue"; import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; import { GridCard } from "../Shared/GridCard"; +import { RatingBanner } from "../Shared/RatingBanner"; interface IScenePreviewProps { isPortrait: boolean; @@ -89,21 +90,6 @@ export const SceneCard: React.FC = ( missingStudioImage || (config?.data?.configuration.interface.showStudioAsText ?? false); - function maybeRenderRatingBanner() { - if (!props.scene.rating) { - return; - } - return ( -
- RATING: {props.scene.rating} -
- ); - } - function maybeRenderSceneSpecsOverlay() { return (
@@ -333,7 +319,7 @@ export const SceneCard: React.FC = ( config.data?.configuration?.interface?.soundOnPreview ?? false } /> - {maybeRenderRatingBanner()} + {maybeRenderSceneSpecsOverlay()} } diff --git a/ui/v2.5/src/components/Shared/MultiSet.tsx b/ui/v2.5/src/components/Shared/MultiSet.tsx index f0ce5cf9e..e5064d0ee 100644 --- a/ui/v2.5/src/components/Shared/MultiSet.tsx +++ b/ui/v2.5/src/components/Shared/MultiSet.tsx @@ -13,10 +13,11 @@ type ValidTypes = interface IMultiSetProps { type: "performers" | "studios" | "tags"; + existingIds?: string[]; ids?: string[]; mode: GQL.BulkUpdateIdMode; disabled?: boolean; - onUpdate: (items: ValidTypes[]) => void; + onUpdate: (ids: string[]) => void; onSetMode: (mode: GQL.BulkUpdateIdMode) => void; } @@ -31,7 +32,7 @@ const MultiSet: React.FunctionComponent = ( ]; function onUpdate(items: ValidTypes[]) { - props.onUpdate(items); + props.onUpdate(items.map((i) => i.id)); } function getModeText(mode: GQL.BulkUpdateIdMode) { @@ -51,13 +52,32 @@ const MultiSet: React.FunctionComponent = ( } } + function onSetMode(mode: GQL.BulkUpdateIdMode) { + if (mode === props.mode) { + return; + } + + // if going to Set, set the existing ids + if (mode === GQL.BulkUpdateIdMode.Set && props.existingIds) { + props.onUpdate(props.existingIds); + // if going from Set, wipe the ids + } else if ( + mode !== GQL.BulkUpdateIdMode.Set && + props.mode === GQL.BulkUpdateIdMode.Set + ) { + props.onUpdate([]); + } + + props.onSetMode(mode); + } + function renderModeButton(mode: GQL.BulkUpdateIdMode) { return (