@pipedream/topdesk 0.0.1 → 0.2.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.
@@ -0,0 +1,442 @@
1
+ import app from "../../topdesk.app.mjs";
2
+
3
+ export default {
4
+ key: "topdesk-update-incident",
5
+ name: "Update Incident",
6
+ description: "Updates an existing incident. [See the documentation](https://developers.topdesk.com/explorer/?page=incident#/incident/patchIncident)",
7
+ version: "0.0.2",
8
+ type: "action",
9
+ props: {
10
+ app,
11
+ incidentId: {
12
+ propDefinition: [
13
+ app,
14
+ "incidentId",
15
+ ],
16
+ },
17
+ callerLookupId: {
18
+ type: "string",
19
+ label: "Caller Lookup ID",
20
+ description: "Lookup value for filling in a registered caller's contact details (UUID). Can only be set by operators.",
21
+ optional: true,
22
+ propDefinition: [
23
+ app,
24
+ "personId",
25
+ ],
26
+ },
27
+ briefDescription: {
28
+ propDefinition: [
29
+ app,
30
+ "briefDescription",
31
+ ],
32
+ },
33
+ request: {
34
+ propDefinition: [
35
+ app,
36
+ "request",
37
+ ],
38
+ },
39
+ action: {
40
+ propDefinition: [
41
+ app,
42
+ "action",
43
+ ],
44
+ },
45
+ actionInvisibleForCaller: {
46
+ propDefinition: [
47
+ app,
48
+ "actionInvisibleForCaller",
49
+ ],
50
+ },
51
+ categoryId: {
52
+ propDefinition: [
53
+ app,
54
+ "categoryId",
55
+ ],
56
+ },
57
+ subcategoryId: {
58
+ propDefinition: [
59
+ app,
60
+ "subcategoryId",
61
+ ({ categoryId }) => ({
62
+ categoryId,
63
+ }),
64
+ ],
65
+ },
66
+ callTypeId: {
67
+ propDefinition: [
68
+ app,
69
+ "callTypeId",
70
+ ],
71
+ },
72
+ callDate: {
73
+ type: "string",
74
+ label: "Call Date",
75
+ description: "The date when this call was registered in ISO 8601 format (e.g., `2024-08-01T12:00:00.000+0200`). Can only be set by operators.",
76
+ optional: true,
77
+ },
78
+ entryTypeId: {
79
+ propDefinition: [
80
+ app,
81
+ "entryTypeId",
82
+ ],
83
+ },
84
+ externalNumber: {
85
+ propDefinition: [
86
+ app,
87
+ "externalNumber",
88
+ ],
89
+ },
90
+ objectName: {
91
+ propDefinition: [
92
+ app,
93
+ "objectName",
94
+ ],
95
+ },
96
+ locationId: {
97
+ propDefinition: [
98
+ app,
99
+ "locationId",
100
+ ],
101
+ },
102
+ branchId: {
103
+ propDefinition: [
104
+ app,
105
+ "branchId",
106
+ ],
107
+ },
108
+ impact: {
109
+ propDefinition: [
110
+ app,
111
+ "impactId",
112
+ ],
113
+ },
114
+ urgency: {
115
+ propDefinition: [
116
+ app,
117
+ "urgencyId",
118
+ ],
119
+ },
120
+ priority: {
121
+ propDefinition: [
122
+ app,
123
+ "priorityId",
124
+ ],
125
+ },
126
+ duration: {
127
+ propDefinition: [
128
+ app,
129
+ "durationId",
130
+ ],
131
+ },
132
+ targetDate: {
133
+ propDefinition: [
134
+ app,
135
+ "targetDate",
136
+ ],
137
+ },
138
+ slaId: {
139
+ propDefinition: [
140
+ app,
141
+ "slaId",
142
+ ],
143
+ },
144
+ onHold: {
145
+ propDefinition: [
146
+ app,
147
+ "onHold",
148
+ ],
149
+ },
150
+ operatorId: {
151
+ propDefinition: [
152
+ app,
153
+ "operatorId",
154
+ ],
155
+ label: "Operator",
156
+ description: "The operator assigned to the incident. Can only be set by operators.",
157
+ optional: true,
158
+ },
159
+ operatorGroupId: {
160
+ propDefinition: [
161
+ app,
162
+ "operatorGroupId",
163
+ ],
164
+ },
165
+ supplierId: {
166
+ propDefinition: [
167
+ app,
168
+ "supplierId",
169
+ ],
170
+ },
171
+ processingStatusId: {
172
+ propDefinition: [
173
+ app,
174
+ "processingStatusId",
175
+ ],
176
+ },
177
+ responded: {
178
+ propDefinition: [
179
+ app,
180
+ "responded",
181
+ ],
182
+ },
183
+ responseDate: {
184
+ propDefinition: [
185
+ app,
186
+ "responseDate",
187
+ ],
188
+ },
189
+ completed: {
190
+ propDefinition: [
191
+ app,
192
+ "completed",
193
+ ],
194
+ },
195
+ completedDate: {
196
+ propDefinition: [
197
+ app,
198
+ "completedDate",
199
+ ],
200
+ },
201
+ closed: {
202
+ propDefinition: [
203
+ app,
204
+ "closed",
205
+ ],
206
+ },
207
+ closedDate: {
208
+ propDefinition: [
209
+ app,
210
+ "closedDate",
211
+ ],
212
+ },
213
+ closureCodeId: {
214
+ propDefinition: [
215
+ app,
216
+ "closureCodeId",
217
+ ],
218
+ },
219
+ costs: {
220
+ type: "string",
221
+ label: "Costs",
222
+ description: "Costs as a decimal number. Can only be set by operators.",
223
+ optional: true,
224
+ },
225
+ feedbackMessage: {
226
+ type: "string",
227
+ label: "Feedback Message",
228
+ description: "Feedback message from the caller",
229
+ optional: true,
230
+ },
231
+ feedbackRating: {
232
+ type: "integer",
233
+ label: "Feedback Rating",
234
+ description: "Feedback rating (1-5). Can be set by persons.",
235
+ optional: true,
236
+ min: 1,
237
+ max: 5,
238
+ },
239
+ majorCall: {
240
+ propDefinition: [
241
+ app,
242
+ "majorCall",
243
+ ],
244
+ },
245
+ majorCallObject: {
246
+ type: "object",
247
+ label: "Major Call Object",
248
+ description: "Major call details as a JSON object. Can only be set by operators.",
249
+ optional: true,
250
+ },
251
+ publishToSsd: {
252
+ propDefinition: [
253
+ app,
254
+ "publishToSsd",
255
+ ],
256
+ },
257
+ optionalFields1: {
258
+ propDefinition: [
259
+ app,
260
+ "optionalFields1",
261
+ ],
262
+ },
263
+ optionalFields2: {
264
+ propDefinition: [
265
+ app,
266
+ "optionalFields2",
267
+ ],
268
+ },
269
+ },
270
+ annotations: {
271
+ readOnlyHint: false,
272
+ destructiveHint: false,
273
+ openWorldHint: true,
274
+ idempotentHint: false,
275
+ },
276
+ async run({ $ }) {
277
+ const {
278
+ app,
279
+ incidentId,
280
+ callerLookupId,
281
+ briefDescription,
282
+ request,
283
+ action,
284
+ actionInvisibleForCaller,
285
+ categoryId,
286
+ subcategoryId,
287
+ callTypeId,
288
+ callDate,
289
+ entryTypeId,
290
+ externalNumber,
291
+ objectName,
292
+ locationId,
293
+ branchId,
294
+ impact,
295
+ urgency,
296
+ priority,
297
+ duration,
298
+ targetDate,
299
+ slaId,
300
+ onHold,
301
+ operatorId,
302
+ operatorGroupId,
303
+ supplierId,
304
+ processingStatusId,
305
+ responded,
306
+ responseDate,
307
+ completed,
308
+ completedDate,
309
+ closed,
310
+ closedDate,
311
+ closureCodeId,
312
+ costs,
313
+ feedbackMessage,
314
+ feedbackRating,
315
+ majorCall,
316
+ majorCallObject,
317
+ publishToSsd,
318
+ optionalFields1,
319
+ optionalFields2,
320
+ } = this;
321
+
322
+ // Fields that take { id: value } structure
323
+ const idFields = [
324
+ {
325
+ value: callerLookupId,
326
+ key: "callerLookup",
327
+ },
328
+ {
329
+ value: categoryId,
330
+ key: "category",
331
+ },
332
+ {
333
+ value: subcategoryId,
334
+ key: "subcategory",
335
+ },
336
+ {
337
+ value: callTypeId,
338
+ key: "callType",
339
+ },
340
+ {
341
+ value: entryTypeId,
342
+ key: "entryType",
343
+ },
344
+ {
345
+ value: locationId,
346
+ key: "location",
347
+ },
348
+ {
349
+ value: branchId,
350
+ key: "branch",
351
+ },
352
+ {
353
+ value: impact,
354
+ key: "impact",
355
+ },
356
+ {
357
+ value: urgency,
358
+ key: "urgency",
359
+ },
360
+ {
361
+ value: priority,
362
+ key: "priority",
363
+ },
364
+ {
365
+ value: duration,
366
+ key: "duration",
367
+ },
368
+ {
369
+ value: slaId,
370
+ key: "sla",
371
+ },
372
+ {
373
+ value: operatorId,
374
+ key: "operator",
375
+ },
376
+ {
377
+ value: operatorGroupId,
378
+ key: "operatorGroup",
379
+ },
380
+ {
381
+ value: supplierId,
382
+ key: "supplier",
383
+ },
384
+ {
385
+ value: processingStatusId,
386
+ key: "processingStatus",
387
+ },
388
+ {
389
+ value: closureCodeId,
390
+ key: "closureCode",
391
+ },
392
+ ];
393
+
394
+ const response = await app.updateIncident({
395
+ $,
396
+ incidentId,
397
+ data: {
398
+ briefDescription,
399
+ request,
400
+ action,
401
+ actionInvisibleForCaller,
402
+ callDate,
403
+ externalNumber,
404
+ targetDate,
405
+ onHold,
406
+ responded,
407
+ responseDate,
408
+ completed,
409
+ completedDate,
410
+ closed,
411
+ closedDate,
412
+ costs,
413
+ feedbackMessage,
414
+ feedbackRating,
415
+ majorCall,
416
+ majorCallObject,
417
+ publishToSsd,
418
+ optionalFields1,
419
+ optionalFields2,
420
+ ...(objectName && {
421
+ object: {
422
+ name: objectName,
423
+ },
424
+ }),
425
+ ...idFields.reduce((acc, {
426
+ value, key,
427
+ }) => ({
428
+ ...acc,
429
+ ...value && {
430
+ [key]: {
431
+ id: value,
432
+ },
433
+ },
434
+ }), {}),
435
+ },
436
+ });
437
+
438
+ $.export("$summary", `Successfully updated incident with ID \`${response.id}\``);
439
+
440
+ return response;
441
+ },
442
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipedream/topdesk",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "Pipedream TOPdesk Components",
5
5
  "main": "topdesk.app.mjs",
6
6
  "keywords": [
@@ -11,5 +11,8 @@
11
11
  "author": "Pipedream <support@pipedream.com> (https://pipedream.com/)",
12
12
  "publishConfig": {
13
13
  "access": "public"
14
+ },
15
+ "dependencies": {
16
+ "@pipedream/platform": "^3.1.1"
14
17
  }
15
18
  }
@@ -0,0 +1,99 @@
1
+ import topdesk from "../../topdesk.app.mjs";
2
+ import {
3
+ DEFAULT_POLLING_SOURCE_TIMER_INTERVAL, ConfigurationError,
4
+ } from "@pipedream/platform";
5
+
6
+ export default {
7
+ props: {
8
+ topdesk,
9
+ db: "$.service.db",
10
+ timer: {
11
+ type: "$.interface.timer",
12
+ default: {
13
+ intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
14
+ },
15
+ },
16
+ },
17
+ methods: {
18
+ _getLastTs() {
19
+ return this.db.get("lastTs") || 0;
20
+ },
21
+ _setLastTs(lastTs) {
22
+ this.db.set("lastTs", lastTs);
23
+ },
24
+ _getPreviousValue() {
25
+ return this.db.get("previousValue");
26
+ },
27
+ _setPreviousValue(previousValue) {
28
+ this.db.set("previousValue", previousValue);
29
+ },
30
+ getArgs() {
31
+ return {};
32
+ },
33
+ getTsField() {
34
+ return "modificationDate";
35
+ },
36
+ paginateResults() {
37
+ return false;
38
+ },
39
+ isRelevant() {
40
+ return true;
41
+ },
42
+ async getPaginatedResources(opts = {}) {
43
+ const results = this.topdesk.paginate(opts);
44
+ const items = [];
45
+ for await (const result of results) {
46
+ items.push(result);
47
+ }
48
+ return items;
49
+ },
50
+ async processEvents(max) {
51
+ const lastTs = this._getLastTs();
52
+ let maxTs = lastTs;
53
+
54
+ const resourceFn = this.getResourceFn();
55
+ const args = this.getArgs();
56
+ const tsField = this.getTsField();
57
+
58
+ const results = this.paginateResults()
59
+ ? await this.getPaginatedResources({
60
+ fn: resourceFn,
61
+ fnArgs: args,
62
+ maxResults: max,
63
+ })
64
+ : [
65
+ await resourceFn(args),
66
+ ];
67
+
68
+ if (!results.length) {
69
+ return;
70
+ }
71
+
72
+ for (const result of results.reverse()) {
73
+ const ts = Date.parse(result[tsField]);
74
+ if (ts >= lastTs) {
75
+ maxTs = Math.max(ts, maxTs);
76
+ if (this.isRelevant(result)) {
77
+ this.$emit(result, this.generateMeta(result));
78
+ }
79
+ }
80
+ }
81
+
82
+ this._setLastTs(maxTs);
83
+ },
84
+ getResourceFn() {
85
+ throw new ConfigurationError("getResourceFn must be implemented");
86
+ },
87
+ generateMeta() {
88
+ throw new ConfigurationError("generateMeta must be implemented");
89
+ },
90
+ },
91
+ hooks: {
92
+ async deploy() {
93
+ await this.processEvents(10);
94
+ },
95
+ },
96
+ async run() {
97
+ await this.processEvents();
98
+ },
99
+ };
@@ -0,0 +1,28 @@
1
+ import common from "../common/base-polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "topdesk-incident-updated",
6
+ name: "Incident Updated",
7
+ description: "Emit new event when an incident is updated. [See the documentation](https://developers.topdesk.com/explorer/?page=incident#/incident/get_incidents)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.topdesk.listIncidents;
15
+ },
16
+ paginateResults() {
17
+ return true;
18
+ },
19
+ generateMeta(incident) {
20
+ const ts = Date.parse(incident.modificationDate);
21
+ return {
22
+ id: `${incident.id}-${ts}`,
23
+ summary: `Incident Updated: ${incident.id}`,
24
+ ts,
25
+ };
26
+ },
27
+ },
28
+ };
@@ -0,0 +1,52 @@
1
+ import common from "../common/base-polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "topdesk-new-incident-assignee",
6
+ name: "New Incident Assignee",
7
+ description: "Emit new event when an incident is assigned to a new user. [See the documentation](https://developers.topdesk.com/explorer/?page=incident#/incident/get_incidents_id__id_)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ props: {
12
+ ...common.props,
13
+ incidentId: {
14
+ propDefinition: [
15
+ common.props.topdesk,
16
+ "incidentId",
17
+ ],
18
+ },
19
+ },
20
+ methods: {
21
+ ...common.methods,
22
+ getResourceFn() {
23
+ return this.topdesk.getIncident;
24
+ },
25
+ getArgs() {
26
+ return {
27
+ incidentId: this.incidentId,
28
+ };
29
+ },
30
+ getTsField() {
31
+ return "modificationDate";
32
+ },
33
+ paginateResults() {
34
+ return false;
35
+ },
36
+ isRelevant(incident) {
37
+ const previousValue = this._getPreviousValue();
38
+ if (incident.operator?.id !== previousValue) {
39
+ this._setPreviousValue(incident.operator?.id);
40
+ return true;
41
+ }
42
+ return false;
43
+ },
44
+ generateMeta(incident) {
45
+ return {
46
+ id: incident.id,
47
+ summary: `New Incident Assignee: ${incident.operator?.name || `ID: ${incident.operator?.id}`}`,
48
+ ts: Date.parse(incident.modificationDate),
49
+ };
50
+ },
51
+ },
52
+ };
@@ -0,0 +1,30 @@
1
+ import common from "../common/base-polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "topdesk-new-incident-created",
6
+ name: "New Incident Created",
7
+ description: "Emit new event when a new incident is created. [See the documentation](https://developers.topdesk.com/explorer/?page=incident#/incident/get_incidents)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ methods: {
12
+ ...common.methods,
13
+ getResourceFn() {
14
+ return this.topdesk.listIncidents;
15
+ },
16
+ getTsField() {
17
+ return "creationDate";
18
+ },
19
+ paginateResults() {
20
+ return true;
21
+ },
22
+ generateMeta(incident) {
23
+ return {
24
+ id: incident.id,
25
+ summary: `New Incident: ${incident.id}`,
26
+ ts: Date.parse(incident.creationDate),
27
+ };
28
+ },
29
+ },
30
+ };
@@ -0,0 +1,52 @@
1
+ import common from "../common/base-polling.mjs";
2
+
3
+ export default {
4
+ ...common,
5
+ key: "topdesk-new-incident-group-assigned",
6
+ name: "New Incident Group Assigned",
7
+ description: "Emit new event when an incident is assigned to a new group. [See the documentation](https://developers.topdesk.com/explorer/?page=incident#/incident/get_incidents_id__id_)",
8
+ version: "0.0.1",
9
+ type: "source",
10
+ dedupe: "unique",
11
+ props: {
12
+ ...common.props,
13
+ incidentId: {
14
+ propDefinition: [
15
+ common.props.topdesk,
16
+ "incidentId",
17
+ ],
18
+ },
19
+ },
20
+ methods: {
21
+ ...common.methods,
22
+ getResourceFn() {
23
+ return this.topdesk.getIncident;
24
+ },
25
+ getArgs() {
26
+ return {
27
+ incidentId: this.incidentId,
28
+ };
29
+ },
30
+ getTsField() {
31
+ return "modificationDate";
32
+ },
33
+ paginateResults() {
34
+ return false;
35
+ },
36
+ isRelevant(incident) {
37
+ const previousValue = this._getPreviousValue();
38
+ if (incident.caller.department?.id !== previousValue) {
39
+ this._setPreviousValue(incident.caller.department?.id);
40
+ return true;
41
+ }
42
+ return false;
43
+ },
44
+ generateMeta(incident) {
45
+ return {
46
+ id: incident.id,
47
+ summary: `New Incident Group Assigned: ${incident.caller.department?.name || `ID: ${incident.caller.department?.id}`}`,
48
+ ts: Date.parse(incident.modificationDate),
49
+ };
50
+ },
51
+ },
52
+ };