From 0b40017b098a931a79f9c81b882cfe8747b43389 Mon Sep 17 00:00:00 2001 From: WithoutPants <53250216+WithoutPants@users.noreply.github.com> Date: Thu, 15 Apr 2021 11:33:20 +1000 Subject: [PATCH] Sort performers in popover and card views (#1294) --- graphql/documents/data/image-slim.graphql | 1 + graphql/documents/data/scene-slim.graphql | 1 + .../src/components/Changelog/versions/v070.md | 1 + .../src/components/Galleries/GalleryCard.tsx | 26 +----------- .../GalleryDetails/GalleryDetailPanel.tsx | 4 +- ui/v2.5/src/components/Images/ImageCard.tsx | 26 +----------- .../Images/ImageDetails/ImageDetailPanel.tsx | 4 +- ui/v2.5/src/components/Scenes/SceneCard.tsx | 26 +----------- .../Scenes/SceneDetails/SceneDetailPanel.tsx | 4 +- .../Shared/PerformerPopoverButton.tsx | 40 +++++++++++++++++++ ui/v2.5/src/core/performers.ts | 35 ++++++++++++++++ 11 files changed, 93 insertions(+), 75 deletions(-) create mode 100644 ui/v2.5/src/components/Shared/PerformerPopoverButton.tsx diff --git a/graphql/documents/data/image-slim.graphql b/graphql/documents/data/image-slim.graphql index ce80786ee..b1c066ee2 100644 --- a/graphql/documents/data/image-slim.graphql +++ b/graphql/documents/data/image-slim.graphql @@ -38,6 +38,7 @@ fragment SlimImageData on Image { performers { id name + gender favorite image_path } diff --git a/graphql/documents/data/scene-slim.graphql b/graphql/documents/data/scene-slim.graphql index f427eb904..4aacf27e4 100644 --- a/graphql/documents/data/scene-slim.graphql +++ b/graphql/documents/data/scene-slim.graphql @@ -68,6 +68,7 @@ fragment SlimSceneData on Scene { performers { id name + gender favorite image_path } diff --git a/ui/v2.5/src/components/Changelog/versions/v070.md b/ui/v2.5/src/components/Changelog/versions/v070.md index 132a6f8ac..6a76e8fb4 100644 --- a/ui/v2.5/src/components/Changelog/versions/v070.md +++ b/ui/v2.5/src/components/Changelog/versions/v070.md @@ -4,6 +4,7 @@ * Added scene queue. ### 🎨 Improvements +* Sort performers by gender in scene/image/gallery cards and details. * Add popover buttons for scenes/images/galleries on performer/studio/tag cards. * Add slideshow to image wall view. * Support API key via URL query parameter, and added API key to stream link in Scene File Info. diff --git a/ui/v2.5/src/components/Galleries/GalleryCard.tsx b/ui/v2.5/src/components/Galleries/GalleryCard.tsx index 7bfb14398..6bbb4a952 100644 --- a/ui/v2.5/src/components/Galleries/GalleryCard.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryCard.tsx @@ -12,6 +12,7 @@ import { TruncatedText, } from "src/components/Shared"; import { TextUtils } from "src/utils"; +import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; interface IProps { gallery: GQL.GallerySlimDataFragment; @@ -63,30 +64,7 @@ export const GalleryCard: React.FC = (props) => { function maybeRenderPerformerPopoverButton() { if (props.gallery.performers.length <= 0) return; - const popoverContent = props.gallery.performers.map((performer) => ( -
- - {performer.name - - -
- )); - - return ( - - - - ); + return ; } function maybeRenderSceneStudioOverlay() { diff --git a/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryDetailPanel.tsx b/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryDetailPanel.tsx index 3b9bf1b47..878137d0f 100644 --- a/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryDetailPanel.tsx +++ b/ui/v2.5/src/components/Galleries/GalleryDetails/GalleryDetailPanel.tsx @@ -6,6 +6,7 @@ import { TextUtils } from "src/utils"; import { TagLink, TruncatedText } from "src/components/Shared"; import { PerformerCard } from "src/components/Performers/PerformerCard"; import { RatingStars } from "src/components/Scenes/SceneDetails/RatingStars"; +import { sortPerformers } from "src/core/performers"; interface IGalleryDetailProps { gallery: Partial; @@ -38,7 +39,8 @@ export const GalleryDetailPanel: React.FC = (props) => { function renderPerformers() { if (!props.gallery.performers || props.gallery.performers.length === 0) return; - const cards = props.gallery.performers.map((performer) => ( + const performers = sortPerformers(props.gallery.performers); + const cards = performers.map((performer) => ( = ( function maybeRenderPerformerPopoverButton() { if (props.image.performers.length <= 0) return; - const popoverContent = props.image.performers.map((performer) => ( -
- - {performer.name - - -
- )); - - return ( - - - - ); + return ; } function maybeRenderOCounter() { diff --git a/ui/v2.5/src/components/Images/ImageDetails/ImageDetailPanel.tsx b/ui/v2.5/src/components/Images/ImageDetails/ImageDetailPanel.tsx index ff741f39f..237312411 100644 --- a/ui/v2.5/src/components/Images/ImageDetails/ImageDetailPanel.tsx +++ b/ui/v2.5/src/components/Images/ImageDetails/ImageDetailPanel.tsx @@ -5,6 +5,7 @@ import { TextUtils } from "src/utils"; import { TagLink, TruncatedText } from "src/components/Shared"; import { PerformerCard } from "src/components/Performers/PerformerCard"; import { RatingStars } from "src/components/Scenes/SceneDetails/RatingStars"; +import { sortPerformers } from "src/core/performers"; interface IImageDetailProps { image: GQL.ImageDataFragment; @@ -26,7 +27,8 @@ export const ImageDetailPanel: React.FC = (props) => { function renderPerformers() { if (props.image.performers.length === 0) return; - const cards = props.image.performers.map((performer) => ( + const performers = sortPerformers(props.image.performers); + const cards = performers.map((performer) => ( )); diff --git a/ui/v2.5/src/components/Scenes/SceneCard.tsx b/ui/v2.5/src/components/Scenes/SceneCard.tsx index 99844a722..49bee3148 100644 --- a/ui/v2.5/src/components/Scenes/SceneCard.tsx +++ b/ui/v2.5/src/components/Scenes/SceneCard.tsx @@ -12,6 +12,7 @@ import { TruncatedText, } from "src/components/Shared"; import { TextUtils } from "src/utils"; +import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton"; interface IScenePreviewProps { isPortrait: boolean; @@ -161,30 +162,7 @@ export const SceneCard: React.FC = ( function maybeRenderPerformerPopoverButton() { if (props.scene.performers.length <= 0) return; - const popoverContent = props.scene.performers.map((performer) => ( -
- - {performer.name - - -
- )); - - return ( - - - - ); + return ; } function maybeRenderMoviePopoverButton() { diff --git a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx index a811ebc60..18bc0a985 100644 --- a/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx +++ b/ui/v2.5/src/components/Scenes/SceneDetails/SceneDetailPanel.tsx @@ -5,6 +5,7 @@ import * as GQL from "src/core/generated-graphql"; import { TextUtils } from "src/utils"; import { TagLink, TruncatedText } from "src/components/Shared"; import { PerformerCard } from "src/components/Performers/PerformerCard"; +import { sortPerformers } from "src/core/performers"; import { RatingStars } from "./RatingStars"; interface ISceneDetailProps { @@ -37,7 +38,8 @@ export const SceneDetailPanel: React.FC = (props) => { function renderPerformers() { if (props.scene.performers.length === 0) return; - const cards = props.scene.performers.map((performer) => ( + const performers = sortPerformers(props.scene.performers); + const cards = performers.map((performer) => ( []; +} + +export const PerformerPopoverButton: React.FC = ({ performers }) => { + const sorted = sortPerformers(performers); + const popoverContent = sorted.map((performer) => ( +
+ + {performer.name + + +
+ )); + + return ( + + + + ); +}; diff --git a/ui/v2.5/src/core/performers.ts b/ui/v2.5/src/core/performers.ts index e7552b447..ecada4495 100644 --- a/ui/v2.5/src/core/performers.ts +++ b/ui/v2.5/src/core/performers.ts @@ -37,3 +37,38 @@ export const performerFilterHook = ( return filter; }; }; + +interface IPerformerFragment { + name?: GQL.Maybe; + gender?: GQL.Maybe; +} + +export function sortPerformers(performers: T[]) { + const ret = performers.slice(); + ret.sort((a, b) => { + if (a.gender === b.gender) { + // sort by name + return (a.name ?? "").localeCompare(b.name ?? ""); + } + + // TODO - may want to customise gender order + const genderOrder = [ + GQL.GenderEnum.Female, + GQL.GenderEnum.TransgenderFemale, + GQL.GenderEnum.Male, + GQL.GenderEnum.TransgenderMale, + GQL.GenderEnum.Intersex, + GQL.GenderEnum.NonBinary, + ]; + + const aIndex = a.gender + ? genderOrder.indexOf(a.gender) + : genderOrder.length; + const bIndex = b.gender + ? genderOrder.indexOf(b.gender) + : genderOrder.length; + return aIndex - bIndex; + }); + + return ret; +}