Skip to content

Commit

Permalink
WIP fronts integration PLUS 'suggest alternate crops' buttons (for co…
Browse files Browse the repository at this point in the history
…mposer trail image, see guardian/flexible-content#4984)
  • Loading branch information
twrichards committed Oct 10, 2024
1 parent 9a2870b commit 9794e12
Show file tree
Hide file tree
Showing 8 changed files with 465 additions and 55 deletions.
7 changes: 7 additions & 0 deletions bootstrapping-lambda/local/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ <h3>Override unread notifications bubble</h3>
<button id="btn-unset-unread-notifications-bubble">Unset</button>
</div>

<h3>Fronts Integration</h3>
<pinboard-article-button
data-url-path="global/2024/oct/08/testing"
></pinboard-article-button>
<pinboard-suggest-alternate-crops
data-current-crop-url="https://media.test.dev-gutools.co.uk/images/0b146eaac0b6a83727568c8e47eb52d78d83bc72?crop=0_175_4362_2615"
></pinboard-suggest-alternate-crops>
<h3><code>Add to 📌</code> button</h3>
<ul id="button_section">
<h4>present initially</h4>
Expand Down
45 changes: 8 additions & 37 deletions client/src/addToPinboardButton.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import ReactDOM from "react-dom";
import React, { ReactPortal, useContext } from "react";
import PinIcon from "../icons/pin-icon.svg";
import { css } from "@emotion/react";
import { pinboard, pinMetal } from "../colours";
import { buildPayloadAndType, PayloadAndType } from "./types/PayloadAndType";
import { space } from "@guardian/source-foundations";
import { agateSans } from "../fontNormaliser";
Expand All @@ -13,35 +11,10 @@ import {
IMAGINE_REQUEST_TYPES,
IMAGING_REQUEST_ITEM_TYPE,
} from "shared/octopusImaging";
import { ButtonInOtherTools } from "./buttonInOtherTools";

export const ASSET_HANDLE_HTML_TAG = "asset-handle";

const buttonCss = css`
display: flex;
align-items: center;
background-color: ${pinboard[500]};
${agateSans.xxsmall({ fontWeight: "bold" })};
border: none;
border-radius: 100px;
padding: 0 6px 0 10px;
line-height: 2;
cursor: pointer;
color: ${pinMetal};
`;

const pinIcon = (
<PinIcon
css={css`
height: 14px;
margin-left: 2px;
path {
stroke: ${pinMetal};
stroke-width: 1px;
}
`}
/>
);

interface AddToPinboardButtonProps {
dataAttributes: DOMStringMap;
setPayloadToBeSent: (payload: PayloadAndType | null) => void;
Expand Down Expand Up @@ -75,23 +48,23 @@ const AddToPinboardButton = (props: AddToPinboardButtonProps) => {
${agateSans.small()}
`}
>
<button
<ButtonInOtherTools
iconAtEnd
onClick={() => {
props.setPayloadToBeSent(payloadToBeSent);
props.expand();
sendTelemetryEvent?.(PINBOARD_TELEMETRY_TYPE.ADD_TO_PINBOARD_BUTTON, {
assetType: payloadToBeSent.type,
});
}}
css={buttonCss}
>
{payloadToBeSent.type === "grid-search"
? "Add this search to"
: "Add to"}
{pinIcon}
</button>
</ButtonInOtherTools>
{payloadToBeSent.type === "grid-original" && (
<button
<ButtonInOtherTools
iconAtEnd
onClick={() => {
props.setPayloadToBeSent({
type: IMAGING_REQUEST_ITEM_TYPE,
Expand All @@ -108,15 +81,13 @@ const AddToPinboardButton = (props: AddToPinboardButtonProps) => {
}
);
}}
css={css`
${buttonCss};
extraCss={css`
white-space: nowrap;
margin-top: ${space[1]}px;
`}
>
Imaging order
{pinIcon}
</button>
</ButtonInOtherTools>
)}
</root.div>
);
Expand Down
43 changes: 43 additions & 0 deletions client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ import { getAgateFontFaceIfApplicable } from "../fontNormaliser";
import { Global } from "@emotion/react";
import { TourStateProvider } from "./tour/tourState";
import { demoMentionableUsers, demoUser } from "./tour/tourConstants";
import {
FRONTS_PINBOARD_ELEMENTS_QUERY_SELECTOR,
FrontsIntegration,
} from "./fronts/frontsIntegration";
import {
SUGGEST_ALTERNATE_CROP_QUERY_SELECTOR,
SuggestAlternateCrops,
} from "./fronts/suggestAlternateCrops";

