Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON to client #5553

Merged
merged 32 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0a82c5d
wip
tommoor Jul 5, 2023
4cb2e0e
fix editor tasks parsing on server
tommoor Jul 5, 2023
fc2277d
Add getEmptyDocument helper
tommoor Jul 6, 2023
b001da6
Clone template instead of reference
tommoor Jul 6, 2023
6118545
Merge branch 'main' into tom/3000-json-to-client
tommoor Jul 8, 2023
59b7544
Need to include state by default now
tommoor Jul 9, 2023
db0f3c5
Merge branch 'main' into tom/3000-json-to-client
tommoor Jul 15, 2023
3f487c9
test
tommoor Jul 15, 2023
dd267da
Merge branch 'main' into tom/3000-json-to-client
tommoor Aug 20, 2023
94f7434
Merge branch 'main' into tom/3000-json-to-client
tommoor Sep 1, 2023
dda5c83
Merge branch 'main' into tom/3000-json-to-client
tommoor Nov 18, 2023
fe8b34c
test
tommoor Nov 18, 2023
f007111
Support public page url signing
tommoor Nov 18, 2023
4a85f45
Add API response backwards compat, move API version to header
tommoor Nov 18, 2023
1526a98
test
tommoor Nov 18, 2023
40e58db
fix response
tommoor Nov 18, 2023
c60de30
Can no longer share toMarkdown method
tommoor Dec 18, 2023
47f0787
test
tommoor Dec 18, 2023
541a989
wip
tommoor Dec 19, 2023
dfa6d63
Merge main
tommoor May 19, 2024
2c42cdc
More test support
tommoor May 19, 2024
4ebcb00
test
tommoor May 19, 2024
b189d33
Prefer content over state for performance if available
tommoor May 20, 2024
b2d4b8c
Move DocumentHelper to named export
tommoor May 21, 2024
13634b9
fix: Backwards compatability of text field
tommoor May 21, 2024
906dfd3
Named exports
tommoor May 21, 2024
1004f9b
docs
tommoor May 21, 2024
2827c49
Write .content on welcome docs
tommoor May 21, 2024
86ffae7
fix: Facepile style and count
tommoor May 21, 2024
31091c6
fix: Incorrect fetching into store
tommoor May 22, 2024
489d194
Remove comment marks from publicly shared documents
tommoor May 23, 2024
08f4dfe
lint
tommoor May 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions app/actions/definitions/documents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import {
import * as React from "react";
import { toast } from "sonner";
import { ExportContentType, TeamPreference } from "@shared/types";
import MarkdownHelper from "@shared/utils/MarkdownHelper";
import { getEventFiles } from "@shared/utils/files";
import DocumentDelete from "~/scenes/DocumentDelete";
import DocumentMove from "~/scenes/DocumentMove";
Expand Down Expand Up @@ -454,7 +453,7 @@ export const copyDocumentAsMarkdown = createAction({
? stores.documents.get(activeDocumentId)
: undefined;
if (document) {
copy(MarkdownHelper.toMarkdown(document));
copy(document.toMarkdown());
toast.success(t("Markdown copied to clipboard"));
}
},
Expand Down
11 changes: 6 additions & 5 deletions app/components/Facepile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { s } from "@shared/styles";
import User from "~/models/User";
import Avatar from "~/components/Avatar";
import Flex from "~/components/Flex";
import { AvatarSize } from "./Avatar/Avatar";

type Props = {
users: User[];
Expand All @@ -17,7 +18,7 @@ type Props = {
function Facepile({
users,
overflow = 0,
size = 32,
size = AvatarSize.Large,
limit = 8,
renderAvatar = DefaultAvatar,
...rest
Expand All @@ -43,7 +44,7 @@ function Facepile({
}

function DefaultAvatar(user: User) {
return <Avatar model={user} size={32} />;
return <Avatar model={user} size={AvatarSize.Large} />;
}

const AvatarWrapper = styled.div`
Expand All @@ -62,11 +63,11 @@ const More = styled.div<{ size: number }>`
min-width: ${(props) => props.size}px;
height: ${(props) => props.size}px;
border-radius: 100%;
background: ${(props) => props.theme.slate};
color: ${s("text")};
background: ${(props) => props.theme.textTertiary};
color: ${s("white")};
border: 2px solid ${s("background")};
text-align: center;
font-size: 11px;
font-size: 12px;
font-weight: 600;
`;

Expand Down
6 changes: 3 additions & 3 deletions app/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ import { basicExtensions as extensions } from "@shared/editor/nodes";
import Node from "@shared/editor/nodes/Node";
import ReactNode from "@shared/editor/nodes/ReactNode";
import { EventType } from "@shared/editor/types";
import { UserPreferences } from "@shared/types";
import ProsemirrorHelper from "@shared/utils/ProsemirrorHelper";
import { ProsemirrorData, UserPreferences } from "@shared/types";
import { ProsemirrorHelper } from "@shared/utils/ProsemirrorHelper";
import EventEmitter from "@shared/utils/events";
import Flex from "~/components/Flex";
import { PortalContext } from "~/components/Portal";
Expand All @@ -59,7 +59,7 @@ export type Props = {
/** The user id of the current user */
userId?: string;
/** The editor content, should only be changed if you wish to reset the content */
value?: string;
value?: string | ProsemirrorData;
/** The initial editor content as a markdown string or JSON object */
defaultValue: string | object;
/** Placeholder displayed when the editor is empty */
Expand Down
56 changes: 46 additions & 10 deletions app/models/Document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@ import i18n, { t } from "i18next";
import capitalize from "lodash/capitalize";
import floor from "lodash/floor";
import { action, autorun, computed, observable, set } from "mobx";
import { Node, Schema } from "prosemirror-model";
import ExtensionManager from "@shared/editor/lib/ExtensionManager";
import { richExtensions } from "@shared/editor/nodes";
import type {
JSONObject,
NavigationNode,
ProsemirrorData,
} from "@shared/types";
import {
ExportContentType,
FileOperationFormat,
NotificationEventType,
} from "@shared/types";
import type { JSONObject, NavigationNode } from "@shared/types";
import Storage from "@shared/utils/Storage";
import { isRTL } from "@shared/utils/rtl";
import slugify from "@shared/utils/slugify";
Expand Down Expand Up @@ -61,6 +68,9 @@ export default class Document extends ParanoidModel {
@observable
id: string;

@observable.shallow
data: ProsemirrorData;

/**
* The original data source of the document, if imported.
*/
Expand Down Expand Up @@ -111,12 +121,6 @@ export default class Document extends ParanoidModel {
@Relation(() => Collection, { onDelete: "cascade" })
collection?: Collection;

/**
* The text content of the document as Markdown.
*/
@observable
text: string;

/**
* The title of the document.
*/
Expand Down Expand Up @@ -515,6 +519,17 @@ export default class Document extends ParanoidModel {
recursive?: boolean;
}) => this.store.duplicate(this, options);

/**
* Returns the first blocks of the document, useful for displaying a preview.
*
* @param blocks The number of blocks to return, defaults to 4.
* @returns A new ProseMirror document.
*/
getSummary = (blocks = 4) => ({
...this.data,
content: this.data.content.slice(0, blocks),
});

@computed
get pinned(): boolean {
return !!this.store.rootStore.pins.orderedData.find(
Expand All @@ -535,19 +550,40 @@ export default class Document extends ParanoidModel {
return !this.isDeleted && !this.isTemplate && !this.isArchived;
}

@computed
get childDocuments() {
return this.store.orderedData.filter(
(doc) => doc.parentDocumentId === this.id
);
}

@computed
get asNavigationNode(): NavigationNode {
return {
id: this.id,
title: this.title,
children: this.store.orderedData
.filter((doc) => doc.parentDocumentId === this.id)
.map((doc) => doc.asNavigationNode),
children: this.childDocuments.map((doc) => doc.asNavigationNode),
url: this.url,
isDraft: this.isDraft,
};
}

/**
* Returns the markdown representation of the document derived from the ProseMirror data.
*
* @returns The markdown representation of the document as a string.
*/
toMarkdown = () => {
const extensionManager = new ExtensionManager(richExtensions);
const serializer = extensionManager.serializer();
const schema = new Schema({
nodes: extensionManager.nodes,
marks: extensionManager.marks,
});
const markdown = serializer.serialize(Node.fromJSON(schema, this.data));
return markdown;
};

download = (contentType: ExportContentType) =>
client.post(
`/documents.export`,
Expand Down
5 changes: 3 additions & 2 deletions app/models/Revision.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { computed } from "mobx";
import { ProsemirrorData } from "@shared/types";
import { isRTL } from "@shared/utils/rtl";
import Document from "./Document";
import User from "./User";
Expand All @@ -18,8 +19,8 @@ class Revision extends Model {
/** The document title when the revision was created */
title: string;

/** Markdown string of the content when revision was created */
text: string;
/** Prosemirror data of the content when revision was created */
data: ProsemirrorData;

/** The emoji of the document when the revision was created */
emoji: string | null;
Expand Down
7 changes: 5 additions & 2 deletions app/scenes/Collection/components/MembershipPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
import { PAGINATION_SYMBOL } from "~/stores/base/Store";
import Collection from "~/models/Collection";
import Avatar from "~/components/Avatar";
import { AvatarSize } from "~/components/Avatar/Avatar";
import Facepile from "~/components/Facepile";
import Fade from "~/components/Fade";
import NudeButton from "~/components/NudeButton";
Expand Down Expand Up @@ -66,7 +67,7 @@ const MembershipPreview = ({ collection, limit = 8 }: Props) => {
return null;
}

const overflow = usersCount - groupsCount - collectionUsers.length;
const overflow = usersCount + groupsCount - collectionUsers.length;

return (
<NudeButton
Expand Down Expand Up @@ -107,7 +108,9 @@ const MembershipPreview = ({ collection, limit = 8 }: Props) => {
users={sortBy(collectionUsers, "lastActiveAt")}
overflow={overflow}
limit={limit}
renderAvatar={(user) => <Avatar model={user} size={32} />}
renderAvatar={(item) => (
<Avatar model={item} size={AvatarSize.Large} />
)}
/>
</Fade>
</NudeButton>
Expand Down
4 changes: 2 additions & 2 deletions app/scenes/Document/Shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ function SharedDocumentScene(props: Props) {
React.useEffect(() => {
async function fetchData() {
try {
const response = await documents.fetchWithSharedTree(documentSlug, {
const res = await documents.fetchWithSharedTree(documentSlug, {
shareId,
});
setResponse(response);
setResponse(res);
} catch (err) {
setError(err);
}
Expand Down
4 changes: 2 additions & 2 deletions app/scenes/Document/components/CommentThreadItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { toast } from "sonner";
import styled, { css } from "styled-components";
import breakpoint from "styled-components-breakpoint";
import { s } from "@shared/styles";
import { JSONObject } from "@shared/types";
import { ProsemirrorData } from "@shared/types";
import { dateToRelative } from "@shared/utils/date";
import { Minute } from "@shared/utils/time";
import Comment from "~/models/Comment";
Expand Down Expand Up @@ -100,7 +100,7 @@ function CommentThreadItem({
const [isEditing, setEditing, setReadOnly] = useBoolean();
const formRef = React.useRef<HTMLFormElement>(null);

const handleChange = (value: (asString: boolean) => JSONObject) => {
const handleChange = (value: (asString: boolean) => ProsemirrorData) => {
setData(value(false));
};

Expand Down
5 changes: 3 additions & 2 deletions app/scenes/Document/components/DataLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 { ProsemirrorHelper } from "@shared/utils/ProsemirrorHelper";
import { RevisionHelper } from "@shared/utils/RevisionHelper";
import Document from "~/models/Document";
import Revision from "~/models/Revision";
Expand Down Expand Up @@ -92,7 +93,7 @@ function DataLoader({ match, children }: Props) {
}
}
void fetchDocument();
}, [ui, documents, document, shareId, documentSlug]);
}, [ui, documents, shareId, documentSlug]);

React.useEffect(() => {
async function fetchRevision() {
Expand Down Expand Up @@ -161,7 +162,7 @@ function DataLoader({ match, children }: Props) {
collectionId: document.collectionId,
parentDocumentId: nested ? document.id : document.parentDocumentId,
title,
text: "",
data: ProsemirrorHelper.getEmptyDocument(),
});

return newDocument.url;
Expand Down