mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 12:54:38 +03:00
Various UI fixes (#1502)
* Set/unset existing ids when moving to/from set * Refactor rating banner * Fix overlapping in multi set * Prevent UI crash on bad hierarchical input value
This commit is contained in:
@@ -27,10 +27,12 @@ export const EditGalleriesDialog: React.FC<IListOperationProps> = (
|
|||||||
setPerformerMode,
|
setPerformerMode,
|
||||||
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||||
|
const [existingPerformerIds, setExistingPerformerIds] = useState<string[]>();
|
||||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
GQL.BulkUpdateIdMode.Add
|
GQL.BulkUpdateIdMode.Add
|
||||||
);
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
|
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
||||||
const [organized, setOrganized] = useState<boolean | undefined>();
|
const [organized, setOrganized] = useState<boolean | undefined>();
|
||||||
|
|
||||||
const [updateGalleries] = useBulkGalleryUpdate();
|
const [updateGalleries] = useBulkGalleryUpdate();
|
||||||
@@ -279,16 +281,11 @@ export const EditGalleriesDialog: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
setRating(updateRating);
|
setRating(updateRating);
|
||||||
setStudioId(updateStudioID);
|
setStudioId(updateStudioID);
|
||||||
if (performerMode === GQL.BulkUpdateIdMode.Set) {
|
setExistingPerformerIds(updatePerformerIds);
|
||||||
setPerformerIds(updatePerformerIds);
|
setExistingTagIds(updateTagIds);
|
||||||
}
|
|
||||||
|
|
||||||
if (tagMode === GQL.BulkUpdateIdMode.Set) {
|
|
||||||
setTagIds(updateTagIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
setOrganized(updateOrganized);
|
setOrganized(updateOrganized);
|
||||||
}, [props.selected, performerMode, tagMode]);
|
}, [props.selected]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (checkboxRef.current) {
|
if (checkboxRef.current) {
|
||||||
@@ -301,12 +298,15 @@ export const EditGalleriesDialog: React.FC<IListOperationProps> = (
|
|||||||
ids: string[] | undefined
|
ids: string[] | undefined
|
||||||
) {
|
) {
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
let mode = GQL.BulkUpdateIdMode.Add;
|
||||||
|
let existingIds: string[] | undefined = [];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
mode = performerMode;
|
mode = performerMode;
|
||||||
|
existingIds = existingPerformerIds;
|
||||||
break;
|
break;
|
||||||
case "tags":
|
case "tags":
|
||||||
mode = tagMode;
|
mode = tagMode;
|
||||||
|
existingIds = existingTagIds;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,8 +314,7 @@ export const EditGalleriesDialog: React.FC<IListOperationProps> = (
|
|||||||
<MultiSet
|
<MultiSet
|
||||||
type={type}
|
type={type}
|
||||||
disabled={isUpdating}
|
disabled={isUpdating}
|
||||||
onUpdate={(items) => {
|
onUpdate={(itemIDs) => {
|
||||||
const itemIDs = items.map((i) => i.id);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
setPerformerIds(itemIDs);
|
setPerformerIds(itemIDs);
|
||||||
@@ -335,6 +334,7 @@ export const EditGalleriesDialog: React.FC<IListOperationProps> = (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
existingIds={existingIds ?? []}
|
||||||
ids={ids ?? []}
|
ids={ids ?? []}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useConfiguration } from "src/core/StashService";
|
|||||||
import { GridCard, HoverPopover, Icon, TagLink } from "src/components/Shared";
|
import { GridCard, HoverPopover, Icon, TagLink } from "src/components/Shared";
|
||||||
import { TextUtils } from "src/utils";
|
import { TextUtils } from "src/utils";
|
||||||
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
||||||
|
import { RatingBanner } from "../Shared/RatingBanner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
gallery: GQL.SlimGalleryDataFragment;
|
gallery: GQL.SlimGalleryDataFragment;
|
||||||
@@ -114,21 +115,6 @@ export const GalleryCard: React.FC<IProps> = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeRenderRatingBanner() {
|
|
||||||
if (!props.gallery.rating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`rating-banner ${
|
|
||||||
props.gallery.rating ? `rating-${props.gallery.rating}` : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
RATING: {props.gallery.rating}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GridCard
|
<GridCard
|
||||||
className={`gallery-card zoom-${props.zoomIndex}`}
|
className={`gallery-card zoom-${props.zoomIndex}`}
|
||||||
@@ -148,7 +134,7 @@ export const GalleryCard: React.FC<IProps> = (props) => {
|
|||||||
src={`${props.gallery.cover.paths.thumbnail}`}
|
src={`${props.gallery.cover.paths.thumbnail}`}
|
||||||
/>
|
/>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{maybeRenderRatingBanner()}
|
<RatingBanner rating={props.gallery.rating} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
overlays={maybeRenderSceneStudioOverlay()}
|
overlays={maybeRenderSceneStudioOverlay()}
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
setPerformerMode,
|
setPerformerMode,
|
||||||
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||||
|
const [existingPerformerIds, setExistingPerformerIds] = useState<string[]>();
|
||||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
GQL.BulkUpdateIdMode.Add
|
GQL.BulkUpdateIdMode.Add
|
||||||
);
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
|
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
||||||
const [organized, setOrganized] = useState<boolean | undefined>();
|
const [organized, setOrganized] = useState<boolean | undefined>();
|
||||||
|
|
||||||
const [updateImages] = useBulkImageUpdate();
|
const [updateImages] = useBulkImageUpdate();
|
||||||
@@ -275,13 +277,8 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
setRating(updateRating);
|
setRating(updateRating);
|
||||||
setStudioId(updateStudioID);
|
setStudioId(updateStudioID);
|
||||||
if (performerMode === GQL.BulkUpdateIdMode.Set) {
|
setExistingPerformerIds(updatePerformerIds);
|
||||||
setPerformerIds(updatePerformerIds);
|
setExistingTagIds(updateTagIds);
|
||||||
}
|
|
||||||
|
|
||||||
if (tagMode === GQL.BulkUpdateIdMode.Set) {
|
|
||||||
setTagIds(updateTagIds);
|
|
||||||
}
|
|
||||||
setOrganized(updateOrganized);
|
setOrganized(updateOrganized);
|
||||||
}, [props.selected, performerMode, tagMode]);
|
}, [props.selected, performerMode, tagMode]);
|
||||||
|
|
||||||
@@ -296,12 +293,15 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
ids: string[] | undefined
|
ids: string[] | undefined
|
||||||
) {
|
) {
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
let mode = GQL.BulkUpdateIdMode.Add;
|
||||||
|
let existingIds: string[] | undefined = [];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
mode = performerMode;
|
mode = performerMode;
|
||||||
|
existingIds = existingPerformerIds;
|
||||||
break;
|
break;
|
||||||
case "tags":
|
case "tags":
|
||||||
mode = tagMode;
|
mode = tagMode;
|
||||||
|
existingIds = existingTagIds;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,8 +309,7 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
<MultiSet
|
<MultiSet
|
||||||
type={type}
|
type={type}
|
||||||
disabled={isUpdating}
|
disabled={isUpdating}
|
||||||
onUpdate={(items) => {
|
onUpdate={(itemIDs) => {
|
||||||
const itemIDs = items.map((i) => i.id);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
setPerformerIds(itemIDs);
|
setPerformerIds(itemIDs);
|
||||||
@@ -330,6 +329,7 @@ export const EditImagesDialog: React.FC<IListOperationProps> = (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
existingIds={existingIds ?? []}
|
||||||
ids={ids ?? []}
|
ids={ids ?? []}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { Icon, TagLink, HoverPopover, SweatDrops } from "src/components/Shared";
|
|||||||
import { TextUtils } from "src/utils";
|
import { TextUtils } from "src/utils";
|
||||||
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
||||||
import { GridCard } from "../Shared/GridCard";
|
import { GridCard } from "../Shared/GridCard";
|
||||||
|
import { RatingBanner } from "../Shared/RatingBanner";
|
||||||
|
|
||||||
interface IImageCardProps {
|
interface IImageCardProps {
|
||||||
image: GQL.SlimImageDataFragment;
|
image: GQL.SlimImageDataFragment;
|
||||||
@@ -18,21 +19,6 @@ interface IImageCardProps {
|
|||||||
export const ImageCard: React.FC<IImageCardProps> = (
|
export const ImageCard: React.FC<IImageCardProps> = (
|
||||||
props: IImageCardProps
|
props: IImageCardProps
|
||||||
) => {
|
) => {
|
||||||
function maybeRenderRatingBanner() {
|
|
||||||
if (!props.image.rating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`rating-banner ${
|
|
||||||
props.image.rating ? `rating-${props.image.rating}` : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
RATING: {props.image.rating}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeRenderTagPopoverButton() {
|
function maybeRenderTagPopoverButton() {
|
||||||
if (props.image.tags.length <= 0) return;
|
if (props.image.tags.length <= 0) return;
|
||||||
|
|
||||||
@@ -130,7 +116,7 @@ export const ImageCard: React.FC<IImageCardProps> = (
|
|||||||
src={props.image.paths.thumbnail ?? ""}
|
src={props.image.paths.thumbnail ?? ""}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{maybeRenderRatingBanner()}
|
<RatingBanner rating={props.image.rating} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
popovers={maybeRenderPopoverButtonGroup()}
|
popovers={maybeRenderPopoverButtonGroup()}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React, { FunctionComponent } from "react";
|
|||||||
import { FormattedPlural } from "react-intl";
|
import { FormattedPlural } from "react-intl";
|
||||||
import * as GQL from "src/core/generated-graphql";
|
import * as GQL from "src/core/generated-graphql";
|
||||||
import { GridCard } from "src/components/Shared";
|
import { GridCard } from "src/components/Shared";
|
||||||
|
import { RatingBanner } from "../Shared/RatingBanner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
movie: GQL.MovieDataFragment;
|
movie: GQL.MovieDataFragment;
|
||||||
@@ -12,21 +13,6 @@ interface IProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const MovieCard: FunctionComponent<IProps> = (props: IProps) => {
|
export const MovieCard: FunctionComponent<IProps> = (props: IProps) => {
|
||||||
function maybeRenderRatingBanner() {
|
|
||||||
if (!props.movie.rating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`rating-banner ${
|
|
||||||
props.movie.rating ? `rating-${props.movie.rating}` : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
RATING: {props.movie.rating}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeRenderSceneNumber() {
|
function maybeRenderSceneNumber() {
|
||||||
if (!props.sceneIndex) {
|
if (!props.sceneIndex) {
|
||||||
return (
|
return (
|
||||||
@@ -57,7 +43,7 @@ export const MovieCard: FunctionComponent<IProps> = (props: IProps) => {
|
|||||||
alt={props.movie.name ?? ""}
|
alt={props.movie.name ?? ""}
|
||||||
src={props.movie.front_image_path ?? ""}
|
src={props.movie.front_image_path ?? ""}
|
||||||
/>
|
/>
|
||||||
{maybeRenderRatingBanner()}
|
<RatingBanner rating={props.movie.rating} />
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
details={maybeRenderSceneNumber()}
|
details={maybeRenderSceneNumber()}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
|
|||||||
GQL.BulkUpdateIdMode.Add
|
GQL.BulkUpdateIdMode.Add
|
||||||
);
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
|
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
||||||
const [favorite, setFavorite] = useState<boolean | undefined>();
|
const [favorite, setFavorite] = useState<boolean | undefined>();
|
||||||
|
|
||||||
const [updatePerformers] = useBulkPerformerUpdate(getPerformerInput());
|
const [updatePerformers] = useBulkPerformerUpdate(getPerformerInput());
|
||||||
@@ -178,9 +179,7 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tagMode === GQL.BulkUpdateIdMode.Set) {
|
setExistingTagIds(updateTagIds);
|
||||||
setTagIds(updateTagIds);
|
|
||||||
}
|
|
||||||
setFavorite(updateFavorite);
|
setFavorite(updateFavorite);
|
||||||
setRating(updateRating);
|
setRating(updateRating);
|
||||||
}, [props.selected, tagMode]);
|
}, [props.selected, tagMode]);
|
||||||
@@ -191,42 +190,6 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
|
|||||||
}
|
}
|
||||||
}, [favorite, checkboxRef]);
|
}, [favorite, checkboxRef]);
|
||||||
|
|
||||||
function renderMultiSelect(
|
|
||||||
type: "performers" | "tags",
|
|
||||||
ids: string[] | undefined
|
|
||||||
) {
|
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
|
||||||
switch (type) {
|
|
||||||
case "tags":
|
|
||||||
mode = tagMode;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MultiSet
|
|
||||||
type={type}
|
|
||||||
disabled={isUpdating}
|
|
||||||
onUpdate={(items) => {
|
|
||||||
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() {
|
function cycleFavorite() {
|
||||||
if (favorite) {
|
if (favorite) {
|
||||||
setFavorite(undefined);
|
setFavorite(undefined);
|
||||||
@@ -271,7 +234,15 @@ export const EditPerformersDialog: React.FC<IListOperationProps> = (
|
|||||||
<Form.Label>
|
<Form.Label>
|
||||||
<FormattedMessage id="tags" />
|
<FormattedMessage id="tags" />
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
{renderMultiSelect("tags", tagIds)}
|
<MultiSet
|
||||||
|
type="tags"
|
||||||
|
disabled={isUpdating}
|
||||||
|
onUpdate={(itemIDs) => setTagIds(itemIDs)}
|
||||||
|
onSetMode={(newMode) => setTagMode(newMode)}
|
||||||
|
existingIds={existingTagIds ?? []}
|
||||||
|
ids={tagIds ?? []}
|
||||||
|
mode={tagMode}
|
||||||
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|
||||||
<Form.Group controlId="favorite">
|
<Form.Group controlId="favorite">
|
||||||
|
|||||||
@@ -27,10 +27,12 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
setPerformerMode,
|
setPerformerMode,
|
||||||
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
] = React.useState<GQL.BulkUpdateIdMode>(GQL.BulkUpdateIdMode.Add);
|
||||||
const [performerIds, setPerformerIds] = useState<string[]>();
|
const [performerIds, setPerformerIds] = useState<string[]>();
|
||||||
|
const [existingPerformerIds, setExistingPerformerIds] = useState<string[]>();
|
||||||
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
const [tagMode, setTagMode] = React.useState<GQL.BulkUpdateIdMode>(
|
||||||
GQL.BulkUpdateIdMode.Add
|
GQL.BulkUpdateIdMode.Add
|
||||||
);
|
);
|
||||||
const [tagIds, setTagIds] = useState<string[]>();
|
const [tagIds, setTagIds] = useState<string[]>();
|
||||||
|
const [existingTagIds, setExistingTagIds] = useState<string[]>();
|
||||||
const [organized, setOrganized] = useState<boolean | undefined>();
|
const [organized, setOrganized] = useState<boolean | undefined>();
|
||||||
|
|
||||||
const [updateScenes] = useBulkSceneUpdate(getSceneInput());
|
const [updateScenes] = useBulkSceneUpdate(getSceneInput());
|
||||||
@@ -271,13 +273,8 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
setRating(updateRating);
|
setRating(updateRating);
|
||||||
setStudioId(updateStudioID);
|
setStudioId(updateStudioID);
|
||||||
if (performerMode === GQL.BulkUpdateIdMode.Set) {
|
setExistingPerformerIds(updatePerformerIds);
|
||||||
setPerformerIds(updatePerformerIds);
|
setExistingTagIds(updateTagIds);
|
||||||
}
|
|
||||||
|
|
||||||
if (tagMode === GQL.BulkUpdateIdMode.Set) {
|
|
||||||
setTagIds(updateTagIds);
|
|
||||||
}
|
|
||||||
setOrganized(updateOrganized);
|
setOrganized(updateOrganized);
|
||||||
}, [props.selected, performerMode, tagMode]);
|
}, [props.selected, performerMode, tagMode]);
|
||||||
|
|
||||||
@@ -292,12 +289,15 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
ids: string[] | undefined
|
ids: string[] | undefined
|
||||||
) {
|
) {
|
||||||
let mode = GQL.BulkUpdateIdMode.Add;
|
let mode = GQL.BulkUpdateIdMode.Add;
|
||||||
|
let existingIds: string[] | undefined = [];
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
mode = performerMode;
|
mode = performerMode;
|
||||||
|
existingIds = existingPerformerIds;
|
||||||
break;
|
break;
|
||||||
case "tags":
|
case "tags":
|
||||||
mode = tagMode;
|
mode = tagMode;
|
||||||
|
existingIds = existingTagIds;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,8 +305,7 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
<MultiSet
|
<MultiSet
|
||||||
type={type}
|
type={type}
|
||||||
disabled={isUpdating}
|
disabled={isUpdating}
|
||||||
onUpdate={(items) => {
|
onUpdate={(itemIDs) => {
|
||||||
const itemIDs = items.map((i) => i.id);
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "performers":
|
case "performers":
|
||||||
setPerformerIds(itemIDs);
|
setPerformerIds(itemIDs);
|
||||||
@@ -327,6 +326,7 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
ids={ids ?? []}
|
ids={ids ?? []}
|
||||||
|
existingIds={existingIds ?? []}
|
||||||
mode={mode}
|
mode={mode}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -404,7 +404,7 @@ export const EditScenesDialog: React.FC<IListOperationProps> = (
|
|||||||
|
|
||||||
<Form.Group controlId="tags">
|
<Form.Group controlId="tags">
|
||||||
<Form.Label>
|
<Form.Label>
|
||||||
<FormattedMessage id="performers" />
|
<FormattedMessage id="tags" />
|
||||||
</Form.Label>
|
</Form.Label>
|
||||||
{renderMultiSelect("tags", tagIds)}
|
{renderMultiSelect("tags", tagIds)}
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import { TextUtils } from "src/utils";
|
|||||||
import { SceneQueue } from "src/models/sceneQueue";
|
import { SceneQueue } from "src/models/sceneQueue";
|
||||||
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
import { PerformerPopoverButton } from "../Shared/PerformerPopoverButton";
|
||||||
import { GridCard } from "../Shared/GridCard";
|
import { GridCard } from "../Shared/GridCard";
|
||||||
|
import { RatingBanner } from "../Shared/RatingBanner";
|
||||||
|
|
||||||
interface IScenePreviewProps {
|
interface IScenePreviewProps {
|
||||||
isPortrait: boolean;
|
isPortrait: boolean;
|
||||||
@@ -89,21 +90,6 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
missingStudioImage ||
|
missingStudioImage ||
|
||||||
(config?.data?.configuration.interface.showStudioAsText ?? false);
|
(config?.data?.configuration.interface.showStudioAsText ?? false);
|
||||||
|
|
||||||
function maybeRenderRatingBanner() {
|
|
||||||
if (!props.scene.rating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`rating-banner ${
|
|
||||||
props.scene.rating ? `rating-${props.scene.rating}` : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
RATING: {props.scene.rating}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function maybeRenderSceneSpecsOverlay() {
|
function maybeRenderSceneSpecsOverlay() {
|
||||||
return (
|
return (
|
||||||
<div className="scene-specs-overlay">
|
<div className="scene-specs-overlay">
|
||||||
@@ -333,7 +319,7 @@ export const SceneCard: React.FC<ISceneCardProps> = (
|
|||||||
config.data?.configuration?.interface?.soundOnPreview ?? false
|
config.data?.configuration?.interface?.soundOnPreview ?? false
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{maybeRenderRatingBanner()}
|
<RatingBanner rating={props.scene.rating} />
|
||||||
{maybeRenderSceneSpecsOverlay()}
|
{maybeRenderSceneSpecsOverlay()}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ type ValidTypes =
|
|||||||
|
|
||||||
interface IMultiSetProps {
|
interface IMultiSetProps {
|
||||||
type: "performers" | "studios" | "tags";
|
type: "performers" | "studios" | "tags";
|
||||||
|
existingIds?: string[];
|
||||||
ids?: string[];
|
ids?: string[];
|
||||||
mode: GQL.BulkUpdateIdMode;
|
mode: GQL.BulkUpdateIdMode;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
onUpdate: (items: ValidTypes[]) => void;
|
onUpdate: (ids: string[]) => void;
|
||||||
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
onSetMode: (mode: GQL.BulkUpdateIdMode) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +32,7 @@ const MultiSet: React.FunctionComponent<IMultiSetProps> = (
|
|||||||
];
|
];
|
||||||
|
|
||||||
function onUpdate(items: ValidTypes[]) {
|
function onUpdate(items: ValidTypes[]) {
|
||||||
props.onUpdate(items);
|
props.onUpdate(items.map((i) => i.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getModeText(mode: GQL.BulkUpdateIdMode) {
|
function getModeText(mode: GQL.BulkUpdateIdMode) {
|
||||||
@@ -51,13 +52,32 @@ const MultiSet: React.FunctionComponent<IMultiSetProps> = (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
function renderModeButton(mode: GQL.BulkUpdateIdMode) {
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
active={props.mode === mode}
|
active={props.mode === mode}
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => props.onSetMode(mode)}
|
onClick={() => onSetMode(mode)}
|
||||||
disabled={props.disabled}
|
disabled={props.disabled}
|
||||||
>
|
>
|
||||||
{getModeText(mode)}
|
{getModeText(mode)}
|
||||||
@@ -66,7 +86,7 @@ const MultiSet: React.FunctionComponent<IMultiSetProps> = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="multi-set">
|
||||||
<ButtonGroup className="button-group-above">
|
<ButtonGroup className="button-group-above">
|
||||||
{modes.map((m) => renderModeButton(m))}
|
{modes.map((m) => renderModeButton(m))}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|||||||
15
ui/v2.5/src/components/Shared/RatingBanner.tsx
Normal file
15
ui/v2.5/src/components/Shared/RatingBanner.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
rating?: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RatingBanner: React.FC<IProps> = ({ rating }) =>
|
||||||
|
rating ? (
|
||||||
|
<div className={`rating-banner rating-${rating}`}>
|
||||||
|
<FormattedMessage id="rating" />: {rating}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
);
|
||||||
@@ -76,11 +76,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.multi-set > div.input-group-prepend + div {
|
// z-index gets set on button groups for some reason
|
||||||
flex: 1 1;
|
.multi-set .btn-group > button.btn {
|
||||||
margin-bottom: 0;
|
z-index: auto;
|
||||||
min-width: 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.folder-list {
|
.folder-list {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { NavUtils } from "src/utils";
|
|||||||
import { GridCard } from "src/components/Shared";
|
import { GridCard } from "src/components/Shared";
|
||||||
import { ButtonGroup } from "react-bootstrap";
|
import { ButtonGroup } from "react-bootstrap";
|
||||||
import { PopoverCountButton } from "../Shared/PopoverCountButton";
|
import { PopoverCountButton } from "../Shared/PopoverCountButton";
|
||||||
|
import { RatingBanner } from "../Shared/RatingBanner";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
studio: GQL.StudioDataFragment;
|
studio: GQL.StudioDataFragment;
|
||||||
@@ -45,21 +46,6 @@ function maybeRenderChildren(studio: GQL.StudioDataFragment) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeRenderRatingBanner(studio: GQL.StudioDataFragment) {
|
|
||||||
if (!studio.rating) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`rating-banner ${
|
|
||||||
studio.rating ? `rating-${studio.rating}` : ""
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
RATING: {studio.rating}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export const StudioCard: React.FC<IProps> = ({
|
export const StudioCard: React.FC<IProps> = ({
|
||||||
studio,
|
studio,
|
||||||
hideParent,
|
hideParent,
|
||||||
@@ -135,7 +121,7 @@ export const StudioCard: React.FC<IProps> = ({
|
|||||||
<>
|
<>
|
||||||
{maybeRenderParent(studio, hideParent)}
|
{maybeRenderParent(studio, hideParent)}
|
||||||
{maybeRenderChildren(studio)}
|
{maybeRenderChildren(studio)}
|
||||||
{maybeRenderRatingBanner(studio)}
|
<RatingBanner rating={studio.rating} />
|
||||||
{maybeRenderPopoverButtonGroup()}
|
{maybeRenderPopoverButtonGroup()}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ div.dropdown-menu {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-size-adjust: none;
|
text-size-adjust: none;
|
||||||
|
text-transform: uppercase;
|
||||||
top: 14px;
|
top: 14px;
|
||||||
transform: rotate(-36deg);
|
transform: rotate(-36deg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -341,14 +341,14 @@ export abstract class IHierarchicalLabeledIdCriterion extends Criterion<IHierarc
|
|||||||
|
|
||||||
protected toCriterionInput(): HierarchicalMultiCriterionInput {
|
protected toCriterionInput(): HierarchicalMultiCriterionInput {
|
||||||
return {
|
return {
|
||||||
value: this.value.items.map((v) => v.id),
|
value: (this.value.items ?? []).map((v) => v.id),
|
||||||
modifier: this.modifier,
|
modifier: this.modifier,
|
||||||
depth: this.value.depth,
|
depth: this.value.depth,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public getLabelValue(): string {
|
public getLabelValue(): string {
|
||||||
const labels = this.value.items.map((v) => v.label).join(", ");
|
const labels = (this.value.items ?? []).map((v) => v.label).join(", ");
|
||||||
|
|
||||||
if (this.value.depth === 0) {
|
if (this.value.depth === 0) {
|
||||||
return labels;
|
return labels;
|
||||||
|
|||||||
Reference in New Issue
Block a user