const PRESELECT_PINBOARD_HTML_TAG = "pinboard-preselect";
const PRESET_UNREAD_NOTIFICATIONS_COUNT_HTML_TAG = "pinboard-bubble-preset";
Expand All @@ -67,6 +75,11 @@ export const PinBoardApp = ({
const [workflowPinboardElements, setWorkflowPinboardElements] = useState<
HTMLElement[]
>([]);
const [frontsPinboardElements, setFrontsPinboardElements] = useState<
HTMLElement[]
>([]);
const [alternateCropSuggestionElements, setAlternateCropSuggestionElements] =
useState<HTMLElement[]>([]);

const [maybeInlineSelectedPinboardId, _setMaybeInlineSelectedPinboardId] =
useState<string | null>(null);
Expand Down Expand Up @@ -95,6 +108,20 @@ export const PinBoardApp = ({
)
);

const refreshFrontsPinboardElements = () =>
setFrontsPinboardElements(
Array.from(
document.querySelectorAll(FRONTS_PINBOARD_ELEMENTS_QUERY_SELECTOR)
)
);

const refreshAlternateCropSuggestionElements = () =>
setAlternateCropSuggestionElements(
Array.from(
document.querySelectorAll(SUGGEST_ALTERNATE_CROP_QUERY_SELECTOR)
)
);

const refreshPreselectedPinboard = () => {
const preselectPinboardHTMLElement: HTMLElement | null =
document.querySelector(PRESELECT_PINBOARD_HTML_TAG);
Expand Down Expand Up @@ -129,6 +156,8 @@ export const PinBoardApp = ({
// Add nodes that already exist at time React app is instantiated
refreshAssetHandleNodes();
refreshWorkflowPinboardElements();
refreshFrontsPinboardElements();
refreshAlternateCropSuggestionElements();

refreshPreselectedPinboard();

Expand All @@ -138,6 +167,8 @@ export const PinBoardApp = ({
new MutationObserver(() => {
refreshAssetHandleNodes();
refreshWorkflowPinboardElements();
refreshFrontsPinboardElements();
refreshAlternateCropSuggestionElements();
refreshPreselectedPinboard();
refreshPresetUnreadNotifications();
}).observe(document.body, {
Expand Down Expand Up @@ -436,6 +467,18 @@ export const PinBoardApp = ({
)}
</TickContext.Provider>
</root.div>
{frontsPinboardElements.length > 0 && (
<FrontsIntegration
frontsPinboardElements={frontsPinboardElements}
/>
)}
{alternateCropSuggestionElements.length > 0 && (
<SuggestAlternateCrops
alternateCropSuggestionElements={
alternateCropSuggestionElements
}
/>
)}
{assetHandles.map((node, index) => (
<AddToPinboardButtonPortal
key={index}
Expand Down
47 changes: 47 additions & 0 deletions client/src/buttonInOtherTools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { PropsWithChildren } from "react";
import { css, SerializedStyles } from "@emotion/react";
import { pinboard, pinMetal } from "../colours";
import PinIcon from "../icons/pin-icon.svg";
import { agateSans } from "../fontNormaliser";

interface ButtonInOtherToolsProps {
iconAtEnd?: true;
onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
extraCss?: SerializedStyles;
}
export const ButtonInOtherTools = ({
children,
iconAtEnd,
onClick,
extraCss,
}: PropsWithChildren<ButtonInOtherToolsProps>) => (
<button
onClick={onClick}
css={css`
display: flex;
align-items: center;
background-color: ${pinboard[500]};
${agateSans.xxsmall({ fontWeight: "bold" })};
border: none;
border-radius: 100px;
padding: 0 ${iconAtEnd ? 6 : 10}px 0 ${iconAtEnd ? 10 : 6}px;
line-height: 2;
cursor: pointer;
color: ${pinMetal};
${extraCss};
`}
>
{iconAtEnd && children}
<PinIcon
css={css`
height: 14px;
margin-${iconAtEnd ? "left" : "right"}: 2px;
path {
stroke: ${pinMetal};
stroke-width: 1px;
}
`}
/>
{!iconAtEnd && children}
</button>
);
Loading

0 comments on commit 9794e12

Please sign in to comment.