Skip to content

Commit

Permalink
Merge pull request #69 from wwsalmon/dev
Browse files Browse the repository at this point in the history
0.24.3
  • Loading branch information
wwsalmon authored Jan 19, 2022
2 parents 36f5794 + d73898b commit 94a1943
Show file tree
Hide file tree
Showing 24 changed files with 279 additions and 182 deletions.
51 changes: 0 additions & 51 deletions components/project/EvergreenInner.tsx

This file was deleted.

2 changes: 2 additions & 0 deletions components/project/HomePostItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {getPlainTextFromSlateValue} from "../../slate/SlateEditor";
import {ExternalBadge} from "./NodeCard";

function HomePostItem({pageNode, pageProject, pageUser, thisUser, ...props}: PublicNodePageProps & HTMLProps<HTMLAnchorElement>) {
if (!(pageNode.type === "post" && "publishedTitle" in pageNode.body)) return <></>;

const {publishedTitle: title, publishedBody: body, publishedDate, urlName} = pageNode.body;

const isExternal = !!pageNode.shortcutArr;
Expand Down
4 changes: 2 additions & 2 deletions components/project/MainShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import UiModal from "../style/UiModal";
import UiH3 from "../style/UiH3";
import AsyncSelect from "react-select/async";
import axios from "axios";
import {DatedObj, NodeObj, NodeTypes, ProjectObj, ShortcutObj} from "../../utils/types";
import {DatedObj, NodeObj, NodeObjPublic, NodeTypes, ProjectObj, ShortcutObj} from "../../utils/types";
import {getInputStateProps, getSelectStateProps} from "react-controlled-component-helpers";
import useSWR from "swr";
import {fetcher} from "../../utils/utils";
Expand Down Expand Up @@ -63,7 +63,7 @@ function NewShortcutModal({pageProject, pageUser, thisUser, isOpen, setIsOpen}:
});
}

