proca 1.7.4 → 1.7.6
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 +14 -9
- package/package.json +96 -96
- package/src/commands/campaign/get.mjs +94 -91
- package/src/commands/campaign/mtt.mjs +116 -93
- package/src/commands/org/get.mjs +91 -77
- package/src/commands/user/list.mjs +41 -38
- package/src/commands/widget/add.mjs +96 -72
- package/src/queries/campaign.mjs +3 -0
package/README.md
CHANGED
|
@@ -445,20 +445,23 @@ set the mail to target (mtt) params
|
|
|
445
445
|
|
|
446
446
|
```
|
|
447
447
|
USAGE
|
|
448
|
-
$ proca campaign mtt [ID_NAME_DXID] --
|
|
449
|
-
|
|
450
|
-
<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] [--drip]
|
|
451
451
|
|
|
452
452
|
FLAGS
|
|
453
453
|
-i, --id=<value>
|
|
454
454
|
-n, --name=<the_short_name> name
|
|
455
455
|
-x, --dxid=<value> dxid
|
|
456
|
+
--cc=<value> comma-separated list of CC email addresses
|
|
457
|
+
--drip drip delivery or deliver as fast as possible
|
|
456
458
|
--email=<value> test email address
|
|
457
459
|
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
458
|
-
--from=<value>
|
|
460
|
+
--from=<value> start date (yyyy-mm-dd)
|
|
459
461
|
--period=<value> [default: 09:09-18:18] period of the day (HH:HH-HH:HH)
|
|
462
|
+
--sender add sender to CC
|
|
460
463
|
--template=<value> mtt template to use
|
|
461
|
-
--to=<value>
|
|
464
|
+
--to=<value> end date (yyyy-mm-dd)
|
|
462
465
|
|
|
463
466
|
OUTPUT FLAGS
|
|
464
467
|
--csv Format output as csv
|
|
@@ -925,14 +928,16 @@ view a org
|
|
|
925
928
|
```
|
|
926
929
|
USAGE
|
|
927
930
|
$ proca org get [ID_NAME_DXID] [--json | --human | --csv] [--env <value>]
|
|
928
|
-
[--simplify] [-n <org name>] [--config] [--keys] [--campaigns] [--users]
|
|
931
|
+
[--simplify] [-n <org name>] [--config] [--personaldata] [--processing] [--keys] [--campaigns] [--users]
|
|
929
932
|
|
|
930
933
|
FLAGS
|
|
931
|
-
-n, --name=<org name>
|
|
934
|
+
-n, --name=<org name> name of the org
|
|
932
935
|
--[no-]campaigns
|
|
933
|
-
--[no-]config
|
|
934
|
-
--env=<value>
|
|
936
|
+
--[no-]config display the config
|
|
937
|
+
--env=<value> [default: default] allow to switch between configurations (server or users)
|
|
935
938
|
--[no-]keys
|
|
939
|
+
--[no-]personaldata how are the personal data of the supporter processed
|
|
940
|
+
--[no-]processing additional processing workflows on the actions
|
|
936
941
|
--[no-]users
|
|
937
942
|
|
|
938
943
|
OUTPUT FLAGS
|
package/package.json
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
2
|
+
"name": "proca",
|
|
3
|
+
"description": "Access the proca api",
|
|
4
|
+
"version": "1.7.6",
|
|
5
|
+
"author": "Xavier",
|
|
6
|
+
"bin": {
|
|
7
|
+
"proca": "proca-cli"
|
|
8
|
+
},
|
|
9
|
+
"bugs": "https://github.com/fixthestatusquo/git@github.com:fixthestatusquo/proca-cli.git/issues",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@oclif/core": "^4.2.10",
|
|
12
|
+
"@oclif/plugin-help": "^6",
|
|
13
|
+
"@oclif/plugin-plugins": "^5",
|
|
14
|
+
"@urql/exchange-auth": "^2.2.0",
|
|
15
|
+
"date-fns": "^4.1.0",
|
|
16
|
+
"dotenv": "^16.4.5",
|
|
17
|
+
"dxid": "^2.2.1",
|
|
18
|
+
"easy-table": "^1.2.0",
|
|
19
|
+
"fast-csv": "^5.0.1",
|
|
20
|
+
"graphql": "^16.10.0",
|
|
21
|
+
"typescript": "^5.7.3",
|
|
22
|
+
"urql": "^4.1.0",
|
|
23
|
+
"prompts": "^2.4.2"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@biomejs/biome": "^1.9.3",
|
|
27
|
+
"@graphql-codegen/cli": "^2.x.x",
|
|
28
|
+
"@graphql-codegen/introspection": "^2.x.x",
|
|
29
|
+
"@graphql-codegen/typescript-operations": "^4.2.3",
|
|
30
|
+
"@graphql-codegen/typescript-urql": "^4.0.0",
|
|
31
|
+
"@oclif/plugin-autocomplete": "^3.2.5",
|
|
32
|
+
"@oclif/plugin-commands": "^4.1.3",
|
|
33
|
+
"@oclif/plugin-not-found": "^3.2.22",
|
|
34
|
+
"lefthook": "^1.7.18",
|
|
35
|
+
"oclif": "^4.17.46"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18.0.0"
|
|
39
|
+
},
|
|
40
|
+
"files": ["/proca-cli", "/src", "/theme.json"],
|
|
41
|
+
"homepage": "https://github.com/fixthestatusquo/git@github.com:fixthestatusquo/proca-cli.git",
|
|
42
|
+
"keywords": [
|
|
43
|
+
"cli",
|
|
44
|
+
"petition",
|
|
45
|
+
"proca",
|
|
46
|
+
"campaigning",
|
|
47
|
+
"digital-engagement",
|
|
48
|
+
"social-change",
|
|
49
|
+
"nonprofit",
|
|
50
|
+
"civic-tech",
|
|
51
|
+
"mobilisation",
|
|
52
|
+
"advocacy",
|
|
53
|
+
"activism",
|
|
54
|
+
"email-campaign",
|
|
55
|
+
"grassroots",
|
|
56
|
+
"gdpr"
|
|
57
|
+
],
|
|
58
|
+
"imports": {
|
|
59
|
+
"#src/*": "./src/*"
|
|
60
|
+
},
|
|
61
|
+
"license": "aGPL3",
|
|
62
|
+
"main": "./proca-cli",
|
|
63
|
+
"oclif": {
|
|
64
|
+
"repository": "github:fixthestatusquo/proca-cli",
|
|
65
|
+
"bin": "proca",
|
|
66
|
+
"theme": "theme.json",
|
|
67
|
+
"topicSeparator": " ",
|
|
68
|
+
"commands": "./src/commands",
|
|
69
|
+
"helpClass": "./src/hooks/help.mjs",
|
|
70
|
+
"topics": {
|
|
71
|
+
"widget": {
|
|
72
|
+
"description": "widgets (actionPages in the API)"
|
|
73
|
+
},
|
|
74
|
+
"campaign": {
|
|
75
|
+
"description": "campaigns"
|
|
76
|
+
},
|
|
77
|
+
"user": {
|
|
78
|
+
"description": "campaigners and other users"
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"plugins": [
|
|
82
|
+
"@oclif/plugin-plugins",
|
|
83
|
+
"@oclif/plugin-help",
|
|
84
|
+
"@oclif/plugin-commands"
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
"repository": {
|
|
88
|
+
"type": "git",
|
|
89
|
+
"url": "git+ssh://git@github.com/fixthestatusquo/proca-cli.git"
|
|
90
|
+
},
|
|
91
|
+
"scripts": {
|
|
92
|
+
"check": "npx @biomejs/biome check --write",
|
|
93
|
+
"format": "npx @biomejs/biome format --write",
|
|
94
|
+
"lint": "npx @biomejs/biome lint --write",
|
|
95
|
+
"prepack": "oclif manifest && oclif readme",
|
|
96
|
+
"version": "oclif readme && git add README.md"
|
|
97
|
+
}
|
|
98
98
|
}
|
|
@@ -2,42 +2,42 @@ 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
4
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
FragmentMtt,
|
|
6
|
+
FragmentOrg,
|
|
7
|
+
FragmentStats,
|
|
8
|
+
FragmentSummary,
|
|
9
9
|
} from "#src/queries/campaign.mjs";
|
|
10
10
|
import { gql, query } from "#src/urql.mjs";
|
|
11
11
|
|
|
12
12
|
export default class CampaignGet extends Command {
|
|
13
|
-
|
|
13
|
+
actionTypes = new Set();
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
static args = this.multiid();
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
static description = "view a campaign";
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
static examples = ["<%= config.bin %> <%= command.id %> -i 42"];
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
21
|
+
static flags = {
|
|
22
|
+
// flag with no value (-f, --force)
|
|
23
|
+
...this.flagify({ multiid: true }),
|
|
24
|
+
config: Flags.boolean({
|
|
25
|
+
description: "display the config",
|
|
26
|
+
default: false,
|
|
27
|
+
allowNo: true,
|
|
28
|
+
}),
|
|
29
|
+
stats: Flags.boolean({
|
|
30
|
+
description: "display the stats",
|
|
31
|
+
default: true,
|
|
32
|
+
allowNo: true,
|
|
33
|
+
}),
|
|
34
|
+
locale: Flags.string({
|
|
35
|
+
description: "display a locale",
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
fetch = async ({ id, name }) => {
|
|
40
|
+
const GetCampaignDocument = gql`
|
|
41
41
|
query GetCampaign($id: Int, $name: String, $withStats: Boolean = false) {
|
|
42
42
|
campaign (name: $name, id: $id) {
|
|
43
43
|
...Summary
|
|
@@ -52,73 +52,76 @@ export default class CampaignGet extends Command {
|
|
|
52
52
|
${FragmentOrg}
|
|
53
53
|
${FragmentMtt}
|
|
54
54
|
`;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
const result = await query(GetCampaignDocument, {
|
|
56
|
+
id: id,
|
|
57
|
+
name: name,
|
|
58
|
+
withStats: this.flags.stats,
|
|
59
|
+
});
|
|
60
|
+
return result.campaign;
|
|
61
|
+
};
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
63
|
+
simplify = (d) => {
|
|
64
|
+
const result = {
|
|
65
|
+
id: d.id,
|
|
66
|
+
Name: d.name,
|
|
67
|
+
Title: d.title,
|
|
68
|
+
Org: d.org.name,
|
|
69
|
+
Status: d.status,
|
|
70
|
+
locales: d.config.locales && Object.keys(d.config.locales).join(" "),
|
|
71
|
+
journey: d.config.journey?.join(" → "),
|
|
72
|
+
};
|
|
73
|
+
if (d.mtt) {
|
|
74
|
+
// we have an mtt
|
|
75
|
+
const hhmm = (date) =>
|
|
76
|
+
new Date(date).toLocaleTimeString(undefined, {
|
|
77
|
+
hour: "2-digit",
|
|
78
|
+
minute: "2-digit",
|
|
79
|
+
hour12: false,
|
|
80
|
+
});
|
|
81
|
+
result.from = d.mtt.startAt.substring(0, 10);
|
|
82
|
+
result.to = d.mtt.endAt.substring(0, 10);
|
|
83
|
+
result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
|
|
84
|
+
result["test email"] = d.mtt.testEmail;
|
|
85
|
+
result["mtt template"] = d.mtt.template;
|
|
86
|
+
result["cc contacts"] = d.mtt.ccContacts?.join(", ");
|
|
87
|
+
result["cc sender"] = d.mtt.ccSender;
|
|
88
|
+
result["drip delivery"] = d.mtt.dripDelivery;
|
|
89
|
+
}
|
|
90
|
+
if (this.flags.stats) {
|
|
91
|
+
result["#Supporters"] = d.stats.supporterCount;
|
|
89
92
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
this.actionTypes.forEach((type) => {
|
|
94
|
+
const action = d.stats.actionCount.find(
|
|
95
|
+
(action) => action.actionType === type,
|
|
96
|
+
);
|
|
97
|
+
if (action) result[`#${type}`] = action.count;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
table = (r) => {
|
|
104
|
+
r.config = JSON.parse(r.config);
|
|
105
|
+
super.table(r, null, null);
|
|
106
|
+
if (this.flags.locale) {
|
|
107
|
+
this.prettyJson(r.config?.locales[this.flags.locale]);
|
|
108
|
+
}
|
|
109
|
+
if (this.flags.config) {
|
|
110
|
+
r.config.locales = undefined;
|
|
111
|
+
this.prettyJson(r.config);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
111
114
|
|
|
112
|
-
|
|
113
|
-
|
|
115
|
+
async run() {
|
|
116
|
+
const { args, flags } = await this.parse();
|
|
114
117
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
118
|
+
const data = await this.fetch({ id: flags.id, name: flags.name });
|
|
119
|
+
if (this.flags.stats) {
|
|
120
|
+
data.stats.actionCount.forEach((d) => {
|
|
121
|
+
//skip share_confirmed?
|
|
122
|
+
this.actionTypes.add(d.actionType);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return this.output(data);
|
|
126
|
+
}
|
|
124
127
|
}
|
|
@@ -1,42 +1,52 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { error, stdout, ux } from "@oclif/core/ux";
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
3
2
|
import Command from "#src/procaCommand.mjs";
|
|
4
3
|
import { FragmentMtt } from "#src/queries/campaign.mjs";
|
|
5
4
|
import { gql, mutation } from "#src/urql.mjs";
|
|
6
5
|
|
|
7
6
|
export default class CampaignMtt extends Command {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
7
|
+
static args = this.multiid();
|
|
8
|
+
|
|
9
|
+
static description = "set the mail to target (mtt) params";
|
|
10
|
+
|
|
11
|
+
static examples = [
|
|
12
|
+
"<%= config.bin %> <%= command.id %> -n <test-mtt-campaign>",
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
static flags = {
|
|
16
|
+
...this.flagify({ multiid: true }),
|
|
17
|
+
from: Flags.string({
|
|
18
|
+
description: "start date (yyyy-mm-dd)",
|
|
19
|
+
required: false,
|
|
20
|
+
}),
|
|
21
|
+
to: Flags.string({
|
|
22
|
+
description: "end date (yyyy-mm-dd)",
|
|
23
|
+
required: false,
|
|
24
|
+
}),
|
|
25
|
+
template: Flags.string({
|
|
26
|
+
description: "mtt template to use",
|
|
27
|
+
}),
|
|
28
|
+
period: Flags.string({
|
|
29
|
+
description: "period of the day (HH:HH-HH:HH)",
|
|
30
|
+
default: "09:09-18:18",
|
|
31
|
+
}),
|
|
32
|
+
email: Flags.string({
|
|
33
|
+
description: "test email address",
|
|
34
|
+
}),
|
|
35
|
+
cc: Flags.string({
|
|
36
|
+
description: "comma-separated list of CC email addresses",
|
|
37
|
+
}),
|
|
38
|
+
sender: Flags.boolean({
|
|
39
|
+
description: "add sender to CC",
|
|
40
|
+
default: false,
|
|
41
|
+
}),
|
|
42
|
+
drip: Flags.boolean({
|
|
43
|
+
description: "drip delivery or deliver as fast as possible",
|
|
44
|
+
default: false,
|
|
45
|
+
}),
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
updateMtt = async (flags) => {
|
|
49
|
+
const Query = gql`
|
|
40
50
|
mutation (
|
|
41
51
|
$id: Int,
|
|
42
52
|
$name: String
|
|
@@ -45,64 +55,77 @@ $mtt: CampaignMttInput!
|
|
|
45
55
|
updateCampaign (id:$id, name: $name, input: { mtt: $mtt }) {
|
|
46
56
|
id, name
|
|
47
57
|
...Mtt
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
58
|
+
}
|
|
59
|
+
${FragmentMtt}
|
|
60
|
+
}
|
|
51
61
|
`;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
62
|
+
|
|
63
|
+
const testEmail = flags.email || `campaign+${flags.name}@proca.app`;
|
|
64
|
+
|
|
65
|
+
const [startPeriod, endPeriod] = flags.period.split("-");
|
|
66
|
+
const [startHour, startMinute] = startPeriod.split(":");
|
|
67
|
+
const [endHour, endMinute] = endPeriod.split(":");
|
|
68
|
+
|
|
69
|
+
const mtt = {
|
|
70
|
+
testEmail,
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
if (flags.template) mtt.messageTemplate = flags.template;
|
|
74
|
+
if (flags.email) mtt.testEmail = testEmail;
|
|
75
|
+
if (flags.cc) mtt.ccContacts = flags.cc.split(",").map((e) => e.trim());
|
|
76
|
+
if (flags.sender) mtt.ccSender = flags.sender;
|
|
77
|
+
|
|
78
|
+
if (flags.from) {
|
|
79
|
+
const startAt = new Date(flags.from);
|
|
80
|
+
startAt.setHours(startHour, startMinute, 0, 0);
|
|
81
|
+
mtt.startAt = startAt.toISOString();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (flags.to) {
|
|
85
|
+
const endAt = new Date(flags.to);
|
|
86
|
+
endAt.setHours(endHour, endMinute, 0, 0);
|
|
87
|
+
mtt.endAt = endAt.toISOString();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const result = await mutation(Query, {
|
|
91
|
+
id: flags.id,
|
|
92
|
+
name: flags.name,
|
|
93
|
+
mtt,
|
|
94
|
+
});
|
|
95
|
+
return result.updateCampaign;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
simplify = (d) => {
|
|
99
|
+
const result = { id: d.id, Name: d.name };
|
|
100
|
+
const hhmm = (date) =>
|
|
101
|
+
new Date(date).toLocaleTimeString(undefined, {
|
|
102
|
+
hour: "2-digit",
|
|
103
|
+
minute: "2-digit",
|
|
104
|
+
hour12: false,
|
|
105
|
+
});
|
|
106
|
+
if (d.mtt.startAt && d.mtt.endAt) {
|
|
107
|
+
result.from = d.mtt.startAt.substring(0, 10);
|
|
108
|
+
result.to = d.mtt.endAt.substring(0, 10);
|
|
109
|
+
result.period = `${hhmm(d.mtt.startAt)}↔${hhmm(d.mtt.endAt)}`;
|
|
110
|
+
}
|
|
111
|
+
result["test email"] = d.mtt.testEmail;
|
|
112
|
+
result["mtt template"] = d.mtt.messageTemplate;
|
|
113
|
+
if (d.mtt.ccContacts?.length)
|
|
114
|
+
result["cc contacts"] = d.mtt.ccContacts.join(", ");
|
|
115
|
+
if (typeof d.mtt.ccSender !== "undefined") {
|
|
116
|
+
result["cc sender"] = d.mtt.ccSender ? "yes" : "no";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return result;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
table = (r) => {
|
|
123
|
+
super.table(r, null, null);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
async run() {
|
|
127
|
+
const { args, flags } = await this.parse();
|
|
128
|
+
const result = await this.updateMtt(flags);
|
|
129
|
+
this.output(result);
|
|
130
|
+
}
|
|
108
131
|
}
|
package/src/commands/org/get.mjs
CHANGED
|
@@ -5,50 +5,60 @@ import Command from "#src/procaCommand.mjs";
|
|
|
5
5
|
import { gql, query } from "#src/urql.mjs";
|
|
6
6
|
|
|
7
7
|
export default class OrgGet extends Command {
|
|
8
|
-
|
|
8
|
+
static description = "view a org";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
static examples = ["<%= config.bin %> <%= command.id %> <name of the ngo>"];
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
static args = this.multiid();
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
14
|
+
static flags = {
|
|
15
|
+
// flag with no value (-f, --force)
|
|
16
|
+
...this.flagify({ multiid: false }),
|
|
17
|
+
name: Flags.string({
|
|
18
|
+
char: "n",
|
|
19
|
+
charAliases: ["o"],
|
|
20
|
+
description: "name of the org",
|
|
21
|
+
helpValue: "<org name>",
|
|
22
|
+
}),
|
|
23
|
+
config: Flags.boolean({
|
|
24
|
+
description: "display the config",
|
|
25
|
+
default: false,
|
|
26
|
+
allowNo: true,
|
|
27
|
+
}),
|
|
28
|
+
personaldata: Flags.boolean({
|
|
29
|
+
description: "how are the personal data of the supporter processed",
|
|
30
|
+
default: true,
|
|
31
|
+
allowNo: true,
|
|
32
|
+
}),
|
|
33
|
+
processing: Flags.boolean({
|
|
34
|
+
description: "additional processing workflows on the actions",
|
|
35
|
+
default: true,
|
|
36
|
+
allowNo: true,
|
|
37
|
+
}),
|
|
38
|
+
keys: Flags.boolean({
|
|
39
|
+
default: true,
|
|
40
|
+
allowNo: true,
|
|
41
|
+
}),
|
|
42
|
+
campaigns: Flags.boolean({
|
|
43
|
+
default: false,
|
|
44
|
+
allowNo: true,
|
|
45
|
+
}),
|
|
46
|
+
users: Flags.boolean({
|
|
47
|
+
default: true,
|
|
48
|
+
allowNo: true,
|
|
49
|
+
}),
|
|
50
|
+
};
|
|
41
51
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
query GetOrg($name: String!, $withCampaigns: Boolean = true, $withKeys: Boolean = true) {
|
|
52
|
+
fetch = async (params) => {
|
|
53
|
+
const GetOrgDocument = gql`
|
|
54
|
+
query GetOrg($name: String!, $withCampaigns: Boolean = true, $withKeys: Boolean = true, $withPersonalData: Boolean = false, $withProcessing: Boolean= false ) {
|
|
45
55
|
org (name: $name) {
|
|
46
56
|
id name title
|
|
47
57
|
config
|
|
48
58
|
keys @include(if: $withKeys) {id, name, expired, expiredAt, public}
|
|
49
59
|
|
|
50
60
|
campaigns @include(if: $withCampaigns) {id, name, title, org {name}}
|
|
51
|
-
personalData {
|
|
61
|
+
personalData @include(if: $withPersonalData) {
|
|
52
62
|
contactSchema
|
|
53
63
|
doiThankYou
|
|
54
64
|
highSecurity
|
|
@@ -56,7 +66,7 @@ export default class OrgGet extends Command {
|
|
|
56
66
|
supporterConfirm
|
|
57
67
|
supporterConfirmTemplate
|
|
58
68
|
}
|
|
59
|
-
processing {
|
|
69
|
+
processing @include(if: $withProcessing) {
|
|
60
70
|
customActionConfirm
|
|
61
71
|
customActionDeliver
|
|
62
72
|
customEventDeliver
|
|
@@ -84,50 +94,54 @@ export default class OrgGet extends Command {
|
|
|
84
94
|
}
|
|
85
95
|
`;
|
|
86
96
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
const result = await query(GetOrgDocument, {
|
|
98
|
+
name: params.name,
|
|
99
|
+
withCampaigns: params.campaigns,
|
|
100
|
+
withKeys: params.keys || true,
|
|
101
|
+
withPersonalData: params.personaldata,
|
|
102
|
+
$withProcessing: params.processing,
|
|
103
|
+
});
|
|
104
|
+
if (result.org.config) {
|
|
105
|
+
result.org.config = JSON.parse(result.org.config);
|
|
106
|
+
}
|
|
107
|
+
return result.org;
|
|
108
|
+
};
|
|
95
109
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
simplify = (d) => {
|
|
111
|
+
const result = {
|
|
112
|
+
id: d.id,
|
|
113
|
+
Name: d.name,
|
|
114
|
+
Title: d.title,
|
|
115
|
+
"can targets reply?": d.replyEnabled ? true : undefined,
|
|
116
|
+
"confirm actions?": d.supporterConfirm
|
|
117
|
+
? d.supporterConfirmTemplate
|
|
118
|
+
: undefined,
|
|
119
|
+
};
|
|
120
|
+
if (this.flags.stats) {
|
|
121
|
+
result["#Supporters"] = d.stats.supporterCount;
|
|
108
122
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
this.actionTypes.forEach((type) => {
|
|
124
|
+
const action = d.stats.actionCount.find(
|
|
125
|
+
(action) => action.actionType === type,
|
|
126
|
+
);
|
|
127
|
+
if (action) result[`#${type}`] = action.count;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return result;
|
|
131
|
+
};
|
|
118
132
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
133
|
+
table = (r) => {
|
|
134
|
+
r.config = JSON.parse(r.config);
|
|
135
|
+
super.table(r, null, null);
|
|
136
|
+
if (this.flags.config) {
|
|
137
|
+
r.config.locales = undefined;
|
|
138
|
+
this.prettyJson(r.config);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
127
141
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
142
|
+
async run() {
|
|
143
|
+
const { args, flags } = await this.parse();
|
|
144
|
+
const data = await this.fetch(flags);
|
|
145
|
+
return this.output(data);
|
|
146
|
+
}
|
|
133
147
|
}
|
|
@@ -4,24 +4,24 @@ import Command from "#src/procaCommand.mjs";
|
|
|
4
4
|
import { gql, query } from "#src/urql.mjs";
|
|
5
5
|
|
|
6
6
|
export default class UserList extends Command {
|
|
7
|
-
|
|
7
|
+
actionTypes = new Set();
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
static description = "list all the users";
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
static examples = ["<%= config.bin %> <%= command.id %> %pizza%"];
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
static flags = {
|
|
14
|
+
// flag with no value (-f, --force)
|
|
15
|
+
...super.globalFlags,
|
|
16
|
+
org: Flags.string({
|
|
17
|
+
char: "o",
|
|
18
|
+
description: "organisation",
|
|
19
|
+
required: true,
|
|
20
|
+
}),
|
|
21
|
+
};
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
fetch = async (org) => {
|
|
24
|
+
const SearchUsersDocument = gql`
|
|
25
25
|
query ($org: String!) {
|
|
26
26
|
users(select: {orgName: $org}) {
|
|
27
27
|
apiToken {
|
|
@@ -39,33 +39,36 @@ query ($org: String!) {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
`;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
const result = await query(SearchUsersDocument, { org: org });
|
|
43
|
+
return result.users;
|
|
44
|
+
//return result.users.map (d => {d.config = JSON.parse(d.config); return d});
|
|
45
|
+
};
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if (d.isAdmin) {
|
|
54
|
-
result.superadmin = true;
|
|
55
|
-
}
|
|
56
|
-
if (d.apiToken) {
|
|
57
|
-
result.tokenExpire = d.apiToken.tokenExpire;
|
|
58
|
-
}
|
|
47
|
+
simplify = (d) => {
|
|
48
|
+
const result = {
|
|
49
|
+
id: d.id,
|
|
50
|
+
email: d.email,
|
|
51
|
+
};
|
|
52
|
+
result.orgs = d.roles.map((d) => d.org.name).join(",");
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
};
|
|
54
|
+
d.roles.filter((d) => d.org.name === this.flags.org)[0]?.role || "??";
|
|
62
55
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
if (d.isAdmin) {
|
|
57
|
+
result.superadmin = true;
|
|
58
|
+
}
|
|
59
|
+
if (d.apiToken) {
|
|
60
|
+
result.tokenExpire = d.apiToken.tokenExpire;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
async run() {
|
|
67
|
+
const { flags } = await this.parse(UserList);
|
|
68
|
+
let data = [];
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
data = await this.fetch(flags.org);
|
|
71
|
+
|
|
72
|
+
return this.output(data);
|
|
73
|
+
}
|
|
71
74
|
}
|
|
@@ -1,101 +1,125 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { error, stdout, ux } from "@oclif/core/ux";
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
3
2
|
import CampaignGet from "#src/commands/campaign/get.mjs";
|
|
3
|
+
import OrgGet from "#src/commands/org/get.mjs";
|
|
4
4
|
import Command from "#src/procaCommand.mjs";
|
|
5
5
|
import { gql, mutation } from "#src/urql.mjs";
|
|
6
6
|
|
|
7
7
|
export default class WidgetAdd extends Command {
|
|
8
|
-
|
|
8
|
+
//static args = { path: { description: "" } };
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
10
|
+
static flags = {
|
|
11
|
+
// flag with no value (-f, --force)
|
|
12
|
+
...super.globalFlags,
|
|
13
|
+
campaign: Flags.string({
|
|
14
|
+
char: "c",
|
|
15
|
+
required: true,
|
|
16
|
+
description: "name of the campaign",
|
|
17
|
+
helpValue: "<campaign name>",
|
|
18
|
+
}),
|
|
19
|
+
org: Flags.string({
|
|
20
|
+
char: "o",
|
|
21
|
+
description: "organisation",
|
|
22
|
+
helpValue: "<en>",
|
|
23
|
+
}),
|
|
24
|
+
lang: Flags.string({
|
|
25
|
+
char: "l",
|
|
26
|
+
description: "language",
|
|
27
|
+
default: "en",
|
|
28
|
+
helpValue: "<en>",
|
|
29
|
+
}),
|
|
30
|
+
name: Flags.string({
|
|
31
|
+
char: "n",
|
|
32
|
+
description: "url slug",
|
|
33
|
+
helpValue: "by default <campaign>/<org>/<lang>",
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
create = async (flag) => {
|
|
38
|
+
const orgName = flag.org;
|
|
39
|
+
let campaign = { org: { name: orgName } }; // no need to fetch the campaign if the orgName is specified
|
|
40
|
+
let org = {}; // no need to fetch the campaign if the orgName is specified
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
const addWidgetDocument = gql`
|
|
42
43
|
mutation addPage(
|
|
43
44
|
$campaign: String!
|
|
44
45
|
$org: String!
|
|
45
46
|
$name: String!
|
|
46
47
|
$lang: String!
|
|
48
|
+
$config: Json
|
|
47
49
|
) {
|
|
48
50
|
addActionPage(
|
|
49
51
|
campaignName: $campaign
|
|
50
52
|
orgName: $org
|
|
51
|
-
input: { name: $name, locale: $lang }
|
|
53
|
+
input: { name: $name, locale: $lang, config: $config }
|
|
52
54
|
) {
|
|
53
55
|
id
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
`;
|
|
57
59
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
60
|
+
if (!orgName) {
|
|
61
|
+
try {
|
|
62
|
+
const campapi = new CampaignGet();
|
|
63
|
+
campaign = await campapi.fetch({ name: flag.campaign });
|
|
64
|
+
flag.org = campaign.org.name;
|
|
65
|
+
if (!flag.name) {
|
|
66
|
+
flag.name = `${campaign.name}/${flag.lang}`;
|
|
67
|
+
}
|
|
68
|
+
} catch (e) {
|
|
69
|
+
console.log("error", e);
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (!campaign) {
|
|
75
|
+
throw new Error(`campaign not found: ${flag.campaign}`);
|
|
76
|
+
}
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
try {
|
|
79
|
+
const orgapi = new OrgGet();
|
|
80
|
+
org = await orgapi.fetch({
|
|
81
|
+
name: flag.org,
|
|
82
|
+
campaigns: false,
|
|
83
|
+
keys: false,
|
|
84
|
+
});
|
|
85
|
+
if (org.config.layout) {
|
|
86
|
+
flag.config = JSON.stringify({ layout: org.config.layout });
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
console.log("error", e);
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
72
92
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
if (!flag.name) {
|
|
94
|
+
flag.name = `${flag.campaign}/${flag.org}/${flag.lang}`;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const r = await mutation(addWidgetDocument, flag);
|
|
98
|
+
return { id: r.addActionPage.id };
|
|
99
|
+
} catch (e) {
|
|
100
|
+
const errors = e.graphQLErrors;
|
|
101
|
+
console.log(JSON.stringify(errors, null, 2), flag);
|
|
102
|
+
if (errors[0].path[1] === "name") {
|
|
103
|
+
this.error(`invalid name (already taken?): ${flag.name}`);
|
|
104
|
+
throw new Error(errors[0].message);
|
|
105
|
+
}
|
|
106
|
+
if (errors[0].extensions?.code === "permission_denied") {
|
|
107
|
+
console.error("permission denied to create", name, campaign?.org.name);
|
|
108
|
+
throw new Error(errors[0].message);
|
|
109
|
+
}
|
|
110
|
+
console.log(flag);
|
|
111
|
+
// const page = await fetchByName(name);
|
|
112
|
+
// console.warn("duplicate of widget", page.id);
|
|
113
|
+
throw new Error(errors[0].message);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
92
116
|
|
|
93
|
-
|
|
94
|
-
|
|
117
|
+
async run() {
|
|
118
|
+
const { args, flags } = await this.parse();
|
|
95
119
|
|
|
96
|
-
|
|
120
|
+
// const org = { name: flags.twitter || flags.name, config: {} };
|
|
97
121
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
122
|
+
const data = await this.create(flags);
|
|
123
|
+
return this.output(data);
|
|
124
|
+
}
|
|
101
125
|
}
|