feat: add "Copy document" dialog (#6009)

This commit is contained in:
Tom Moor
2023-10-16 19:13:57 -04:00
committed by GitHub
parent 1ce0d3470e
commit faf97401e6
17 changed files with 415 additions and 41 deletions

View File

@@ -0,0 +1,74 @@
import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { DocumentValidation } from "@shared/validations";
import Document from "~/models/Document";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import Input from "./Input";
import Text from "./Text";
type Props = {
/** The original document to duplicate */
document: Document;
onSubmit: (documents: Document[]) => void;
};
function DuplicateDialog({ document, onSubmit }: Props) {
const { t } = useTranslation();
const defaultTitle = t(`Copy of {{ documentName }}`, {
documentName: document.title,
});
const [recursive, setRecursive] = React.useState<boolean>(true);
const [title, setTitle] = React.useState<string>(defaultTitle);
const handleRecursiveChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setRecursive(ev.target.checked);
},
[]
);
const handleTitleChange = React.useCallback(
(ev: React.ChangeEvent<HTMLInputElement>) => {
setTitle(ev.target.value);
},
[]
);
const handleSubmit = async () => {
const result = await document.duplicate({
recursive,
title,
});
onSubmit(result);
};
return (
<ConfirmationDialog onSubmit={handleSubmit} submitText={t("Duplicate")}>
<Input
autoFocus
autoSelect
name="title"
label={t("Title")}
onChange={handleTitleChange}
maxLength={DocumentValidation.maxTitleLength}
defaultValue={defaultTitle}
/>
{document.publishedAt && !document.isTemplate && (
<label>
<Text size="small">
<input
type="checkbox"
name="recursive"
checked={recursive}
onChange={handleRecursiveChange}
/>{" "}
{t("Include nested documents")}
</Text>
</label>
)}
</ConfirmationDialog>
);
}
export default observer(DuplicateDialog);

View File

@@ -1,4 +1,5 @@
import * as React from "react";
import { mergeRefs } from "react-merge-refs";
import { VisuallyHidden } from "reakit/VisuallyHidden";
import styled from "styled-components";
import breakpoint from "styled-components-breakpoint";
@@ -121,6 +122,8 @@ export type Props = React.InputHTMLAttributes<
margin?: string | number;
error?: string;
icon?: React.ReactNode;
/** Like autoFocus, but also select any text in the input */
autoSelect?: boolean;
/** Callback is triggered with the CMD+Enter keyboard combo */
onRequestSubmit?: (
ev: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>
@@ -133,6 +136,7 @@ function Input(
props: Props,
ref: React.RefObject<HTMLInputElement | HTMLTextAreaElement>
) {
const internalRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>();
const [focused, setFocused] = React.useState(false);
const handleBlur = (ev: React.SyntheticEvent) => {
@@ -165,6 +169,12 @@ function Input(
}
};
React.useEffect(() => {
if (props.autoSelect && internalRef.current) {
internalRef.current.select();
}
}, [props.autoSelect, internalRef]);
const {
type = "text",
icon,
@@ -197,7 +207,10 @@ function Input(
{icon && <IconWrapper>{icon}</IconWrapper>}
{type === "textarea" ? (
<RealTextarea
ref={ref as React.RefObject<HTMLTextAreaElement>}
ref={mergeRefs([
internalRef,
ref as React.RefObject<HTMLTextAreaElement>,
])}
onBlur={handleBlur}
onFocus={handleFocus}
onKeyDown={handleKeyDown}
@@ -206,7 +219,10 @@ function Input(
/>
) : (
<RealInput
ref={ref as React.RefObject<HTMLInputElement>}
ref={mergeRefs([
internalRef,
ref as React.RefObject<HTMLInputElement>,
])}
onBlur={handleBlur}
onFocus={handleFocus}
onKeyDown={handleKeyDown}

View File

@@ -257,7 +257,7 @@ const Small = styled.div`
margin: auto auto;
width: 30vw;
min-width: 350px;
max-width: 500px;
max-width: 450px;
z-index: ${depths.modal};
display: flex;
justify-content: center;