Share document link that opens full editor (#4134)

Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
Denis Olsem
2022-09-29 06:49:35 -05:00
committed by GitHub
parent 5b33aa6649
commit 492affb29a
4 changed files with 86 additions and 21 deletions

View File

@@ -46,7 +46,7 @@ const Contents = styled.div<{ $shrink?: boolean; $width?: number }>`
border-radius: 6px;
padding: ${(props) => (props.$shrink ? "6px 0" : "12px 24px")};
max-height: 50vh;
overflow-y: scroll;
overflow-y: auto;
box-shadow: ${(props) => props.theme.menuShadow};
width: ${(props) => props.$width}px;

View File

@@ -3,7 +3,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { Helmet } from "react-helmet";
import { useTranslation } from "react-i18next";
import { RouteComponentProps, useLocation } from "react-router-dom";
import { RouteComponentProps, useLocation, Redirect } from "react-router-dom";
import styled, { useTheme } from "styled-components";
import { setCookie } from "tiny-cookie";
import DocumentModel from "~/models/Document";
@@ -12,6 +12,7 @@ import ErrorOffline from "~/scenes/ErrorOffline";
import Layout from "~/components/Layout";
import Sidebar from "~/components/Sidebar/Shared";
import Text from "~/components/Text";
import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores";
import { NavigationNode } from "~/types";
import { AuthorizationError, OfflineError } from "~/utils/errors";
@@ -78,12 +79,17 @@ function SharedDocumentScene(props: Props) {
const { ui } = useStores();
const theme = useTheme();
const location = useLocation();
const searchParams = React.useMemo(
() => new URLSearchParams(location.search),
[location.search]
);
const { t } = useTranslation();
const [response, setResponse] = React.useState<Response>();
const [error, setError] = React.useState<Error | null | undefined>();
const { documents } = useStores();
const { shareId, documentSlug } = props.match.params;
const documentId = useDocumentId(documentSlug, response);
const can = usePolicy(response?.document.id ?? "");
// ensure the wider page color always matches the theme
React.useEffect(() => {
@@ -140,6 +146,10 @@ function SharedDocumentScene(props: Props) {
return <Loading location={props.location} />;
}
if (response && searchParams.get("edit") === "true" && can.update) {
return <Redirect to={response.document.url} />;
}
const sidebar = response.sharedTree ? (
<Sidebar rootNode={response.sharedTree} shareId={shareId} />
) : undefined;

View File

@@ -1,7 +1,7 @@
import { formatDistanceToNow } from "date-fns";
import invariant from "invariant";
import { observer } from "mobx-react";
import { GlobeIcon, PadlockIcon } from "outline-icons";
import { ExpandedIcon, GlobeIcon, PadlockIcon } from "outline-icons";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import styled from "styled-components";
@@ -10,7 +10,6 @@ import Share from "~/models/Share";
import Button from "~/components/Button";
import CopyToClipboard from "~/components/CopyToClipboard";
import Flex from "~/components/Flex";
import Input from "~/components/Input";
import Notice from "~/components/Notice";
import Switch from "~/components/Switch";
import Text from "~/components/Text";
@@ -42,6 +41,8 @@ function SharePopover({
const { shares } = useStores();
const { showToast } = useToasts();
const [isCopied, setIsCopied] = React.useState(false);
const [expandedOptions, setExpandedOptions] = React.useState(false);
const [isEditMode, setIsEditMode] = React.useState(false);
const timeout = React.useRef<ReturnType<typeof setTimeout>>();
const buttonRef = React.useRef<HTMLButtonElement>(null);
const can = usePolicy(share ? share.id : "");
@@ -56,6 +57,11 @@ function SharePopover({
((share && share.published) ||
(sharedParent && sharedParent.published && !document.isDraft));
React.useEffect(() => {
if (!visible && expandedOptions) {
setExpandedOptions(false);
}
}, [visible]); // eslint-disable-line react-hooks/exhaustive-deps
useKeyDown("Escape", onRequestClose);
React.useEffect(() => {
@@ -116,9 +122,10 @@ function SharePopover({
const userLocale = useUserLocale();
const locale = userLocale ? dateLocale(userLocale) : undefined;
const shareUrl = team.sharing
? share?.url ?? ""
: `${team.url}${document.url}`;
let shareUrl = team.sharing ? share?.url ?? "" : `${team.url}${document.url}`;
if (isEditMode) {
shareUrl += "?edit=true";
}
return (
<>
@@ -127,8 +134,8 @@ function SharePopover({
<GlobeIcon size={28} color="currentColor" />
) : (
<PadlockIcon size={28} color="currentColor" />
)}{" "}
{t("Share this document")}
)}
<span>{t("Share this document")}</span>
</Heading>
{sharedParent && !document.isDraft && (
@@ -196,19 +203,52 @@ function SharePopover({
{share.includeChildDocuments
? t("Nested documents are publicly available")
: t("Nested documents are not shared")}
.
</SwitchText>
</SwitchLabel>
</SwitchWrapper>
)}
<Flex>
<InputLink
type="text"
label={t("Link")}
placeholder={`${t("Loading")}`}
value={shareUrl}
labelHidden
readOnly
{expandedOptions && (
<>
<Separator />
<SwitchWrapper>
<Switch
id="enableEditMode"
label={t("Automatically redirect to the editor")}
onChange={({ currentTarget: { checked } }) =>
setIsEditMode(checked)
}
checked={isEditMode}
disabled={!share}
/>
<SwitchLabel>
<SwitchText>
{isEditMode
? t(
"Users with edit permission will be redirected to the main app"
)
: t("All users see the same publicly shared view")}
.
</SwitchText>
</SwitchLabel>
</SwitchWrapper>
</>
)}
<Flex justify="space-between" style={{ marginBottom: 8 }}>
{expandedOptions ? (
<span />
) : (
<MoreOptionsButton
icon={<ExpandedIcon />}
onClick={() => setExpandedOptions(true)}
neutral
borderOnHover
>
{t("More options")}
</MoreOptionsButton>
)}
<CopyToClipboard text={shareUrl} onCopy={handleCopied}>
<Button
type="submit"
@@ -228,6 +268,9 @@ const Heading = styled.h2`
display: flex;
align-items: center;
margin-top: 12px;
gap: 8px;
/* accounts for icon padding */
margin-left: -4px;
`;
@@ -235,9 +278,17 @@ const SwitchWrapper = styled.div`
margin: 20px 0;
`;
const InputLink = styled(Input)`
flex-grow: 1;
margin-right: 8px;
const MoreOptionsButton = styled(Button)`
background: none;
font-size: 14px;
color: ${(props) => props.theme.textSecondary};
margin-left: -8px;
`;
const Separator = styled.div`
height: 1px;
width: 100%;
background-color: ${(props) => props.theme.divider};
`;
const SwitchLabel = styled(Flex)`

View File

@@ -449,6 +449,10 @@
"Share nested documents": "Share nested documents",
"Nested documents are publicly available": "Nested documents are publicly available",
"Nested documents are not shared": "Nested documents are not shared",
"Automatically redirect to the editor": "Automatically redirect to the editor",
"Users with edit permission will be redirected to the main app": "Users with edit permission will be redirected to the main app",
"All users see the same publicly shared view": "All users see the same publicly shared view",
"More options": "More options",
"{{ teamName }} is using Outline to share documents, please login to continue.": "{{ teamName }} is using Outline to share documents, please login to continue.",
"Are you sure you want to delete the <em>{{ documentTitle }}</em> template?": "Are you sure you want to delete the <em>{{ documentTitle }}</em> template?",
"Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.": "Are you sure about that? Deleting the <em>{{ documentTitle }}</em> document will delete all of its history</em>.",