Improve scrape url button UX (#1903)

* change button label to icon
* add URLField component
This commit is contained in:
7dJx1qP
2021-10-28 02:22:26 -04:00
committed by GitHub
parent bf59028bcd
commit b01c4468d8
8 changed files with 68 additions and 113 deletions

View File

@@ -27,6 +27,7 @@ import {
StudioSelect,
Icon,
LoadingIndicator,
URLField,
} from "src/components/Shared";
import { useToast } from "src/hooks";
import { useFormik } from "formik";
@@ -384,21 +385,6 @@ export const GalleryEditPanel: React.FC<
}
}
function maybeRenderScrapeButton() {
if (!formik.values.url || !urlScrapable(formik.values.url)) {
return undefined;
}
return (
<Button
className="minimal scrape-url-button"
onClick={onScrapeGalleryURL}
title="Scrape"
>
<Icon className="fa-fw" icon="file-download" />
</Button>
);
}
function renderTextField(field: string, title: string, placeholder?: string) {
return (
<Form.Group controlId={title} as={Row}>
@@ -461,15 +447,12 @@ export const GalleryEditPanel: React.FC<
<Form.Label className="col-form-label">
<FormattedMessage id="url" />
</Form.Label>
<div className="float-right scrape-button-container">
{maybeRenderScrapeButton()}
</div>
</Col>
<Col xs={9}>
<Form.Control
className="text-input"
placeholder={intl.formatMessage({ id: "url" })}
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapeGalleryURL}
urlScrapable={urlScrapable}
isInvalid={!!formik.getFieldMeta("url").error}
/>
</Col>

View File

@@ -10,19 +10,12 @@ import {
import {
LoadingIndicator,
StudioSelect,
Icon,
DetailsEditNavbar,
DurationInput,
URLField,
} from "src/components/Shared";
import { useToast } from "src/hooks";
import {
Modal as BSModal,
Form,
Button,
Col,
Row,
InputGroup,
} from "react-bootstrap";
import { Modal as BSModal, Form, Button, Col, Row } from "react-bootstrap";
import { DurationUtils, FormUtils, ImageUtils } from "src/utils";
import { RatingStars } from "src/components/Scenes/SceneDetails/RatingStars";
import { useFormik } from "formik";
@@ -257,21 +250,6 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
);
}
function maybeRenderScrapeButton() {
const { url } = formik.values;
if (!url || !urlScrapable(url)) {
return undefined;
}
return (
<Button
className="minimal scrape-url-button"
onClick={() => onScrapeMovieURL()}
>
<Icon icon="file-upload" />
</Button>
);
}
function maybeRenderScrapeDialog() {
if (!scrapedMovie) {
return;
@@ -468,14 +446,11 @@ export const MovieEditPanel: React.FC<IMovieEditPanel> = ({
title: intl.formatMessage({ id: "url" }),
})}
<Col xs={9}>
<InputGroup>
<Form.Control
className="text-input"
placeholder={intl.formatMessage({ id: "url" })}
{...formik.getFieldProps("url")}
/>
<InputGroup.Append>{maybeRenderScrapeButton()}</InputGroup.Append>
</InputGroup>
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapeMovieURL}
urlScrapable={urlScrapable}
/>
</Col>
</Form.Group>

View File

