mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
Add disambiguation and links to tagger results (#4180)
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
@@ -122,7 +122,14 @@ export const PerformerSelect: React.FC<
|
||||
|
||||
thisOptionProps = {
|
||||
...optionProps,
|
||||
children: object.name,
|
||||
children: (
|
||||
<>
|
||||
{object.name}
|
||||
{object.disambiguation && (
|
||||
<span className="performer-disambiguation">{` (${object.disambiguation})`}</span>
|
||||
)}
|
||||
</>
|
||||
),
|
||||
};
|
||||
|
||||
return <reactSelectComponents.SingleValue {...thisOptionProps} />;
|
||||
|
||||
@@ -11,6 +11,41 @@ import {
|
||||
Performer,
|
||||
PerformerSelect,
|
||||
} from "src/components/Performers/PerformerSelect";
|
||||
import { getStashboxBase } from "src/utils/stashbox";
|
||||
|
||||
interface IPerformerName {
|
||||
performer: GQL.ScrapedPerformer | Performer;
|
||||
className?: string;
|
||||
baseURL: string | undefined;
|
||||
id: string | undefined | null;
|
||||
}
|
||||
|
||||
const PerformerName: React.FC<IPerformerName> = ({
|
||||
performer,
|
||||
className,
|
||||
baseURL,
|
||||
id,
|
||||
}) => {
|
||||
const name =
|
||||
baseURL && id ? (
|
||||
<a href={`${baseURL}${id}`} target="_blank" rel="noreferrer">
|
||||
{performer.name}
|
||||
</a>
|
||||
) : (
|
||||
performer.name
|
||||
);
|
||||
|
||||
return (
|
||||
<span className={className}>
|
||||
<span>{name}</span>
|
||||
{performer.disambiguation && (
|
||||
<span className="performer-disambiguation">
|
||||
{` (${performer.disambiguation})`}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
interface IPerformerResultProps {
|
||||
performer: GQL.ScrapedPerformer;
|
||||
@@ -44,6 +79,11 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
|
||||
|
||||
const [selectedPerformer, setSelectedPerformer] = useState<Performer>();
|
||||
|
||||
const stashboxPerformerPrefix = endpoint
|
||||
? `${getStashboxBase(endpoint)}performers/`
|
||||
: undefined;
|
||||
const performerURLPrefix = "/performers/";
|
||||
|
||||
function selectPerformer(selected: Performer | undefined) {
|
||||
setSelectedPerformer(selected);
|
||||
setSelectedID(selected?.id);
|
||||
@@ -77,7 +117,12 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
|
||||
<div className="row no-gutters my-2">
|
||||
<div className="entity-name">
|
||||
<FormattedMessage id="countables.performers" values={{ count: 1 }} />:
|
||||
<b className="ml-2">{performer.name}</b>
|
||||
<PerformerName
|
||||
performer={performer}
|
||||
className="ml-2"
|
||||
id={performer.remote_site_id}
|
||||
baseURL={stashboxPerformerPrefix}
|
||||
/>
|
||||
</div>
|
||||
<span className="ml-auto">
|
||||
<OptionalField
|
||||
@@ -90,7 +135,12 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
|
||||
<span className="mr-2">
|
||||
<FormattedMessage id="component_tagger.verb_matched" />:
|
||||
</span>
|
||||
<b className="col-3 text-right">{matchedPerformer.name}</b>
|
||||
<PerformerName
|
||||
performer={matchedPerformer}
|
||||
className="ml-3 text-right"
|
||||
id={matchedPerformer.id}
|
||||
baseURL={performerURLPrefix}
|
||||
/>
|
||||
</div>
|
||||
</OptionalField>
|
||||
</span>
|
||||
@@ -119,7 +169,12 @@ const PerformerResult: React.FC<IPerformerResultProps> = ({
|
||||
<div className="row no-gutters align-items-center mt-2">
|
||||
<div className="entity-name">
|
||||
<FormattedMessage id="countables.performers" values={{ count: 1 }} />:
|
||||
<b className="ml-2">{performer.name}</b>
|
||||
<PerformerName
|
||||
performer={performer}
|
||||
className="ml-2"
|
||||
id={performer.remote_site_id}
|
||||
baseURL={stashboxPerformerPrefix}
|
||||
/>
|
||||
</div>
|
||||
<ButtonGroup>
|
||||
<Button variant="secondary" onClick={() => onCreate()}>
|
||||
|
||||
@@ -23,6 +23,7 @@ import PerformerResult from "./PerformerResult";
|
||||
import StudioResult from "./StudioResult";
|
||||
import { useInitialState } from "src/hooks/state";
|
||||
import { faPlus } from "@fortawesome/free-solid-svg-icons";
|
||||
import { getStashboxBase } from "src/utils/stashbox";
|
||||
|
||||
const getDurationStatus = (
|
||||
scene: IScrapedScene,
|
||||
@@ -301,13 +302,14 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
||||
}
|
||||
}, [isActive, loading, stashScene, index, resolveScene, scene]);
|
||||
|
||||
const stashBoxBaseURL = currentSource?.stashboxEndpoint
|
||||
? getStashboxBase(currentSource.stashboxEndpoint)
|
||||
: undefined;
|
||||
const stashBoxURL = useMemo(() => {
|
||||
if (currentSource?.stashboxEndpoint && scene.remote_site_id) {
|
||||
const endpoint = currentSource.stashboxEndpoint;
|
||||
const endpointBase = endpoint.match(/https?:\/\/.*?\//)?.[0];
|
||||
return `${endpointBase}scenes/${scene.remote_site_id}`;
|
||||
if (stashBoxBaseURL) {
|
||||
return `${stashBoxBaseURL}scenes/${scene.remote_site_id}`;
|
||||
}
|
||||
}, [currentSource, scene]);
|
||||
}, [scene, stashBoxBaseURL]);
|
||||
|
||||
const setExcludedField = (name: string, value: boolean) =>
|
||||
setExcludedFields({
|
||||
|
||||
@@ -10,6 +10,7 @@ import * as GQL from "src/core/generated-graphql";
|
||||
|
||||
import { OptionalField } from "../IncludeButton";
|
||||
import { faSave } from "@fortawesome/free-solid-svg-icons";
|
||||
import { getStashboxBase } from "src/utils/stashbox";
|
||||
|
||||
interface IStudioResultProps {
|
||||
studio: GQL.ScrapedStudio;
|
||||
@@ -38,6 +39,11 @@ const StudioResult: React.FC<IStudioResultProps> = ({
|
||||
(stashID) => stashID.endpoint === endpoint && stashID.stash_id
|
||||
);
|
||||
|
||||
const stashboxStudioPrefix = endpoint
|
||||
? `${getStashboxBase(endpoint)}studios/`
|
||||
: undefined;
|
||||
const studioURLPrefix = "/studios/";
|
||||
|
||||
const handleSelect = (studios: SelectObject[]) => {
|
||||
if (studios.length) {
|
||||
setSelectedID(studios[0].id);
|
||||
@@ -52,12 +58,36 @@ const StudioResult: React.FC<IStudioResultProps> = ({
|
||||
|
||||
if (stashLoading) return <div>Loading studio</div>;
|
||||
|
||||
const StudioName = ({
|
||||
name,
|
||||
baseURL,
|
||||
id,
|
||||
}: {
|
||||
name: string;
|
||||
baseURL: string | undefined;
|
||||
id: string | undefined | null;
|
||||
}) => {
|
||||
return baseURL && id ? (
|
||||
<a href={`${baseURL}${id}`} target="_blank" rel="noreferrer">
|
||||
{name}
|
||||
</a>
|
||||
) : (
|
||||
<span>name</span>
|
||||
);
|
||||
};
|
||||
|
||||
if (matchedStudio && matchedStashID) {
|
||||
return (
|
||||
<div className="row no-gutters my-2">
|
||||
<div className="entity-name">
|
||||
<FormattedMessage id="countables.studios" values={{ count: 1 }} />:
|
||||
<b className="ml-2">{studio.name}</b>
|
||||
<b className="ml-2">
|
||||
<StudioName
|
||||
name={studio.name}
|
||||
baseURL={stashboxStudioPrefix}
|
||||
id={studio.remote_site_id}
|
||||
/>
|
||||
</b>
|
||||
</div>
|
||||
<span className="ml-auto">
|
||||
<OptionalField
|
||||
@@ -70,7 +100,13 @@ const StudioResult: React.FC<IStudioResultProps> = ({
|
||||
<span className="mr-2">
|
||||
<FormattedMessage id="component_tagger.verb_matched" />:
|
||||
</span>
|
||||
<b className="col-3 text-right">{matchedStudio.name}</b>
|
||||
<b className="col-3 text-right">
|
||||
<StudioName
|
||||
name={matchedStudio.name}
|
||||
baseURL={studioURLPrefix}
|
||||
id={matchedStudio.id}
|
||||
/>
|
||||
</b>
|
||||
</div>
|
||||
</OptionalField>
|
||||
</span>
|
||||
@@ -99,7 +135,13 @@ const StudioResult: React.FC<IStudioResultProps> = ({
|
||||
<div className="row no-gutters align-items-center mt-2">
|
||||
<div className="entity-name">
|
||||
<FormattedMessage id="countables.studios" values={{ count: 1 }} />:
|
||||
<b className="ml-2">{studio.name}</b>
|
||||
<b className="ml-2">
|
||||
<StudioName
|
||||
name={studio.name}
|
||||
baseURL={stashboxStudioPrefix}
|
||||
id={studio.remote_site_id}
|
||||
/>
|
||||
</b>
|
||||
</div>
|
||||
<ButtonGroup>
|
||||
<Button variant="secondary" onClick={() => onCreate()}>
|
||||
|
||||
Reference in New Issue
Block a user