Skip to content

Commit

Permalink
UI changes
Browse files Browse the repository at this point in the history
  • Loading branch information
WithoutPants committed Sep 12, 2023
1 parent c0a8aa0 commit 549edeb
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
} from "src/components/Shared/Select";
import { Icon } from "src/components/Shared/Icon";
import { LoadingIndicator } from "src/components/Shared/LoadingIndicator";
import { URLField } from "src/components/Shared/URLField";
import { URLListInput } from "src/components/Shared/URLField";
import { useToast } from "src/hooks/Toast";
import { useFormik } from "formik";
import FormUtils from "src/utils/form";
Expand All @@ -42,6 +42,7 @@ import {
Performer,
PerformerSelect,
} from "src/components/Performers/PerformerSelect";
import { yupDateString, yupUniqueStringList } from "src/utils/yup";

interface IProps {
gallery: Partial<GQL.GalleryDataFragment>;
Expand Down Expand Up @@ -84,20 +85,8 @@ export const GalleryEditPanel: React.FC<IProps> = ({

const schema = yup.object({
title: titleRequired ? yup.string().required() : yup.string().ensure(),
url: yup.string().ensure(),
date: yup
.string()
.ensure()
.test({
name: "date",
test: (value) => {
if (!value) return true;
if (!value.match(/^\d{4}-\d{2}-\d{2}$/)) return false;
if (Number.isNaN(Date.parse(value))) return false;
return true;
},
message: intl.formatMessage({ id: "validation.date_invalid_form" }),
}),
urls: yupUniqueStringList("urls"),
date: yupDateString(intl),
rating100: yup.number().nullable().defined(),
studio_id: yup.string().required().nullable(),
performer_ids: yup.array(yup.string().required()).defined(),
Expand All @@ -108,7 +97,7 @@ export const GalleryEditPanel: React.FC<IProps> = ({

const initialValues = {
title: gallery?.title ?? "",
url: gallery?.url ?? "",
urls: gallery?.urls ?? [],
date: gallery?.date ?? "",
rating100: gallery?.rating100 ?? null,
studio_id: gallery?.studio?.id ?? null,
Expand Down Expand Up @@ -313,8 +302,8 @@ export const GalleryEditPanel: React.FC<IProps> = ({
formik.setFieldValue("date", galleryData.date);
}

if (galleryData.url) {
formik.setFieldValue("url", galleryData.url);
if (galleryData.urls) {
formik.setFieldValue("url", galleryData.urls);
}

if (galleryData.studio?.stored_id) {
Expand Down Expand Up @@ -351,13 +340,13 @@ export const GalleryEditPanel: React.FC<IProps> = ({
}
}

async function onScrapeGalleryURL() {
if (!formik.values.url) {
async function onScrapeGalleryURL(url: string) {
if (!url) {
return;
}
setIsLoading(true);
try {
const result = await queryScrapeGalleryURL(formik.values.url);
const result = await queryScrapeGalleryURL(url);
if (!result || !result.data || !result.data.scrapeGalleryURL) {
return;
}
Expand Down Expand Up @@ -392,6 +381,14 @@ export const GalleryEditPanel: React.FC<IProps> = ({

if (isLoading) return <LoadingIndicator />;

const urlsErrors = Array.isArray(formik.errors.urls)
? formik.errors.urls[0]
: formik.errors.urls;
const urlsErrorMsg = urlsErrors
? intl.formatMessage({ id: "validation.urls_must_be_unique" })
: undefined;
const urlsErrorIdx = urlsErrors?.split(" ").map((e) => parseInt(e));

return (
<div id="gallery-edit-details">
<Prompt
Expand Down Expand Up @@ -428,18 +425,20 @@ export const GalleryEditPanel: React.FC<IProps> = ({
<div className="form-container row px-3">
<div className="col-12 col-lg-6 col-xl-12">
{renderTextField("title", intl.formatMessage({ id: "title" }))}
<Form.Group controlId="url" as={Row}>
<Form.Group controlId="urls" as={Row}>
<Col xs={3} className="pr-0 url-label">
<Form.Label className="col-form-label">
<FormattedMessage id="url" />
<FormattedMessage id="urls" />
</Form.Label>
</Col>
<Col xs={9}>
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapeGalleryURL}
<URLListInput
value={formik.values.urls ?? []}
setValue={(value) => formik.setFieldValue("urls", value)}
errors={urlsErrorMsg}
errorIdx={urlsErrorIdx}
onScrapeClick={(url) => onScrapeGalleryURL(url)}
urlScrapable={urlScrapable}
isInvalid={!!formik.getFieldMeta("url").error}
/>
</Col>
</Form.Group>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import * as GQL from "src/core/generated-graphql";
import { mutateGallerySetPrimaryFile } from "src/core/StashService";
import { useToast } from "src/hooks/Toast";
import TextUtils from "src/utils/text";
import { TextField, URLField } from "src/utils/field";
import { TextField, URLField, URLsField } from "src/utils/field";

interface IFileInfoPanelProps {
folder?: Pick<GQL.Folder, "id" | "path">;
Expand Down Expand Up @@ -147,12 +147,7 @@ export const GalleryFileInfoPanel: React.FC<IGalleryFileInfoPanelProps> = (
return (
<>
<dl className="container gallery-file-info details-list">
<URLField
id="media_info.downloaded_from"
url={props.gallery.url}
value={props.gallery.url}
truncate
/>
<URLsField id="urls" urls={props.gallery.urls} truncate />
</dl>

{filesPanel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as GQL from "src/core/generated-graphql";
import {
ScrapeDialog,
ScrapedInputGroupRow,
ScrapedStringListRow,
ScrapedTextAreaRow,
} from "src/components/Shared/ScrapeDialog/ScrapeDialog";
import clone from "lodash-es/clone";
Expand All @@ -23,6 +24,7 @@ import {
useCreateScrapedStudio,
useCreateScrapedTag,
} from "src/components/Shared/ScrapeDialog/createObjects";
import { uniq } from "lodash-es";

interface IGalleryScrapeDialogProps {
gallery: Partial<GQL.GalleryUpdateInput>;
Expand All @@ -36,29 +38,32 @@ interface IHasStoredID {
stored_id?: string | null;
}

export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (
props: IGalleryScrapeDialogProps
) => {
export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = ({
gallery,
galleryPerformers,
scraped,
onClose,
}) => {
const intl = useIntl();
const [title, setTitle] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.gallery.title, props.scraped.title)
new ScrapeResult<string>(gallery.title, scraped.title)
);
const [url, setURL] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.gallery.url, props.scraped.url)
const [urls, setURLs] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(
gallery.urls,
scraped.urls
? uniq((gallery.urls ?? []).concat(scraped.urls ?? []))
: undefined
)
);
const [date, setDate] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.gallery.date, props.scraped.date)
new ScrapeResult<string>(gallery.date, scraped.date)
);
const [studio, setStudio] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(
props.gallery.studio_id,
props.scraped.studio?.stored_id
)
new ScrapeResult<string>(gallery.studio_id, scraped.studio?.stored_id)
);
const [newStudio, setNewStudio] = useState<GQL.ScrapedStudio | undefined>(
props.scraped.studio && !props.scraped.studio.stored_id
? props.scraped.studio
: undefined
scraped.studio && !scraped.studio.stored_id ? scraped.studio : undefined
);

function mapStoredIdObjects(
Expand Down Expand Up @@ -104,30 +109,30 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (
>(
new ObjectListScrapeResult<GQL.ScrapedPerformer>(
sortStoredIdObjects(
props.galleryPerformers.map((p) => ({
galleryPerformers.map((p) => ({
stored_id: p.id,
name: p.name,
}))
),
sortStoredIdObjects(props.scraped.performers ?? undefined)
sortStoredIdObjects(scraped.performers ?? undefined)
)
);
const [newPerformers, setNewPerformers] = useState<GQL.ScrapedPerformer[]>(
props.scraped.performers?.filter((t) => !t.stored_id) ?? []
scraped.performers?.filter((t) => !t.stored_id) ?? []
);

const [tags, setTags] = useState<ScrapeResult<string[]>>(
new ScrapeResult<string[]>(
sortIdList(props.gallery.tag_ids),
mapStoredIdObjects(props.scraped.tags ?? undefined)
sortIdList(gallery.tag_ids),
mapStoredIdObjects(scraped.tags ?? undefined)
)
);
const [newTags, setNewTags] = useState<GQL.ScrapedTag[]>(
props.scraped.tags?.filter((t) => !t.stored_id) ?? []
scraped.tags?.filter((t) => !t.stored_id) ?? []
);

const [details, setDetails] = useState<ScrapeResult<string>>(
new ScrapeResult<string>(props.gallery.details, props.scraped.details)
new ScrapeResult<string>(gallery.details, scraped.details)
);

const createNewStudio = useCreateScrapedStudio({
Expand All @@ -152,14 +157,14 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (

// don't show the dialog if nothing was scraped
if (
[title, url, date, studio, performers, tags, details].every(
[title, urls, date, studio, performers, tags, details].every(
(r) => !r.scraped
) &&
!newStudio &&
newPerformers.length === 0 &&
newTags.length === 0
) {
props.onClose();
onClose();
return <></>;
}

Expand All @@ -168,7 +173,7 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (

return {
title: title.getNewValue(),
url: url.getNewValue(),
urls: urls.getNewValue(),
date: date.getNewValue(),
studio: newStudioValue
? {
Expand All @@ -195,10 +200,10 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (
result={title}
onChange={(value) => setTitle(value)}
/>
<ScrapedInputGroupRow
title={intl.formatMessage({ id: "url" })}
result={url}
onChange={(value) => setURL(value)}
<ScrapedStringListRow
title={intl.formatMessage({ id: "urls" })}
result={urls}
onChange={(value) => setURLs(value)}
/>
<ScrapedInputGroupRow
title={intl.formatMessage({ id: "date" })}
Expand Down Expand Up @@ -244,7 +249,7 @@ export const GalleryScrapeDialog: React.FC<IGalleryScrapeDialogProps> = (
)}
renderScrapeRows={renderScrapeRows}
onClose={(apply) => {
props.onClose(apply ? makeNewScrapedItem() : undefined);
onClose(apply ? makeNewScrapedItem() : undefined);
}}
/>
);
Expand Down

0 comments on commit 549edeb

Please sign in to comment.