Set stash id during performer scrape (#1608)

This commit is contained in:
WithoutPants
2021-08-04 09:33:21 +10:00
committed by GitHub
parent 7287ad3a05
commit f52bfae8ac
7 changed files with 69 additions and 8 deletions

View File

@@ -23,6 +23,7 @@ fragment ScrapedPerformerData on ScrapedPerformer {
death_date death_date
hair_color hair_color
weight weight
remote_site_id
} }
fragment ScrapedScenePerformerData on ScrapedScenePerformer { fragment ScrapedScenePerformerData on ScrapedScenePerformer {

View File

@@ -25,6 +25,7 @@ type ScrapedPerformer {
death_date: String death_date: String
hair_color: String hair_color: String
weight: String weight: String
remote_site_id: String
} }
input ScrapedPerformerInput { input ScrapedPerformerInput {
@@ -51,4 +52,5 @@ input ScrapedPerformerInput {
death_date: String death_date: String
hair_color: String hair_color: String
weight: String weight: String
remote_site_id: String
} }

View File

@@ -46,6 +46,7 @@ type ScrapedPerformer struct {
DeathDate *string `graphql:"death_date" json:"death_date"` DeathDate *string `graphql:"death_date" json:"death_date"`
HairColor *string `graphql:"hair_color" json:"hair_color"` HairColor *string `graphql:"hair_color" json:"hair_color"`
Weight *string `graphql:"weight" json:"weight"` Weight *string `graphql:"weight" json:"weight"`
RemoteSiteID *string `graphql:"remote_site_id" json:"remote_site_id"`
} }
// this type has no Image field // this type has no Image field

View File

@@ -7,6 +7,7 @@
* Added de-DE language option. ([#1578](https://github.com/stashapp/stash/pull/1578)) * Added de-DE language option. ([#1578](https://github.com/stashapp/stash/pull/1578))
### 🐛 Bug fixes ### 🐛 Bug fixes
* Include stash id when scraping performer from stash-box. ([#1608](https://github.com/stashapp/stash/pull/1608))
* Fix infinity framerate values causing resolver error. ([#1607](https://github.com/stashapp/stash/pull/1607)) * Fix infinity framerate values causing resolver error. ([#1607](https://github.com/stashapp/stash/pull/1607))
* Fix unsetting performer gender not working correctly. ([#1606](https://github.com/stashapp/stash/pull/1606)) * Fix unsetting performer gender not working correctly. ([#1606](https://github.com/stashapp/stash/pull/1606))
* Fix is missing date scene criterion causing invalid SQL. ([#1577](https://github.com/stashapp/stash/pull/1577)) * Fix is missing date scene criterion causing invalid SQL. ([#1577](https://github.com/stashapp/stash/pull/1577))

View File

@@ -74,6 +74,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
// Editing state // Editing state
const [scraper, setScraper] = useState<GQL.Scraper | IStashBox | undefined>(); const [scraper, setScraper] = useState<GQL.Scraper | IStashBox | undefined>();
const [newTags, setNewTags] = useState<GQL.ScrapedSceneTag[]>(); const [newTags, setNewTags] = useState<GQL.ScrapedSceneTag[]>();
const [isScraperModalOpen, setIsScraperModalOpen] = useState<boolean>(false);
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false); const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
// Network state // Network state
@@ -351,6 +352,19 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
if (state.weight) { if (state.weight) {
formik.setFieldValue("weight", state.weight); formik.setFieldValue("weight", state.weight);
} }
const remoteSiteID = state.remote_site_id;
if (remoteSiteID && (scraper as IStashBox).endpoint) {
const newIDs =
formik.values.stash_ids?.filter(
(s) => s.endpoint !== (scraper as IStashBox).endpoint
) ?? [];
newIDs?.push({
endpoint: (scraper as IStashBox).endpoint,
stash_id: remoteSiteID,
});
formik.setFieldValue("stash_ids", newIDs);
}
} }
function onImageLoad(imageData: string) { function onImageLoad(imageData: string) {
@@ -507,7 +521,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
selectedPerformer: GQL.ScrapedPerformerDataFragment, selectedPerformer: GQL.ScrapedPerformerDataFragment,
selectedScraper: GQL.Scraper selectedScraper: GQL.Scraper
) { ) {
setScraper(undefined); setIsScraperModalOpen(false);
try { try {
if (!scraper) return; if (!scraper) return;
setIsLoading(true); setIsLoading(true);
@@ -525,6 +539,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
// if this is a new performer, just dump the data // if this is a new performer, just dump the data
if (isNew) { if (isNew) {
updatePerformerEditStateFromScraper(result.data.scrapePerformer); updatePerformerEditStateFromScraper(result.data.scrapePerformer);
setScraper(undefined);
} else { } else {
setScrapedPerformer(result.data.scrapePerformer); setScrapedPerformer(result.data.scrapePerformer);
} }
@@ -559,7 +574,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
} }
async function onScrapeStashBox(performerResult: GQL.ScrapedScenePerformer) { async function onScrapeStashBox(performerResult: GQL.ScrapedScenePerformer) {
setScraper(undefined); setIsScraperModalOpen(false);
const result: Partial<GQL.ScrapedPerformerDataFragment> = { const result: Partial<GQL.ScrapedPerformerDataFragment> = {
...performerResult, ...performerResult,
@@ -571,11 +586,17 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
// if this is a new performer, just dump the data // if this is a new performer, just dump the data
if (isNew) { if (isNew) {
updatePerformerEditStateFromScraper(result); updatePerformerEditStateFromScraper(result);
setScraper(undefined);
} else { } else {
setScrapedPerformer(result); setScrapedPerformer(result);
} }
} }
function onScraperSelected(s: GQL.Scraper | IStashBox | undefined) {
setScraper(s);
setIsScraperModalOpen(true);
}
function renderScraperMenu() { function renderScraperMenu() {
if (!performer) { if (!performer) {
return; return;
@@ -590,7 +611,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<div key={s.endpoint}> <div key={s.endpoint}>
<Button <Button
className="minimal" className="minimal"
onClick={() => setScraper({ ...s, index })} onClick={() => onScraperSelected({ ...s, index })}
> >
{s.name ?? "Stash-Box"} {s.name ?? "Stash-Box"}
</Button> </Button>
@@ -602,7 +623,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<Button <Button
key={s.name} key={s.name}
className="minimal" className="minimal"
onClick={() => setScraper(s)} onClick={() => onScraperSelected(s)}
> >
{s.name} {s.name}
</Button> </Button>
@@ -648,7 +669,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
} }
function maybeRenderScrapeDialog() { function maybeRenderScrapeDialog() {
if (!scrapedPerformer) { if (!scrapedPerformer || !scraper) {
return; return;
} }
@@ -663,6 +684,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<PerformerScrapeDialog <PerformerScrapeDialog
performer={currentPerformer} performer={currentPerformer}
scraped={scrapedPerformer} scraped={scrapedPerformer}
scraper={scraper}
onClose={(p) => { onClose={(p) => {
onScrapeDialogClosed(p); onScrapeDialogClosed(p);
}} }}
@@ -675,6 +697,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
updatePerformerEditStateFromScraper(p); updatePerformerEditStateFromScraper(p);
} }
setScrapedPerformer(undefined); setScrapedPerformer(undefined);
setScraper(undefined);
} }
function maybeRenderScrapeButton() { function maybeRenderScrapeButton() {
@@ -731,8 +754,10 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
); );
} }
const renderScrapeModal = () => const renderScrapeModal = () => {
scraper !== undefined && isScraper(scraper) ? ( if (!isScraperModalOpen) return;
return scraper !== undefined && isScraper(scraper) ? (
<PerformerScrapeModal <PerformerScrapeModal
scraper={scraper} scraper={scraper}
onHide={() => setScraper(undefined)} onHide={() => setScraper(undefined)}
@@ -747,6 +772,7 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
name={formik.values.name || ""} name={formik.values.name || ""}
/> />
) : undefined; ) : undefined;
};
function renderDeleteAlert() { function renderDeleteAlert() {
return ( return (

View File

@@ -19,6 +19,7 @@ import {
genderToString, genderToString,
stringToGender, stringToGender,
} from "src/utils/gender"; } from "src/utils/gender";
import { IStashBox } from "./PerformerStashBoxModal";
function renderScrapedGender( function renderScrapedGender(
result: ScrapeResult<string>, result: ScrapeResult<string>,
@@ -119,6 +120,7 @@ function renderScrapedTagsRow(
interface IPerformerScrapeDialogProps { interface IPerformerScrapeDialogProps {
performer: Partial<GQL.PerformerUpdateInput>; performer: Partial<GQL.PerformerUpdateInput>;
scraped: GQL.ScrapedPerformer; scraped: GQL.ScrapedPerformer;
scraper?: GQL.Scraper | IStashBox;
onClose: (scrapedPerformer?: GQL.ScrapedPerformer) => void; onClose: (scrapedPerformer?: GQL.ScrapedPerformer) => void;
} }
@@ -128,6 +130,17 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
) => { ) => {
const intl = useIntl(); const intl = useIntl();
const endpoint = (props.scraper as IStashBox).endpoint ?? undefined;
function getCurrentRemoteSiteID() {
if (!endpoint) {
return;
}
return props.performer.stash_ids?.find((s) => s.endpoint === endpoint)
?.stash_id;
}
function translateScrapedGender(scrapedGender?: string | null) { function translateScrapedGender(scrapedGender?: string | null) {
if (!scrapedGender) { if (!scrapedGender) {
return; return;
@@ -227,6 +240,12 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
const [details, setDetails] = useState<ScrapeResult<string>>( const [details, setDetails] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.performer.details, props.scraped.details) new ScrapeResult<string>(props.performer.details, props.scraped.details)
); );
const [remoteSiteID, setRemoteSiteID] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(
getCurrentRemoteSiteID(),
props.scraped.remote_site_id
)
);
const [createTag] = useTagCreate(); const [createTag] = useTagCreate();
const Toast = useToast(); const Toast = useToast();
@@ -311,6 +330,7 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
deathDate, deathDate,
hairColor, hairColor,
weight, weight,
remoteSiteID,
]; ];
// don't show the dialog if nothing was scraped // don't show the dialog if nothing was scraped
if (allFields.every((r) => !r.scraped)) { if (allFields.every((r) => !r.scraped)) {
@@ -383,6 +403,7 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
death_date: deathDate.getNewValue(), death_date: deathDate.getNewValue(),
hair_color: hairColor.getNewValue(), hair_color: hairColor.getNewValue(),
weight: weight.getNewValue(), weight: weight.getNewValue(),
remote_site_id: remoteSiteID.getNewValue(),
}; };
} }
@@ -502,6 +523,12 @@ export const PerformerScrapeDialog: React.FC<IPerformerScrapeDialogProps> = (
result={image} result={image}
onChange={(value) => setImage(value)} onChange={(value) => setImage(value)}
/> />
<ScrapedInputGroupRow
title={intl.formatMessage({ id: "stash_id" })}
result={remoteSiteID}
locked
onChange={(value) => setRemoteSiteID(value)}
/>
</> </>
); );
} }

View File

@@ -175,6 +175,7 @@ export const ScrapeDialogRow = <T, V extends IHasName>(
interface IScrapedInputGroupProps { interface IScrapedInputGroupProps {
isNew?: boolean; isNew?: boolean;
placeholder?: string; placeholder?: string;
locked?: boolean;
result: ScrapeResult<string>; result: ScrapeResult<string>;
onChange?: (value: string) => void; onChange?: (value: string) => void;
} }
@@ -184,7 +185,7 @@ const ScrapedInputGroup: React.FC<IScrapedInputGroupProps> = (props) => {
<FormControl <FormControl
placeholder={props.placeholder} placeholder={props.placeholder}
value={props.isNew ? props.result.newValue : props.result.originalValue} value={props.isNew ? props.result.newValue : props.result.originalValue}
readOnly={!props.isNew} readOnly={!props.isNew || props.locked}
onChange={(e) => { onChange={(e) => {
if (props.isNew && props.onChange) { if (props.isNew && props.onChange) {
props.onChange(e.target.value); props.onChange(e.target.value);
@@ -199,6 +200,7 @@ interface IScrapedInputGroupRowProps {
title: string; title: string;
placeholder?: string; placeholder?: string;
result: ScrapeResult<string>; result: ScrapeResult<string>;
locked?: boolean;
onChange: (value: ScrapeResult<string>) => void; onChange: (value: ScrapeResult<string>) => void;
} }
@@ -220,6 +222,7 @@ export const ScrapedInputGroupRow: React.FC<IScrapedInputGroupRowProps> = (
placeholder={props.placeholder || props.title} placeholder={props.placeholder || props.title}
result={props.result} result={props.result}
isNew isNew
locked={props.locked}
onChange={(value) => onChange={(value) =>
props.onChange(props.result.cloneWithValue(value)) props.onChange(props.result.cloneWithValue(value))
} }