Skip to content

Commit

Permalink
WIP: Display starred messages in dedicated component (which will disp…
Browse files Browse the repository at this point in the history
…lay at the top of Composer articles)

Co-Authored-By: Tom Richards <[email protected]>
  • Loading branch information
frederickobrien and twrichards committed Sep 29, 2023
1 parent 28165b1 commit 02f3625
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 20 deletions.
2 changes: 1 addition & 1 deletion bootstrapping-lambda/local/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ <h4>
Remove pinboard pre-selection
</button>

<h5>Starred messages</h5>
<h5>Starred messages (requires pinboard pre-selection)</h5>
<pinboard-starred-messages></pinboard-starred-messages>

<h4>via hidden element (for invalid/untracked composer ID)</h4>
Expand Down
2 changes: 1 addition & 1 deletion client/src/formattedDateTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { formatDateTime } from "./util";
export const TickContext = React.createContext<number>(Date.now());

interface FormattedDateTimeProps {
timestamp: number;
timestamp: number | string;
isPartOfSentence?: true;
withAgo?: true;
}
Expand Down
4 changes: 1 addition & 3 deletions client/src/itemDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ export const ItemDisplay = ({
[item.id, item.message]
);

const dateInMillisecs = new Date(item.timestamp).valueOf();

const isDifferentUserFromPreviousItem =
maybePreviousItem?.userEmail !== item.userEmail;

Expand Down Expand Up @@ -172,7 +170,7 @@ export const ItemDisplay = ({
margin-bottom: 2px;
`}
>
<FormattedDateTime timestamp={dateInMillisecs} />
<FormattedDateTime timestamp={item.timestamp} />
{isEdited && <span>&nbsp;-&nbsp;Edited</span>}
{maybeRelatedItem && item.type !== "claim" && (
<span>&nbsp;-&nbsp;Reply</span>
Expand Down
2 changes: 1 addition & 1 deletion client/src/nestedItemDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const NestedItemDisplay = ({
margin-left: ${payloadAndType ? 0 : 10}px;
`}
>
<FormattedDateTime timestamp={new Date(item.timestamp).valueOf()} />
<FormattedDateTime timestamp={item.timestamp} />
{item.editHistory && item.editHistory.length > 0 && (
<span> - Edited</span>
)}
Expand Down
6 changes: 5 additions & 1 deletion client/src/pinboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,11 @@ export const Pinboard: React.FC<PinboardProps> = ({
{isPinboardData(preselectedPinboard) &&
preselectedPinboard.id === pinboardId &&
maybeStarredMessagesArea && (
<StarredMessagesPortal node={maybeStarredMessagesArea} />
<StarredMessagesPortal
node={maybeStarredMessagesArea}
items={items}
userLookup={userLookup}
/>
)}
</React.Fragment>
);
Expand Down
72 changes: 63 additions & 9 deletions client/src/starred/starredMessages.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div
css={css`
${agateSans.xsmall()};
display: flex;
align-items: flex-end;
gap: ${space[1]}px;
color: ${neutral[20]};
`}
>
<span
css={css`
color: ${neutral[0]};
${agateSans.medium()};
`}
>
{item.message}
</span>
<span title={item.userEmail}>
{user.firstName} {user.lastName}
</span>
<span>
<FormattedDateTime timestamp={item.timestamp} withAgo />
</span>
</div>
);
};

const StarredMessages = (/* props: StarredMessagesProps */) => (
<div>
<p>Starred Messages</p>
</div>
);
interface StarredMessagesProps {
items: Item[];
userLookup: UserLookup;
}

const StarredMessages = ({ items, userLookup }: StarredMessagesProps) => {
const starredMessages = items.filter((item) => item.isStarred);
return (
<root.div>
{starredMessages.map((item) => (
<StarredItemDisplay key={item.id} item={item} userLookup={userLookup} />
))}
</root.div>
);
};

interface StarredMessagesPortalProps {
interface StarredMessagesPortalProps extends StarredMessagesProps {
node: Element;
}

export const StarredMessagesPortal = ({ node }: StarredMessagesPortalProps) =>
ReactDOM.createPortal(<StarredMessages />, node);
export const StarredMessagesPortal = ({
node,
...props
}: StarredMessagesPortalProps) =>
ReactDOM.createPortal(<StarredMessages {...props} />, node);
12 changes: 8 additions & 4 deletions client/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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");
Expand Down
7 changes: 7 additions & 0 deletions client/test/formattedDateTime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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", () => {
Expand Down

0 comments on commit 02f3625

Please sign in to comment.