@@ -1,13 +1,5 @@
import React, { useEffect, useState } from "react";
import {
Button,
Form,
Col,
InputGroup,
Row,
Badge,
Dropdown,
} from "react-bootstrap";
import { Button, Form, Col, Row, Badge, Dropdown } from "react-bootstrap";
import { FormattedMessage, useIntl } from "react-intl";
import Mousetrap from "mousetrap";
import * as GQL from "src/core/generated-graphql";
@@ -28,6 +20,7 @@ import {
CollapseButton,
Modal,
TagSelect,
URLField,
} from "src/components/Shared";
import { ImageUtils, getStashIDs } from "src/utils";
import { getCountryByISO } from "src/utils/country";
@@ -662,19 +655,6 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
setScraper(undefined);
}
function maybeRenderScrapeButton() {
return (
<Button
variant="secondary"
disabled={!urlScrapable(formik.values.url)}
className="scrape-url-button text-input"
onClick={() => onScrapePerformerURL()}
>
<Icon icon="file-upload" />
</Button>
);
}
function renderButtons() {
return (
<Row>
@@ -963,14 +943,11 @@ export const PerformerEditPanel: React.FC<IPerformerDetails> = ({
<FormattedMessage id="url" />
</Form.Label>
<Col xs={fieldXS} xl={fieldXL}>
<InputGroup>
<Form.Control
className="text-input"
placeholder="URL"
{...formik.getFieldProps("url")}
/>
<InputGroup.Append>{maybeRenderScrapeButton()}</InputGroup.Append>
</InputGroup>
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapePerformerURL}
urlScrapable={urlScrapable}
/>
</Col>
</Form.Group>

View File

@@ -28,6 +28,7 @@ import {
Icon,
LoadingIndicator,
ImageInput,
URLField,
} from "src/components/Shared";
import { useToast } from "src/hooks";
import { ImageUtils, FormUtils, TextUtils, getStashIDs } from "src/utils";
@@ -574,21 +575,6 @@ export const SceneEditPanel: React.FC<IProps> = ({
}
}
function maybeRenderScrapeButton() {
if (!formik.values.url || !urlScrapable(formik.values.url)) {
return undefined;
}
return (
<Button
className="minimal scrape-url-button"
onClick={onScrapeSceneURL}
title="Scrape"
>
<Icon className="fa-fw" icon="file-download" />
</Button>
);
}
function renderTextField(field: string, title: string, placeholder?: string) {
return (
<Form.Group controlId={title} as={Row}>
@@ -652,15 +638,12 @@ export const SceneEditPanel: React.FC<IProps> = ({
<Form.Label className="col-form-label">
<FormattedMessage id="url" />
</Form.Label>
<div className="float-right scrape-button-container">
{maybeRenderScrapeButton()}
</div>
</Col>
<Col xs={9}>
<Form.Control
className="text-input"
placeholder={intl.formatMessage({ id: "url" })}
<URLField
{...formik.getFieldProps("url")}
onScrapeClick={onScrapeSceneURL}
urlScrapable={urlScrapable}
isInvalid={!!formik.getFieldMeta("url").error}
/>
</Col>

View File

@@ -500,15 +500,6 @@ input[type="range"].blue-slider {
font-size: 1.3em;
height: calc(1.5em + 0.75rem + 2px);
}
.scrape-button-container {
margin-right: -15px;
}
.scrape-url-button {
color: $text-color;
margin-right: 0;
}
}
.scene-markers-panel {

View File

@@ -0,0 +1,44 @@
import React from "react";
import { useIntl } from "react-intl";
import { Button, InputGroup, Form } from "react-bootstrap";
import { Icon } from "src/components/Shared";
import { FormikHandlers } from "formik";
interface IProps {
value: string;
name: string;
onChange: FormikHandlers["handleChange"];
onBlur: FormikHandlers["handleBlur"];
onScrapeClick(): void;
urlScrapable(url: string): boolean;
isInvalid?: boolean;
}
export const URLField: React.FC<IProps> = (props: IProps) => {
const intl = useIntl();
return (
<InputGroup className="mr-2 flex-grow-1">
<Form.Control
className="text-input"
placeholder={intl.formatMessage({ id: "url" })}
value={props.value}
name={props.name}
onChange={props.onChange}
onBlur={props.onBlur}
isInvalid={props.isInvalid}
/>
<InputGroup.Append>
<Button
className="scrape-url-button text-input"
variant="secondary"
onClick={props.onScrapeClick}
disabled={!props.value || !props.urlScrapable(props.value)}
title={intl.formatMessage({ id: "actions.scrape" })}
>
<Icon icon="file-download" />
</Button>
</InputGroup.Append>
</InputGroup>
);
};

View File

@@ -19,4 +19,5 @@ export { ExportDialog } from "./ExportDialog";
export { default as DeleteEntityDialog } from "./DeleteEntityDialog";
export { IndeterminateCheckbox } from "./IndeterminateCheckbox";
export { OperationButton } from "./OperationButton";
export { URLField } from "./URLField";
export const TITLE_SUFFIX = " | Stash";

View File

@@ -64,6 +64,7 @@
"save_delete_settings": "Use these options by default when deleting",
"save_filter": "Save filter",
"scan": "Scan",
"scrape": "Scrape",
"scrape_with": "Scrape with…",
"scrape_query": "Scrape query",
"scrape_scene_fragment": "Scrape by fragment",