Add galleries to image edit panel (#4573)

* Add Galleries to ImageEditPanel
* Exclude filesystem-based galleries from selection
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
bob123491234 2024-02-18 21:45:29 -06:00 committed by GitHub
parent 7bb38ae6dc
commit f5a42ede2d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 59 additions and 0 deletions

View file

@ -28,6 +28,10 @@ import { Placement } from "react-bootstrap/esm/Overlay";
import { sortByRelevance } from "src/utils/query"; import { sortByRelevance } from "src/utils/query";
import { galleryTitle } from "src/core/galleries"; import { galleryTitle } from "src/core/galleries";
import { PatchComponent } from "src/patch"; import { PatchComponent } from "src/patch";
import {
Criterion,
CriterionValue,
} from "src/models/list-filter/criteria/criterion";
export type Gallery = Pick<GQL.Gallery, "id" | "title"> & { export type Gallery = Pick<GQL.Gallery, "id" | "title"> & {
files: Pick<GQL.GalleryFile, "path">[]; files: Pick<GQL.GalleryFile, "path">[];
@ -40,6 +44,8 @@ const _GallerySelect: React.FC<
IFilterValueProps<Gallery> & { IFilterValueProps<Gallery> & {
hoverPlacement?: Placement; hoverPlacement?: Placement;
excludeIds?: string[]; excludeIds?: string[];
} & {
extraCriteria?: Array<Criterion<CriterionValue>>;
} }
> = (props) => { > = (props) => {
const { configuration } = React.useContext(ConfigurationContext); const { configuration } = React.useContext(ConfigurationContext);
@ -56,6 +62,11 @@ const _GallerySelect: React.FC<
filter.itemsPerPage = maxOptionsShown; filter.itemsPerPage = maxOptionsShown;
filter.sortBy = "title"; filter.sortBy = "title";
filter.sortDirection = GQL.SortDirectionEnum.Asc; filter.sortDirection = GQL.SortDirectionEnum.Asc;
if (props.extraCriteria) {
filter.criteria = [...props.extraCriteria];
}
const query = await queryFindGalleriesForSelect(filter); const query = await queryFindGalleriesForSelect(filter);
let ret = query.data.findGalleries.galleries.filter((gallery) => { let ret = query.data.findGalleries.galleries.filter((gallery) => {
// HACK - we should probably exclude these in the backend query, but // HACK - we should probably exclude these in the backend query, but

View file

@ -23,6 +23,9 @@ import {
import { formikUtils } from "src/utils/form"; import { formikUtils } from "src/utils/form";
import { Tag, TagSelect } from "src/components/Tags/TagSelect"; import { Tag, TagSelect } from "src/components/Tags/TagSelect";
import { Studio, StudioSelect } from "src/components/Studios/StudioSelect"; import { Studio, StudioSelect } from "src/components/Studios/StudioSelect";
import { galleryTitle } from "src/core/galleries";
import { Gallery, GallerySelect } from "src/components/Galleries/GallerySelect";
import { PathCriterion } from "src/models/list-filter/criteria/path";
interface IProps { interface IProps {
image: GQL.ImageDataFragment; image: GQL.ImageDataFragment;
@ -31,6 +34,14 @@ interface IProps {
onDelete: () => void; onDelete: () => void;
} }
function getExcludeFilebaseGalleriesFilter() {
const ret = new PathCriterion();
ret.modifier = GQL.CriterionModifier.IsNull;
return ret;
}
const excludeFileBasedGalleries = [getExcludeFilebaseGalleriesFilter()];
export const ImageEditPanel: React.FC<IProps> = ({ export const ImageEditPanel: React.FC<IProps> = ({
image, image,
isVisible, isVisible,
@ -45,10 +56,22 @@ export const ImageEditPanel: React.FC<IProps> = ({
const { configuration } = React.useContext(ConfigurationContext); const { configuration } = React.useContext(ConfigurationContext);
const [galleries, setGalleries] = useState<Gallery[]>([]);
const [performers, setPerformers] = useState<Performer[]>([]); const [performers, setPerformers] = useState<Performer[]>([]);
const [tags, setTags] = useState<Tag[]>([]); const [tags, setTags] = useState<Tag[]>([]);
const [studio, setStudio] = useState<Studio | null>(null); const [studio, setStudio] = useState<Studio | null>(null);
useEffect(() => {
setGalleries(
image.galleries?.map((g) => ({
id: g.id,
title: galleryTitle(g),
files: g.files,
folder: g.folder,
})) ?? []
);
}, [image.galleries]);
const schema = yup.object({ const schema = yup.object({
title: yup.string().ensure(), title: yup.string().ensure(),
code: yup.string().ensure(), code: yup.string().ensure(),
@ -57,6 +80,7 @@ export const ImageEditPanel: React.FC<IProps> = ({
details: yup.string().ensure(), details: yup.string().ensure(),
photographer: yup.string().ensure(), photographer: yup.string().ensure(),
rating100: yup.number().integer().nullable().defined(), rating100: yup.number().integer().nullable().defined(),
gallery_ids: yup.array(yup.string().required()).defined(),
studio_id: yup.string().required().nullable(), studio_id: yup.string().required().nullable(),
performer_ids: yup.array(yup.string().required()).defined(), performer_ids: yup.array(yup.string().required()).defined(),
tag_ids: yup.array(yup.string().required()).defined(), tag_ids: yup.array(yup.string().required()).defined(),
@ -70,6 +94,7 @@ export const ImageEditPanel: React.FC<IProps> = ({
details: image.details ?? "", details: image.details ?? "",
photographer: image.photographer ?? "", photographer: image.photographer ?? "",
rating100: image.rating100 ?? null, rating100: image.rating100 ?? null,
gallery_ids: (image.galleries ?? []).map((g) => g.id),
studio_id: image.studio?.id ?? null, studio_id: image.studio?.id ?? null,
performer_ids: (image.performers ?? []).map((p) => p.id), performer_ids: (image.performers ?? []).map((p) => p.id),
tag_ids: (image.tags ?? []).map((t) => t.id), tag_ids: (image.tags ?? []).map((t) => t.id),
@ -88,6 +113,14 @@ export const ImageEditPanel: React.FC<IProps> = ({
formik.setFieldValue("rating100", v); formik.setFieldValue("rating100", v);
} }
function onSetGalleries(items: Gallery[]) {
setGalleries(items);
formik.setFieldValue(
"gallery_ids",
items.map((i) => i.id)
);
}
function onSetPerformers(items: Performer[]) { function onSetPerformers(items: Performer[]) {
setPerformers(items); setPerformers(items);
formik.setFieldValue( formik.setFieldValue(
@ -189,6 +222,20 @@ export const ImageEditPanel: React.FC<IProps> = ({
renderURLListField, renderURLListField,
} = formikUtils(intl, formik, splitProps); } = formikUtils(intl, formik, splitProps);
function renderGalleriesField() {
const title = intl.formatMessage({ id: "galleries" });
const control = (
<GallerySelect
values={galleries}
onSelect={(items) => onSetGalleries(items)}
isMulti
extraCriteria={excludeFileBasedGalleries}
/>
);
return renderField("gallery_ids", title, control);
}
function renderStudioField() { function renderStudioField() {
const title = intl.formatMessage({ id: "studio" }); const title = intl.formatMessage({ id: "studio" });
const control = ( const control = (
@ -278,6 +325,7 @@ export const ImageEditPanel: React.FC<IProps> = ({
{renderInputField("photographer")} {renderInputField("photographer")}
{renderRatingField("rating100", "rating")} {renderRatingField("rating100", "rating")}
{renderGalleriesField()}
{renderStudioField()} {renderStudioField()}
{renderPerformersField()} {renderPerformersField()}
{renderTagsField()} {renderTagsField()}