diff --git a/bootstrapping-lambda/local/index.html b/bootstrapping-lambda/local/index.html
index 23aa3dda..c7d318c7 100644
--- a/bootstrapping-lambda/local/index.html
+++ b/bootstrapping-lambda/local/index.html
@@ -38,7 +38,7 @@
Remove pinboard pre-selection
- Starred messages
+ Starred messages (requires pinboard pre-selection)
via hidden element (for invalid/untracked composer ID)
diff --git a/client/src/formattedDateTime.tsx b/client/src/formattedDateTime.tsx
index 74180a19..9e9d3b14 100644
--- a/client/src/formattedDateTime.tsx
+++ b/client/src/formattedDateTime.tsx
@@ -4,7 +4,7 @@ import { formatDateTime } from "./util";
export const TickContext = React.createContext(Date.now());
interface FormattedDateTimeProps {
- timestamp: number;
+ timestamp: number | string;
isPartOfSentence?: true;
withAgo?: true;
}
diff --git a/client/src/itemDisplay.tsx b/client/src/itemDisplay.tsx
index 17184101..e4612423 100644
--- a/client/src/itemDisplay.tsx
+++ b/client/src/itemDisplay.tsx
@@ -78,8 +78,6 @@ export const ItemDisplay = ({
[item.id, item.message]
);
- const dateInMillisecs = new Date(item.timestamp).valueOf();
-
const isDifferentUserFromPreviousItem =
maybePreviousItem?.userEmail !== item.userEmail;
@@ -172,7 +170,7 @@ export const ItemDisplay = ({
margin-bottom: 2px;
`}
>
-
+
{isEdited && - Edited}
{maybeRelatedItem && item.type !== "claim" && (
- Reply
diff --git a/client/src/nestedItemDisplay.tsx b/client/src/nestedItemDisplay.tsx
index 13362a23..a68933c0 100644
--- a/client/src/nestedItemDisplay.tsx
+++ b/client/src/nestedItemDisplay.tsx
@@ -103,7 +103,7 @@ export const NestedItemDisplay = ({
margin-left: ${payloadAndType ? 0 : 10}px;
`}
>
-
+
{item.editHistory && item.editHistory.length > 0 && (
- Edited
)}
diff --git a/client/src/pinboard.tsx b/client/src/pinboard.tsx
index ea9206ac..a29e2b3d 100644
--- a/client/src/pinboard.tsx
+++ b/client/src/pinboard.tsx
@@ -400,7 +400,11 @@ export const Pinboard: React.FC = ({
{isPinboardData(preselectedPinboard) &&
preselectedPinboard.id === pinboardId &&
maybeStarredMessagesArea && (
-
+
)}
);
diff --git a/client/src/starred/starredMessages.tsx b/client/src/starred/starredMessages.tsx
index 4235a230..0574b552 100644
--- a/client/src/starred/starredMessages.tsx
+++ b/client/src/starred/starredMessages.tsx
@@ -1,19 +1,73 @@
import React from "react";
import ReactDOM from "react-dom";
+import { Item } from "shared/graphql/graphql";
+import root from "react-shadow/emotion";
+import { UserLookup } from "../types/UserLookup";
+import { FormattedDateTime } from "../formattedDateTime";
+import { css } from "@emotion/react";
+import { agateSans } from "../../fontNormaliser";
+import { neutral, space } from "@guardian/source-foundations";
export const STARRED_MESSAGES_HTML_TAG = "pinboard-starred-messages";
-// interface StarredMessagesProps {}
+const StarredItemDisplay = ({
+ item,
+ userLookup,
+}: {
+ item: Item;
+ userLookup: UserLookup;
+}) => {
+ const user = userLookup[item.userEmail];
+ return (
+
+
+ {item.message}
+
+
+ {user.firstName} {user.lastName}
+
+
+
+
+
+ );
+};
-const StarredMessages = (/* props: StarredMessagesProps */) => (
-
-);
+interface StarredMessagesProps {
+ items: Item[];
+ userLookup: UserLookup;
+}
+
+const StarredMessages = ({ items, userLookup }: StarredMessagesProps) => {
+ const starredMessages = items.filter((item) => item.isStarred);
+ return (
+
+ {starredMessages.map((item) => (
+
+ ))}
+
+ );
+};
-interface StarredMessagesPortalProps {
+interface StarredMessagesPortalProps extends StarredMessagesProps {
node: Element;
}
-export const StarredMessagesPortal = ({ node }: StarredMessagesPortalProps) =>
- ReactDOM.createPortal(, node);
+export const StarredMessagesPortal = ({
+ node,
+ ...props
+}: StarredMessagesPortalProps) =>
+ ReactDOM.createPortal(, node);
diff --git a/client/src/util.ts b/client/src/util.ts
index 2650e8e8..87db7be2 100644
--- a/client/src/util.ts
+++ b/client/src/util.ts
@@ -13,11 +13,15 @@ export const getTooltipText = (
) => `WT: ${workingTitle}` + (headline ? `\nHL: ${headline}` : "");
export const formatDateTime = (
- timestamp: number,
- isPartOfSentence?: true,
- withAgo?: true
+ timestampStringOrEpochMillis: number | string,
+ isPartOfSentence?: boolean,
+ withAgo?: boolean
): string => {
const now = Date.now();
+ const timestamp =
+ typeof timestampStringOrEpochMillis === "string"
+ ? new Date(timestampStringOrEpochMillis).valueOf()
+ : timestampStringOrEpochMillis;
if (isThisYear(timestamp)) {
if (isToday(timestamp)) {
if (differenceInMinutes(now, timestamp) < 1) {
@@ -32,7 +36,7 @@ export const formatDateTime = (
return (
formatDistanceStrict(timestamp, now, {
roundingMethod: "floor",
- }).slice(0, -4) + (withAgo ? " ago" : "")
+ }).slice(0, -4) + (withAgo ? "s ago" : "")
);
}
return format(timestamp, "HH:mm");
diff --git a/client/test/formattedDateTime.test.ts b/client/test/formattedDateTime.test.ts
index 0592f1e4..a1711bda 100644
--- a/client/test/formattedDateTime.test.ts
+++ b/client/test/formattedDateTime.test.ts
@@ -28,6 +28,13 @@ test("display is correct if timestamp is between 2 min and 1 hr ago", () => {
expect(formatDateTime(twoMinsAgo)).toBe("2 min");
const lessThanHr = subMinutes(Date.now(), 59).valueOf();
expect(formatDateTime(lessThanHr)).toBe("59 min");
+ const pluralMinsWithAgo = subMinutes(Date.now(), 3).valueOf();
+ expect(formatDateTime(pluralMinsWithAgo, false, true)).toBe("3 mins ago");
+});
+
+test("display is correct if passed a string", () => {
+ const twoMinsAgoString = subMinutes(Date.now(), 2).toISOString();
+ expect(formatDateTime(twoMinsAgoString)).toBe("2 min");
});
test("display is correct if timestamp is 1 hr ago exactly", () => {