Show stash-ids with their endpoint (#4216)

This commit is contained in:
WithoutPants
2023-10-18 07:56:49 +11:00
committed by GitHub
parent 21baa23fc5
commit a83dfff5ff
8 changed files with 79 additions and 87 deletions

View File

@@ -3,10 +3,10 @@ import { useIntl } from "react-intl";
import { TagLink } from "src/components/Shared/TagLink"; import { TagLink } from "src/components/Shared/TagLink";
import * as GQL from "src/core/generated-graphql"; import * as GQL from "src/core/generated-graphql";
import TextUtils from "src/utils/text"; import TextUtils from "src/utils/text";
import { getStashboxBase } from "src/utils/stashbox";
import { cmToImperial, cmToInches, kgToLbs } from "src/utils/units"; import { cmToImperial, cmToInches, kgToLbs } from "src/utils/units";
import { DetailItem } from "src/components/Shared/DetailItem"; import { DetailItem } from "src/components/Shared/DetailItem";
import { CountryFlag } from "src/components/Shared/CountryFlag"; import { CountryFlag } from "src/components/Shared/CountryFlag";
import { StashIDPill } from "src/components/Shared/StashID";
interface IPerformerDetails { interface IPerformerDetails {
performer: GQL.PerformerDataFragment; performer: GQL.PerformerDataFragment;
@@ -42,25 +42,11 @@ export const PerformerDetailsPanel: React.FC<IPerformerDetails> = ({
return ( return (
<ul className="pl-0"> <ul className="pl-0">
{performer.stash_ids.map((stashID) => { {performer.stash_ids.map((stashID) => (
const base = getStashboxBase(stashID.endpoint); <li key={stashID.stash_id} className="row no-gutters">
const link = base ? ( <StashIDPill stashID={stashID} linkType="performers" />
<a </li>
href={`${base}performers/${stashID.stash_id}`} ))}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return (
<li key={stashID.stash_id} className="row no-gutters">
{link}
</li>
);
})}
</ul> </ul>
); );
} }

View File

@@ -47,6 +47,7 @@ import {
import { StringListInput } from "src/components/Shared/StringListInput"; import { StringListInput } from "src/components/Shared/StringListInput";
import isEqual from "lodash-es/isEqual"; import isEqual from "lodash-es/isEqual";
import { DateInput } from "src/components/Shared/DateInput"; import { DateInput } from "src/components/Shared/DateInput";
import { StashIDPill } from "src/components/Shared/StashID";
const isScraper = ( const isScraper = (
scraper: GQL.Scraper | GQL.StashBox scraper: GQL.Scraper | GQL.StashBox
@@ -792,18 +793,6 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<Col sm={fieldXS} xl={fieldXL}> <Col sm={fieldXS} xl={fieldXL}>
<ul className="pl-0"> <ul className="pl-0">
{formik.values.stash_ids.map((stashID) => { {formik.values.stash_ids.map((stashID) => {
const base = stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
const link = base ? (
<a
href={`${base}performers/${stashID.stash_id}`}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return ( return (
<li key={stashID.stash_id} className="row no-gutters mb-1"> <li key={stashID.stash_id} className="row no-gutters mb-1">
<Button <Button
@@ -814,7 +803,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
> >
<Icon icon={faTrashAlt} /> <Icon icon={faTrashAlt} />
</Button> </Button>
{link} <StashIDPill stashID={stashID} linkType="performers" />
</li> </li>
); );
})} })}

View File

@@ -55,6 +55,7 @@ import {
Performer, Performer,
PerformerSelect, PerformerSelect,
} from "src/components/Performers/PerformerSelect"; } from "src/components/Performers/PerformerSelect";
import { StashIDPill } from "src/components/Shared/StashID";
const SceneScrapeDialog = lazyComponent(() => import("./SceneScrapeDialog")); const SceneScrapeDialog = lazyComponent(() => import("./SceneScrapeDialog"));
const SceneQueryModal = lazyComponent(() => import("./SceneQueryModal")); const SceneQueryModal = lazyComponent(() => import("./SceneQueryModal"));
@@ -904,19 +905,6 @@ export const SceneEditPanel: React.FC<IProps> = ({
</Form.Label> </Form.Label>
<ul className="pl-0"> <ul className="pl-0">
{formik.values.stash_ids.map((stashID) => { {formik.values.stash_ids.map((stashID) => {
const base =
stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
const link = base ? (
<a
href={`${base}scenes/${stashID.stash_id}`}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return ( return (
<li key={stashID.stash_id} className="row no-gutters"> <li key={stashID.stash_id} className="row no-gutters">
<Button <Button
@@ -934,7 +922,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
> >
<Icon icon={faTrashAlt} /> <Icon icon={faTrashAlt} />
</Button> </Button>
{link} <StashIDPill stashID={stashID} linkType="scenes" />
</li> </li>
); );
})} })}

View File

@@ -15,8 +15,8 @@ import { mutateSceneSetPrimaryFile } from "src/core/StashService";
import { useToast } from "src/hooks/Toast"; import { useToast } from "src/hooks/Toast";
import NavUtils from "src/utils/navigation"; import NavUtils from "src/utils/navigation";
import TextUtils from "src/utils/text"; import TextUtils from "src/utils/text";
import { getStashboxBase } from "src/utils/stashbox";
import { TextField, URLField, URLsField } from "src/utils/field"; import { TextField, URLField, URLsField } from "src/utils/field";
import { StashIDPill } from "src/components/Shared/StashID";
interface IFileInfoPanelProps { interface IFileInfoPanelProps {
sceneID: string; sceneID: string;
@@ -197,21 +197,9 @@ export const SceneFileInfoPanel: React.FC<ISceneFileInfoPanelProps> = (
<dd> <dd>
<dl> <dl>
{props.scene.stash_ids.map((stashID) => { {props.scene.stash_ids.map((stashID) => {
const base = getStashboxBase(stashID.endpoint);
const link = base ? (
<a
href={`${base}scenes/${stashID.stash_id}`}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return ( return (
<dd key={stashID.stash_id} className="row no-gutters"> <dd key={stashID.stash_id} className="row no-gutters">
{link} <StashIDPill stashID={stashID} linkType="scenes" />
</dd> </dd>
); );
})} })}

View File

@@ -0,0 +1,34 @@
import React, { useMemo } from "react";
import { StashId } from "src/core/generated-graphql";
import { ConfigurationContext } from "src/hooks/Config";
import { getStashboxBase } from "src/utils/stashbox";
type LinkType = "performers" | "scenes" | "studios";
export const StashIDPill: React.FC<{
stashID: StashId;
linkType: LinkType;
}> = ({ stashID, linkType }) => {
const { configuration } = React.useContext(ConfigurationContext);
const { endpoint, stash_id } = stashID;
const endpointName = useMemo(() => {
return (
configuration?.general.stashBoxes.find((sb) => sb.endpoint === endpoint)
?.name ?? endpoint
);
}, [configuration?.general.stashBoxes, endpoint]);
const base = getStashboxBase(endpoint);
const link = `${base}${linkType}/${stash_id}`;
return (
<span className="stash-id-pill" data-endpoint={endpointName}>
<span>{endpointName}</span>
<a href={link} target="_blank" rel="noopener noreferrer">
{stash_id}
</a>
</span>
);
};

View File

@@ -480,3 +480,32 @@ div.react-datepicker {
.string-list-row .input-group { .string-list-row .input-group {
flex-wrap: nowrap; flex-wrap: nowrap;
} }
.stash-id-pill {
display: inline-block;
font-size: 90%;
font-weight: 700;
line-height: 1;
padding-bottom: 0.25em;
padding-top: 0.25em;
text-align: center;
vertical-align: baseline;
white-space: nowrap;
span,
a {
display: inline-block;
padding: 0.25em 0.6em;
}
span {
background-color: $primary;
border-radius: 0.25rem 0 0 0.25rem;
min-width: 5em;
}
a {
background-color: $secondary;
border-radius: 0 0.25rem 0.25rem 0;
}
}

View File

@@ -1,6 +1,7 @@
import React from "react"; import React from "react";
import * as GQL from "src/core/generated-graphql"; import * as GQL from "src/core/generated-graphql";
import { DetailItem } from "src/components/Shared/DetailItem"; import { DetailItem } from "src/components/Shared/DetailItem";
import { StashIDPill } from "src/components/Shared/StashID";
interface IStudioDetailsPanel { interface IStudioDetailsPanel {
studio: GQL.StudioDataFragment; studio: GQL.StudioDataFragment;
@@ -21,21 +22,9 @@ export const StudioDetailsPanel: React.FC<IStudioDetailsPanel> = ({
return ( return (
<ul className="pl-0"> <ul className="pl-0">
{studio.stash_ids.map((stashID) => { {studio.stash_ids.map((stashID) => {
const base = stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
const link = base ? (
<a
href={`${base}studios/${stashID.stash_id}`}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return ( return (
<li key={stashID.stash_id} className="row no-gutters"> <li key={stashID.stash_id} className="row no-gutters">
{link} <StashIDPill stashID={stashID} linkType="studios" />
</li> </li>
); );
})} })}

View File

@@ -17,6 +17,7 @@ import { faTrashAlt } from "@fortawesome/free-solid-svg-icons";
import isEqual from "lodash-es/isEqual"; import isEqual from "lodash-es/isEqual";
import { useToast } from "src/hooks/Toast"; import { useToast } from "src/hooks/Toast";
import { handleUnsavedChanges } from "src/utils/navigation"; import { handleUnsavedChanges } from "src/utils/navigation";
import { StashIDPill } from "src/components/Shared/StashID";
interface IStudioEditPanel { interface IStudioEditPanel {
studio: Partial<GQL.StudioDataFragment>; studio: Partial<GQL.StudioDataFragment>;
@@ -165,18 +166,6 @@ export const StudioEditPanel: React.FC<IStudioEditPanel> = ({
<Col xs={fieldXS} xl={fieldXL}> <Col xs={fieldXS} xl={fieldXL}>
<ul className="pl-0"> <ul className="pl-0">
{formik.values.stash_ids.map((stashID) => { {formik.values.stash_ids.map((stashID) => {
const base = stashID.endpoint.match(/https?:\/\/.*?\//)?.[0];
const link = base ? (
<a
href={`${base}studios/${stashID.stash_id}`}
target="_blank"
rel="noopener noreferrer"
>
{stashID.stash_id}
</a>
) : (
stashID.stash_id
);
return ( return (
<li key={stashID.stash_id} className="row no-gutters"> <li key={stashID.stash_id} className="row no-gutters">
<Button <Button
@@ -190,7 +179,7 @@ export const StudioEditPanel: React.FC<IStudioEditPanel> = ({
> >
<Icon icon={faTrashAlt} /> <Icon icon={faTrashAlt} />
</Button> </Button>
{link} <StashIDPill stashID={stashID} linkType="studios" />
</li> </li>
); );
})} })}