mirror of
https://github.com/stashapp/stash.git
synced 2026-04-21 14:34:16 +02:00
FR: Auto Tag Confirmation Modal (#6735)
* Improve folder list styling --------- Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
parent
c5034422cb
commit
e0f2c8e96d
6 changed files with 106 additions and 9 deletions
|
|
@ -20,7 +20,13 @@ interface IDirectorySelectionDialogProps {
|
|||
|
||||
export const DirectorySelectionDialog: React.FC<
|
||||
IDirectorySelectionDialogProps
|
||||
> = ({ animation, allowEmpty = false, initialPaths = [], onClose }) => {
|
||||
> = ({
|
||||
animation,
|
||||
allowEmpty = false,
|
||||
initialPaths = [],
|
||||
onClose,
|
||||
children,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
const { configuration } = useConfigurationContext();
|
||||
|
||||
|
|
@ -91,6 +97,8 @@ export const DirectorySelectionDialog: React.FC<
|
|||
</Button>
|
||||
}
|
||||
/>
|
||||
|
||||
{children}
|
||||
</div>
|
||||
</ModalComponent>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ import { BooleanSetting, Setting, SettingGroup } from "../Inputs";
|
|||
import { ManualLink } from "src/components/Help/context";
|
||||
import { Icon } from "src/components/Shared/Icon";
|
||||
import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons";
|
||||
import {
|
||||
AutoTagConfirmDialog,
|
||||
AutoTagWarning,
|
||||
} from "src/components/Shared/AutoTagConfirmDialog";
|
||||
import { useSettings } from "../context";
|
||||
|
||||
interface IAutoTagOptions {
|
||||
|
|
@ -78,6 +82,7 @@ export const LibraryTasks: React.FC = () => {
|
|||
const [dialogOpen, setDialogOpenState] = useState({
|
||||
scan: false,
|
||||
autoTag: false,
|
||||
autoTagAlert: false,
|
||||
identify: false,
|
||||
generate: false,
|
||||
});
|
||||
|
|
@ -224,12 +229,29 @@ export const LibraryTasks: React.FC = () => {
|
|||
}
|
||||
}
|
||||
|
||||
function renderAutoTagAlert() {
|
||||
return (
|
||||
<AutoTagConfirmDialog
|
||||
show={dialogOpen.autoTagAlert}
|
||||
onConfirm={() => {
|
||||
setDialogOpen({ autoTagAlert: false });
|
||||
runAutoTag();
|
||||
}}
|
||||
onCancel={() => setDialogOpen({ autoTagAlert: false })}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function renderAutoTagDialog() {
|
||||
if (!dialogOpen.autoTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
return <DirectorySelectionDialog onClose={onAutoTagDialogClosed} />;
|
||||
return (
|
||||
<DirectorySelectionDialog onClose={onAutoTagDialogClosed}>
|
||||
<AutoTagWarning />
|
||||
</DirectorySelectionDialog>
|
||||
);
|
||||
}
|
||||
|
||||
function onAutoTagDialogClosed(paths?: string[]) {
|
||||
|
|
@ -341,6 +363,7 @@ export const LibraryTasks: React.FC = () => {
|
|||
return (
|
||||
<Form.Group>
|
||||
{renderScanDialog()}
|
||||
{renderAutoTagAlert()}
|
||||
{renderAutoTagDialog()}
|
||||
{maybeRenderIdentifyDialog()}
|
||||
{renderGenerateDialog()}
|
||||
|
|
@ -426,9 +449,9 @@ export const LibraryTasks: React.FC = () => {
|
|||
variant="secondary"
|
||||
type="submit"
|
||||
className="mr-2"
|
||||
onClick={() => runAutoTag()}
|
||||
onClick={() => setDialogOpen({ autoTagAlert: true })}
|
||||
>
|
||||
<FormattedMessage id="actions.auto_tag" />
|
||||
<FormattedMessage id="actions.auto_tag" />…
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
|
|
|
|||
52
ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx
Normal file
52
ui/v2.5/src/components/Shared/AutoTagConfirmDialog.tsx
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import React from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons";
|
||||
import { ModalComponent } from "./Modal";
|
||||
import { Icon } from "./Icon";
|
||||
|
||||
interface IAutoTagConfirmDialog {
|
||||
show: boolean;
|
||||
onConfirm: () => void;
|
||||
onCancel: () => void;
|
||||
}
|
||||
|
||||
export const AutoTagWarning = () => (
|
||||
<>
|
||||
<p>
|
||||
<FormattedMessage id="config.tasks.auto_tag_based_on_filenames" />
|
||||
</p>
|
||||
<p>
|
||||
<FormattedMessage id="config.tasks.auto_tag_confirm" />
|
||||
</p>
|
||||
<p className="lead">
|
||||
<Icon icon={faExclamationTriangle} className="text-warning" />
|
||||
<FormattedMessage id="config.tasks.auto_tag_warning" />
|
||||
</p>
|
||||
</>
|
||||
);
|
||||
|
||||
export const AutoTagConfirmDialog: React.FC<IAutoTagConfirmDialog> = ({
|
||||
show,
|
||||
onConfirm,
|
||||
onCancel,
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
return (
|
||||
<ModalComponent
|
||||
show={show}
|
||||
icon={faExclamationTriangle}
|
||||
header={intl.formatMessage({ id: "actions.auto_tag" })}
|
||||
accept={{
|
||||
text: intl.formatMessage({ id: "actions.confirm" }),
|
||||
variant: "danger",
|
||||
onClick: onConfirm,
|
||||
}}
|
||||
cancel={{
|
||||
onClick: onCancel,
|
||||
}}
|
||||
>
|
||||
<AutoTagWarning />
|
||||
</ModalComponent>
|
||||
);
|
||||
};
|
||||
|
|
@ -2,6 +2,7 @@ import { Button, Dropdown, Modal, SplitButton } from "react-bootstrap";
|
|||
import React, { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import { ImageInput } from "./ImageInput";
|
||||
import { AutoTagConfirmDialog } from "./AutoTagConfirmDialog";
|
||||
import cx from "classnames";
|
||||
|
||||
interface IProps {
|
||||
|
|
@ -30,6 +31,7 @@ interface IProps {
|
|||
export const DetailsEditNavbar: React.FC<IProps> = (props: IProps) => {
|
||||
const intl = useIntl();
|
||||
const [isDeleteAlertOpen, setIsDeleteAlertOpen] = useState<boolean>(false);
|
||||
const [isAutoTagAlertOpen, setIsAutoTagAlertOpen] = useState<boolean>(false);
|
||||
|
||||
function renderEditButton() {
|
||||
if (props.isNew) return;
|
||||
|
|
@ -114,14 +116,20 @@ export const DetailsEditNavbar: React.FC<IProps> = (props: IProps) => {
|
|||
<Button
|
||||
variant="secondary"
|
||||
disabled={props.autoTagDisabled}
|
||||
onClick={() => {
|
||||
onClick={() => setIsAutoTagAlertOpen(true)}
|
||||
>
|
||||
<FormattedMessage id="actions.auto_tag" />…
|
||||
</Button>
|
||||
<AutoTagConfirmDialog
|
||||
show={isAutoTagAlertOpen}
|
||||
onConfirm={() => {
|
||||
setIsAutoTagAlertOpen(false);
|
||||
if (props.onAutoTag) {
|
||||
props.onAutoTag();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="actions.auto_tag" />
|
||||
</Button>
|
||||
onCancel={() => setIsAutoTagAlertOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,11 +127,15 @@
|
|||
.folder-list {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
max-height: 30vw;
|
||||
max-height: 300px;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 0.5rem;
|
||||
padding-top: 1rem;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
&-item {
|
||||
white-space: nowrap;
|
||||
|
||||
|
|
|
|||
|
|
@ -512,6 +512,8 @@
|
|||
"auto_tagging_paths": "Auto tagging the following paths"
|
||||
},
|
||||
"auto_tag_based_on_filenames": "Auto tag content based on file paths.",
|
||||
"auto_tag_confirm": "This will attempt to match your content against existing metadata.",
|
||||
"auto_tag_warning": "This process cannot be undone and may produce incorrect matches.",
|
||||
"auto_tagging": "Auto tagging",
|
||||
"backing_up_database": "Backing up database",
|
||||
"backup_and_download": "Performs a backup of the database and downloads the resulting file.",
|
||||
|
|
|
|||
Loading…
Reference in a new issue