@pipedream/redmine 0.0.1 → 0.1.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/actions/create-issue/create-issue.mjs +69 -0
- package/actions/delete-user/delete-user.mjs +40 -0
- package/actions/update-project/update-project.mjs +75 -0
- package/common/constants.mjs +15 -0
- package/common/utils.mjs +43 -0
- package/package.json +1 -1
- package/redmine.app.mjs +220 -5
- package/sources/common/base.mjs +14 -0
- package/sources/common/polling.mjs +58 -0
- package/sources/issue-created/issue-created.mjs +34 -0
- package/sources/project-updated/project-updated.mjs +35 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import app from "../../redmine.app.mjs";
|
|
2
|
+
import utils from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "redmine-create-issue",
|
|
6
|
+
name: "Create Issue",
|
|
7
|
+
description: "Creates a new issue in Redmine. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_issues#creating-an-issue)",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
app,
|
|
12
|
+
projectId: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
app,
|
|
15
|
+
"projectId",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
trackerId: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
app,
|
|
21
|
+
"trackerId",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
subject: {
|
|
25
|
+
type: "string",
|
|
26
|
+
label: "Subject",
|
|
27
|
+
description: "The subject of the issue",
|
|
28
|
+
},
|
|
29
|
+
description: {
|
|
30
|
+
type: "string",
|
|
31
|
+
label: "Description",
|
|
32
|
+
description: "The description of the issue",
|
|
33
|
+
},
|
|
34
|
+
statusId: {
|
|
35
|
+
propDefinition: [
|
|
36
|
+
app,
|
|
37
|
+
"statusId",
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
priorityId: {
|
|
41
|
+
propDefinition: [
|
|
42
|
+
app,
|
|
43
|
+
"priorityId",
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
methods: {
|
|
48
|
+
createIssue(args = {}) {
|
|
49
|
+
return this.app.post({
|
|
50
|
+
path: "/issues.json",
|
|
51
|
+
...args,
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
run({ $: step }) {
|
|
56
|
+
const {
|
|
57
|
+
createIssue,
|
|
58
|
+
...issue
|
|
59
|
+
} = this;
|
|
60
|
+
|
|
61
|
+
return createIssue({
|
|
62
|
+
step,
|
|
63
|
+
data: {
|
|
64
|
+
issue: utils.transformProps(issue),
|
|
65
|
+
},
|
|
66
|
+
summary: (response) => `Successfully created issue with ID: \`${response.issue?.id}\``,
|
|
67
|
+
});
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import app from "../../redmine.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "redmine-delete-user",
|
|
5
|
+
name: "Delete User",
|
|
6
|
+
description: "Deletes a user from the Redmine platform. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_users#delete)",
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
type: "action",
|
|
9
|
+
props: {
|
|
10
|
+
app,
|
|
11
|
+
userId: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
app,
|
|
14
|
+
"userId",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
methods: {
|
|
19
|
+
deleteUser({
|
|
20
|
+
userId, ...args
|
|
21
|
+
} = {}) {
|
|
22
|
+
return this.app.delete({
|
|
23
|
+
path: `/users/${userId}.json`,
|
|
24
|
+
...args,
|
|
25
|
+
});
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
run({ $: step }) {
|
|
29
|
+
const {
|
|
30
|
+
deleteUser,
|
|
31
|
+
userId,
|
|
32
|
+
} = this;
|
|
33
|
+
|
|
34
|
+
return deleteUser({
|
|
35
|
+
step,
|
|
36
|
+
userId,
|
|
37
|
+
summary: () => "Successfully deleted user",
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import app from "../../redmine.app.mjs";
|
|
2
|
+
import utils from "../../common/utils.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
key: "redmine-update-project",
|
|
6
|
+
name: "Update Project",
|
|
7
|
+
description: "Updates an existing project in Redmine. [See the documentation](https://www.redmine.org/projects/redmine/wiki/rest_projects#updating-a-project)",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "action",
|
|
10
|
+
props: {
|
|
11
|
+
app,
|
|
12
|
+
projectId: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
app,
|
|
15
|
+
"projectId",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
name: {
|
|
19
|
+
type: "string",
|
|
20
|
+
label: "Name",
|
|
21
|
+
description: "The name of the project",
|
|
22
|
+
optional: true,
|
|
23
|
+
},
|
|
24
|
+
description: {
|
|
25
|
+
type: "string",
|
|
26
|
+
label: "Description",
|
|
27
|
+
description: "The description of the project",
|
|
28
|
+
optional: true,
|
|
29
|
+
},
|
|
30
|
+
homepage: {
|
|
31
|
+
type: "string",
|
|
32
|
+
label: "Homepage",
|
|
33
|
+
description: "The homepage of the project",
|
|
34
|
+
optional: true,
|
|
35
|
+
},
|
|
36
|
+
isPublic: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
label: "Is Public",
|
|
39
|
+
description: "Whether the project is public",
|
|
40
|
+
optional: true,
|
|
41
|
+
},
|
|
42
|
+
inheritMembers: {
|
|
43
|
+
type: "boolean",
|
|
44
|
+
label: "Inherit Members",
|
|
45
|
+
description: "Whether the project should inherit members from its parent",
|
|
46
|
+
optional: true,
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
methods: {
|
|
50
|
+
updateProject({
|
|
51
|
+
projectId, ...args
|
|
52
|
+
} = {}) {
|
|
53
|
+
return this.app.put({
|
|
54
|
+
path: `/projects/${projectId}.json`,
|
|
55
|
+
...args,
|
|
56
|
+
});
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
run({ $: step }) {
|
|
60
|
+
const {
|
|
61
|
+
updateProject,
|
|
62
|
+
projectId,
|
|
63
|
+
...project
|
|
64
|
+
} = this;
|
|
65
|
+
|
|
66
|
+
return updateProject({
|
|
67
|
+
step,
|
|
68
|
+
projectId,
|
|
69
|
+
data: {
|
|
70
|
+
project: utils.transformProps(project),
|
|
71
|
+
},
|
|
72
|
+
summary: () => "Successfully updated project",
|
|
73
|
+
});
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const SUMMARY_LABEL = "$summary";
|
|
2
|
+
const DOMAIN_PLACEHOLDER = "{domain}";
|
|
3
|
+
const BASE_URL = `https://${DOMAIN_PLACEHOLDER}`;
|
|
4
|
+
const LAST_CREATED_AT = "lastCreatedAt";
|
|
5
|
+
const DEFAULT_MAX = 600;
|
|
6
|
+
const DEFAULT_LIMIT = 60;
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
SUMMARY_LABEL,
|
|
10
|
+
DOMAIN_PLACEHOLDER,
|
|
11
|
+
BASE_URL,
|
|
12
|
+
DEFAULT_MAX,
|
|
13
|
+
DEFAULT_LIMIT,
|
|
14
|
+
LAST_CREATED_AT,
|
|
15
|
+
};
|
package/common/utils.mjs
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function toSnakeCase(str) {
|
|
2
|
+
return str?.replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function keysToSnakeCase(data = {}) {
|
|
6
|
+
return Object.entries(data)
|
|
7
|
+
.reduce((acc, [
|
|
8
|
+
key,
|
|
9
|
+
value,
|
|
10
|
+
]) => ({
|
|
11
|
+
...acc,
|
|
12
|
+
[toSnakeCase(key)]: value,
|
|
13
|
+
}), {});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function transformProps(props) {
|
|
17
|
+
if (!props) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return keysToSnakeCase(
|
|
22
|
+
Object.fromEntries(
|
|
23
|
+
Object.entries(props)
|
|
24
|
+
.filter(([
|
|
25
|
+
key,
|
|
26
|
+
value,
|
|
27
|
+
]) => typeof(value) !== "function" && key !== "app"),
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function iterate(iterations) {
|
|
33
|
+
const items = [];
|
|
34
|
+
for await (const item of iterations) {
|
|
35
|
+
items.push(item);
|
|
36
|
+
}
|
|
37
|
+
return items;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default {
|
|
41
|
+
transformProps,
|
|
42
|
+
iterate,
|
|
43
|
+
};
|
package/package.json
CHANGED
package/redmine.app.mjs
CHANGED
|
@@ -1,11 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
axios, ConfigurationError,
|
|
3
|
+
} from "@pipedream/platform";
|
|
4
|
+
import constants from "./common/constants.mjs";
|
|
5
|
+
import utils from "./common/utils.mjs";
|
|
6
|
+
|
|
1
7
|
export default {
|
|
2
8
|
type: "app",
|
|
3
9
|
app: "redmine",
|
|
4
|
-
propDefinitions: {
|
|
10
|
+
propDefinitions: {
|
|
11
|
+
projectId: {
|
|
12
|
+
type: "integer",
|
|
13
|
+
label: "Project ID",
|
|
14
|
+
description: "The ID of the project",
|
|
15
|
+
async options() {
|
|
16
|
+
const response = await this.listProjects();
|
|
17
|
+
console.log(response);
|
|
18
|
+
const { projects } = response;
|
|
19
|
+
return projects.map(({
|
|
20
|
+
id: value, name: label,
|
|
21
|
+
}) => ({
|
|
22
|
+
label,
|
|
23
|
+
value,
|
|
24
|
+
}));
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
trackerId: {
|
|
28
|
+
type: "integer",
|
|
29
|
+
label: "Tracker ID",
|
|
30
|
+
description: "The ID of the tracker",
|
|
31
|
+
async options() {
|
|
32
|
+
const { trackers } = await this.listTrackers();
|
|
33
|
+
return trackers.map(({
|
|
34
|
+
id: value, name: label,
|
|
35
|
+
}) => ({
|
|
36
|
+
label,
|
|
37
|
+
value,
|
|
38
|
+
}));
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
statusId: {
|
|
42
|
+
type: "integer",
|
|
43
|
+
label: "Status ID",
|
|
44
|
+
description: "The ID of the status",
|
|
45
|
+
async options() {
|
|
46
|
+
const { issue_statuses: statuses } = await this.listIssueStatuses();
|
|
47
|
+
return statuses.map(({
|
|
48
|
+
id: value, name: label,
|
|
49
|
+
}) => ({
|
|
50
|
+
label,
|
|
51
|
+
value,
|
|
52
|
+
}));
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
priorityId: {
|
|
56
|
+
type: "integer",
|
|
57
|
+
label: "Priority ID",
|
|
58
|
+
description: "The ID of the priority",
|
|
59
|
+
async options() {
|
|
60
|
+
const { issue_priorities: priorities } = await this.listIssuePriorities();
|
|
61
|
+
return priorities.map(({
|
|
62
|
+
id: value, name: label,
|
|
63
|
+
}) => ({
|
|
64
|
+
label,
|
|
65
|
+
value,
|
|
66
|
+
}));
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
userId: {
|
|
70
|
+
type: "integer",
|
|
71
|
+
label: "User ID",
|
|
72
|
+
description: "The ID of the user",
|
|
73
|
+
async options() {
|
|
74
|
+
const { users } = await this.listUsers();
|
|
75
|
+
return users.map(({
|
|
76
|
+
id: value, login: label,
|
|
77
|
+
}) => ({
|
|
78
|
+
label,
|
|
79
|
+
value,
|
|
80
|
+
}));
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
5
84
|
methods: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
85
|
+
exportSummary(step) {
|
|
86
|
+
if (!step?.export) {
|
|
87
|
+
throw new ConfigurationError("The summary method should be bind to the step object aka `$`");
|
|
88
|
+
}
|
|
89
|
+
return (msg = "") => step.export(constants.SUMMARY_LABEL, msg);
|
|
90
|
+
},
|
|
91
|
+
getUrl(path) {
|
|
92
|
+
const baseUrl = constants.BASE_URL
|
|
93
|
+
.replace(constants.DOMAIN_PLACEHOLDER, this.$auth.hostname);
|
|
94
|
+
return `${baseUrl}${path}`;
|
|
95
|
+
},
|
|
96
|
+
async makeRequest({
|
|
97
|
+
step = this, path, headers, summary, ...args
|
|
98
|
+
} = {}) {
|
|
99
|
+
const {
|
|
100
|
+
getUrl,
|
|
101
|
+
exportSummary,
|
|
102
|
+
$auth: { api_key: apiKey },
|
|
103
|
+
} = this;
|
|
104
|
+
|
|
105
|
+
const config = {
|
|
106
|
+
...args,
|
|
107
|
+
url: getUrl(path),
|
|
108
|
+
headers: {
|
|
109
|
+
...headers,
|
|
110
|
+
"X-Redmine-API-Key": apiKey,
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const response = await axios(step, config);
|
|
115
|
+
|
|
116
|
+
if (typeof(summary) === "function") {
|
|
117
|
+
exportSummary(step)(summary(response));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return response || {
|
|
121
|
+
success: true,
|
|
122
|
+
};
|
|
123
|
+
},
|
|
124
|
+
post(args = {}) {
|
|
125
|
+
return this.makeRequest({
|
|
126
|
+
method: "post",
|
|
127
|
+
...args,
|
|
128
|
+
});
|
|
129
|
+
},
|
|
130
|
+
put(args = {}) {
|
|
131
|
+
return this.makeRequest({
|
|
132
|
+
method: "put",
|
|
133
|
+
...args,
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
delete(args = {}) {
|
|
137
|
+
return this.makeRequest({
|
|
138
|
+
method: "delete",
|
|
139
|
+
...args,
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
listIssues(args = {}) {
|
|
143
|
+
return this.makeRequest({
|
|
144
|
+
path: "/issues.json",
|
|
145
|
+
...args,
|
|
146
|
+
});
|
|
147
|
+
},
|
|
148
|
+
listProjects(args = {}) {
|
|
149
|
+
return this.makeRequest({
|
|
150
|
+
path: "/projects.json",
|
|
151
|
+
...args,
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
listTrackers(args = {}) {
|
|
155
|
+
return this.makeRequest({
|
|
156
|
+
path: "/trackers.json",
|
|
157
|
+
...args,
|
|
158
|
+
});
|
|
159
|
+
},
|
|
160
|
+
listIssueStatuses(args = {}) {
|
|
161
|
+
return this.makeRequest({
|
|
162
|
+
path: "/issue_statuses.json",
|
|
163
|
+
...args,
|
|
164
|
+
});
|
|
165
|
+
},
|
|
166
|
+
listIssuePriorities(args = {}) {
|
|
167
|
+
return this.makeRequest({
|
|
168
|
+
path: "/enumerations/issue_priorities.json",
|
|
169
|
+
...args,
|
|
170
|
+
});
|
|
171
|
+
},
|
|
172
|
+
listUsers(args = {}) {
|
|
173
|
+
return this.makeRequest({
|
|
174
|
+
path: "/users.json",
|
|
175
|
+
...args,
|
|
176
|
+
});
|
|
177
|
+
},
|
|
178
|
+
async *getIterations({
|
|
179
|
+
resourceFn,
|
|
180
|
+
resourceFnArgs,
|
|
181
|
+
resourceName,
|
|
182
|
+
max = constants.DEFAULT_MAX,
|
|
183
|
+
}) {
|
|
184
|
+
let offset = 0;
|
|
185
|
+
let resourcesCount = 0;
|
|
186
|
+
|
|
187
|
+
while (true) {
|
|
188
|
+
const response =
|
|
189
|
+
await resourceFn({
|
|
190
|
+
...resourceFnArgs,
|
|
191
|
+
params: {
|
|
192
|
+
offset,
|
|
193
|
+
limit: constants.DEFAULT_LIMIT,
|
|
194
|
+
...resourceFnArgs?.params,
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const nextResources = resourceName && response[resourceName] || response;
|
|
199
|
+
|
|
200
|
+
if (!nextResources?.length) {
|
|
201
|
+
console.log("No more resources found");
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
for (const resource of nextResources) {
|
|
206
|
+
yield resource;
|
|
207
|
+
resourcesCount += 1;
|
|
208
|
+
|
|
209
|
+
if (resourcesCount >= max) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (nextResources.length < constants.DEFAULT_LIMIT) {
|
|
215
|
+
console.log("Less resources than the limit found, no more resources to fetch");
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
offset += constants.DEFAULT_LIMIT;
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
paginate(args = {}) {
|
|
223
|
+
return utils.iterate(this.getIterations(args));
|
|
9
224
|
},
|
|
10
225
|
},
|
|
11
|
-
};
|
|
226
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ConfigurationError } from "@pipedream/platform";
|
|
2
|
+
import app from "../../redmine.app.mjs";
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
props: {
|
|
6
|
+
app,
|
|
7
|
+
db: "$.service.db",
|
|
8
|
+
},
|
|
9
|
+
methods: {
|
|
10
|
+
generateMeta() {
|
|
11
|
+
throw new ConfigurationError("generateMeta is not implemented");
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConfigurationError,
|
|
3
|
+
DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
|
|
4
|
+
} from "@pipedream/platform";
|
|
5
|
+
import common from "./base.mjs";
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
...common,
|
|
9
|
+
props: {
|
|
10
|
+
...common.props,
|
|
11
|
+
timer: {
|
|
12
|
+
type: "$.interface.timer",
|
|
13
|
+
label: "Polling schedule",
|
|
14
|
+
description: "How often to poll the API",
|
|
15
|
+
default: {
|
|
16
|
+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
methods: {
|
|
21
|
+
...common.methods,
|
|
22
|
+
getResourceName() {
|
|
23
|
+
throw new ConfigurationError("getResourceName is not implemented");
|
|
24
|
+
},
|
|
25
|
+
getResourceFn() {
|
|
26
|
+
throw new ConfigurationError("getResourceFn is not implemented");
|
|
27
|
+
},
|
|
28
|
+
getResourceFnArgs() {
|
|
29
|
+
throw new ConfigurationError("getResourceFnArgs is not implemented");
|
|
30
|
+
},
|
|
31
|
+
processEvent(resource) {
|
|
32
|
+
const meta = this.generateMeta(resource);
|
|
33
|
+
this.$emit(resource, meta);
|
|
34
|
+
},
|
|
35
|
+
async processResources(resources) {
|
|
36
|
+
Array.from(resources)
|
|
37
|
+
.reverse()
|
|
38
|
+
.forEach(this.processEvent);
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
async run() {
|
|
42
|
+
const {
|
|
43
|
+
app,
|
|
44
|
+
getResourceFn,
|
|
45
|
+
getResourceFnArgs,
|
|
46
|
+
getResourceName,
|
|
47
|
+
processResources,
|
|
48
|
+
} = this;
|
|
49
|
+
|
|
50
|
+
const resources = await app.paginate({
|
|
51
|
+
resourceFn: getResourceFn(),
|
|
52
|
+
resourceFnArgs: getResourceFnArgs(),
|
|
53
|
+
resourceName: getResourceName(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
processResources(resources);
|
|
57
|
+
},
|
|
58
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import common from "../common/polling.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...common,
|
|
5
|
+
key: "redmine-issue-created",
|
|
6
|
+
name: "New Issue Created",
|
|
7
|
+
description: "Emit new event when a new issue is created in Redmine",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "source",
|
|
10
|
+
dedupe: "unique",
|
|
11
|
+
methods: {
|
|
12
|
+
...common.methods,
|
|
13
|
+
getResourceName() {
|
|
14
|
+
return "issues";
|
|
15
|
+
},
|
|
16
|
+
getResourceFn() {
|
|
17
|
+
return this.app.listIssues;
|
|
18
|
+
},
|
|
19
|
+
getResourceFnArgs() {
|
|
20
|
+
return {
|
|
21
|
+
params: {
|
|
22
|
+
sort: "created_on:desc",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
generateMeta(resource) {
|
|
27
|
+
return {
|
|
28
|
+
id: resource.id,
|
|
29
|
+
summary: `New Issue: ${resource.subject}`,
|
|
30
|
+
ts: Date.parse(resource.created_on),
|
|
31
|
+
};
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import common from "../common/polling.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...common,
|
|
5
|
+
key: "redmine-project-updated",
|
|
6
|
+
name: "Project Updated",
|
|
7
|
+
description: "Emits an event whenever a project is updated in Redmine",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "source",
|
|
10
|
+
dedupe: "unique",
|
|
11
|
+
methods: {
|
|
12
|
+
...common.methods,
|
|
13
|
+
getResourceName() {
|
|
14
|
+
return "projects";
|
|
15
|
+
},
|
|
16
|
+
getResourceFn() {
|
|
17
|
+
return this.app.listProjects;
|
|
18
|
+
},
|
|
19
|
+
getResourceFnArgs() {
|
|
20
|
+
return {
|
|
21
|
+
params: {
|
|
22
|
+
sort: "updated_on:desc",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
generateMeta(resource) {
|
|
27
|
+
const ts = Date.parse(resource.updated_on);
|
|
28
|
+
return {
|
|
29
|
+
id: `${resource.id}-${ts}`,
|
|
30
|
+
summary: `Project Updated: ${resource.name}`,
|
|
31
|
+
ts,
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|