mirror of
https://fast.feibisi.com/https://github.com/parcelvoy/platform.git
synced 2025-09-01 12:26:08 +08:00
Improved Webhook Handling (#676)
This commit is contained in:
parent
d1e9df8f70
commit
6374fbabd2
14 changed files with 55 additions and 16 deletions
|
@ -29,7 +29,9 @@ export class SQLModel extends RawModel {
|
|||
|
||||
// Take JSON attributes and stringify before insertion
|
||||
for (const attribute of this.jsonAttributes) {
|
||||
obj[attribute] = JSON.stringify(obj[attribute])
|
||||
obj[attribute] = obj[attribute] == null
|
||||
? undefined
|
||||
: JSON.stringify(obj[attribute])
|
||||
}
|
||||
|
||||
return this.formatJson(obj)
|
||||
|
|
|
@ -221,9 +221,7 @@ export const notifyJourney = async (reference_id: string, response?: any) => {
|
|||
// Save response into user step
|
||||
if (response) {
|
||||
await JourneyUserStep.update(q => q.where('id', referenceId), {
|
||||
data: {
|
||||
response,
|
||||
},
|
||||
data: response,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ export default class LocalWebhookProvider extends WebhookProvider {
|
|||
|
||||
if (response.ok) {
|
||||
return {
|
||||
message: options,
|
||||
request: options,
|
||||
success: true,
|
||||
response: responseBody,
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export default class LoggerWebhookProvider extends WebhookProvider {
|
|||
|
||||
logger.info(options, 'provider:webhook:logger')
|
||||
return {
|
||||
message: options,
|
||||
request: options,
|
||||
success: true,
|
||||
response: '',
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ export interface Webhook {
|
|||
}
|
||||
|
||||
export interface WebhookResponse {
|
||||
message: Webhook
|
||||
request: Webhook
|
||||
success: boolean
|
||||
response: Record<string, any> | string
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ export default class WebhookJob extends Job {
|
|||
|
||||
try {
|
||||
const result = await channel.send(template, data)
|
||||
await finalizeSend(data, result)
|
||||
await finalizeSend(data, result.response)
|
||||
} catch (error: any) {
|
||||
await failSend(data, error)
|
||||
} finally {
|
||||
|
|
|
@ -124,7 +124,7 @@ export const sendProof = async (template: TemplateType, variables: Variables, re
|
|||
logger.info(response, 'template:proof:push:result')
|
||||
} else if (template.type === 'webhook') {
|
||||
const channel = await loadWebhookChannel(campaign.provider_id, project.id)
|
||||
await channel?.send(template, variables)
|
||||
response = await channel?.send(template, variables)
|
||||
} else {
|
||||
throw new RequestError('Sending template proofs is only supported for email and text message types as this time.')
|
||||
}
|
||||
|
@ -141,6 +141,8 @@ export const sendProof = async (template: TemplateType, variables: Variables, re
|
|||
},
|
||||
},
|
||||
}).queue()
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// Determine what template to send to the user based on the following:
|
||||
|
|
|
@ -48,6 +48,14 @@
|
|||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.heading.heading-h5 {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.heading.heading-h4 h4 {
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.heading label, .heading input {
|
||||
margin: 0;
|
||||
}
|
|
@ -2,7 +2,7 @@ import './Heading.css'
|
|||
|
||||
interface HeadingProps {
|
||||
title: React.ReactNode
|
||||
size?: 'h2' | 'h3' | 'h4'
|
||||
size?: 'h2' | 'h3' | 'h4' | 'h5'
|
||||
actions?: React.ReactNode
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
|
|
@ -157,6 +157,17 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.webhook-frame .heading {
|
||||
background: var(--color-grey);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 5px 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.webhook-frame .webhook-block {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.preview.small .email-frame iframe {
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
|
@ -173,4 +184,11 @@
|
|||
border-radius: 0;
|
||||
transform: scale(0.8);
|
||||
transform-origin: top left;
|
||||
}
|
||||
|
||||
.preview.small .webhook-frame {
|
||||
padding: 5px 10px;
|
||||
transform: scale(0.8);
|
||||
transform-origin: top left;
|
||||
width: 125%;
|
||||
}
|
|
@ -6,13 +6,15 @@ import { ReactNode, useContext } from 'react'
|
|||
import { ProjectContext } from '../contexts'
|
||||
import JsonPreview from './JsonPreview'
|
||||
import clsx from 'clsx'
|
||||
import Heading from './Heading'
|
||||
|
||||
interface PreviewProps {
|
||||
template: Pick<Template, 'type' | 'data'>
|
||||
response?: any
|
||||
size?: 'small' | 'large'
|
||||
}
|
||||
|
||||
export default function Preview({ template, size = 'large' }: PreviewProps) {
|
||||
export default function Preview({ template, response, size = 'large' }: PreviewProps) {
|
||||
const [project] = useContext(ProjectContext)
|
||||
const { data, type } = template
|
||||
|
||||
|
@ -59,7 +61,14 @@ export default function Preview({ template, size = 'large' }: PreviewProps) {
|
|||
} else if (type === 'webhook') {
|
||||
preview = (
|
||||
<div className="webhook-frame">
|
||||
<JsonPreview value={data} />
|
||||
<div className="webhook-block">
|
||||
<Heading title="Request" size="h5" />
|
||||
<JsonPreview value={data} />
|
||||
</div>
|
||||
{response && <div className="webhook-block">
|
||||
<Heading title="Response" size="h5" />
|
||||
<JsonPreview value={response.data} />
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
--color-primary: var(--color-black);
|
||||
--color-primary-soft: #6b707b;
|
||||
|
||||
--color-grey: #eae8e8;
|
||||
--color-grey: #e8e8ea;
|
||||
--color-grey-soft: #F5F5F7;
|
||||
--color-grey-hard: #cecfd2;
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ export default function CampaignPreview() {
|
|||
const [isUserLookupOpen, setIsUserLookupOpen] = useState(false)
|
||||
const [isSendProofOpen, setIsSendProofOpen] = useState(false)
|
||||
const template = campaignState[0].templates.find(template => template.locale === currentLocale?.key)
|
||||
const [proofResponse, setProofResponse] = useState<any>(undefined)
|
||||
|
||||
if (!template) {
|
||||
return (<>
|
||||
|
@ -82,10 +83,11 @@ export default function CampaignPreview() {
|
|||
|
||||
const handleSendProof = async (recipient: string) => {
|
||||
try {
|
||||
await api.templates.proof(project.id, template.id, {
|
||||
const response = await api.templates.proof(project.id, template.id, {
|
||||
variables: JSON.parse(value ?? '{}'),
|
||||
recipient,
|
||||
})
|
||||
setProofResponse(response)
|
||||
} catch (error: any) {
|
||||
if (error.response.data.error) {
|
||||
toast.error(error.response.data.error)
|
||||
|
@ -136,7 +138,7 @@ export default function CampaignPreview() {
|
|||
variant="secondary"
|
||||
onClick={() => setIsSendProofOpen(true)}>{t('send_proof')}</Button>
|
||||
} />
|
||||
<Preview template={{ type: template.type, data }} />
|
||||
<Preview template={{ type: template.type, data }} response={proofResponse} />
|
||||
</Column>
|
||||
</Columns>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ title: Weekly Summary
|
|||
sidebar_position: 3
|
||||
---
|
||||
|
||||
# Weely Summary
|
||||
# Weekly Summary
|
||||
|
||||
## Scenario
|
||||
You have an e-commerce site and you want to sent weekly stats to all vendors that sell products through your platform, letting them know how many people viewed and purchased their products in the past 7 days.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue