Allow viewing diff before revision is written (#5399)
This commit is contained in:
@@ -2,6 +2,7 @@ import { observer } from "mobx-react";
|
||||
import * as React from "react";
|
||||
import { useLocation, RouteComponentProps, StaticContext } from "react-router";
|
||||
import { NavigationNode, TeamPreference } from "@shared/types";
|
||||
import { RevisionHelper } from "@shared/utils/RevisionHelper";
|
||||
import Document from "~/models/Document";
|
||||
import Revision from "~/models/Revision";
|
||||
import Error404 from "~/scenes/Error404";
|
||||
@@ -59,7 +60,14 @@ function DataLoader({ match, children }: Props) {
|
||||
documents.getByUrl(match.params.documentSlug) ??
|
||||
documents.get(match.params.documentSlug);
|
||||
|
||||
const revision = revisionId ? revisions.get(revisionId) : undefined;
|
||||
const revision = revisionId
|
||||
? revisions.get(
|
||||
revisionId === "latest"
|
||||
? RevisionHelper.latestId(document?.id)
|
||||
: revisionId
|
||||
)
|
||||
: undefined;
|
||||
|
||||
const sharedTree = document
|
||||
? documents.getSharedTree(document.id)
|
||||
: undefined;
|
||||
@@ -94,6 +102,19 @@ function DataLoader({ match, children }: Props) {
|
||||
fetchRevision();
|
||||
}, [revisions, revisionId]);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchRevision() {
|
||||
if (document && revisionId === "latest") {
|
||||
try {
|
||||
await revisions.fetchLatest(document.id);
|
||||
} catch (err) {
|
||||
setError(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
fetchRevision();
|
||||
}, [document, revisionId, revisions]);
|
||||
|
||||
React.useEffect(() => {
|
||||
async function fetchSubscription() {
|
||||
if (document?.id && !revisionId) {
|
||||
|
||||
@@ -451,8 +451,8 @@ class DocumentScene extends React.Component<Props> {
|
||||
<Header
|
||||
document={document}
|
||||
documentHasHeadings={hasHeadings}
|
||||
revision={revision}
|
||||
shareId={shareId}
|
||||
isRevision={!!revision}
|
||||
isDraft={document.isDraft}
|
||||
isEditing={!readOnly && !team?.seamlessEditing}
|
||||
isSaving={this.isSaving}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Link, useRouteMatch } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { TeamPreference } from "@shared/types";
|
||||
import Document from "~/models/Document";
|
||||
import Revision from "~/models/Revision";
|
||||
import DocumentMeta from "~/components/DocumentMeta";
|
||||
import Fade from "~/components/Fade";
|
||||
import useStores from "~/hooks/useStores";
|
||||
@@ -15,12 +16,19 @@ import { documentPath, documentInsightsPath } from "~/utils/routeHelpers";
|
||||
type Props = {
|
||||
/* The document to display meta data for */
|
||||
document: Document;
|
||||
revision?: Revision;
|
||||
isDraft: boolean;
|
||||
to?: LocationDescriptor;
|
||||
rtl?: boolean;
|
||||
};
|
||||
|
||||
function TitleDocumentMeta({ to, isDraft, document, ...rest }: Props) {
|
||||
function TitleDocumentMeta({
|
||||
to,
|
||||
isDraft,
|
||||
document,
|
||||
revision,
|
||||
...rest
|
||||
}: Props) {
|
||||
const { auth, views, comments, ui } = useStores();
|
||||
const { t } = useTranslation();
|
||||
const { team } = auth;
|
||||
@@ -36,7 +44,7 @@ function TitleDocumentMeta({ to, isDraft, document, ...rest }: Props) {
|
||||
const commentsCount = comments.inDocument(document.id).length;
|
||||
|
||||
return (
|
||||
<Meta document={document} to={to} replace {...rest}>
|
||||
<Meta document={document} revision={revision} to={to} replace {...rest}>
|
||||
{team?.getPreference(TeamPreference.Commenting) && (
|
||||
<>
|
||||
•
|
||||
|
||||
@@ -14,6 +14,7 @@ import styled from "styled-components";
|
||||
import { NavigationNode } from "@shared/types";
|
||||
import { Theme } from "~/stores/UiStore";
|
||||
import Document from "~/models/Document";
|
||||
import Revision from "~/models/Revision";
|
||||
import { Action, Separator } from "~/components/Actions";
|
||||
import Badge from "~/components/Badge";
|
||||
import Button from "~/components/Button";
|
||||
@@ -40,11 +41,11 @@ import ShareButton from "./ShareButton";
|
||||
type Props = {
|
||||
document: Document;
|
||||
documentHasHeadings: boolean;
|
||||
revision: Revision | undefined;
|
||||
sharedTree: NavigationNode | undefined;
|
||||
shareId: string | null | undefined;
|
||||
isDraft: boolean;
|
||||
isEditing: boolean;
|
||||
isRevision: boolean;
|
||||
isSaving: boolean;
|
||||
isPublishing: boolean;
|
||||
publishingIsDisabled: boolean;
|
||||
@@ -65,11 +66,11 @@ type Props = {
|
||||
function DocumentHeader({
|
||||
document,
|
||||
documentHasHeadings,
|
||||
revision,
|
||||
shareId,
|
||||
isEditing,
|
||||
isDraft,
|
||||
isPublishing,
|
||||
isRevision,
|
||||
isSaving,
|
||||
savingIsDisabled,
|
||||
publishingIsDisabled,
|
||||
@@ -83,6 +84,7 @@ function DocumentHeader({
|
||||
const { resolvedTheme } = ui;
|
||||
const { team } = auth;
|
||||
const isMobile = useMobile();
|
||||
const isRevision = !!revision;
|
||||
|
||||
// We cache this value for as long as the component is mounted so that if you
|
||||
// apply a template there is still the option to replace it until the user
|
||||
@@ -287,7 +289,7 @@ function DocumentHeader({
|
||||
</Button>
|
||||
</Action>
|
||||
)}
|
||||
{isRevision && (
|
||||
{revision && revision.createdAt !== document.updatedAt && (
|
||||
<Action>
|
||||
<Tooltip
|
||||
tooltip={t("Restore version")}
|
||||
|
||||
@@ -3,6 +3,7 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useHistory, useRouteMatch } from "react-router-dom";
|
||||
import styled from "styled-components";
|
||||
import { RevisionHelper } from "@shared/utils/RevisionHelper";
|
||||
import Event from "~/models/Event";
|
||||
import Empty from "~/components/Empty";
|
||||
import PaginatedEventList from "~/components/PaginatedEventList";
|
||||
@@ -41,8 +42,8 @@ function History() {
|
||||
eventsInDocument.unshift(
|
||||
new Event(
|
||||
{
|
||||
id: "live",
|
||||
name: "documents.live_editing",
|
||||
id: RevisionHelper.latestId(document.id),
|
||||
name: "revisions.create",
|
||||
documentId: document.id,
|
||||
createdAt: document.updatedAt,
|
||||
actor: document.updatedBy,
|
||||
|
||||
@@ -20,18 +20,17 @@ type Props = Omit<EditorProps, "extensions"> & {
|
||||
* Displays revision HTML pre-rendered on the server.
|
||||
*/
|
||||
function RevisionViewer(props: Props) {
|
||||
const { document, shareId, children, revision } = props;
|
||||
const { document, children, revision } = props;
|
||||
|
||||
return (
|
||||
<Flex auto column>
|
||||
<h1 dir={revision.dir}>{revision.title}</h1>
|
||||
{!shareId && (
|
||||
<DocumentMeta
|
||||
document={document}
|
||||
to={documentPath(document)}
|
||||
rtl={revision.rtl}
|
||||
/>
|
||||
)}
|
||||
<DocumentMeta
|
||||
document={document}
|
||||
revision={revision}
|
||||
to={documentPath(document)}
|
||||
rtl={revision.rtl}
|
||||
/>
|
||||
<EditorContainer
|
||||
dangerouslySetInnerHTML={{ __html: revision.html }}
|
||||
dir={revision.dir}
|
||||
|
||||
Reference in New Issue
Block a user