n8n-nodes-salvia 0.2.0 → 0.4.0
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/nodes/Salvia/Salvia.node.js +116 -21
- package/package.json +1 -1
|
@@ -6,8 +6,16 @@ const STAGE_TYPE_LABEL = {
|
|
|
6
6
|
won: " (ganho)",
|
|
7
7
|
lost: " (perda)",
|
|
8
8
|
};
|
|
9
|
+
const FIELD_TYPE_LABEL = {
|
|
10
|
+
text: "texto",
|
|
11
|
+
number: "número",
|
|
12
|
+
date: "data",
|
|
13
|
+
datetime: "data e hora",
|
|
14
|
+
boolean: "sim/não",
|
|
15
|
+
select: "seleção",
|
|
16
|
+
};
|
|
9
17
|
async function fetchCatalog(ctx) {
|
|
10
|
-
var _a, _b;
|
|
18
|
+
var _a, _b, _c, _d;
|
|
11
19
|
const creds = (await ctx.getCredentials("salviaApi"));
|
|
12
20
|
const res = (await ctx.helpers.httpRequestWithAuthentication.call(ctx, "salviaApi", {
|
|
13
21
|
method: "GET",
|
|
@@ -15,21 +23,24 @@ async function fetchCatalog(ctx) {
|
|
|
15
23
|
url: "/api/v1/catalog",
|
|
16
24
|
json: true,
|
|
17
25
|
}));
|
|
18
|
-
return
|
|
26
|
+
return {
|
|
27
|
+
pipelines: (_b = (_a = res.data) === null || _a === void 0 ? void 0 : _a.pipelines) !== null && _b !== void 0 ? _b : [],
|
|
28
|
+
customFields: (_d = (_c = res.data) === null || _c === void 0 ? void 0 : _c.customFields) !== null && _d !== void 0 ? _d : [],
|
|
29
|
+
};
|
|
19
30
|
}
|
|
20
31
|
class Salvia {
|
|
21
32
|
constructor() {
|
|
22
33
|
this.methods = {
|
|
23
34
|
loadOptions: {
|
|
24
35
|
async getPipelines() {
|
|
25
|
-
const pipelines = await fetchCatalog(this);
|
|
36
|
+
const { pipelines } = await fetchCatalog(this);
|
|
26
37
|
return [
|
|
27
38
|
{ name: "— Funil padrão do Salvia —", value: "" },
|
|
28
39
|
...pipelines.map((p) => ({ name: p.name, value: p.id })),
|
|
29
40
|
];
|
|
30
41
|
},
|
|
31
42
|
async getStages() {
|
|
32
|
-
const pipelines = await fetchCatalog(this);
|
|
43
|
+
const { pipelines } = await fetchCatalog(this);
|
|
33
44
|
const pipelineId = this.getCurrentNodeParameter("pipelineId") || "";
|
|
34
45
|
// Sem funil escolhido, lista as etapas de todos com o funil no rótulo —
|
|
35
46
|
// escolher a etapa já basta (a API deriva o funil dela).
|
|
@@ -46,6 +57,20 @@ class Salvia {
|
|
|
46
57
|
})),
|
|
47
58
|
];
|
|
48
59
|
},
|
|
60
|
+
async getCustomFields() {
|
|
61
|
+
const { customFields } = await fetchCatalog(this);
|
|
62
|
+
return customFields.map((f) => {
|
|
63
|
+
var _a;
|
|
64
|
+
const opt = {
|
|
65
|
+
name: `${f.label} (${(_a = FIELD_TYPE_LABEL[f.type]) !== null && _a !== void 0 ? _a : f.type})`,
|
|
66
|
+
value: f.key,
|
|
67
|
+
};
|
|
68
|
+
if (f.type === "select" && f.options.length) {
|
|
69
|
+
opt.description = `Opções: ${f.options.join(", ")}`;
|
|
70
|
+
}
|
|
71
|
+
return opt;
|
|
72
|
+
});
|
|
73
|
+
},
|
|
49
74
|
},
|
|
50
75
|
};
|
|
51
76
|
this.description = {
|
|
@@ -191,6 +216,71 @@ class Salvia {
|
|
|
191
216
|
},
|
|
192
217
|
},
|
|
193
218
|
},
|
|
219
|
+
{
|
|
220
|
+
displayName: "Rastrear campanha (UTMs e click ids)",
|
|
221
|
+
name: "autoUtm",
|
|
222
|
+
type: "boolean",
|
|
223
|
+
default: true,
|
|
224
|
+
description: "Envia utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid e fbclid do próprio payload que chegou (nomes padrão). Desligue se preferir preencher à mão nas Opções adicionais.",
|
|
225
|
+
displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
|
|
226
|
+
routing: {
|
|
227
|
+
request: {
|
|
228
|
+
body: {
|
|
229
|
+
// Aceita o payload cru e o de webhook (que aninha em `body`).
|
|
230
|
+
// undefined em vez de "" porque a API descarta chave ausente, e
|
|
231
|
+
// string vazia sobrescreveria UTM que o lead já tinha.
|
|
232
|
+
utmSource: "={{ $value ? ($json.body?.utm_source || $json.utm_source || undefined) : undefined }}",
|
|
233
|
+
utmMedium: "={{ $value ? ($json.body?.utm_medium || $json.utm_medium || undefined) : undefined }}",
|
|
234
|
+
utmCampaign: "={{ $value ? ($json.body?.utm_campaign || $json.utm_campaign || undefined) : undefined }}",
|
|
235
|
+
utmTerm: "={{ $value ? ($json.body?.utm_term || $json.utm_term || undefined) : undefined }}",
|
|
236
|
+
utmContent: "={{ $value ? ($json.body?.utm_content || $json.utm_content || undefined) : undefined }}",
|
|
237
|
+
// Click ids vêm no mesmo pacote e pela mesma razão: sem eles a
|
|
238
|
+
// campanha não fica sabendo quais cliques viraram cliente.
|
|
239
|
+
gclid: "={{ $value ? ($json.body?.gclid || $json.gclid || undefined) : undefined }}",
|
|
240
|
+
fbclid: "={{ $value ? ($json.body?.fbclid || $json.fbclid || undefined) : undefined }}",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
displayName: "Campos personalizados",
|
|
247
|
+
name: "customFieldsUi",
|
|
248
|
+
type: "fixedCollection",
|
|
249
|
+
typeOptions: { multipleValues: true },
|
|
250
|
+
placeholder: "Adicionar campo personalizado",
|
|
251
|
+
default: {},
|
|
252
|
+
description: "Campos criados na sua conta do Salvia. O dropdown carrega direto de lá — crie o campo no Salvia e ele aparece aqui.",
|
|
253
|
+
displayOptions: { show: { resource: ["lead"], operation: ["create"] } },
|
|
254
|
+
options: [
|
|
255
|
+
{
|
|
256
|
+
displayName: "Campo",
|
|
257
|
+
name: "values",
|
|
258
|
+
values: [
|
|
259
|
+
{
|
|
260
|
+
displayName: "Campo",
|
|
261
|
+
name: "key",
|
|
262
|
+
type: "options",
|
|
263
|
+
typeOptions: { loadOptionsMethod: "getCustomFields" },
|
|
264
|
+
default: "",
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
displayName: "Valor",
|
|
268
|
+
name: "value",
|
|
269
|
+
type: "string",
|
|
270
|
+
default: "",
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
routing: {
|
|
276
|
+
send: {
|
|
277
|
+
type: "body",
|
|
278
|
+
property: "customFields",
|
|
279
|
+
// Vira {"chave": "valor"} no corpo; sem linhas preenchidas, nem vai.
|
|
280
|
+
value: "={{ (($value && $value.values) || []).filter(v => v.key).length ? Object.fromEntries($value.values.filter(v => v.key).map(v => [v.key, v.value])) : undefined }}",
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
},
|
|
194
284
|
{
|
|
195
285
|
displayName: "Opções adicionais",
|
|
196
286
|
name: "additionalFields",
|
|
@@ -208,40 +298,45 @@ class Salvia {
|
|
|
208
298
|
routing: { send: { type: "body", property: "ownerEmail" } },
|
|
209
299
|
},
|
|
210
300
|
{
|
|
211
|
-
displayName: "
|
|
212
|
-
name: "customFields",
|
|
213
|
-
type: "json",
|
|
214
|
-
default: "{}",
|
|
215
|
-
description: 'Ex.: {"convenio": "Unimed", "procedimento": "Botox"}',
|
|
216
|
-
routing: {
|
|
217
|
-
send: {
|
|
218
|
-
type: "body",
|
|
219
|
-
property: "customFields",
|
|
220
|
-
value: "={{ typeof $value === 'string' ? JSON.parse($value || '{}') : $value }}",
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
displayName: "UTM Source",
|
|
301
|
+
displayName: "UTM Source (manual)",
|
|
226
302
|
name: "utmSource",
|
|
227
303
|
type: "string",
|
|
228
304
|
default: "",
|
|
305
|
+
description: "Sobrescreve o valor pego do payload",
|
|
229
306
|
routing: { send: { type: "body", property: "utmSource" } },
|
|
230
307
|
},
|
|
231
308
|
{
|
|
232
|
-
displayName: "UTM Medium",
|
|
309
|
+
displayName: "UTM Medium (manual)",
|
|
233
310
|
name: "utmMedium",
|
|
234
311
|
type: "string",
|
|
235
312
|
default: "",
|
|
313
|
+
description: "Sobrescreve o valor pego do payload",
|
|
236
314
|
routing: { send: { type: "body", property: "utmMedium" } },
|
|
237
315
|
},
|
|
238
316
|
{
|
|
239
|
-
displayName: "UTM Campaign",
|
|
317
|
+
displayName: "UTM Campaign (manual)",
|
|
240
318
|
name: "utmCampaign",
|
|
241
319
|
type: "string",
|
|
242
320
|
default: "",
|
|
321
|
+
description: "Sobrescreve o valor pego do payload",
|
|
243
322
|
routing: { send: { type: "body", property: "utmCampaign" } },
|
|
244
323
|
},
|
|
324
|
+
{
|
|
325
|
+
displayName: "UTM Term (manual)",
|
|
326
|
+
name: "utmTerm",
|
|
327
|
+
type: "string",
|
|
328
|
+
default: "",
|
|
329
|
+
description: "Sobrescreve o valor pego do payload",
|
|
330
|
+
routing: { send: { type: "body", property: "utmTerm" } },
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
displayName: "UTM Content (manual)",
|
|
334
|
+
name: "utmContent",
|
|
335
|
+
type: "string",
|
|
336
|
+
default: "",
|
|
337
|
+
description: "Sobrescreve o valor pego do payload",
|
|
338
|
+
routing: { send: { type: "body", property: "utmContent" } },
|
|
339
|
+
},
|
|
245
340
|
{
|
|
246
341
|
displayName: "Permitir telefone duplicado",
|
|
247
342
|
name: "forceDuplicate",
|