From 04c1ad665385a12ba17ffb1aae7ca8a9d167f71c Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 3 Nov 2020 14:55:32 +1000 Subject: [PATCH] hark: add publish support --- pkg/arvo/mar/graph/validator/publish.hoon | 8 + pkg/interface/src/logic/lib/util.ts | 4 + .../src/views/apps/notifications/graph.tsx | 145 +++++++++++++----- .../src/views/apps/notifications/inbox.tsx | 2 +- .../landscape/components/ChannelMenu.tsx | 3 +- 5 files changed, 122 insertions(+), 40 deletions(-) diff --git a/pkg/arvo/mar/graph/validator/publish.hoon b/pkg/arvo/mar/graph/validator/publish.hoon index 7688b4a281..7c06e56f7f 100644 --- a/pkg/arvo/mar/graph/validator/publish.hoon +++ b/pkg/arvo/mar/graph/validator/publish.hoon @@ -3,6 +3,14 @@ ++ grow |% ++ noun i + :: +notification-kind + :: Ignore all containers, only notify on content + :: + ++ notification-kind + ?+ index.p.i ~ + [@ %1 @ ~] `%note + [@ %2 @ ~] `%comment + == -- ++ grab |% diff --git a/pkg/interface/src/logic/lib/util.ts b/pkg/interface/src/logic/lib/util.ts index f09a999bdf..53cd38c306 100644 --- a/pkg/interface/src/logic/lib/util.ts +++ b/pkg/interface/src/logic/lib/util.ts @@ -354,3 +354,7 @@ export function usePreventWindowUnload(shouldPreventDefault: boolean, message = } }, [shouldPreventDefault]); } + +export function pluralize(text: string, isPlural = false, vowel = false) { + return isPlural ? `${text}s`: `${vowel ? 'an' : 'a'} ${text}`; +} diff --git a/pkg/interface/src/views/apps/notifications/graph.tsx b/pkg/interface/src/views/apps/notifications/graph.tsx index cabe058c7d..e7f68ef9cc 100644 --- a/pkg/interface/src/views/apps/notifications/graph.tsx +++ b/pkg/interface/src/views/apps/notifications/graph.tsx @@ -1,6 +1,7 @@ import React, { ReactNode, useCallback } from "react"; import moment from "moment"; import { Row, Box, Col, Text, Anchor, Icon, Action } from "@tlon/indigo-react"; +import { Link } from "react-router-dom"; import _ from "lodash"; import { Post, @@ -11,10 +12,13 @@ import { Rolodex, } from "~/types"; import { Header } from "./header"; -import { cite, deSig } from "~/logic/lib/util"; +import { cite, deSig, pluralize } from "~/logic/lib/util"; import { Sigil } from "~/logic/lib/sigil"; import RichText from "~/views/components/RichText"; import GlobalApi from "~/logic/api/global"; +import ReactMarkdown from "react-markdown"; +import { getSnippet } from "~/logic/lib/publish"; +import styled from "styled-components"; function getGraphModuleIcon(module: string) { if (module === "link") { @@ -23,12 +27,22 @@ function getGraphModuleIcon(module: string) { return _.capitalize(module); } +const FilterBox = styled(Box)` + background: linear-gradient( + ${(p) => p.theme.colors.scales.white10} 0%, + ${(p) => p.theme.colors.scales.white60} 40%, + ${(p) => p.theme.colors.scales.white100} 100% + ); +`; + function describeNotification(description: string, plural: boolean) { switch (description) { case "link": - return `added ${plural ? "new links" : "a new link"} to`; + return `added ${pluralize("new link", plural)} to`; case "comment": - return `left ${plural ? "comments" : "a comment"} on`; + return `left ${pluralize("comment", plural)} on`; + case "note": + return `posted ${pluralize("note", plural)} to`; case "mention": return "mentioned you on"; default: @@ -45,21 +59,71 @@ const GraphUrl = ({ url, title }) => ( ); -const GraphNodeContent = ({ contents, module, description, index }) => { - if (module === "link") { - const lent = index.slice(1).split("/").length; - if (lent === 1) { +const GraphNodeContent = ({ contents, mod, description, index }) => { + const idx = index.slice(1).split("/"); + if (mod === "link") { + if (idx.length === 1) { const [{ text }, { url }] = contents; return ; - } else if (lent === 2) { + } else if (idx.length === 2) { const [{ text }] = contents; return {text}; } return null; } + if (mod === "publish") { + if (idx.length !== 3) { + return null; + } else if (idx[1] === "2") { + const [{ text }] = contents; + return {text}; + } else if (idx[1] === "1") { + const [{ text: header }, { text: body }] = contents; + const snippet = getSnippet(body); + return ( + + + {header} + + + {snippet} + + + + ); + } + } return null; }; -const GraphNode = ({ contents, author, module, description, time, index }) => { + +function getNodeUrl(mod: string, group: string, graph: string, index: string) { + const graphUrl = `/~landscape${group}/resource/${mod}${graph}`; + const idx = index.slice(1).split("/"); + if (mod === "publish") { + const [noteId] = idx; + return `${graphUrl}/note/${noteId}`; + } else if (mod === "link") { + const [linkId] = idx; + return `${graphUrl}/-${linkId}`; + } + return ""; +} +const GraphNode = ({ + contents, + author, + mod, + description, + time, + index, + graph, + group, +}) => { author = deSig(author); const img = ( @@ -72,34 +136,38 @@ const GraphNode = ({ contents, author, module, description, time, index }) => { /> ); + const nodeUrl = getNodeUrl(mod, group, graph, index); + return ( - - {img} - - - - {cite(author)} - - - {moment(time).format("HH:mm")} - - - - - - - + + + {img} + + + + {cite(author)} + + + {moment(time).format("HH:mm")} + + + + + + + + ); }; @@ -149,14 +217,15 @@ export function GraphNotification(props: { ))} ); } - diff --git a/pkg/interface/src/views/apps/notifications/inbox.tsx b/pkg/interface/src/views/apps/notifications/inbox.tsx index 4dfd5421bd..6792eca4fa 100644 --- a/pkg/interface/src/views/apps/notifications/inbox.tsx +++ b/pkg/interface/src/views/apps/notifications/inbox.tsx @@ -129,7 +129,7 @@ function DaySection({ return ( <> - + {moment(daToUnix(timeboxes[0][0])).calendar(null, calendar)} diff --git a/pkg/interface/src/views/landscape/components/ChannelMenu.tsx b/pkg/interface/src/views/landscape/components/ChannelMenu.tsx index 11d2e8a7d4..2599a7e641 100644 --- a/pkg/interface/src/views/landscape/components/ChannelMenu.tsx +++ b/pkg/interface/src/views/landscape/components/ChannelMenu.tsx @@ -6,6 +6,7 @@ import { Dropdown } from "~/views/components/Dropdown"; import { Association, NotificationGraphConfig } from "~/types"; import GlobalApi from "~/logic/api/global"; import { StatelessAsyncAction } from "~/views/components/StatelessAsyncAction"; +import {appIsGraph} from "~/logic/lib/util"; const ChannelMenuItem = ({ icon, @@ -99,7 +100,7 @@ export function ChannelMenu(props: ChannelMenuProps) { borderRadius={1} borderColor="lightGray" > - {metadata.module === "link" && ( + {appIsGraph(metadata.module) && (