proca 1.7.3 → 1.7.5
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/README.md +37 -25
- package/package.json +1 -1
- package/src/commands/action/list.mjs +1 -1
- package/src/commands/action/replay.mjs +2 -0
- package/src/commands/action/requeue.mjs +116 -20
- package/src/commands/campaign/get.mjs +2 -0
- package/src/commands/campaign/mtt.mjs +46 -26
- package/src/commands/widget/add.mjs +6 -0
- package/src/queries/campaign.mjs +2 -0
package/README.md
CHANGED
|
@@ -209,24 +209,24 @@ EXAMPLES
|
|
|
209
209
|
```
|
|
210
210
|
USAGE
|
|
211
211
|
$ proca action list [TITLE] -o <organisation name> [--json | --human | --csv] [--env
|
|
212
|
-
<value>] [-c <campaign
|
|
212
|
+
<value>] [-c <campaign name>] [--limit <value>] [--today | --after 2025-04-09] [--optin] [--testing] [--doi] [--utm
|
|
213
213
|
| --simplify] [--comment | ]
|
|
214
214
|
|
|
215
215
|
ARGUMENTS
|
|
216
216
|
TITLE name of the campaign, % for wildchar
|
|
217
217
|
|
|
218
218
|
FLAGS
|
|
219
|
-
-c, --campaign=<campaign
|
|
220
|
-
-o, --org=<organisation name>
|
|
221
|
-
--after=2025-04-09
|
|
222
|
-
--[no-]comment
|
|
223
|
-
--doi
|
|
224
|
-
--env=<value>
|
|
225
|
-
--limit=<value>
|
|
226
|
-
--optin
|
|
227
|
-
--testing
|
|
228
|
-
--today
|
|
229
|
-
--[no-]utm
|
|
219
|
+
-c, --campaign=<campaign name> name of the campaign, % for wildchar
|
|
220
|
+
-o, --org=<organisation name> (required) campaigns of the organisation (coordinator or partner)
|
|
221
|
+
--after=2025-04-09 only actions after a date
|
|
222
|
+
--[no-]comment display the comment
|
|
223
|
+
--doi only export the double optin actions
|
|
224
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
225
|
+
--limit=<value> max number of actions
|
|
226
|
+
--optin only export the optin actions
|
|
227
|
+
--testing also export the test actions
|
|
228
|
+
--today only actions today
|
|
229
|
+
--[no-]utm display the utm tracking parameters
|
|
230
230
|
|
|
231
231
|
OUTPUT FLAGS
|
|
232
232
|
--csv Format output as csv
|
|
@@ -262,18 +262,28 @@ EXAMPLES
|
|
|
262
262
|
|
|
263
263
|
## `proca action requeue`
|
|
264
264
|
|
|
265
|
-
requeue
|
|
265
|
+
requeue actions
|
|
266
266
|
|
|
267
267
|
```
|
|
268
268
|
USAGE
|
|
269
|
-
$ proca action requeue
|
|
270
|
-
|
|
269
|
+
$ proca action requeue -o <org name> -q
|
|
270
|
+
CUSTOM_ACTION_CONFIRM|CUSTOM_ACTION_DELIVER|CUSTOM_SUPPORTER_CONFIRM|EMAIL_SUPPORTER|SQS|WEBHOOK [--json | --human |
|
|
271
|
+
--csv] [--env <value>] [--simplify] [-c <campaign name>] [--limit <value>] [--today | --after 2025-04-09] [--optin]
|
|
272
|
+
[--testing] [--doi]
|
|
271
273
|
|
|
272
274
|
FLAGS
|
|
273
|
-
-
|
|
274
|
-
-
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
-c, --campaign=<campaign name> name of the campaign, % for wildchar
|
|
276
|
+
-o, --org=<org name> (required) name of the org
|
|
277
|
+
-q, --queue=<option> (required) [default: CUSTOM_ACTION_DELIVER] queue to redeliver to
|
|
278
|
+
<options: CUSTOM_ACTION_CONFIRM|CUSTOM_ACTION_DELIVER|CUSTOM_SUPPORTER_CONFIRM|EMAIL_S
|
|
279
|
+
UPPORTER|SQS|WEBHOOK>
|
|
280
|
+
--after=2025-04-09 only actions after a date
|
|
281
|
+
--doi only export the double optin actions
|
|
282
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
283
|
+
--limit=<value> [default: 1000] how many actions per page
|
|
284
|
+
--optin only export the optin actions
|
|
285
|
+
--testing also export the test actions
|
|
286
|
+
--today only actions today
|
|
277
287
|
|
|
278
288
|
OUTPUT FLAGS
|
|
279
289
|
--csv Format output as csv
|
|
@@ -282,7 +292,7 @@ OUTPUT FLAGS
|
|
|
282
292
|
--[no-]simplify flatten and filter to output only the most important attributes, mostly relevant for json
|
|
283
293
|
|
|
284
294
|
DESCRIPTION
|
|
285
|
-
requeue
|
|
295
|
+
requeue actions
|
|
286
296
|
|
|
287
297
|
EXAMPLES
|
|
288
298
|
$ proca action requeue
|
|
@@ -435,20 +445,22 @@ set the mail to target (mtt) params
|
|
|
435
445
|
|
|
436
446
|
```
|
|
437
447
|
USAGE
|
|
438
|
-
$ proca campaign mtt [ID_NAME_DXID] --
|
|
439
|
-
|
|
440
|
-
<value>] [--email <value>]
|
|
448
|
+
$ proca campaign mtt [ID_NAME_DXID] [--json | --human | --csv] [--env <value>]
|
|
449
|
+
[--simplify] [-i <value> | -n <the_short_name> | -x <value>] [--from <value>] [--to <value>] [--template <value>]
|
|
450
|
+
[--period <value>] [--email <value>] [--cc <value>] [--sender]
|
|
441
451
|
|
|
442
452
|
FLAGS
|
|
443
453
|
-i, --id=<value>
|
|
444
454
|
-n, --name=<the_short_name> name
|
|
445
455
|
-x, --dxid=<value> dxid
|
|
456
|
+
--cc=<value> comma-separated list of CC email addresses
|
|
446
457
|
--email=<value> test email address
|
|
447
458
|
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
448
|
-
--from=<value>
|
|
459
|
+
--from=<value> start date (yyyy-mm-dd)
|
|
449
460
|
--period=<value> [default: 09:09-18:18] period of the day (HH:HH-HH:HH)
|
|
461
|
+
--sender add sender to CC
|
|
450
462
|
--template=<value> mtt template to use
|
|
451
|
-
--to=<value>
|
|
463
|
+
--to=<value> end date (yyyy-mm-dd)
|
|
452
464
|
|
|
453
465
|
OUTPUT FLAGS
|
|
454
466
|
--csv Format output as csv
|
package/package.json
CHANGED
|
@@ -30,7 +30,7 @@ export default class List extends Command {
|
|
|
30
30
|
campaign: Flags.string({
|
|
31
31
|
char: "c",
|
|
32
32
|
description: "name of the campaign, % for wildchar",
|
|
33
|
-
helpValue: "<campaign
|
|
33
|
+
helpValue: "<campaign name>",
|
|
34
34
|
}),
|
|
35
35
|
limit: Flags.string({
|
|
36
36
|
description: "max number of actions",
|
|
@@ -1,50 +1,147 @@
|
|
|
1
1
|
import { Args, Flags } from "@oclif/core";
|
|
2
2
|
import { error, stdout, ux } from "@oclif/core/ux";
|
|
3
3
|
import Command from "#src/procaCommand.mjs";
|
|
4
|
-
import { gql, mutation } from "#src/urql.mjs";
|
|
4
|
+
import { gql, mutation, query } from "#src/urql.mjs";
|
|
5
5
|
|
|
6
6
|
export default class ActionRequeue extends Command {
|
|
7
|
-
static description = "requeue
|
|
7
|
+
static description = "requeue actions";
|
|
8
8
|
|
|
9
9
|
static examples = ["<%= config.bin %> <%= command.id %>"];
|
|
10
10
|
|
|
11
11
|
static flags = {
|
|
12
12
|
...super.globalFlags,
|
|
13
|
-
id: Flags.string({
|
|
14
|
-
description: "action id",
|
|
15
|
-
parse: (input) => Number.parseInt(input, 10),
|
|
16
|
-
required: true,
|
|
17
|
-
}),
|
|
18
13
|
org: Flags.string({
|
|
19
14
|
char: "o",
|
|
20
15
|
required: true,
|
|
21
16
|
description: "name of the org",
|
|
22
17
|
helpValue: "<org name>",
|
|
23
18
|
}),
|
|
19
|
+
campaign: Flags.string({
|
|
20
|
+
char: "c",
|
|
21
|
+
description: "name of the campaign, % for wildchar",
|
|
22
|
+
helpValue: "<campaign name>",
|
|
23
|
+
}),
|
|
24
24
|
queue: Flags.string({
|
|
25
25
|
char: "q",
|
|
26
26
|
required: true,
|
|
27
27
|
description: "queue to redeliver to",
|
|
28
|
-
|
|
28
|
+
default: "CUSTOM_ACTION_DELIVER",
|
|
29
|
+
options: [
|
|
30
|
+
"CUSTOM_ACTION_CONFIRM",
|
|
31
|
+
"CUSTOM_ACTION_DELIVER",
|
|
32
|
+
"CUSTOM_SUPPORTER_CONFIRM",
|
|
33
|
+
"EMAIL_SUPPORTER",
|
|
34
|
+
"SQS",
|
|
35
|
+
"WEBHOOK",
|
|
36
|
+
],
|
|
37
|
+
}),
|
|
38
|
+
limit: Flags.string({
|
|
39
|
+
description: "how many actions per page",
|
|
40
|
+
default: 1000,
|
|
41
|
+
parse: (input) => Number.parseInt(input, 10),
|
|
42
|
+
}),
|
|
43
|
+
after: Flags.string({
|
|
44
|
+
description: "only actions after a date",
|
|
45
|
+
helpValue: "2025-04-09",
|
|
46
|
+
parse: (input) => new Date(input).toISOString(),
|
|
47
|
+
}),
|
|
48
|
+
today: Flags.boolean({
|
|
49
|
+
description: "only actions today",
|
|
50
|
+
exclusive: ["after"],
|
|
51
|
+
parse: (input) => `${new Date().toISOString().split("T")[0]}T00:00:00Z`,
|
|
52
|
+
}),
|
|
53
|
+
optin: Flags.boolean({
|
|
54
|
+
description: "only export the optin actions",
|
|
55
|
+
default: false,
|
|
56
|
+
}),
|
|
57
|
+
testing: Flags.boolean({
|
|
58
|
+
description: "also export the test actions",
|
|
59
|
+
default: false,
|
|
29
60
|
}),
|
|
61
|
+
doi: Flags.boolean({
|
|
62
|
+
description: "only export the double optin actions",
|
|
63
|
+
default: false,
|
|
64
|
+
}),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
process = async (flags) => {
|
|
68
|
+
let page = 0;
|
|
69
|
+
let actions = 0;
|
|
70
|
+
let requeued = 0;
|
|
71
|
+
let error = 0;
|
|
72
|
+
while (true) {
|
|
73
|
+
const ids = await this.fetch(flags);
|
|
74
|
+
if (ids.length === 0) break;
|
|
75
|
+
const result = await this.requeue(flags.org, flags.queue, ids);
|
|
76
|
+
requeued += result.count;
|
|
77
|
+
error += result.failed;
|
|
78
|
+
flags.start = ids[ids.length - 1] + 1;
|
|
79
|
+
process.stdout.write(`\rrequeued ${requeued}, id> ${flags.start}`);
|
|
80
|
+
page += 1;
|
|
81
|
+
actions += ids.length;
|
|
82
|
+
}
|
|
83
|
+
process.stdout.write("\r\x1b[K");
|
|
84
|
+
return { pages: page, actions, requeued, error };
|
|
30
85
|
};
|
|
31
86
|
|
|
32
|
-
|
|
87
|
+
fetch = async (flags) => {
|
|
33
88
|
const Document = gql`
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
89
|
+
query (
|
|
90
|
+
$after: DateTime
|
|
91
|
+
$campaignId: Int
|
|
92
|
+
$campaignName: String
|
|
93
|
+
$includeTesting: Boolean
|
|
94
|
+
$limit: Int
|
|
95
|
+
$onlyDoubleOptIn: Boolean
|
|
96
|
+
$onlyOptIn: Boolean
|
|
97
|
+
$orgName: String!
|
|
98
|
+
$start: Int
|
|
99
|
+
) {
|
|
100
|
+
actions (
|
|
101
|
+
after: $after
|
|
102
|
+
campaignId: $campaignId
|
|
103
|
+
campaignName: $campaignName
|
|
104
|
+
includeTesting: $includeTesting
|
|
105
|
+
limit: $limit
|
|
106
|
+
onlyDoubleOptIn: $onlyDoubleOptIn
|
|
107
|
+
onlyOptIn: $onlyOptIn
|
|
108
|
+
orgName: $orgName
|
|
109
|
+
start: $start
|
|
110
|
+
) {
|
|
111
|
+
actionId
|
|
112
|
+
}
|
|
113
|
+
}
|
|
40
114
|
`;
|
|
115
|
+
const result = await query(Document, {
|
|
116
|
+
after: flags.after,
|
|
117
|
+
campaignName: flags.campaign,
|
|
118
|
+
includeTesting: flags.testing,
|
|
119
|
+
limit: flags.limit,
|
|
120
|
+
onlyDoubleOptIn: flags.doi,
|
|
121
|
+
onlyOptIn: flags.optin,
|
|
122
|
+
orgName: flags.org,
|
|
123
|
+
start: flags.start,
|
|
124
|
+
});
|
|
125
|
+
const ids = [];
|
|
126
|
+
result.actions.forEach((d) => ids.push(d.actionId));
|
|
127
|
+
return ids;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
requeue = async (org, queue, ids) => {
|
|
131
|
+
const Document = gql`
|
|
132
|
+
mutation ($ids: [Int!], $org: String!, $queue: Queue!) {
|
|
133
|
+
requeueActions(ids: $ids, orgName: $org, queue: $queue) {
|
|
134
|
+
count
|
|
135
|
+
failed
|
|
136
|
+
}
|
|
137
|
+
}`;
|
|
41
138
|
const result = await mutation(Document, {
|
|
42
139
|
org,
|
|
43
|
-
|
|
44
|
-
|
|
140
|
+
queue,
|
|
141
|
+
ids,
|
|
45
142
|
});
|
|
46
143
|
//return result.users.map (d => {d.config = JSON.parse(d.config); return d});
|
|
47
|
-
return result.
|
|
144
|
+
return result.requeueActions;
|
|
48
145
|
};
|
|
49
146
|
|
|
50
147
|
table = (r) => {
|
|
@@ -52,9 +149,8 @@ mutation ($user: String!, $role: String!, $org: String!, message: String) {
|
|
|
52
149
|
};
|
|
53
150
|
|
|
54
151
|
async run() {
|
|
55
|
-
throw new Error("NOT IMPLEMENTED");
|
|
56
152
|
const { args, flags } = await this.parse();
|
|
57
|
-
const data = await this.
|
|
153
|
+
const data = await this.process(flags);
|
|
58
154
|
this.output(data);
|
|
59
155
|
}
|
|
60
156
|
}
|
|
@@ -83,6 +83,8 @@ export default class CampaignGet extends Command {
|
|
|
83
83
|
result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
|
|
84
84
|
result["test email"] = d.mtt.testEmail;
|
|
85
85
|
result["mtt template"] = d.mtt.template;
|
|
86
|
+
result["cc contacts"] = d.mtt.ccContacts?.join(", ");
|
|
87
|
+
result["cc sender"] = d.mtt.ccSender;
|
|
86
88
|
}
|
|
87
89
|
if (this.flags.stats) {
|
|
88
90
|
result["#Supporters"] = d.stats.supporterCount;
|
|
@@ -17,11 +17,11 @@ export default class CampaignMtt extends Command {
|
|
|
17
17
|
...this.flagify({ multiid: true }),
|
|
18
18
|
from: Flags.string({
|
|
19
19
|
description: "start date (yyyy-mm-dd)",
|
|
20
|
-
required:
|
|
20
|
+
required: false,
|
|
21
21
|
}),
|
|
22
22
|
to: Flags.string({
|
|
23
23
|
description: "end date (yyyy-mm-dd)",
|
|
24
|
-
required:
|
|
24
|
+
required: false,
|
|
25
25
|
}),
|
|
26
26
|
template: Flags.string({
|
|
27
27
|
description: "mtt template to use",
|
|
@@ -33,6 +33,13 @@ export default class CampaignMtt extends Command {
|
|
|
33
33
|
email: Flags.string({
|
|
34
34
|
description: "test email address",
|
|
35
35
|
}),
|
|
36
|
+
cc: Flags.string({
|
|
37
|
+
description: "comma-separated list of CC email addresses",
|
|
38
|
+
}),
|
|
39
|
+
sender: Flags.boolean({
|
|
40
|
+
description: "add sender to CC",
|
|
41
|
+
default: false,
|
|
42
|
+
}),
|
|
36
43
|
};
|
|
37
44
|
|
|
38
45
|
updateMtt = async (flags) => {
|
|
@@ -45,53 +52,67 @@ $mtt: CampaignMttInput!
|
|
|
45
52
|
updateCampaign (id:$id, name: $name, input: { mtt: $mtt }) {
|
|
46
53
|
id, name
|
|
47
54
|
...Mtt
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
55
|
+
}
|
|
56
|
+
${FragmentMtt}
|
|
57
|
+
}
|
|
51
58
|
`;
|
|
59
|
+
|
|
52
60
|
const testEmail = flags.email || `campaign+${flags.name}@proca.app`;
|
|
53
61
|
|
|
54
62
|
const [startPeriod, endPeriod] = flags.period.split("-");
|
|
55
63
|
const [startHour, startMinute] = startPeriod.split(":");
|
|
56
64
|
const [endHour, endMinute] = endPeriod.split(":");
|
|
57
65
|
|
|
58
|
-
const
|
|
59
|
-
|
|
66
|
+
const mtt = {
|
|
67
|
+
testEmail,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (flags.template) mtt.messageTemplate = flags.template;
|
|
71
|
+
if (flags.email) mtt.testEmail = testEmail;
|
|
72
|
+
if (flags.cc) mtt.ccContacts = flags.cc.split(",").map((e) => e.trim());
|
|
73
|
+
if (flags.sender) mtt.ccSender = flags.sender;
|
|
60
74
|
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
if (flags.from) {
|
|
76
|
+
const startAt = new Date(flags.from);
|
|
77
|
+
startAt.setHours(startHour, startMinute, 0, 0);
|
|
78
|
+
mtt.startAt = startAt.toISOString();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (flags.to) {
|
|
82
|
+
const endAt = new Date(flags.to);
|
|
83
|
+
endAt.setHours(endHour, endMinute, 0, 0);
|
|
84
|
+
mtt.endAt = endAt.toISOString();
|
|
85
|
+
}
|
|
63
86
|
|
|
64
87
|
const result = await mutation(Query, {
|
|
65
|
-
// org: props.org,
|
|
66
88
|
id: flags.id,
|
|
67
89
|
name: flags.name,
|
|
68
|
-
mtt
|
|
69
|
-
startAt: startAt.toISOString(),
|
|
70
|
-
endAt: endAt.toISOString(),
|
|
71
|
-
messageTemplate: flags.template,
|
|
72
|
-
testEmail: testEmail,
|
|
73
|
-
},
|
|
90
|
+
mtt,
|
|
74
91
|
});
|
|
75
|
-
|
|
76
92
|
return result.updateCampaign;
|
|
77
93
|
};
|
|
78
94
|
|
|
79
95
|
simplify = (d) => {
|
|
80
|
-
const result = {
|
|
81
|
-
id: d.id,
|
|
82
|
-
Name: d.name,
|
|
83
|
-
};
|
|
96
|
+
const result = { id: d.id, Name: d.name };
|
|
84
97
|
const hhmm = (date) =>
|
|
85
98
|
new Date(date).toLocaleTimeString(undefined, {
|
|
86
99
|
hour: "2-digit",
|
|
87
100
|
minute: "2-digit",
|
|
88
101
|
hour12: false,
|
|
89
102
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
103
|
+
if (d.mtt.startAt && d.mtt.endAt) {
|
|
104
|
+
result.from = d.mtt.startAt.substring(0, 10);
|
|
105
|
+
result.to = d.mtt.endAt.substring(0, 10);
|
|
106
|
+
result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
|
|
107
|
+
}
|
|
93
108
|
result["test email"] = d.mtt.testEmail;
|
|
94
|
-
result["mtt template"] = d.mtt.
|
|
109
|
+
result["mtt template"] = d.mtt.messageTemplate;
|
|
110
|
+
if (d.mtt.ccContacts?.length)
|
|
111
|
+
result["cc contacts"] = d.mtt.ccContacts.join(", ");
|
|
112
|
+
if (typeof d.mtt.ccSender !== "undefined") {
|
|
113
|
+
result["cc sender"] = d.mtt.ccSender ? "yes" : "no";
|
|
114
|
+
}
|
|
115
|
+
|
|
95
116
|
return result;
|
|
96
117
|
};
|
|
97
118
|
|
|
@@ -101,7 +122,6 @@ $mtt: CampaignMttInput!
|
|
|
101
122
|
|
|
102
123
|
async run() {
|
|
103
124
|
const { args, flags } = await this.parse();
|
|
104
|
-
|
|
105
125
|
const result = await this.updateMtt(flags);
|
|
106
126
|
this.output(result);
|
|
107
127
|
}
|
|
@@ -60,6 +60,9 @@ export default class WidgetAdd extends Command {
|
|
|
60
60
|
const campapi = new CampaignGet();
|
|
61
61
|
campaign = await campapi.fetch({ name: flag.campaign });
|
|
62
62
|
flag.org = campaign.org.name;
|
|
63
|
+
if (!flag.name) {
|
|
64
|
+
flag.name = `${campaign.name}/${flag.lang}`;
|
|
65
|
+
}
|
|
63
66
|
} catch (e) {
|
|
64
67
|
console.log("error", e);
|
|
65
68
|
throw e;
|
|
@@ -70,6 +73,9 @@ export default class WidgetAdd extends Command {
|
|
|
70
73
|
throw new Error(`campaign not found: ${flag.campaign}`);
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
if (!flag.name) {
|
|
77
|
+
flag.name = `${flag.campaign}/${flag.org}/${flag.lang}`;
|
|
78
|
+
}
|
|
73
79
|
try {
|
|
74
80
|
const r = await mutation(addWidgetDocument, flag);
|
|
75
81
|
return { id: r.addActionPage.id };
|