@heliyos/heliyos-api-core 1.0.68 → 1.0.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/email/index.d.ts
CHANGED
|
@@ -9,5 +9,6 @@ export declare const emailTemplates: {
|
|
|
9
9
|
notificationImmediateGrouped: string;
|
|
10
10
|
notificationDailySummary: string;
|
|
11
11
|
organizationDailySummary: string;
|
|
12
|
+
integrationNotSynced: string;
|
|
12
13
|
};
|
|
13
14
|
export declare const getEmailTemplate: (template: string, data: object) => string;
|
package/dist/email/index.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.emailTemplates = {
|
|
|
41
41
|
notificationImmediateGrouped: "notification-immediate-grouped.html",
|
|
42
42
|
notificationDailySummary: "notification-daily-summary.html",
|
|
43
43
|
organizationDailySummary: "organization-daily-summary.html",
|
|
44
|
+
integrationNotSynced: "integration-not-synced.html",
|
|
44
45
|
};
|
|
45
46
|
/**
|
|
46
47
|
* Simple markdown to HTML converter for email templates
|
|
@@ -52,12 +53,12 @@ const markdownToHtml = (text) => {
|
|
|
52
53
|
// Bold: **text** or __text__
|
|
53
54
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
54
55
|
.replace(/__(.*?)__/g, "<strong>$1</strong>")
|
|
55
|
-
// Italics: *text*
|
|
56
|
+
// Italics: *text* (intentionally avoid _text_ to keep URLs/query keys intact)
|
|
56
57
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
57
|
-
.replace(/_(.*?)_/g, "<em>$1</em>")
|
|
58
58
|
// Newlines to <br>
|
|
59
59
|
.replace(/\n/g, "<br>");
|
|
60
60
|
};
|
|
61
|
+
const URL_LIKE_PATTERN = /^(https?:\/\/|mailto:|tel:)\S+$/i;
|
|
61
62
|
/**
|
|
62
63
|
* Recursively process object values to convert markdown to HTML
|
|
63
64
|
*/
|
|
@@ -65,6 +66,9 @@ const processMarkdownData = (data) => {
|
|
|
65
66
|
if (!data)
|
|
66
67
|
return data;
|
|
67
68
|
if (typeof data === "string") {
|
|
69
|
+
if (URL_LIKE_PATTERN.test(data.trim())) {
|
|
70
|
+
return data;
|
|
71
|
+
}
|
|
68
72
|
return markdownToHtml(data);
|
|
69
73
|
}
|
|
70
74
|
if (Array.isArray(data)) {
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Integration Not Synched</title>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: Arial, sans-serif;
|
|
11
|
+
line-height: 1.6;
|
|
12
|
+
color: #0e0d0c;
|
|
13
|
+
background-color: #f8f8f6;
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.container {
|
|
19
|
+
max-width: 600px;
|
|
20
|
+
margin: 20px auto;
|
|
21
|
+
background-color: #ffffff;
|
|
22
|
+
border: 2px solid #7c3aed;
|
|
23
|
+
border-radius: 12px;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.header {
|
|
28
|
+
background-color: #7c3aed;
|
|
29
|
+
padding: 30px 20px;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.header img {
|
|
34
|
+
max-width: 180px;
|
|
35
|
+
height: auto;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.content {
|
|
39
|
+
padding: 30px;
|
|
40
|
+
color: #2c2721;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.button {
|
|
44
|
+
display: inline-block;
|
|
45
|
+
padding: 12px 24px;
|
|
46
|
+
background-color: #7c3aed;
|
|
47
|
+
color: #ffffff !important;
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
border-radius: 8px;
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
margin-top: 20px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.button:hover {
|
|
55
|
+
background-color: #6d28d9;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.footer {
|
|
59
|
+
background-color: #ebe7db;
|
|
60
|
+
padding: 20px;
|
|
61
|
+
text-align: center;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
color: #5c5545;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.warning-box {
|
|
67
|
+
background-color: #fff3cd;
|
|
68
|
+
border-left: 4px solid #ffc107;
|
|
69
|
+
padding: 16px;
|
|
70
|
+
margin: 20px 0;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.details-table {
|
|
75
|
+
width: 100%;
|
|
76
|
+
border: 1px solid #e5e7eb;
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
border-collapse: collapse;
|
|
79
|
+
margin: 20px 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.details-table td {
|
|
83
|
+
padding: 10px 12px;
|
|
84
|
+
border-bottom: 1px solid #f3f4f6;
|
|
85
|
+
font-size: 13px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.details-label {
|
|
89
|
+
color: #5c5545;
|
|
90
|
+
width: 160px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.details-value {
|
|
94
|
+
color: #0e0d0c;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
|
|
99
|
+
<body>
|
|
100
|
+
<div class="container">
|
|
101
|
+
<div class="header">
|
|
102
|
+
<img src="https://assets.heliyos.ai/heliyos-logo-white.png" alt="Heliyos AI">
|
|
103
|
+
</div>
|
|
104
|
+
<div class="content">
|
|
105
|
+
<h2 style="margin-top: 0; color: #0e0d0c;">Action Required: Integration Not Synched</h2>
|
|
106
|
+
<p>Hi {{first_name}},</p>
|
|
107
|
+
<p>We detected that your integration <strong>{{integration_name}}</strong> is currently not synched.</p>
|
|
108
|
+
<p>{{summary}}</p>
|
|
109
|
+
|
|
110
|
+
<div class="warning-box">
|
|
111
|
+
<p style="margin: 0;"><strong>Detected at:</strong> {{timestamp}}</p>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{{#if details}}
|
|
115
|
+
<table class="details-table">
|
|
116
|
+
{{#each details}}
|
|
117
|
+
<tr>
|
|
118
|
+
<td class="details-label">{{label}}</td>
|
|
119
|
+
<td class="details-value">{{value}}</td>
|
|
120
|
+
</tr>
|
|
121
|
+
{{/each}}
|
|
122
|
+
</table>
|
|
123
|
+
{{/if}}
|
|
124
|
+
|
|
125
|
+
<p style="text-align: center;">
|
|
126
|
+
<a href="{{reconnect_url}}" class="button">Reconnect Integration</a>
|
|
127
|
+
</p>
|
|
128
|
+
<p>If you're having trouble clicking the button, copy and paste the following URL into your web browser:</p>
|
|
129
|
+
<p style="word-break: break-all; font-size: 13px; color: #5c5545;">{{reconnect_url}}</p>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="footer">
|
|
132
|
+
<p>© {{year}} {{company_name}}. All rights reserved.</p>
|
|
133
|
+
<p>This is an automated message, please do not reply to this email.</p>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</body>
|
|
137
|
+
|
|
138
|
+
</html>
|
package/package.json
CHANGED
package/src/email/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ export const emailTemplates = {
|
|
|
13
13
|
notificationImmediateGrouped: "notification-immediate-grouped.html",
|
|
14
14
|
notificationDailySummary: "notification-daily-summary.html",
|
|
15
15
|
organizationDailySummary: "organization-daily-summary.html",
|
|
16
|
+
integrationNotSynced: "integration-not-synced.html",
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -25,13 +26,14 @@ const markdownToHtml = (text: string): string => {
|
|
|
25
26
|
// Bold: **text** or __text__
|
|
26
27
|
.replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
|
|
27
28
|
.replace(/__(.*?)__/g, "<strong>$1</strong>")
|
|
28
|
-
// Italics: *text*
|
|
29
|
+
// Italics: *text* (intentionally avoid _text_ to keep URLs/query keys intact)
|
|
29
30
|
.replace(/\*(.*?)\*/g, "<em>$1</em>")
|
|
30
|
-
.replace(/_(.*?)_/g, "<em>$1</em>")
|
|
31
31
|
// Newlines to <br>
|
|
32
32
|
.replace(/\n/g, "<br>");
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
const URL_LIKE_PATTERN = /^(https?:\/\/|mailto:|tel:)\S+$/i;
|
|
36
|
+
|
|
35
37
|
/**
|
|
36
38
|
* Recursively process object values to convert markdown to HTML
|
|
37
39
|
*/
|
|
@@ -39,6 +41,9 @@ const processMarkdownData = (data: any): any => {
|
|
|
39
41
|
if (!data) return data;
|
|
40
42
|
|
|
41
43
|
if (typeof data === "string") {
|
|
44
|
+
if (URL_LIKE_PATTERN.test(data.trim())) {
|
|
45
|
+
return data;
|
|
46
|
+
}
|
|
42
47
|
return markdownToHtml(data);
|
|
43
48
|
}
|
|
44
49
|
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>Integration Not Synched</title>
|
|
8
|
+
<style>
|
|
9
|
+
body {
|
|
10
|
+
font-family: Arial, sans-serif;
|
|
11
|
+
line-height: 1.6;
|
|
12
|
+
color: #0e0d0c;
|
|
13
|
+
background-color: #f8f8f6;
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.container {
|
|
19
|
+
max-width: 600px;
|
|
20
|
+
margin: 20px auto;
|
|
21
|
+
background-color: #ffffff;
|
|
22
|
+
border: 2px solid #7c3aed;
|
|
23
|
+
border-radius: 12px;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.header {
|
|
28
|
+
background-color: #7c3aed;
|
|
29
|
+
padding: 30px 20px;
|
|
30
|
+
text-align: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.header img {
|
|
34
|
+
max-width: 180px;
|
|
35
|
+
height: auto;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.content {
|
|
39
|
+
padding: 30px;
|
|
40
|
+
color: #2c2721;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.button {
|
|
44
|
+
display: inline-block;
|
|
45
|
+
padding: 12px 24px;
|
|
46
|
+
background-color: #7c3aed;
|
|
47
|
+
color: #ffffff !important;
|
|
48
|
+
text-decoration: none;
|
|
49
|
+
border-radius: 8px;
|
|
50
|
+
font-weight: bold;
|
|
51
|
+
margin-top: 20px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.button:hover {
|
|
55
|
+
background-color: #6d28d9;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.footer {
|
|
59
|
+
background-color: #ebe7db;
|
|
60
|
+
padding: 20px;
|
|
61
|
+
text-align: center;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
color: #5c5545;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.warning-box {
|
|
67
|
+
background-color: #fff3cd;
|
|
68
|
+
border-left: 4px solid #ffc107;
|
|
69
|
+
padding: 16px;
|
|
70
|
+
margin: 20px 0;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.details-table {
|
|
75
|
+
width: 100%;
|
|
76
|
+
border: 1px solid #e5e7eb;
|
|
77
|
+
border-radius: 8px;
|
|
78
|
+
border-collapse: collapse;
|
|
79
|
+
margin: 20px 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.details-table td {
|
|
83
|
+
padding: 10px 12px;
|
|
84
|
+
border-bottom: 1px solid #f3f4f6;
|
|
85
|
+
font-size: 13px;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.details-label {
|
|
89
|
+
color: #5c5545;
|
|
90
|
+
width: 160px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.details-value {
|
|
94
|
+
color: #0e0d0c;
|
|
95
|
+
}
|
|
96
|
+
</style>
|
|
97
|
+
</head>
|
|
98
|
+
|
|
99
|
+
<body>
|
|
100
|
+
<div class="container">
|
|
101
|
+
<div class="header">
|
|
102
|
+
<img src="https://assets.heliyos.ai/heliyos-logo-white.png" alt="Heliyos AI">
|
|
103
|
+
</div>
|
|
104
|
+
<div class="content">
|
|
105
|
+
<h2 style="margin-top: 0; color: #0e0d0c;">Action Required: Integration Not Synched</h2>
|
|
106
|
+
<p>Hi {{first_name}},</p>
|
|
107
|
+
<p>We detected that your integration <strong>{{integration_name}}</strong> is currently not synched.</p>
|
|
108
|
+
<p>{{summary}}</p>
|
|
109
|
+
|
|
110
|
+
<div class="warning-box">
|
|
111
|
+
<p style="margin: 0;"><strong>Detected at:</strong> {{timestamp}}</p>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
{{#if details}}
|
|
115
|
+
<table class="details-table">
|
|
116
|
+
{{#each details}}
|
|
117
|
+
<tr>
|
|
118
|
+
<td class="details-label">{{label}}</td>
|
|
119
|
+
<td class="details-value">{{value}}</td>
|
|
120
|
+
</tr>
|
|
121
|
+
{{/each}}
|
|
122
|
+
</table>
|
|
123
|
+
{{/if}}
|
|
124
|
+
|
|
125
|
+
<p style="text-align: center;">
|
|
126
|
+
<a href="{{reconnect_url}}" class="button">Reconnect Integration</a>
|
|
127
|
+
</p>
|
|
128
|
+
<p>If you're having trouble clicking the button, copy and paste the following URL into your web browser:</p>
|
|
129
|
+
<p style="word-break: break-all; font-size: 13px; color: #5c5545;">{{reconnect_url}}</p>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="footer">
|
|
132
|
+
<p>© {{year}} {{company_name}}. All rights reserved.</p>
|
|
133
|
+
<p>This is an automated message, please do not reply to this email.</p>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</body>
|
|
137
|
+
|
|
138
|
+
</html>
|