feat: add freescout app with new event trigger (#2287)
* added FreeScout plugin * docs: add freescout in sidebar * docs(freescout): add missing app icon * refactor(freescout): rename filter as eventType --------- Co-authored-by: Ali BARIN <ali.barin53@gmail.com>
This commit is contained in:
25
packages/backend/src/apps/freescout/assets/favicon.svg
Normal file
25
packages/backend/src/apps/freescout/assets/favicon.svg
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
|
||||
fill="#0078D7" stroke="none">
|
||||
<path d="M1120 2544 c-220 -44 -286 -64 -425 -136 -331 -170 -574 -485 -656
|
||||
-850 -27 -120 -38 -419 -18 -512 28 -134 72 -219 156 -302 72 -70 153 -108
|
||||
265 -124 160 -22 303 23 414 129 39 36 49 42 63 33 41 -30 160 -85 210 -99 78
|
||||
-21 220 -20 306 1 214 54 387 228 441 441 35 143 16 318 -50 441 -112 208
|
||||
-311 327 -546 327 -235 0 -434 -119 -546 -327 -49 -92 -65 -171 -71 -346 -3
|
||||
-85 -10 -163 -15 -173 -5 -10 -27 -31 -50 -47 -73 -53 -163 -32 -205 49 -60
|
||||
118 -29 435 61 621 198 406 644 609 1075 489 418 -117 708 -541 660 -967 -64
|
||||
-573 -607 -944 -1159 -791 -41 12 -93 30 -114 40 -46 22 -46 22 -46 10 0 -4
|
||||
-27 -49 -60 -99 -33 -51 -60 -94 -60 -98 0 -3 -15 -26 -32 -51 -31 -43 -32
|
||||
-45 -14 -59 36 -26 201 -85 301 -107 143 -31 406 -31 547 0 486 110 861 485
|
||||
971 971 31 140 31 404 0 544 -109 484 -485 862 -965 969 -91 20 -375 35 -438
|
||||
23z m252 -1025 c29 -11 69 -36 90 -56 41 -40 78 -126 78 -183 0 -57 -37 -143
|
||||
-78 -183 -43 -42 -127 -77 -182 -77 -55 0 -139 35 -182 77 -41 40 -78 126 -78
|
||||
181 0 62 31 133 80 182 77 77 173 98 272 59z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
44
packages/backend/src/apps/freescout/auth/index.js
Normal file
44
packages/backend/src/apps/freescout/auth/index.js
Normal file
@@ -0,0 +1,44 @@
|
||||
import verifyCredentials from './verify-credentials.js';
|
||||
import isStillVerified from './is-still-verified.js';
|
||||
|
||||
export default {
|
||||
fields: [
|
||||
{
|
||||
key: 'screenName',
|
||||
label: 'Screen Name',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description:
|
||||
'Screen name of your connection to be used on Automatisch UI.',
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'instanceUrl',
|
||||
label: 'FreeScout instance URL',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
description: 'Your FreeScout instance URL.',
|
||||
docUrl: 'https://automatisch.io/docs/freescout#instance-url',
|
||||
clickToCopy: false,
|
||||
},
|
||||
{
|
||||
key: 'apiKey',
|
||||
label: 'API Key',
|
||||
type: 'string',
|
||||
required: true,
|
||||
readOnly: false,
|
||||
value: null,
|
||||
placeholder: null,
|
||||
description: 'FreeScout API key of your account.',
|
||||
docUrl: 'https://automatisch.io/docs/freescout#api-key',
|
||||
clickToCopy: false,
|
||||
},
|
||||
],
|
||||
|
||||
verifyCredentials,
|
||||
isStillVerified,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
const isStillVerified = async ($) => {
|
||||
await $.http.get('/api/mailboxes');
|
||||
return true;
|
||||
};
|
||||
|
||||
export default isStillVerified;
|
||||
@@ -0,0 +1,5 @@
|
||||
const verifyCredentials = async ($) => {
|
||||
await $.http.get('/api/mailboxes');
|
||||
};
|
||||
|
||||
export default verifyCredentials;
|
||||
@@ -0,0 +1,9 @@
|
||||
const addAuthHeader = ($, requestConfig) => {
|
||||
if ($.auth.data?.apiKey) {
|
||||
requestConfig.headers['X-FreeScout-API-Key'] = $.auth.data.apiKey;
|
||||
}
|
||||
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default addAuthHeader;
|
||||
@@ -0,0 +1,6 @@
|
||||
const setBaseUrl = ($, requestConfig) => {
|
||||
requestConfig.baseURL = $.auth.data.instanceUrl;
|
||||
return requestConfig;
|
||||
};
|
||||
|
||||
export default setBaseUrl;
|
||||
@@ -0,0 +1,52 @@
|
||||
const webhookFilters = [
|
||||
{
|
||||
value: 'convo.assigned',
|
||||
label: 'Conversation assigned',
|
||||
},
|
||||
{
|
||||
value: 'convo.created',
|
||||
label: 'Conversation created',
|
||||
},
|
||||
{
|
||||
value: 'convo.deleted',
|
||||
label: 'Conversation deleted',
|
||||
},
|
||||
{
|
||||
value: 'convo.deleted_forever',
|
||||
label: 'Conversation deleted forever',
|
||||
},
|
||||
{
|
||||
value: 'convo.restored',
|
||||
label: 'Conversation restored from Deleted folder',
|
||||
},
|
||||
{
|
||||
value: 'convo.moved',
|
||||
label: 'Conversation moved',
|
||||
},
|
||||
{
|
||||
value: 'convo.status',
|
||||
label: 'Conversation status updated',
|
||||
},
|
||||
{
|
||||
value: 'convo.customer.reply.created',
|
||||
label: 'Customer replied',
|
||||
},
|
||||
{
|
||||
value: 'convo.agent.reply.created',
|
||||
label: 'Agent replied',
|
||||
},
|
||||
{
|
||||
value: 'convo.note.created',
|
||||
label: 'Note added',
|
||||
},
|
||||
{
|
||||
value: 'customer.created',
|
||||
label: 'Customer create',
|
||||
},
|
||||
{
|
||||
value: 'customer.updated',
|
||||
label: 'Customer update',
|
||||
},
|
||||
];
|
||||
|
||||
export default webhookFilters;
|
||||
18
packages/backend/src/apps/freescout/index.js
Normal file
18
packages/backend/src/apps/freescout/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import defineApp from '../../helpers/define-app.js';
|
||||
import addAuthHeader from './common/add-auth-header.js';
|
||||
import auth from './auth/index.js';
|
||||
import triggers from './triggers/index.js';
|
||||
import setBaseUrl from './common/set-base-url.js';
|
||||
|
||||
export default defineApp({
|
||||
name: 'FreeScout',
|
||||
key: 'freescout',
|
||||
iconUrl: '{BASE_URL}/apps/freescout/assets/favicon.svg',
|
||||
supportsConnections: true,
|
||||
baseUrl: 'https://freescout.net',
|
||||
primaryColor: '#F5D05E',
|
||||
authDocUrl: '{DOCS_URL}/apps/freescout/connection',
|
||||
beforeRequest: [setBaseUrl, addAuthHeader],
|
||||
auth,
|
||||
triggers,
|
||||
});
|
||||
3
packages/backend/src/apps/freescout/triggers/index.js
Normal file
3
packages/backend/src/apps/freescout/triggers/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
import newEvent from './new-event/index.js';
|
||||
|
||||
export default [newEvent];
|
||||
@@ -0,0 +1,61 @@
|
||||
import Crypto from 'crypto';
|
||||
import isEmpty from 'lodash/isEmpty.js';
|
||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||
import webhookFilters from '../../common/webhook-filters.js';
|
||||
|
||||
export default defineTrigger({
|
||||
name: 'New event',
|
||||
key: 'newEvent',
|
||||
type: 'webhook',
|
||||
description: 'Triggers when a new event occurs.',
|
||||
arguments: [
|
||||
{
|
||||
label: 'Event type',
|
||||
key: 'eventType',
|
||||
type: 'dropdown',
|
||||
required: true,
|
||||
description: 'Pick an event type to receive events for.',
|
||||
variables: false,
|
||||
options: webhookFilters,
|
||||
},
|
||||
],
|
||||
|
||||
async run($) {
|
||||
const dataItem = {
|
||||
raw: $.request.body,
|
||||
meta: {
|
||||
internalId: Crypto.randomUUID(),
|
||||
},
|
||||
};
|
||||
|
||||
$.pushTriggerItem(dataItem);
|
||||
},
|
||||
|
||||
async testRun($) {
|
||||
const lastExecutionStep = await $.getLastExecutionStep();
|
||||
|
||||
if (!isEmpty(lastExecutionStep?.dataOut)) {
|
||||
$.pushTriggerItem({
|
||||
raw: lastExecutionStep.dataOut,
|
||||
meta: {
|
||||
internalId: '',
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
async registerHook($) {
|
||||
const payload = {
|
||||
url: $.webhookUrl,
|
||||
events: [$.step.parameters.eventType],
|
||||
};
|
||||
|
||||
const response = await $.http.post('/api/webhooks', payload);
|
||||
|
||||
await $.flow.setRemoteWebhookId(response.data?.id?.toString());
|
||||
},
|
||||
|
||||
async unregisterHook($) {
|
||||
await $.http.delete(`/api/webhooks/${$.flow.remoteWebhookId}`);
|
||||
},
|
||||
});
|
||||
@@ -19,6 +19,7 @@ exports[`App model > list should have list of applications keys 1`] = `
|
||||
"flickr",
|
||||
"flowers-software",
|
||||
"formatter",
|
||||
"freescout",
|
||||
"ghost",
|
||||
"github",
|
||||
"gitlab",
|
||||
|
||||
@@ -159,6 +159,15 @@ export default defineConfig({
|
||||
{ text: 'Connection', link: '/apps/formatter/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Freescout',
|
||||
collapsible: true,
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Triggers', link: '/apps/freescout/triggers' },
|
||||
{ text: 'Connection', link: '/apps/freescout/connection' },
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Ghost',
|
||||
collapsible: true,
|
||||
|
||||
13
packages/docs/pages/apps/freescout/connection.md
Normal file
13
packages/docs/pages/apps/freescout/connection.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# FreeScout
|
||||
|
||||
:::info
|
||||
This page explains the steps you need to follow to set up the FreeScout
|
||||
connection in Automatisch. If any of the steps are outdated, please let us know!
|
||||
:::
|
||||
|
||||
1. Go to your FreeScout instance.
|
||||
2. Go to the Manage > Settings > API & Webhooks page.
|
||||
3. Generate **API Key**.
|
||||
4. Copy the **API Key** value to the `API Key` field on Automatisch.
|
||||
5. Click **Submit** button on Automatisch.
|
||||
6. Congrats! Start using your new FreeScout connection within the flows.
|
||||
13
packages/docs/pages/apps/freescout/triggers.md
Normal file
13
packages/docs/pages/apps/freescout/triggers.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
favicon: /favicons/freescout.svg
|
||||
items:
|
||||
- name: New event
|
||||
desc: Triggers when a new event is created. The supported events are conversation created, conversation assigned, conversation status updated, conversation moved, conversation deleted, conversation deleted forever, conversation restored from deleted folder, customer replied, agent replied, note added, customer created, customer updated.
|
||||
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import CustomListing from '../../components/CustomListing.vue'
|
||||
</script>
|
||||
|
||||
<CustomListing />
|
||||
24
packages/docs/pages/public/favicons/freescout.svg
Normal file
24
packages/docs/pages/public/favicons/freescout.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
|
||||
fill="#0078D7" stroke="none">
|
||||
<path d="M1120 2544 c-220 -44 -286 -64 -425 -136 -331 -170 -574 -485 -656
|
||||
-850 -27 -120 -38 -419 -18 -512 28 -134 72 -219 156 -302 72 -70 153 -108
|
||||
265 -124 160 -22 303 23 414 129 39 36 49 42 63 33 41 -30 160 -85 210 -99 78
|
||||
-21 220 -20 306 1 214 54 387 228 441 441 35 143 16 318 -50 441 -112 208
|
||||
-311 327 -546 327 -235 0 -434 -119 -546 -327 -49 -92 -65 -171 -71 -346 -3
|
||||
-85 -10 -163 -15 -173 -5 -10 -27 -31 -50 -47 -73 -53 -163 -32 -205 49 -60
|
||||
118 -29 435 61 621 198 406 644 609 1075 489 418 -117 708 -541 660 -967 -64
|
||||
-573 -607 -944 -1159 -791 -41 12 -93 30 -114 40 -46 22 -46 22 -46 10 0 -4
|
||||
-27 -49 -60 -99 -33 -51 -60 -94 -60 -98 0 -3 -15 -26 -32 -51 -31 -43 -32
|
||||
-45 -14 -59 36 -26 201 -85 301 -107 143 -31 406 -31 547 0 486 110 861 485
|
||||
971 971 31 140 31 404 0 544 -109 484 -485 862 -965 969 -91 20 -375 35 -438
|
||||
23z m252 -1025 c29 -11 69 -36 90 -56 41 -40 78 -126 78 -183 0 -57 -37 -143
|
||||
-78 -183 -43 -42 -127 -77 -182 -77 -55 0 -139 35 -182 77 -41 40 -78 126 -78
|
||||
181 0 62 31 133 80 182 77 77 173 98 272 59z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user