Skip to content

Commit

Permalink
Studio select refactor (#4493)
Browse files Browse the repository at this point in the history
* Add id interface to findStudios
* Replace existing selects
* Remove unused code
* Fix scrape/merge select
* Make clearable
  • Loading branch information
WithoutPants authored Feb 6, 2024
1 parent 217c02f commit de2b28d
Show file tree
Hide file tree
Showing 19 changed files with 494 additions and 239 deletions.
13 changes: 13 additions & 0 deletions graphql/documents/data/studio.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,16 @@ fragment StudioData on Studio {
rating100
aliases
}

fragment SelectStudioData on Studio {
id
name
aliases
details
image_path

parent_studio {
id
name
}
}
8 changes: 0 additions & 8 deletions graphql/documents/queries/misc.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,6 @@ query MarkerStrings($q: String, $sort: String) {
}
}

query AllStudiosForFilter {
allStudios {
id
name
aliases
}
}

query AllMoviesForFilter {
allMovies {
id
Expand Down
13 changes: 13 additions & 0 deletions graphql/documents/queries/studio.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,16 @@ query FindStudio($id: ID!) {
...StudioData
}
}

query FindStudiosForSelect(
$filter: FindFilterType
$studio_filter: StudioFilterType
$ids: [ID!]
) {
findStudios(filter: $filter, studio_filter: $studio_filter, ids: $ids) {
count
studios {
...SelectStudioData
}
}
}
3 changes: 2 additions & 1 deletion graphql/schema/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type Query {
findStudios(
studio_filter: StudioFilterType
filter: FindFilterType
ids: [ID!]
): FindStudiosResultType!

"Find a movie by ID"
Expand Down Expand Up @@ -202,11 +203,11 @@ type Query {
allSceneMarkers: [SceneMarker!]!
allImages: [Image!]!
allGalleries: [Gallery!]!
allStudios: [Studio!]!
allMovies: [Movie!]!

allPerformers: [Performer!]! @deprecated(reason: "Use findPerformers instead")
allTags: [Tag!]! @deprecated(reason: "Use findTags instead")
allStudios: [Studio!]! @deprecated(reason: "Use findStudios instead")

# Get everything with minimal metadata

Expand Down
19 changes: 17 additions & 2 deletions internal/api/resolver_query_find_studio.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"

"github.com/stashapp/stash/pkg/models"
"github.com/stashapp/stash/pkg/sliceutil/stringslice"
)

func (r *queryResolver) FindStudio(ctx context.Context, id string) (ret *models.Studio, err error) {
Expand All @@ -24,9 +25,23 @@ func (r *queryResolver) FindStudio(ctx context.Context, id string) (ret *models.
return ret, nil
}

func (r *queryResolver) FindStudios(ctx context.Context, studioFilter *models.StudioFilterType, filter *models.FindFilterType) (ret *FindStudiosResultType, err error) {
func (r *queryResolver) FindStudios(ctx context.Context, studioFilter *models.StudioFilterType, filter *models.FindFilterType, ids []string) (ret *FindStudiosResultType, err error) {
idInts, err := stringslice.StringSliceToIntSlice(ids)
if err != nil {
return nil, err
}

if err := r.withReadTxn(ctx, func(ctx context.Context) error {
studios, total, err := r.repository.Studio.Query(ctx, studioFilter, filter)
var studios []*models.Studio
var err error
var total int

if len(idInts) > 0 {
studios, err = r.repository.Studio.FindMany(ctx, idInts)
total = len(studios)
} else {
studios, total, err = r.repository.Studio.Query(ctx, studioFilter, filter)
}
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
useListGalleryScrapers,
mutateReloadScrapers,
} from "src/core/StashService";
import { SceneSelect, StudioSelect } from "src/components/Shared/Select";
import { SceneSelect } from "src/components/Shared/Select";
import { Icon } from "src/components/Shared/Icon";
import { LoadingIndicator } from "src/components/Shared/LoadingIndicator";
import { useToast } from "src/hooks/Toast";
Expand All @@ -41,6 +41,7 @@ import {
} from "src/utils/yup";
import { formikUtils } from "src/utils/form";
import { Tag, TagSelect } from "src/components/Tags/TagSelect";
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";

interface IProps {
gallery: Partial<GQL.GalleryDataFragment>;
Expand All @@ -66,6 +67,7 @@ export const GalleryEditPanel: React.FC<IProps> = ({

const [performers, setPerformers] = useState<Performer[]>([]);
const [tags, setTags] = useState<Tag[]>([]);
const [studio, setStudio] = useState<Studio | null>(null);

const isNew = gallery.id === undefined;
const { configuration: stashConfig } = React.useContext(ConfigurationContext);
Expand Down Expand Up @@ -152,6 +154,11 @@ export const GalleryEditPanel: React.FC<IProps> = ({
);
}

function onSetStudio(item: Studio | null) {
setStudio(item);
formik.setFieldValue("studio_id", item ? item.id : null);
}

useRatingKeybinds(
isVisible,
stashConfig?.ui?.ratingSystemOptions?.type,
Expand All @@ -166,6 +173,10 @@ export const GalleryEditPanel: React.FC<IProps> = ({
setTags(gallery.tags ?? []);
}, [gallery.tags]);

useEffect(() => {
setStudio(gallery.studio ?? null);
}, [gallery.studio]);

useEffect(() => {
if (isVisible) {
Mousetrap.bind("s s", () => {
Expand Down Expand Up @@ -252,6 +263,7 @@ export const GalleryEditPanel: React.FC<IProps> = ({
return (
<GalleryScrapeDialog
gallery={currentGallery}
galleryStudio={studio}
galleryTags={tags}
galleryPerformers={performers}
scraped={scrapedGallery}
Expand Down Expand Up @@ -324,7 +336,11 @@ export const GalleryEditPanel: React.FC<IProps> = ({
}

if (galleryData.studio?.stored_id) {
formik.setFieldValue("studio_id", galleryData.studio.stored_id);
onSetStudio({
id: galleryData.studio.stored_id,
name: galleryData.studio.name ?? "",
aliases: [],
});
}

if (galleryData.performers?.length) {
Expand Down Expand Up @@ -429,13 +445,8 @@ export const GalleryEditPanel: React.FC<IProps> = ({
const title = intl.formatMessage({ id: "studio" });
const control = (
<StudioSelect
onSelect={(items) =>
formik.setFieldValue(
"studio_id",
items.length > 0 ? items[0]?.id : null
)
}
ids={formik.values.studio_id ? [formik.values.studio_id] : []}
onSelect={(items) => onSetStudio(items.length > 0 ? items[0] : null)}
values={studio ? [studio] : []}
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ import {
} from "src/components/Shared/ScrapeDialog/createObjects";
import { uniq } from "lodash-es";
import { Tag } from "src/components/Tags/TagSelect";
import { Studio } from "src/components/Studios/StudioSelect";

interface IGalleryScrapeDialogProps {
gallery: Partial<GQL.GalleryUpdateInput>;
galleryStudio: Studio | null;
galleryTags: Tag[];
galleryPerformers: Performer[];
scraped: GQL.ScrapedGallery;
Expand All @@ -37,6 +39,7 @@ interface IGalleryScrapeDialogProps {

export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
gallery,
galleryStudio,
galleryTags,
galleryPerformers,
scraped,
Expand All @@ -63,8 +66,16 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
const [photographer, setPhotographer] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(gallery.photographer, scraped.photographer)
);
const [studio, setStudio] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(gallery.studio_id, scraped.studio?.stored_id)
const [studio, setStudio] = useState<ScrapeResult<GQL.ScrapedStudio>>(
new ScrapeResult<GQL.ScrapedStudio>(
galleryStudio
? {
stored_id: galleryStudio.id,
name: galleryStudio.name,
}
: undefined,
scraped.studio
)
);
const [newStudio, setNewStudio] = useState<GQL.ScrapedStudio | undefined>(
scraped.studio && !scraped.studio.stored_id ? scraped.studio : undefined
Expand Down Expand Up @@ -156,12 +167,7 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
urls: urls.getNewValue(),
date: date.getNewValue(),
photographer: photographer.getNewValue(),
studio: newStudioValue
? {
stored_id: newStudioValue,
name: "",
}
: undefined,
studio: newStudioValue,
performers: performers.getNewValue(),
tags: tags.getNewValue(),
details: details.getNewValue(),
Expand Down
21 changes: 13 additions & 8 deletions ui/v2.5/src/components/Images/ImageDetails/ImageEditPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { FormattedMessage, useIntl } from "react-intl";
import Mousetrap from "mousetrap";
import * as GQL from "src/core/generated-graphql";
import * as yup from "yup";
import { StudioSelect } from "src/components/Shared/Select";
import { LoadingIndicator } from "src/components/Shared/LoadingIndicator";
import { useToast } from "src/hooks/Toast";
import { useFormik } from "formik";
Expand All @@ -23,6 +22,7 @@ import {
} from "src/components/Performers/PerformerSelect";
import { formikUtils } from "src/utils/form";
import { Tag, TagSelect } from "src/components/Tags/TagSelect";
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";

interface IProps {
image: GQL.ImageDataFragment;
Expand All @@ -47,6 +47,7 @@ export const ImageEditPanel: React.FC<IProps> = ({

const [performers, setPerformers] = useState<Performer[]>([]);
const [tags, setTags] = useState<Tag[]>([]);
const [studio, setStudio] = useState<Studio | null>(null);

const schema = yup.object({
title: yup.string().ensure(),
Expand Down Expand Up @@ -103,6 +104,11 @@ export const ImageEditPanel: React.FC<IProps> = ({
);
}

function onSetStudio(item: Studio | null) {
setStudio(item);
formik.setFieldValue("studio_id", item ? item.id : null);
}

useRatingKeybinds(
true,
configuration?.ui?.ratingSystemOptions?.type,
Expand All @@ -117,6 +123,10 @@ export const ImageEditPanel: React.FC<IProps> = ({
setTags(image.tags ?? []);
}, [image.tags]);

useEffect(() => {
setStudio(image.studio ?? null);
}, [image.studio]);

useEffect(() => {
if (isVisible) {
Mousetrap.bind("s s", () => {
Expand Down Expand Up @@ -183,13 +193,8 @@ export const ImageEditPanel: React.FC<IProps> = ({
const title = intl.formatMessage({ id: "studio" });
const control = (
<StudioSelect
onSelect={(items) =>
formik.setFieldValue(
"studio_id",
items.length > 0 ? items[0]?.id : null
)
}
ids={formik.values.studio_id ? [formik.values.studio_id] : []}
onSelect={(items) => onSetStudio(items.length > 0 ? items[0] : null)}
values={studio ? [studio] : []}
/>
);

Expand Down
28 changes: 19 additions & 9 deletions ui/v2.5/src/components/Movies/MovieDetails/MovieEditPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
useListMovieScrapers,
} from "src/core/StashService";
import { LoadingIndicator } from "src/components/Shared/LoadingIndicator";
import { StudioSelect } from "src/components/Shared/Select";
import { DetailsEditNavbar } from "src/components/Shared/DetailsEditNavbar";
import { URLField } from "src/components/Shared/URLField";
import { useToast } from "src/hooks/Toast";
Expand All @@ -22,6 +21,7 @@ import isEqual from "lodash-es/isEqual";
import { handleUnsavedChanges } from "src/utils/navigation";
import { formikUtils } from "src/utils/form";
import { yupDateString, yupFormikValidate } from "src/utils/yup";
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";

interface IMovieEditPanel {
movie: Partial<GQL.MovieDataFragment>;
Expand Down Expand Up @@ -55,6 +55,8 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
const Scrapers = useListMovieScrapers();
const [scrapedMovie, setScrapedMovie] = useState<GQL.ScrapedMovie>();

const [studio, setStudio] = useState<Studio | null>(null);

const schema = yup.object({
name: yup.string().required(),
aliases: yup.string().ensure(),
Expand Down Expand Up @@ -88,6 +90,15 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
onSubmit: (values) => onSave(schema.cast(values)),
});

function onSetStudio(item: Studio | null) {
setStudio(item);
formik.setFieldValue("studio_id", item ? item.id : null);
}

useEffect(() => {
setStudio(movie.studio ?? null);
}, [movie.studio]);

// set up hotkeys
useEffect(() => {
// Mousetrap.bind("u", (e) => {
Expand Down Expand Up @@ -129,7 +140,11 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
}

if (state.studio && state.studio.stored_id) {
formik.setFieldValue("studio_id", state.studio.stored_id);
onSetStudio({
id: state.studio.stored_id,
name: state.studio.name ?? "",
aliases: [],
});
}

if (state.director) {
Expand Down Expand Up @@ -324,13 +339,8 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
const title = intl.formatMessage({ id: "studio" });
const control = (
<StudioSelect
onSelect={(items) =>
formik.setFieldValue(
"studio_id",
items.length > 0 ? items[0]?.id : null
)
}
ids={formik.values.studio_id ? [formik.values.studio_id] : []}
onSelect={(items) => onSetStudio(items.length > 0 ? items[0] : null)}
values={studio ? [studio] : []}
/>
);

Expand Down
Loading

0 comments on commit de2b28d

Please sign in to comment.