const {data} = useSWR<{nodes: DatedObj<NodeObj>[]}>(
const {data} = useSWR<{nodes: DatedObj<NodeObjPublic>[]}>(
`/api/search/shortcutNode?query=${query}&projectId=${project ? project.value : ""}&thisProjectId=${pageProject._id}&type=${type}`,
project ? fetcher : async () => ({nodes: []})
);
Expand Down
28 changes: 17 additions & 11 deletions components/project/NodeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import NodeInner from "./NodeInner";
import TruncatedText from "../standard/TruncatedText";
import {PublicNodePageProps} from "../../utils/getPublicNodeSSRFunction";
import {FiExternalLink} from "react-icons/fi";
import {getPlainTextFromSlateValue} from "../../slate/SlateEditor";
import LinesEllipsis from "react-lines-ellipsis";

const ThirdColumn = ({children}: {children: ReactNode}) => (
<div className="md:w-1/3 md:px-4 my-4 md:my-0">
Expand All @@ -27,10 +29,10 @@ export default function NodeCard({isSidebar, ...props}: PublicNodePageProps & {c
const {id} = router.query;
const {pageNode, pageUser, thisUser} = props;

const isPublished = !!pageNode.body.publishedTitle;
const isPublished = "publishedTitle" in pageNode.body;
const isExternal = !!pageNode.shortcutArr;
const isOwner = thisUser && pageUser._id === thisUser._id;
const hasChanges = isOwner && isPublished && JSON.stringify(pageNode.body.publishedBody) !== JSON.stringify(pageNode.body.body);
const hasChanges = isOwner && "publishedBody" in pageNode.body && JSON.stringify(pageNode.body.publishedBody) !== JSON.stringify(pageNode.body.body);

const [isOpen, setIsOpen] = useState<boolean>(false);

Expand All @@ -46,13 +48,13 @@ export default function NodeCard({isSidebar, ...props}: PublicNodePageProps & {c
else setIsOpen(false);
}, [id]);

const title = (isOwner ? pageNode.body.title : pageNode.body.publishedTitle) || `Untitled ${pageNode.type}`;
const body = isPublished ? pageNode.body.publishedBody : pageNode.body.body;
const link = isPublished ? pageNode.body.publishedLink : pageNode.body.link;
const takeaways = isPublished ? pageNode.body.publishedTakeaways : pageNode.body.takeaways;
const summary = isPublished ? pageNode.body.publishedSummary : pageNode.body.summary;
const title = (("urlName" in pageNode.body && !isOwner) ? pageNode.body.publishedTitle : pageNode.body.title) || `Untitled ${pageNode.type}`;
const body = pageNode.type !== "source" && ("urlName" in pageNode.body ? pageNode.body.publishedBody : pageNode.body.body);
const sourceInfo = pageNode.type === "source" && ("urlName" in pageNode.body ? pageNode.body.publishedSourceInfo : pageNode.body.sourceInfo);
const takeaways = pageNode.type === "source" && ("urlName" in pageNode.body ? pageNode.body.publishedTakeaways : pageNode.body.takeaways);
const summary = pageNode.type === "source" && ("urlName" in pageNode.body ? pageNode.body.publishedSummary : pageNode.body.summary);

const dateString = `${format(new Date(isPublished ? pageNode.body.publishedDate : pageNode.createdAt), "MMM d, yyyy")}`;
const dateString = `${format(new Date("urlName" in pageNode.body ? pageNode.body.publishedDate : pageNode.createdAt), "MMM d, yyyy")}`;

const StatusBadge = (props: HTMLProps<HTMLDivElement>) => (
<div {...props}>
Expand Down Expand Up @@ -84,15 +86,15 @@ export default function NodeCard({isSidebar, ...props}: PublicNodePageProps & {c
>
{(pageNode.type === "evergreen" || isSidebar) ? (
<>
<div>
<div className="w-full">
<h3 className={`font-manrope font-semibold ${isSidebar ? "text-sm" : "mb-1"}`}>{title}</h3>
{!isSidebar && (
<StatusBadge/>
)}
{pageNode.type === "evergreen" ? (
<TruncatedText value={body} isSmall={true}/>
) : (
<p className="text-gray-500 text-xs mt-2 font-medium truncate">{link}</p>
<LinesEllipsis className="text-gray-500 text-xs mt-2 font-medium" text={getPlainTextFromSlateValue(sourceInfo)} maxLine={1}/>
)}
</div>
<div className={`flex items-center text-gray-400 text-xs font-manrope font-semibold mt-auto ${isSidebar ? "pt-2" : "pt-4"}`}>
Expand All @@ -110,7 +112,11 @@ export default function NodeCard({isSidebar, ...props}: PublicNodePageProps & {c
<ThirdColumn>
<h3 className="font-manrope font-semibold mb-2">{title}</h3>
<StatusBadge className="mb-2"/>
<p className="text-gray-500 text-sm mb-2 truncate">{link}</p>
<LinesEllipsis
className="text-gray-500 text-xs mb-2"
text={getPlainTextFromSlateValue(sourceInfo)}
maxLine={1}
/>
<p className="text-gray-400 text-sm">{dateString}</p>
{isExternal && (
<ExternalBadge className="mt-2"/>
Expand Down
76 changes: 53 additions & 23 deletions components/project/NodeInner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {useRouter} from "next/router";
import axios from "axios";
import ConfirmModal from "../standard/ConfirmModal";
import slateWordCount from "../../slate/slateWordCount";
import {NodeObjPostOrEvergreenPublic, NodeObjPublic, NodeObjSourcePublic} from "../../utils/types";
import {Node} from "slate";

function DeleteShortcutModal ({pageUser, pageProject, pageNode, isOpen, setIsOpen}: PublicNodePageProps & {isOpen: boolean, setIsOpen: Dispatch<SetStateAction<boolean>>}) {
const router = useRouter();
Expand Down Expand Up @@ -64,23 +66,49 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
const {
body: {
title: privateTitle,
body: privateBody,
},
createdAt,
updatedAt
} = pageNode;

const {
body: {
notes: privateNotes,
summary: privateSummary,
takeaways: privateTakeaways,
link: privateLink,
sourceInfo: privateSourceInfo,
},
} = pageNode.type === "source" ? pageNode : {body: {notes: false, summary: false, takeaways: false, sourceInfo: false}};

const {
body: {
publishedTitle,
publishedBody,
publishedNotes,
publishedSummary,
publishedTakeaways,
publishedLink,
publishedSourceInfo,
},
} = (pageNode.type === "source" && "urlName" in pageNode.body) ? pageNode as NodeObjSourcePublic : {body: {publishedTitle: false, publishedNotes: false, publishedSummary: false, publishedTakeaways: false, publishedSourceInfo: false}};

const {
body: {
publishedDate,
lastPublishedDate
}
} = "urlName" in pageNode.body ? pageNode as NodeObjPublic : {body: {publishedDate: false, lastPublishedDate: false}};

const {
body: {
body: privateBody,
},
createdAt,
updatedAt
} = pageNode;
} = pageNode.type !== "source" ? pageNode : {body: {body: false}};

const {
body: {
publishedBody,
},
} = (pageNode.type !== "source" && "urlName" in pageNode.body) ? pageNode as NodeObjPostOrEvergreenPublic : {body: {publishedBody: false}};

const isPost = pageNode.type === "post";
const isSource = pageNode.type === "source";
const isOwner = thisUser && pageNode.userId === thisUser._id;
Expand All @@ -92,20 +120,20 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
const notes = publishedNotes || privateNotes;
const summary = publishedSummary || privateSummary;
const takeaways = publishedTakeaways || privateTakeaways;
const link = publishedLink || privateLink;
const isUpdated = isOwner && getIsNodeUpdated(pageNode);
const sourceInfo = publishedSourceInfo || privateSourceInfo;
const isUpdated = !isOwner || getIsNodeUpdated(pageNode);

const hasSummaryOrTakeaways = isSource && [summary, takeaways].some(d => !d.every(x => isNodeEmpty(x)));
const hasSummaryOrTakeaways = isSource && [summary, takeaways].some(d => !(d as unknown as Node[]).every(x => isNodeEmpty(x)));

const [isDeleteShortcutOpen, setIsDeleteShortcutOpen] = useState<boolean>(false);
const [isMobile, setIsMobile] = useState<boolean>(false);

useEffect(() => {setIsMobile(window.matchMedia("(max-width: 600px)").matches)}, []);

return (title && (body || (notes && summary && takeaways && link !== undefined))) ? (
return (title && (body || (notes && summary && takeaways && sourceInfo))) ? (
<>
{isSource && (<UiH3 className="mb-2">Source notes</UiH3>)}
{isExternal && isPost && (
{isExternal && isPost && "urlName" in pageNode.body && (
<div className="flex items-center mb-8">
<FiExternalLink/>
<InlineButton href={`${getProjectUrl(pageUser, originalProject)}/p/${pageNode.body.urlName}`} className="ml-2">Originally published</InlineButton>
Expand All @@ -117,8 +145,10 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
{!isModal && (
<UserButton user={pageUser} className="mt-8"/>
)}
{isSource && link && (<a className="text-gray-400 my-4 truncate underline block" href={link}>{link}</a>)}
{isExternal && !isPost && (
{pageNode.type === "source" && !(sourceInfo as unknown as Node[]).every(d => isNodeEmpty(d)) && (
<SlateReadOnly value={sourceInfo as unknown as Node[]} className="text-gray-400" fontSize={16}/>
)}
{isExternal && !isPost && "urlName" in pageNode.body && (
<Banner className="my-6">
<FiExternalLink/>
<div className="ml-4">
Expand All @@ -138,7 +168,7 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
<span>Unpublished draft</span>
</Badge>
)}
{isUpdated && (
{!isUpdated && (
<Badge>
<span>Unpublished changes</span>
</Badge>
Expand All @@ -148,12 +178,12 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
<MoreMenuItem href={`${getProjectUrl(pageUser, originalProject || pageProject)}/${pageNode._id}`}>
{`Edit${isExternal ? " in original project" : ""}`}
</MoreMenuItem>
{isModal && isPublished && (
{isModal && "urlName" in pageNode.body && (
<MoreMenuItem href={`${getProjectUrl(pageUser, pageProject)}/${pageNode.type.charAt(0)}/${pageNode.body.urlName}`}>
View as page
</MoreMenuItem>
)}
{isExternal && (
{isExternal && "urlName" in pageNode.body && (
<>
<MoreMenuItem href={`${getProjectUrl(pageUser, originalProject)}/${pageNode.type.charAt(0)}/${pageNode.body.urlName}`}>
View in original project
Expand All @@ -174,10 +204,10 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
)}
</div>
<div className="flex items-center flex-wrap font-manrope text-gray-400 font-semibold">
<span className="mr-4">{format(new Date(publishedDate || createdAt), "MMM d, yyyy")}</span>
{isPublished && publishedDate !== lastPublishedDate && (<span className="mr-4">Last updated {format(new Date(lastPublishedDate), "MMM d, yyyy")}</span>)}
<span className="mr-4">{format(new Date(("urlName" in pageNode.body ? publishedDate : createdAt) as string), "MMM d, yyyy")}</span>
{"urlName" in pageNode.body && publishedDate !== lastPublishedDate && (<span className="mr-4">Last updated {format(new Date(lastPublishedDate as string), "MMM d, yyyy")}</span>)}
{!isPublished && createdAt !== updatedAt && (<span className="mr-4">Last updated {format(new Date(updatedAt), "MMM d, yyyy")}</span>)}
{isPost && (<span className="mr-4">{Math.ceil(slateWordCount(body) / 200)} min read</span>)}
{pageNode.type === "post" && (<span className="mr-4">{Math.ceil(slateWordCount(body as unknown as Node[]) / 200)} min read</span>)}
</div>
</div>
{isSource ? (
Expand All @@ -200,15 +230,15 @@ export default function NodeInner(props: PublicNodePageProps & {isModal?: boolea
}
</div>
)}
{!notes.every(node => isNodeEmpty(node)) && (
{!(notes as unknown as Node[]).every(node => isNodeEmpty(node)) && (
<>
<UiH3 className="mb-2">Notes</UiH3>
<SlateReadOnly value={notes} fontSize={isModal ? 16 : 18} className="mb-8"/>
<SlateReadOnly value={notes as unknown as Node[]} fontSize={isModal ? 16 : 18} className="mb-8"/>
</>
)}
</>
) : (
<SlateReadOnly value={body} fontSize={isModal ? (isMobile ? 16 : 18) : (isMobile ? 18 : 20)}/>
<SlateReadOnly value={body as unknown as Node[]} fontSize={isModal ? (isMobile ? 16 : 18) : (isMobile ? 18 : 20)}/>
)}
</>
) : (
Expand Down
2 changes: 1 addition & 1 deletion components/project/NodeShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function NodeShell(props: PublicNodePageProps) {

return (
<>
<SEO title={pageNode.body.publishedTitle || `Untitled ${nodeType}`}/>
<SEO title={"publishedTitle" in pageNode.body ? pageNode.body.publishedTitle : `Untitled ${nodeType}`}/>
<PublicNavbar pageUser={pageUser} pageProject={pageProject}/>
<div className="px-4 lg:flex justify-center">
<div
Expand Down
Loading

1 comment on commit 94a1943

@vercel
Copy link

@vercel vercel bot commented on 94a1943 Jan 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.