Skip to content

Commit

Permalink
Fix tag selector in scrape dialogs (#4526)
Browse files Browse the repository at this point in the history
  • Loading branch information
WithoutPants authored Feb 5, 2024
1 parent 3ea31ae commit 217c02f
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ export const GalleryEditPanel: React.FC<IProps> = ({
return (
<GalleryScrapeDialog
gallery={currentGallery}
galleryTags={tags}
galleryPerformers={performers}
scraped={scrapedGallery}
onClose={(data) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
ScrapedStringListRow,
ScrapedTextAreaRow,
} from "src/components/Shared/ScrapeDialog/ScrapeDialog";
import clone from "lodash-es/clone";
import {
ObjectListScrapeResult,
ScrapeResult,
Expand All @@ -25,21 +24,20 @@ import {
useCreateScrapedTag,
} from "src/components/Shared/ScrapeDialog/createObjects";
import { uniq } from "lodash-es";
import { Tag } from "src/components/Tags/TagSelect";

interface IGalleryScrapeDialogProps {
gallery: Partial<GQL.GalleryUpdateInput>;
galleryTags: Tag[];
galleryPerformers: Performer[];
scraped: GQL.ScrapedGallery;

onClose: (scrapedGallery?: GQL.ScrapedGallery) => void;
}

interface IHasStoredID {
stored_id?: string | null;
}

export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
gallery,
galleryTags,
galleryPerformers,
scraped,
onClose,
Expand Down Expand Up @@ -72,44 +70,6 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
scraped.studio && !scraped.studio.stored_id ? scraped.studio : undefined
);

function mapStoredIdObjects(
scrapedObjects?: IHasStoredID[]
): string[] | undefined {
if (!scrapedObjects) {
return undefined;
}
const ret = scrapedObjects
.map((p) => p.stored_id)
.filter((p) => {
return p !== undefined && p !== null;
}) as string[];

if (ret.length === 0) {
return undefined;
}

// sort by id numerically
ret.sort((a, b) => {
return parseInt(a, 10) - parseInt(b, 10);
});

return ret;
}

function sortIdList(idList?: string[] | null) {
if (!idList) {
return;
}

const ret = clone(idList);
// sort by id numerically
ret.sort((a, b) => {
return parseInt(a, 10) - parseInt(b, 10);
});

return ret;
}

const [performers, setPerformers] = useState<
ObjectListScrapeResult<GQL.ScrapedPerformer>
>(
Expand All @@ -127,10 +87,15 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
scraped.performers?.filter((t) => !t.stored_id) ?? []
);

const [tags, setTags] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(
sortIdList(gallery.tag_ids),
mapStoredIdObjects(scraped.tags ?? undefined)
const [tags, setTags] = useState<ObjectListScrapeResult<GQL.ScrapedTag>>(
new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(
galleryTags.map((t) => ({
stored_id: t.id,
name: t.name,
}))
),
sortStoredIdObjects(scraped.tags ?? undefined)
)
);
const [newTags, setNewTags] = useState<GQL.ScrapedTag[]>(
Expand Down Expand Up @@ -198,12 +163,7 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
}
: undefined,
performers: performers.getNewValue(),
tags: tags.getNewValue()?.map((m) => {
return {
stored_id: m,
name: "",
};
}),
tags: tags.getNewValue(),
details: details.getNewValue(),
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ export const SceneEditPanel: React.FC<IProps> = ({
return (
<SceneScrapeDialog
scene={currentScene}
sceneTags={tags}
scenePerformers={performers}
scraped={scrapedScene}
endpoint={endpoint}
Expand Down
23 changes: 13 additions & 10 deletions ui/v2.5/src/components/Scenes/SceneDetails/SceneScrapeDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ import {
useCreateScrapedStudio,
useCreateScrapedTag,
} from "src/components/Shared/ScrapeDialog/createObjects";
import { Tag } from "src/components/Tags/TagSelect";

interface ISceneScrapeDialogProps {
scene: Partial<GQL.SceneUpdateInput>;
scenePerformers: Performer[];
sceneTags: Tag[];
scraped: GQL.ScrapedScene;
endpoint?: string;

Expand All @@ -41,6 +43,7 @@ interface ISceneScrapeDialogProps {
export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
scene,
scenePerformers,
sceneTags,
scraped,
onClose,
endpoint,
Expand Down Expand Up @@ -146,10 +149,15 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
scraped.movies?.filter((t) => !t.stored_id) ?? []
);

const [tags, setTags] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(
sortIdList(scene.tag_ids),
mapStoredIdObjects(scraped.tags ?? undefined)
const [tags, setTags] = useState<ObjectListScrapeResult<GQL.ScrapedTag>>(
new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(
sceneTags.map((t) => ({
stored_id: t.id,
name: t.name,
}))
),
sortStoredIdObjects(scraped.tags ?? undefined)
)
);
const [newTags, setNewTags] = useState<GQL.ScrapedTag[]>(
Expand Down Expand Up @@ -240,12 +248,7 @@ export const SceneScrapeDialog: React.FC<ISceneScrapeDialogProps> = ({
name: "",
};
}),
tags: tags.getNewValue()?.map((m) => {
return {
stored_id: m,
name: "",
};
}),
tags: tags.getNewValue(),
details: details.getNewValue(),
image: image.getNewValue(),
remote_site_id: stashID.getNewValue(),
Expand Down
16 changes: 9 additions & 7 deletions ui/v2.5/src/components/Scenes/SceneMergeDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
};
}

function uniqIDStoredIDs(objs: IHasStoredID[]) {
function uniqIDStoredIDs<T extends IHasStoredID>(objs: T[]) {
return objs.filter((o, i) => {
return objs.findIndex((oo) => oo.stored_id === o.stored_id) === i;
});
Expand All @@ -130,8 +130,10 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
new ScrapeResult<string[]>(sortIdList(dest.movies.map((p) => p.movie.id)))
);

const [tags, setTags] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(sortIdList(dest.tags.map((t) => t.id)))
const [tags, setTags] = useState<ObjectListScrapeResult<GQL.ScrapedTag>>(
new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(dest.tags.map(idToStoredID))
)
);

const [details, setDetails] = useState<ScrapeResult<string>>(
Expand Down Expand Up @@ -210,9 +212,9 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
)
);
setTags(
new ScrapeResult(
dest.tags.map((p) => p.id),
uniq(all.map((s) => s.tags.map((p) => p.id)).flat())
new ObjectListScrapeResult<GQL.ScrapedTag>(
sortStoredIdObjects(dest.tags.map(idToStoredID)),
uniqIDStoredIDs(all.map((s) => s.tags.map(idToStoredID)).flat())
)
);
setDetails(
Expand Down Expand Up @@ -592,7 +594,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
scene_index: found!.scene_index,
};
}),
tag_ids: tags.getNewValue(),
tag_ids: tags.getNewValue()?.map((t) => t.stored_id!),
details: details.getNewValue(),
organized: organized.getNewValue(),
stash_ids: stashIDs.getNewValue(),
Expand Down
31 changes: 19 additions & 12 deletions ui/v2.5/src/components/Shared/ScrapeDialog/ScrapedObjectsRow.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import React, { useMemo } from "react";
import * as GQL from "src/core/generated-graphql";
import {
MovieSelect,
TagSelect,
StudioSelect,
} from "src/components/Shared/Select";
import { MovieSelect, StudioSelect } from "src/components/Shared/Select";
import {
ScrapeDialogRow,
IHasName,
} from "src/components/Shared/ScrapeDialog/ScrapeDialog";
import { PerformerSelect } from "src/components/Performers/PerformerSelect";
import { ScrapeResult } from "src/components/Shared/ScrapeDialog/scrapeResult";
import { TagSelect } from "src/components/Tags/TagSelect";

interface IScrapedStudioRow {
title: string;
Expand Down Expand Up @@ -230,35 +227,45 @@ export const ScrapedMoviesRow: React.FC<
};

export const ScrapedTagsRow: React.FC<
IScrapedObjectRowImpl<GQL.ScrapedTag, string>
IScrapedObjectRowImpl<GQL.ScrapedTag, GQL.ScrapedTag>
> = ({ title, result, onChange, newObjects, onCreateNew }) => {
function renderScrapedTags(
scrapeResult: ScrapeResult<string[]>,
scrapeResult: ScrapeResult<GQL.ScrapedTag[]>,
isNew?: boolean,
onChangeFn?: (value: string[]) => void
onChangeFn?: (value: GQL.ScrapedTag[]) => void
) {
const resultValue = isNew
? scrapeResult.newValue
: scrapeResult.originalValue;
const value = resultValue ?? [];

const selectValue = value.map((p) => {
const aliases: string[] = [];
return {
id: p.stored_id ?? "",
name: p.name ?? "",
aliases,
};
});

return (
<TagSelect
isMulti
className="form-control react-select"
className="form-control"
isDisabled={!isNew}
onSelect={(items) => {
if (onChangeFn) {
onChangeFn(items.map((i) => i.id));
// map the id back to stored_id
onChangeFn(items.map((p) => ({ ...p, stored_id: p.id })));
}
}}
ids={value}
values={selectValue}
/>
);
}

return (
<ScrapedObjectsRow<GQL.ScrapedTag, string>
<ScrapedObjectsRow<GQL.ScrapedTag, GQL.ScrapedTag>
title={title}
result={result}
renderObjects={renderScrapedTags}
Expand Down
47 changes: 34 additions & 13 deletions ui/v2.5/src/components/Shared/ScrapeDialog/createObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,16 @@ export function useCreateScrapedStudio(props: IUseCreateNewStudioProps) {
return useCreateObject("studio", createNewStudio);
}

interface IUseCreateNewPerformerProps {
scrapeResult: ScrapeResult<GQL.ScrapedPerformer[]>;
setScrapeResult: (scrapeResult: ScrapeResult<GQL.ScrapedPerformer[]>) => void;
newObjects: GQL.ScrapedPerformer[];
setNewObjects: (newObject: GQL.ScrapedPerformer[]) => void;
interface IUseCreateNewObjectProps<T> {
scrapeResult: ScrapeResult<T[]>;
setScrapeResult: (scrapeResult: ScrapeResult<T[]>) => void;
newObjects: T[];
setNewObjects: (newObject: T[]) => void;
}

export function useCreateScrapedPerformer(props: IUseCreateNewPerformerProps) {
export function useCreateScrapedPerformer(
props: IUseCreateNewObjectProps<GQL.ScrapedPerformer>
) {
const [createPerformer] = usePerformerCreate();

const { scrapeResult, setScrapeResult, newObjects, setNewObjects } = props;
Expand Down Expand Up @@ -173,20 +175,39 @@ export function useCreateScrapedMovie(
}

export function useCreateScrapedTag(
props: IUseCreateNewObjectIDListProps<GQL.ScrapedTag>
props: IUseCreateNewObjectProps<GQL.ScrapedTag>
) {
const [createTag] = useTagCreate();

const { scrapeResult, setScrapeResult, newObjects, setNewObjects } = props;

async function createNewTag(toCreate: GQL.ScrapedTag) {
const tagInput: GQL.TagCreateInput = { name: toCreate.name ?? "" };
const input: GQL.TagCreateInput = { name: toCreate.name ?? "" };

const result = await createTag({
variables: {
input: tagInput,
},
variables: { input },
});

return result.data?.tagCreate?.id ?? "";
const newValue = [...(scrapeResult.newValue ?? [])];
if (result.data?.tagCreate)
newValue.push({
stored_id: result.data.tagCreate.id,
name: result.data.tagCreate.name,
});

// add the new tag to the new tags value
const tagClone = scrapeResult.cloneWithValue(newValue);
setScrapeResult(tagClone);

// remove the tag from the list
const newTagsClone = newObjects.concat();
const pIndex = newTagsClone.findIndex((p) => p.name === toCreate.name);
if (pIndex === -1) throw new Error("Could not find tag to remove");

newTagsClone.splice(pIndex, 1);

setNewObjects(newTagsClone);
}

return useCreateNewObjectIDList("tag", props, createNewTag);
return useCreateObject("tag", createNewTag);
}
6 changes: 3 additions & 3 deletions ui/v2.5/src/utils/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ export interface IHasStoredID {
stored_id?: string | null;
}

export function sortStoredIdObjects(
scrapedObjects?: IHasStoredID[]
): IHasStoredID[] | undefined {
export function sortStoredIdObjects<T extends IHasStoredID>(
scrapedObjects?: T[]
): T[] | undefined {
if (!scrapedObjects) {
return undefined;
}
Expand Down

0 comments on commit 217c02f

Please sign in to comment.