planflow-plugin 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/LICENSE +21 -0
- package/README.md +93 -0
- package/bin/cli.js +169 -0
- package/bin/postinstall.js +87 -0
- package/commands/pfActivity/SKILL.md +725 -0
- package/commands/pfAssign/SKILL.md +623 -0
- package/commands/pfCloudLink/SKILL.md +192 -0
- package/commands/pfCloudList/SKILL.md +222 -0
- package/commands/pfCloudNew/SKILL.md +187 -0
- package/commands/pfCloudUnlink/SKILL.md +152 -0
- package/commands/pfComment/SKILL.md +227 -0
- package/commands/pfComments/SKILL.md +159 -0
- package/commands/pfConnectionStatus/SKILL.md +433 -0
- package/commands/pfDiscord/SKILL.md +740 -0
- package/commands/pfGithubBranch/SKILL.md +672 -0
- package/commands/pfGithubIssue/SKILL.md +963 -0
- package/commands/pfGithubLink/SKILL.md +859 -0
- package/commands/pfGithubPr/SKILL.md +1335 -0
- package/commands/pfGithubUnlink/SKILL.md +401 -0
- package/commands/pfLive/SKILL.md +185 -0
- package/commands/pfLogin/SKILL.md +249 -0
- package/commands/pfLogout/SKILL.md +155 -0
- package/commands/pfMyTasks/SKILL.md +198 -0
- package/commands/pfNotificationSettings/SKILL.md +619 -0
- package/commands/pfNotifications/SKILL.md +420 -0
- package/commands/pfNotificationsClear/SKILL.md +421 -0
- package/commands/pfReact/SKILL.md +232 -0
- package/commands/pfSlack/SKILL.md +659 -0
- package/commands/pfSyncPull/SKILL.md +210 -0
- package/commands/pfSyncPush/SKILL.md +299 -0
- package/commands/pfSyncStatus/SKILL.md +212 -0
- package/commands/pfTeamInvite/SKILL.md +161 -0
- package/commands/pfTeamList/SKILL.md +253 -0
- package/commands/pfTeamRemove/SKILL.md +115 -0
- package/commands/pfTeamRole/SKILL.md +160 -0
- package/commands/pfTestWebhooks/SKILL.md +722 -0
- package/commands/pfUnassign/SKILL.md +134 -0
- package/commands/pfWhoami/SKILL.md +258 -0
- package/commands/pfWorkload/SKILL.md +219 -0
- package/commands/planExportCsv/SKILL.md +106 -0
- package/commands/planExportGithub/SKILL.md +222 -0
- package/commands/planExportJson/SKILL.md +159 -0
- package/commands/planExportSummary/SKILL.md +158 -0
- package/commands/planNew/SKILL.md +641 -0
- package/commands/planNext/SKILL.md +1200 -0
- package/commands/planSettingsAutoSync/SKILL.md +199 -0
- package/commands/planSettingsLanguage/SKILL.md +201 -0
- package/commands/planSettingsReset/SKILL.md +237 -0
- package/commands/planSettingsShow/SKILL.md +482 -0
- package/commands/planSpec/SKILL.md +929 -0
- package/commands/planUpdate/SKILL.md +2518 -0
- package/commands/team/SKILL.md +740 -0
- package/locales/en.json +1499 -0
- package/locales/ka.json +1499 -0
- package/package.json +48 -0
- package/templates/PROJECT_PLAN.template.md +157 -0
- package/templates/backend-api.template.md +562 -0
- package/templates/frontend-spa.template.md +610 -0
- package/templates/fullstack.template.md +397 -0
- package/templates/ka/backend-api.template.md +562 -0
- package/templates/ka/frontend-spa.template.md +610 -0
- package/templates/ka/fullstack.template.md +397 -0
- package/templates/sections/architecture.md +21 -0
- package/templates/sections/overview.md +15 -0
- package/templates/sections/tasks.md +22 -0
- package/templates/sections/tech-stack.md +19 -0
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pfSlack
|
|
3
|
+
description: Configure Slack webhook integration for PlanFlow notifications
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PlanFlow Slack Integration
|
|
7
|
+
|
|
8
|
+
Configure Slack webhook integration to receive project notifications directly in your Slack workspace.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
/pfSlack # Show current Slack integration status
|
|
14
|
+
/pfSlack setup <webhook-url> # Set up Slack webhook
|
|
15
|
+
/pfSlack test # Send a test notification to Slack
|
|
16
|
+
/pfSlack disable # Disable Slack notifications
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Webhook URL Format:**
|
|
20
|
+
```
|
|
21
|
+
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Process
|
|
25
|
+
|
|
26
|
+
### Step 0: Load Configuration & Translations
|
|
27
|
+
|
|
28
|
+
**CRITICAL: Execute this step FIRST, before any output!**
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
// Merge global and local configs
|
|
32
|
+
function getMergedConfig() {
|
|
33
|
+
let globalConfig = {}
|
|
34
|
+
let localConfig = {}
|
|
35
|
+
|
|
36
|
+
const globalPath = expandPath("~/.config/claude/plan-plugin-config.json")
|
|
37
|
+
if (fileExists(globalPath)) {
|
|
38
|
+
try { globalConfig = JSON.parse(readFile(globalPath)) } catch (e) {}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (fileExists("./.plan-config.json")) {
|
|
42
|
+
try { localConfig = JSON.parse(readFile("./.plan-config.json")) } catch (e) {}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
...globalConfig,
|
|
47
|
+
...localConfig,
|
|
48
|
+
cloud: {
|
|
49
|
+
...(globalConfig.cloud || {}),
|
|
50
|
+
...(localConfig.cloud || {})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const config = getMergedConfig()
|
|
56
|
+
const language = config.language || "en"
|
|
57
|
+
const cloudConfig = config.cloud || {}
|
|
58
|
+
const isAuthenticated = !!cloudConfig.apiToken
|
|
59
|
+
const projectId = cloudConfig.projectId
|
|
60
|
+
const apiUrl = cloudConfig.apiUrl || "https://api.planflow.tools"
|
|
61
|
+
|
|
62
|
+
// Load translations
|
|
63
|
+
const t = JSON.parse(readFile(`locales/${language}.json`))
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Step 1: Check Authentication
|
|
67
|
+
|
|
68
|
+
If not authenticated, show error:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
72
|
+
│ ❌ ERROR │
|
|
73
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
74
|
+
│ │
|
|
75
|
+
│ {t.commands.sync.notAuthenticated} │
|
|
76
|
+
│ │
|
|
77
|
+
│ Slack integration requires a cloud connection. │
|
|
78
|
+
│ │
|
|
79
|
+
│ 💡 Run /pfLogin to authenticate first. │
|
|
80
|
+
│ │
|
|
81
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If no project linked, show error:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
88
|
+
│ ❌ ERROR │
|
|
89
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
90
|
+
│ │
|
|
91
|
+
│ {t.commands.sync.notLinked} │
|
|
92
|
+
│ │
|
|
93
|
+
│ 💡 Run /pfCloudLink to link a project first. │
|
|
94
|
+
│ │
|
|
95
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Step 2: Parse Arguments
|
|
99
|
+
|
|
100
|
+
```javascript
|
|
101
|
+
const args = commandArgs.trim()
|
|
102
|
+
const parts = args.split(/\s+/)
|
|
103
|
+
const action = parts[0] || null // "setup", "test", "disable", or null (show status)
|
|
104
|
+
const webhookUrl = parts[1] || null // Webhook URL for setup action
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Step 3: Handle Actions
|
|
108
|
+
|
|
109
|
+
#### If no action (show current status)
|
|
110
|
+
|
|
111
|
+
Fetch current Slack integration status from API.
|
|
112
|
+
|
|
113
|
+
**API Endpoint:** `GET /projects/:projectId/integrations/slack`
|
|
114
|
+
|
|
115
|
+
**Bash Implementation:**
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
API_URL="https://api.planflow.tools"
|
|
119
|
+
TOKEN="$API_TOKEN"
|
|
120
|
+
PROJECT_ID="$PROJECT_ID"
|
|
121
|
+
|
|
122
|
+
# Fetch current Slack integration status
|
|
123
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
124
|
+
--connect-timeout 5 \
|
|
125
|
+
--max-time 10 \
|
|
126
|
+
-X GET \
|
|
127
|
+
-H "Accept: application/json" \
|
|
128
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
129
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack")
|
|
130
|
+
|
|
131
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
132
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
133
|
+
|
|
134
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
135
|
+
echo "$BODY"
|
|
136
|
+
else
|
|
137
|
+
echo "Error: HTTP $HTTP_CODE"
|
|
138
|
+
fi
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Expected Response:**
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"success": true,
|
|
146
|
+
"data": {
|
|
147
|
+
"integration": {
|
|
148
|
+
"enabled": true,
|
|
149
|
+
"webhookConfigured": true,
|
|
150
|
+
"webhookUrl": "https://hooks.slack.com/services/T.../B.../XXX...",
|
|
151
|
+
"channel": "#planflow-notifications",
|
|
152
|
+
"lastTestAt": "2026-02-20T10:30:00Z",
|
|
153
|
+
"lastNotificationAt": "2026-02-21T08:00:00Z",
|
|
154
|
+
"events": {
|
|
155
|
+
"taskCompleted": true,
|
|
156
|
+
"taskAssigned": true,
|
|
157
|
+
"mentions": true,
|
|
158
|
+
"comments": true
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Status Card (Slack configured):**
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
169
|
+
│ 💬 {t.commands.slack.title} │
|
|
170
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
171
|
+
│ │
|
|
172
|
+
│ 📁 Project: {projectName} │
|
|
173
|
+
│ │
|
|
174
|
+
│ ── {t.commands.slack.status} ─────────────────────────────────────────── │
|
|
175
|
+
│ │
|
|
176
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
177
|
+
│ │ ✅ {t.commands.slack.connected} │ │
|
|
178
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
179
|
+
│ │
|
|
180
|
+
│ 📍 Webhook: ···/services/T.../B.../XXX... (configured) │
|
|
181
|
+
│ 📢 Channel: #planflow-notifications │
|
|
182
|
+
│ 🕐 Last Test: 2 hours ago │
|
|
183
|
+
│ 📨 Last Sent: 30 minutes ago │
|
|
184
|
+
│ │
|
|
185
|
+
│ ── {t.commands.slack.events} ─────────────────────────────────────────── │
|
|
186
|
+
│ │
|
|
187
|
+
│ [✓] Task completed │
|
|
188
|
+
│ [✓] Task assigned │
|
|
189
|
+
│ [✓] @mentions │
|
|
190
|
+
│ [✓] New comments │
|
|
191
|
+
│ │
|
|
192
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
193
|
+
│ │
|
|
194
|
+
│ 💡 {t.ui.labels.commands} │
|
|
195
|
+
│ • /pfSlack test Send a test notification │
|
|
196
|
+
│ • /pfSlack disable Disable Slack notifications │
|
|
197
|
+
│ │
|
|
198
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
199
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Status Card (Slack not configured):**
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
206
|
+
│ 💬 {t.commands.slack.title} │
|
|
207
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
208
|
+
│ │
|
|
209
|
+
│ 📁 Project: {projectName} │
|
|
210
|
+
│ │
|
|
211
|
+
│ ── {t.commands.slack.status} ─────────────────────────────────────────── │
|
|
212
|
+
│ │
|
|
213
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
214
|
+
│ │ ❌ {t.commands.slack.notConfigured} │ │
|
|
215
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
216
|
+
│ │
|
|
217
|
+
│ {t.commands.slack.notConfiguredHint} │
|
|
218
|
+
│ │
|
|
219
|
+
│ ── {t.commands.slack.howToSetup} ─────────────────────────────────────── │
|
|
220
|
+
│ │
|
|
221
|
+
│ 1. Go to your Slack workspace settings │
|
|
222
|
+
│ 2. Navigate to: Apps → Incoming Webhooks │
|
|
223
|
+
│ 3. Create a new webhook for your channel │
|
|
224
|
+
│ 4. Copy the webhook URL │
|
|
225
|
+
│ 5. Run: /pfSlack setup <webhook-url> │
|
|
226
|
+
│ │
|
|
227
|
+
│ 📖 Guide: https://api.slack.com/messaging/webhooks │
|
|
228
|
+
│ │
|
|
229
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
230
|
+
│ │
|
|
231
|
+
│ 💡 {t.ui.labels.commands} │
|
|
232
|
+
│ • /pfSlack setup <url> Configure Slack webhook │
|
|
233
|
+
│ │
|
|
234
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
235
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### If action is "setup"
|
|
239
|
+
|
|
240
|
+
Set up Slack webhook integration.
|
|
241
|
+
|
|
242
|
+
**Validation:**
|
|
243
|
+
1. Webhook URL is required
|
|
244
|
+
2. Must be a valid Slack webhook URL (starts with `https://hooks.slack.com/`)
|
|
245
|
+
|
|
246
|
+
**Invalid URL Error:**
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
250
|
+
│ ❌ ERROR │
|
|
251
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
252
|
+
│ │
|
|
253
|
+
│ {t.commands.slack.invalidUrl} │
|
|
254
|
+
│ │
|
|
255
|
+
│ The webhook URL must be a valid Slack incoming webhook URL. │
|
|
256
|
+
│ │
|
|
257
|
+
│ ── Expected Format ───────────────────────────────────────────────────── │
|
|
258
|
+
│ │
|
|
259
|
+
│ https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX │
|
|
260
|
+
│ │
|
|
261
|
+
│ 💡 Get your webhook URL from: │
|
|
262
|
+
│ Slack → Apps → Incoming Webhooks → Create New │
|
|
263
|
+
│ │
|
|
264
|
+
│ 📖 https://api.slack.com/messaging/webhooks │
|
|
265
|
+
│ │
|
|
266
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**Missing URL Error:**
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
273
|
+
│ ❌ ERROR │
|
|
274
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
275
|
+
│ │
|
|
276
|
+
│ {t.commands.slack.missingUrl} │
|
|
277
|
+
│ │
|
|
278
|
+
│ Please provide the Slack webhook URL. │
|
|
279
|
+
│ │
|
|
280
|
+
│ 💡 Usage: /pfSlack setup <webhook-url> │
|
|
281
|
+
│ │
|
|
282
|
+
│ 📖 Example: │
|
|
283
|
+
│ /pfSlack setup https://hooks.slack.com/services/T.../B.../XXX │
|
|
284
|
+
│ │
|
|
285
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**API Request:**
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
API_URL="https://api.planflow.tools"
|
|
292
|
+
TOKEN="$API_TOKEN"
|
|
293
|
+
PROJECT_ID="$PROJECT_ID"
|
|
294
|
+
WEBHOOK_URL="$WEBHOOK_URL"
|
|
295
|
+
|
|
296
|
+
# Validate webhook URL format
|
|
297
|
+
if [[ ! "$WEBHOOK_URL" =~ ^https://hooks\.slack\.com/services/ ]]; then
|
|
298
|
+
echo "Invalid webhook URL format"
|
|
299
|
+
exit 1
|
|
300
|
+
fi
|
|
301
|
+
|
|
302
|
+
# Save Slack webhook configuration
|
|
303
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
304
|
+
--connect-timeout 5 \
|
|
305
|
+
--max-time 10 \
|
|
306
|
+
-X POST \
|
|
307
|
+
-H "Content-Type: application/json" \
|
|
308
|
+
-H "Accept: application/json" \
|
|
309
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
310
|
+
-d "{\"webhookUrl\": \"${WEBHOOK_URL}\"}" \
|
|
311
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack")
|
|
312
|
+
|
|
313
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
314
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
315
|
+
|
|
316
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
317
|
+
echo "Success"
|
|
318
|
+
else
|
|
319
|
+
echo "Error: HTTP $HTTP_CODE"
|
|
320
|
+
fi
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Success Card:**
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
327
|
+
│ ✅ SUCCESS │
|
|
328
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
329
|
+
│ │
|
|
330
|
+
│ {t.commands.slack.setupSuccess} │
|
|
331
|
+
│ │
|
|
332
|
+
│ ── Slack Integration ─────────────────────────────────────────────────── │
|
|
333
|
+
│ │
|
|
334
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
335
|
+
│ │ ✅ Connected │ │
|
|
336
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
337
|
+
│ │
|
|
338
|
+
│ 📍 Webhook: ···/services/T.../B.../XXX... (configured) │
|
|
339
|
+
│ 📁 Project: {projectName} │
|
|
340
|
+
│ │
|
|
341
|
+
│ {t.commands.slack.willReceive} │
|
|
342
|
+
│ • Task status changes │
|
|
343
|
+
│ • Task assignments │
|
|
344
|
+
│ • @mentions in comments │
|
|
345
|
+
│ • New comments on your tasks │
|
|
346
|
+
│ │
|
|
347
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
348
|
+
│ │
|
|
349
|
+
│ 💡 {t.ui.labels.nextSteps} │
|
|
350
|
+
│ • /pfSlack test Send a test notification │
|
|
351
|
+
│ • /pfSlack View current status │
|
|
352
|
+
│ │
|
|
353
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
354
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### If action is "test"
|
|
358
|
+
|
|
359
|
+
Send a test notification to verify the webhook is working.
|
|
360
|
+
|
|
361
|
+
**API Request:**
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
API_URL="https://api.planflow.tools"
|
|
365
|
+
TOKEN="$API_TOKEN"
|
|
366
|
+
PROJECT_ID="$PROJECT_ID"
|
|
367
|
+
|
|
368
|
+
# Send test notification
|
|
369
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
370
|
+
--connect-timeout 5 \
|
|
371
|
+
--max-time 15 \
|
|
372
|
+
-X POST \
|
|
373
|
+
-H "Content-Type: application/json" \
|
|
374
|
+
-H "Accept: application/json" \
|
|
375
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
376
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack/test")
|
|
377
|
+
|
|
378
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
379
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
380
|
+
|
|
381
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
382
|
+
echo "Test notification sent"
|
|
383
|
+
else
|
|
384
|
+
echo "Error: HTTP $HTTP_CODE"
|
|
385
|
+
fi
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**Success Card:**
|
|
389
|
+
|
|
390
|
+
```
|
|
391
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
392
|
+
│ ✅ SUCCESS │
|
|
393
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
394
|
+
│ │
|
|
395
|
+
│ {t.commands.slack.testSuccess} │
|
|
396
|
+
│ │
|
|
397
|
+
│ ── Test Notification ─────────────────────────────────────────────────── │
|
|
398
|
+
│ │
|
|
399
|
+
│ 📨 A test notification was sent to your Slack channel. │
|
|
400
|
+
│ │
|
|
401
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
402
|
+
│ │ 🔔 PlanFlow Test │ │
|
|
403
|
+
│ │ This is a test notification from PlanFlow. │ │
|
|
404
|
+
│ │ If you see this, Slack integration is working correctly! │ │
|
|
405
|
+
│ │ Project: {projectName} │ │
|
|
406
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
407
|
+
│ │
|
|
408
|
+
│ Check your Slack channel to verify the message arrived. │
|
|
409
|
+
│ │
|
|
410
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
411
|
+
│ │
|
|
412
|
+
│ 💡 {t.ui.labels.commands} │
|
|
413
|
+
│ • /pfSlack View current status │
|
|
414
|
+
│ • /pfSlack disable Disable Slack notifications │
|
|
415
|
+
│ │
|
|
416
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
417
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Test Failed Card:**
|
|
421
|
+
|
|
422
|
+
```
|
|
423
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
424
|
+
│ ❌ ERROR │
|
|
425
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
426
|
+
│ │
|
|
427
|
+
│ {t.commands.slack.testFailed} │
|
|
428
|
+
│ │
|
|
429
|
+
│ Could not send test notification to Slack. │
|
|
430
|
+
│ │
|
|
431
|
+
│ ── Possible Issues ───────────────────────────────────────────────────── │
|
|
432
|
+
│ │
|
|
433
|
+
│ • Webhook URL may be invalid or expired │
|
|
434
|
+
│ • Slack app may have been removed from workspace │
|
|
435
|
+
│ • Network connectivity issues │
|
|
436
|
+
│ │
|
|
437
|
+
│ 💡 {t.ui.labels.commands} │
|
|
438
|
+
│ • /pfSlack setup <new-url> Reconfigure with new webhook │
|
|
439
|
+
│ • /pfSlack View current configuration │
|
|
440
|
+
│ │
|
|
441
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**Not Configured Error:**
|
|
445
|
+
|
|
446
|
+
```
|
|
447
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
448
|
+
│ ❌ ERROR │
|
|
449
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
450
|
+
│ │
|
|
451
|
+
│ {t.commands.slack.notConfiguredError} │
|
|
452
|
+
│ │
|
|
453
|
+
│ Slack webhook is not configured for this project. │
|
|
454
|
+
│ │
|
|
455
|
+
│ 💡 Set up Slack first: │
|
|
456
|
+
│ /pfSlack setup <webhook-url> │
|
|
457
|
+
│ │
|
|
458
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
#### If action is "disable"
|
|
462
|
+
|
|
463
|
+
Disable Slack notifications for this project.
|
|
464
|
+
|
|
465
|
+
**API Request:**
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
API_URL="https://api.planflow.tools"
|
|
469
|
+
TOKEN="$API_TOKEN"
|
|
470
|
+
PROJECT_ID="$PROJECT_ID"
|
|
471
|
+
|
|
472
|
+
# Disable Slack integration
|
|
473
|
+
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
|
474
|
+
--connect-timeout 5 \
|
|
475
|
+
--max-time 10 \
|
|
476
|
+
-X DELETE \
|
|
477
|
+
-H "Accept: application/json" \
|
|
478
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
479
|
+
"${API_URL}/projects/${PROJECT_ID}/integrations/slack")
|
|
480
|
+
|
|
481
|
+
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
|
482
|
+
BODY=$(echo "$RESPONSE" | sed '$d')
|
|
483
|
+
|
|
484
|
+
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
|
485
|
+
echo "Slack integration disabled"
|
|
486
|
+
else
|
|
487
|
+
echo "Error: HTTP $HTTP_CODE"
|
|
488
|
+
fi
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**Success Card:**
|
|
492
|
+
|
|
493
|
+
```
|
|
494
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
495
|
+
│ ✅ SUCCESS │
|
|
496
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
497
|
+
│ │
|
|
498
|
+
│ {t.commands.slack.disableSuccess} │
|
|
499
|
+
│ │
|
|
500
|
+
│ ── Slack Integration ─────────────────────────────────────────────────── │
|
|
501
|
+
│ │
|
|
502
|
+
│ ╭───────────────────────────────────────────────────────────────────────╮ │
|
|
503
|
+
│ │ ❌ Disabled │ │
|
|
504
|
+
│ ╰───────────────────────────────────────────────────────────────────────╯ │
|
|
505
|
+
│ │
|
|
506
|
+
│ Slack notifications have been disabled for this project. │
|
|
507
|
+
│ The webhook URL has been removed. │
|
|
508
|
+
│ │
|
|
509
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
510
|
+
│ │
|
|
511
|
+
│ 💡 {t.ui.labels.commands} │
|
|
512
|
+
│ • /pfSlack setup <url> Re-enable with a new webhook │
|
|
513
|
+
│ │
|
|
514
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
515
|
+
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
### Step 4: Error Handling
|
|
519
|
+
|
|
520
|
+
**Invalid Action Error:**
|
|
521
|
+
|
|
522
|
+
```
|
|
523
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
524
|
+
│ ❌ ERROR │
|
|
525
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
526
|
+
│ │
|
|
527
|
+
│ {t.commands.slack.invalidAction} │
|
|
528
|
+
│ │
|
|
529
|
+
│ Unknown action: "{action}" │
|
|
530
|
+
│ │
|
|
531
|
+
│ ── Valid Actions ─────────────────────────────────────────────────────── │
|
|
532
|
+
│ │
|
|
533
|
+
│ • setup <url> Configure Slack webhook │
|
|
534
|
+
│ • test Send a test notification │
|
|
535
|
+
│ • disable Disable Slack notifications │
|
|
536
|
+
│ │
|
|
537
|
+
│ 💡 Run /pfSlack without arguments to view current status. │
|
|
538
|
+
│ │
|
|
539
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
**Network Error:**
|
|
543
|
+
|
|
544
|
+
```
|
|
545
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
546
|
+
│ ❌ ERROR │
|
|
547
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
548
|
+
│ │
|
|
549
|
+
│ {t.commands.slack.networkError} │
|
|
550
|
+
│ │
|
|
551
|
+
│ Could not connect to PlanFlow API. │
|
|
552
|
+
│ │
|
|
553
|
+
│ {t.commands.slack.tryAgain} │
|
|
554
|
+
│ │
|
|
555
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
**Permission Error:**
|
|
559
|
+
|
|
560
|
+
```
|
|
561
|
+
╭──────────────────────────────────────────────────────────────────────────────╮
|
|
562
|
+
│ ❌ ERROR │
|
|
563
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
564
|
+
│ │
|
|
565
|
+
│ {t.commands.slack.noPermission} │
|
|
566
|
+
│ │
|
|
567
|
+
│ You don't have permission to manage Slack integration. │
|
|
568
|
+
│ │
|
|
569
|
+
│ {t.commands.slack.noPermissionHint} │
|
|
570
|
+
│ │
|
|
571
|
+
╰──────────────────────────────────────────────────────────────────────────────╯
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
## Slack Message Format
|
|
575
|
+
|
|
576
|
+
When PlanFlow sends notifications to Slack, they use this format:
|
|
577
|
+
|
|
578
|
+
**Task Completed:**
|
|
579
|
+
```
|
|
580
|
+
🎉 *Task Completed*
|
|
581
|
+
*T2.1: Implement login API* was marked as done by John Doe
|
|
582
|
+
|
|
583
|
+
Project: My Project
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
**Task Assigned:**
|
|
587
|
+
```
|
|
588
|
+
📋 *Task Assigned*
|
|
589
|
+
*T2.3: Add validation* was assigned to you by Jane Smith
|
|
590
|
+
|
|
591
|
+
Project: My Project
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Mention:**
|
|
595
|
+
```
|
|
596
|
+
💬 *You were mentioned*
|
|
597
|
+
John Doe mentioned you in *T2.1: Implement login API*:
|
|
598
|
+
> @jane please review this when you have time
|
|
599
|
+
|
|
600
|
+
Project: My Project
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
**Comment:**
|
|
604
|
+
```
|
|
605
|
+
💭 *New Comment*
|
|
606
|
+
Jane Smith commented on *T2.1: Implement login API*:
|
|
607
|
+
> Looks good! Just one small fix needed.
|
|
608
|
+
|
|
609
|
+
Project: My Project
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
## Translation Keys Required
|
|
613
|
+
|
|
614
|
+
```json
|
|
615
|
+
{
|
|
616
|
+
"commands": {
|
|
617
|
+
"slack": {
|
|
618
|
+
"title": "Slack Integration",
|
|
619
|
+
"status": "Status",
|
|
620
|
+
"events": "Notification Events",
|
|
621
|
+
"connected": "Connected",
|
|
622
|
+
"notConfigured": "Not Configured",
|
|
623
|
+
"notConfiguredHint": "Slack notifications are not set up for this project.",
|
|
624
|
+
"howToSetup": "How to Set Up",
|
|
625
|
+
"setupSuccess": "Slack integration configured successfully!",
|
|
626
|
+
"willReceive": "You will receive notifications for:",
|
|
627
|
+
"testSuccess": "Test notification sent!",
|
|
628
|
+
"testFailed": "Failed to send test notification.",
|
|
629
|
+
"disableSuccess": "Slack integration disabled.",
|
|
630
|
+
"invalidUrl": "Invalid Slack webhook URL.",
|
|
631
|
+
"missingUrl": "Webhook URL is required.",
|
|
632
|
+
"invalidAction": "Invalid action.",
|
|
633
|
+
"networkError": "Network error. Could not connect to PlanFlow API.",
|
|
634
|
+
"tryAgain": "Please check your connection and try again.",
|
|
635
|
+
"noPermission": "You don't have permission to manage Slack integration.",
|
|
636
|
+
"noPermissionHint": "Only project owners and admins can configure integrations.",
|
|
637
|
+
"notConfiguredError": "Slack is not configured.",
|
|
638
|
+
"webhookLabel": "Webhook",
|
|
639
|
+
"channelLabel": "Channel",
|
|
640
|
+
"lastTestLabel": "Last Test",
|
|
641
|
+
"lastSentLabel": "Last Sent",
|
|
642
|
+
"configured": "Configured",
|
|
643
|
+
"eventTaskCompleted": "Task completed",
|
|
644
|
+
"eventTaskAssigned": "Task assigned",
|
|
645
|
+
"eventMentions": "@mentions",
|
|
646
|
+
"eventComments": "New comments"
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
## Notes
|
|
653
|
+
|
|
654
|
+
- Webhook URLs are stored securely on the server (never exposed in full)
|
|
655
|
+
- Notifications are sent asynchronously and don't block plugin operations
|
|
656
|
+
- Test notifications help verify the webhook is working before real notifications
|
|
657
|
+
- Disabling removes the webhook URL completely (re-setup required to enable again)
|
|
658
|
+
- Only project owners and admins can configure integrations
|
|
659
|
+
- All team members benefit from configured notifications (based on their personal settings)
|