Skip to content

Commit 0e65c48

Browse files
committed
refactor: Slack Templates is replaced by external plugin
1 parent 90be376 commit 0e65c48

34 files changed

Lines changed: 88 additions & 921 deletions

File tree

src/modules/mpn-automation/services/base-action-service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class BaseActionService implements ActionHandler {
3232
*/
3333
registerTemplate(
3434
name: string,
35-
renderer: TemplateRenderer
35+
renderer: any
3636
): void {
3737
this.templates_.set(name, renderer)
3838
}
@@ -42,7 +42,7 @@ export class BaseActionService implements ActionHandler {
4242
* @param name - Template name
4343
* @returns Template renderer or undefined
4444
*/
45-
getTemplate(name: string): TemplateRenderer | undefined {
45+
getTemplate(name: string): any | undefined {
4646
return this.templates_.get(name)
4747
}
4848

src/modules/mpn-automation/services/email-action-service.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FieldConfig } from "../types"
22
import { BaseActionService } from "./base-action-service"
3-
import { renderTemplate } from "@codee-sh/medusa-plugin-notification-emails/templates/emails"
3+
import { emailService } from "@codee-sh/medusa-plugin-notification-emails/templates/emails"
44
import { transformContext } from "@codee-sh/medusa-plugin-notification-emails/utils"
55

66
import type {
@@ -71,8 +71,12 @@ export class EmailActionService extends BaseActionService {
7171
* This method can be used to register custom templates if needed
7272
*/
7373
protected initializeTemplates(): void {
74-
// Email templates are handled by external plugin
75-
// Custom templates can be registered here if needed
74+
// Email engine already has all prebuild templates registered
75+
// You can register custom templates here if needed:
76+
// emailEngine.registerTemplate("custom-template", {
77+
// ...emailEngine.getBaseTemplate(),
78+
// getConfig: () => ({ blocks: [...], translations: {...} })
79+
// })
7680
}
7781

7882
/**
@@ -85,10 +89,6 @@ export class EmailActionService extends BaseActionService {
8589
context: TemplateData
8690
contextType?: string | null
8791
options?: TemplateOptionsType
88-
customTemplateFunction?: (
89-
data: TemplateData,
90-
options: TemplateOptionsType
91-
) => React.ReactElement<any>
9292
}): Promise<{
9393
html: string
9494
text: string
@@ -98,19 +98,21 @@ export class EmailActionService extends BaseActionService {
9898
templateName,
9999
context,
100100
contextType,
101-
options,
102-
customTemplateFunction,
101+
options = {}
103102
} = params
104103

105104
const transformedContext = transformContext(contextType, context)
106105

107-
const result = await renderTemplate(
106+
const result = await emailService.render({
108107
templateName,
109-
transformedContext,
110-
options || {},
111-
customTemplateFunction
112-
)
108+
data: transformedContext,
109+
options: options || {},
110+
})
113111

114-
return result
112+
return {
113+
html: result.html,
114+
text: result.text,
115+
subject: result.subject,
116+
}
115117
}
116118
}
Lines changed: 29 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
import { BaseActionService } from "./base-action-service"
2-
import {
3-
SlackTemplateRenderer,
4-
SlackBlock,
5-
} from "../../../templates/slack/types"
6-
import { renderInventoryLevel } from "../../../templates/slack/inventory-level"
7-
import { renderProductVariant } from "../../../templates/slack/product-variant/product-variant"
8-
import { renderProduct } from "../../../templates/slack/product/product"
9-
import { renderOrderPlaced } from "../../../templates/slack/order/order-placed"
10-
import { renderOrderCompleted } from "../../../templates/slack/order/order-completed"
11-
import { renderOrderUpdated } from "../../../templates/slack/order/order-updated"
12-
import { renderOrderCanceled } from "../../../templates/slack/order/order-canceled"
13-
import { renderOrderArchived } from "../../../templates/slack/order/order-archived"
2+
import { slackService } from "@codee-sh/medusa-plugin-notification-emails/templates/slack"
3+
import { transformContext } from "@codee-sh/medusa-plugin-notification-emails/utils"
144

155
export class SlackActionService extends BaseActionService {
166
id = "slack"
@@ -28,24 +18,16 @@ export class SlackActionService extends BaseActionService {
2818

2919
/**
3020
* Initialize default Slack templates
21+
* Slack engine already has all prebuild templates registered
22+
* This method can be used to register custom templates if needed
3123
*/
3224
protected initializeTemplates(): void {
33-
// Register default templates
34-
this.registerTemplate(
35-
"inventory-level",
36-
renderInventoryLevel as any
37-
)
38-
this.registerTemplate(
39-
"product-variant",
40-
renderProductVariant as any
41-
)
42-
this.registerTemplate("product", renderProduct as any)
43-
44-
this.registerTemplate("order-placed", renderOrderPlaced as any)
45-
this.registerTemplate("order-completed", renderOrderCompleted as any)
46-
this.registerTemplate("order-updated", renderOrderUpdated as any)
47-
this.registerTemplate("order-canceled", renderOrderCanceled as any)
48-
this.registerTemplate("order-archived", renderOrderArchived as any)
25+
// Slack engine already has all prebuild templates registered
26+
// You can register custom templates here if needed:
27+
// slackEngine.registerTemplate("custom-template", {
28+
// ...slackEngine.getBaseTemplate(),
29+
// getConfig: () => ({ blocks: [...], translations: {...} })
30+
// })
4931
}
5032

5133
/**
@@ -58,24 +40,28 @@ export class SlackActionService extends BaseActionService {
5840
context: any
5941
contextType?: string | null
6042
options?: any
61-
}): Promise<{ text: string; blocks: SlackBlock[] }> {
62-
const renderer = this.getTemplate(
63-
params.templateName
64-
) as SlackTemplateRenderer | undefined
43+
}): Promise<{ text: string; blocks: any[] }> {
6544

66-
if (!renderer) {
67-
throw new Error(
68-
`Slack template "${params.templateName}" not found. Available templates: ${Array.from(this.templates_.keys()).join(", ")}`
69-
)
70-
}
45+
const transformedContext = transformContext(params.contextType, params.context)
7146

72-
const result = renderer({
73-
context: params.context,
74-
contextType: params.contextType,
75-
options: params.options || {},
47+
const { blocks } = await slackService.render({
48+
templateName: params.templateName,
49+
data: {
50+
...transformedContext,
51+
backend_url: params.options?.backendUrl,
52+
},
53+
options: params.options
7654
})
7755

78-
// Handle both sync and async renderers
79-
return result instanceof Promise ? await result : result
56+
// For Slack, the 'text' field is a fallback for notifications that don't support blocks.
57+
// We can derive it from the first header block or a generic message.
58+
const fallbackText =
59+
blocks.find((b) => b.type === "header" && b.text?.text)?.text?.text ||
60+
`Notification for ${params.templateName}`
61+
62+
return {
63+
text: fallbackText,
64+
blocks: blocks,
65+
}
8066
}
8167
}

src/modules/mpn-automation/types/modules/inventory/inventory.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ export const INVENTORY_LEVEL_ATTRIBUTES = [
9292
isRelation: true,
9393
relationType: "stock_locations",
9494
},
95+
{
96+
value: "inventory_level.inventory_item.title",
97+
label: "Inventory Item Title",
98+
description: "Inventory item title",
99+
examples: ["Product A", "Product B", "Product C"],
100+
isRelation: true,
101+
relationType: "inventory_item",
102+
},
95103
]
96104

97105
// Fields for use in query.graph() - includes technical relations with *

src/providers/slack/service.ts

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -71,29 +71,40 @@ export class SlackNotificationProviderService extends AbstractNotificationProvid
7171
}
7272
}
7373

74-
const response = await fetch(
75-
this.options_.webhook_url,
76-
{
77-
method: "POST",
78-
body: JSON.stringify({
79-
text: content.text,
80-
blocks: content.blocks,
81-
}),
82-
headers: {
83-
"Content-Type": "application/json",
84-
},
74+
try {
75+
const response = await fetch(
76+
this.options_.webhook_url,
77+
{
78+
method: "POST",
79+
body: JSON.stringify({
80+
text: content.text,
81+
blocks: content.blocks,
82+
}),
83+
headers: {
84+
"Content-Type": "application/json",
85+
},
86+
}
87+
)
88+
89+
// Slack webhook API returns "ok" as plain text, not JSON
90+
const responseText = await response.text()
91+
92+
if (responseText !== "ok") {
93+
throw new MedusaError(
94+
MedusaError.Types.UNEXPECTED_STATE,
95+
`Failed to send notification to Slack: ${responseText}`
96+
)
8597
}
86-
)
8798

88-
if (!response.ok) {
89-
throw new MedusaError(
90-
MedusaError.Types.UNEXPECTED_STATE,
91-
"Failed to send notification to Slack"
92-
)
93-
}
99+
return {
100+
status: responseText === "ok" ? "success" : "failed",
101+
}
102+
} catch (error) {
103+
console.error("Failed to send notification to Slack", error)
94104

95-
return {
96-
status: response.ok ? "success" : "failed",
105+
return {
106+
status: "failed"
107+
}
97108
}
98109
}
99110
}

src/templates/slack/inventory-level/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/templates/slack/inventory-level/inventory-level.ts

Lines changed: 0 additions & 135 deletions
This file was deleted.

0 commit comments

Comments
 (0)