| @@ -1,6 +1,7 @@ | ||
| 1 | 1 | import { useFollowUpHistory } from '@agent/follow-ups/history'; |
| 2 | 2 | import { cards } from '@agent/follow-ups/registry'; |
| 3 | +import { doReload } from '@agent/lib/reload'; | |
| 3 | 4 | import { useChatStore } from '@agent/state/chat'; |
| 4 | 5 | import { workflows } from '@agent/workflows/workflows'; |
| 5 | 6 | import { track } from '@shared/lib/track'; |
| 6 | 7 | import { useEffect } from '@wordpress/element'; |
| @@ -12,8 +13,19 @@ | ||
| 12 | 13 | const target = workflows.find(({ id }) => id === workflowId); |
| 13 | 14 | return { message: target?.example?.text }; |
| 14 | 15 | }; |
| 15 | 16 | |
| 17 | +const newTab = { target: '_blank', rel: 'noopener noreferrer' }; | |
| 18 | + | |
| 19 | +const toolContext = (card, previous) => { | |
| 20 | + try { | |
| 21 | + return card.toolContext?.(previous); | |
| 22 | + } catch (error) { | |
| 23 | + // A throw here would swallow the message the user clicked to send. | |
| 24 | + window.extSharedData?.devbuild && console.error(error); | |
| 25 | + } | |
| 26 | +}; | |
| 27 | + | |
| 16 | 28 | export const FollowUpCard = ({ message }) => { |
| 17 | 29 | const updateMessage = useChatStore((state) => state.updateMessage); |
| 18 | 30 | const { |
| 19 | 31 | cards: history, |
| @@ -20,9 +32,9 @@ | ||
| 20 | 32 | markShown, |
| 21 | 33 | markClicked, |
| 22 | 34 | markDismissed, |
| 23 | 35 | } = useFollowUpHistory(); |
| 24 | - const { workflowId, followUp, followUpData: data } = message.details; | |
| 36 | + const { workflowId, label, followUp, followUpData: data } = message.details; | |
| 25 | 37 | const card = cards.find(({ id }) => id === followUp); |
| 26 | 38 | const shownFor = history[card?.id]?.shownFor; |
| 27 | 39 | |
| 28 | 40 | // Without shownFor, every reload with the card open counts another view. |
| @@ -46,8 +58,14 @@ | ||
| 46 | 58 | track('agent_follow_up_click', { id: card.id, workflowId }); |
| 47 | 59 | card.onClick?.(data); |
| 48 | 60 | close(); |
| 49 | 61 | }; |
| 62 | + const handleLink = (event) => { | |
| 63 | + handleClick(); | |
| 64 | + if (!action.sameTab) return; | |
| 65 | + event.preventDefault(); | |
| 66 | + doReload(action.url); | |
| 67 | + }; | |
| 50 | 68 | const handleDismiss = () => { |
| 51 | 69 | markDismissed(card.id); |
| 52 | 70 | track('agent_follow_up_dismiss', { id: card.id, workflowId }); |
| 53 | 71 | close(); |
| @@ -53,11 +71,21 @@ | ||
| 53 | 71 | close(); |
| 54 | 72 | }; |
| 55 | 73 | const handleAction = () => { |
| 56 | 74 | handleClick(); |
| 75 | + const detail = submitFor(action); | |
| 76 | + const step = { | |
| 77 | + id: 'get-clicked-suggestion-context', | |
| 78 | + // Without suggestionSent and a card nextStep the fill asks what "this" means. | |
| 79 | + result: { | |
| 80 | + suggestionSent: detail.message, | |
| 81 | + shownAfter: label ?? workflowId, | |
| 82 | + ...toolContext(card, { workflowId, data }), | |
| 83 | + }, | |
| 84 | + }; | |
| 57 | 85 | window.dispatchEvent( |
| 58 | 86 | new CustomEvent('extendify-agent:chat-submit', { |
| 59 | - detail: submitFor(action), | |
| 87 | + detail: action.workflowId ? detail : { ...detail, step }, | |
| 60 | 88 | }), |
| 61 | 89 | ); |
| 62 | 90 | }; |
| 63 | 91 | const primary = |
| @@ -87,12 +115,11 @@ | ||
| 87 | 115 | <div className="mt-3 flex flex-wrap gap-2"> |
| 88 | 116 | {action.url ? ( |
| 89 | 117 | <a |
| 90 | 118 | href={action.url} |
| 91 | - target="_blank" | |
| 92 | - rel="noopener noreferrer" | |
| 119 | + {...(!action.sameTab && newTab)} | |
| 93 | 120 | className={`${primary} no-underline`} |
| 94 | - onClick={handleClick} | |
| 121 | + onClick={handleLink} | |
| 95 | 122 | > |
| 96 | 123 | {action.label} |
| 97 | 124 | </a> |
| 98 | 125 | ) : ( |