@blickwerk/n8n-nodes-microsoft-planner 1.4.0 → 1.6.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.md +1 -1
- package/README.md +233 -30
- package/dist/credentials/MicrosoftPlannerOAuth2Api.credentials.d.ts +2 -2
- package/dist/credentials/MicrosoftPlannerOAuth2Api.credentials.js +11 -29
- package/dist/credentials/MicrosoftPlannerOAuth2Api.credentials.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/BucketDescription.d.ts +3 -0
- package/dist/nodes/MicrosoftPlanner/BucketDescription.js +180 -0
- package/dist/nodes/MicrosoftPlanner/BucketDescription.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/CommentDescription.d.ts +3 -0
- package/dist/nodes/MicrosoftPlanner/CommentDescription.js +156 -0
- package/dist/nodes/MicrosoftPlanner/CommentDescription.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/GenericFunctions.d.ts +19 -6
- package/dist/nodes/MicrosoftPlanner/GenericFunctions.js +251 -34
- package/dist/nodes/MicrosoftPlanner/GenericFunctions.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/MicrosoftPlanner.node.d.ts +6 -7
- package/dist/nodes/MicrosoftPlanner/MicrosoftPlanner.node.js +118 -279
- package/dist/nodes/MicrosoftPlanner/MicrosoftPlanner.node.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/MicrosoftPlanner.node.json +18 -0
- package/dist/nodes/MicrosoftPlanner/PlanDescription.d.ts +3 -0
- package/dist/nodes/MicrosoftPlanner/PlanDescription.js +435 -0
- package/dist/nodes/MicrosoftPlanner/PlanDescription.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/SharedFields.d.ts +10 -0
- package/dist/nodes/MicrosoftPlanner/SharedFields.js +316 -0
- package/dist/nodes/MicrosoftPlanner/SharedFields.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/TaskDescription.d.ts +1 -1
- package/dist/nodes/MicrosoftPlanner/TaskDescription.js +271 -177
- package/dist/nodes/MicrosoftPlanner/TaskDescription.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/actions/bucket.d.ts +2 -0
- package/dist/nodes/MicrosoftPlanner/actions/bucket.js +72 -0
- package/dist/nodes/MicrosoftPlanner/actions/bucket.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/actions/comment.d.ts +2 -0
- package/dist/nodes/MicrosoftPlanner/actions/comment.js +100 -0
- package/dist/nodes/MicrosoftPlanner/actions/comment.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/actions/plan.d.ts +4 -0
- package/dist/nodes/MicrosoftPlanner/actions/plan.js +116 -0
- package/dist/nodes/MicrosoftPlanner/actions/plan.js.map +1 -0
- package/dist/nodes/MicrosoftPlanner/actions/task.d.ts +4 -0
- package/dist/nodes/MicrosoftPlanner/actions/task.js +392 -0
- package/dist/nodes/MicrosoftPlanner/actions/task.js.map +1 -0
- package/dist/package.json +60 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +22 -20
package/LICENSE.md
CHANGED
package/README.md
CHANGED
|
@@ -33,10 +33,11 @@ npm install @blickwerk/n8n-nodes-microsoft-planner
|
|
|
33
33
|
You need to have:
|
|
34
34
|
- An active Microsoft 365 subscription
|
|
35
35
|
- A Microsoft Planner plan created
|
|
36
|
-
- Azure AD
|
|
36
|
+
- A Microsoft Entra ID (Azure AD) app registration with the following delegated API permissions:
|
|
37
|
+
- `User.Read` - Sign in and read the own profile
|
|
38
|
+
- `User.ReadBasic.All` - Read basic profiles of all users (required to assign tasks by email)
|
|
37
39
|
- `Tasks.ReadWrite` - Read and write tasks
|
|
38
|
-
- `Group.ReadWrite.All` - Read and write all groups (required for Planner)
|
|
39
|
-
- `User.Read.All` - Read all users (required for user assignment by email)
|
|
40
|
+
- `Group.ReadWrite.All` - Read and write all groups (required for Planner plans and comments)
|
|
40
41
|
|
|
41
42
|
## Setting up Azure AD App
|
|
42
43
|
|
|
@@ -55,12 +56,15 @@ You need to have:
|
|
|
55
56
|
3. Select **Microsoft Graph**
|
|
56
57
|
4. Select **Delegated permissions**
|
|
57
58
|
5. Add the following permissions:
|
|
59
|
+
- `User.Read` - Sign in and read the own profile
|
|
60
|
+
- `User.ReadBasic.All` - Read basic profiles of all users (required for user assignment by email)
|
|
58
61
|
- `Tasks.ReadWrite` - Read and write tasks
|
|
59
|
-
- `Group.ReadWrite.All` - Read and write all groups (required for Planner)
|
|
60
|
-
- `User.Read.All` - Read all users' basic profiles (required for user assignment)
|
|
62
|
+
- `Group.ReadWrite.All` - Read and write all groups (required for Planner and comments)
|
|
61
63
|
6. Click **Grant admin consent**
|
|
62
64
|
|
|
63
|
-
**Note**:
|
|
65
|
+
**Note**: `User.ReadBasic.All` is required if you want to assign tasks to users by email address. `Group.ReadWrite.All` is required for both Planner operations and creating/reading comments.
|
|
66
|
+
|
|
67
|
+
> **Upgrading from 1.5.x?** Version 1.6.0 requests the additional scopes `User.Read` and `User.ReadBasic.All`. Add them to your app registration and click **Reconnect** on your existing credential once.
|
|
64
68
|
|
|
65
69
|
### Create Client Secret
|
|
66
70
|
|
|
@@ -81,26 +85,55 @@ Configure the Microsoft Planner OAuth2 API credentials in n8n:
|
|
|
81
85
|
1. In n8n, go to **Credentials > New**
|
|
82
86
|
2. Search for **Microsoft Planner OAuth2 API**
|
|
83
87
|
3. Enter your **Client ID** and **Client Secret**
|
|
84
|
-
4.
|
|
85
|
-
5.
|
|
88
|
+
4. If your app registration is **single tenant** ("Accounts in this organizational directory only"), replace `common` in the **Authorization URL** and **Access Token URL** with your Directory (tenant) ID, e.g. `https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/authorize`
|
|
89
|
+
5. Click **Connect my account**
|
|
90
|
+
6. Complete the OAuth flow
|
|
86
91
|
|
|
87
92
|
## Features
|
|
88
93
|
|
|
89
94
|
- **Resource Locator UI**: Choose between "From List" (dropdown) or "By ID" (manual input) for Buckets
|
|
90
95
|
- **User Assignment**: Assign tasks to users by email address
|
|
91
96
|
- **Priority Management**: Easy-to-use priority dropdown (Urgent, Important, Medium, Low)
|
|
92
|
-
- **
|
|
97
|
+
- **Comprehensive Task Support**: Full support for Task details including Checklist items and Attachments
|
|
98
|
+
- **Labels**: Apply and remove Planner labels (category1 - category25), the dropdown shows the label names of your plan
|
|
99
|
+
- **Full CRUD Support**: Manage Tasks, Plans, and Buckets
|
|
100
|
+
- **Comment Support**: Create and retrieve comments on tasks
|
|
101
|
+
- **AI Agent Tool**: The node can be used as a tool by n8n AI agents
|
|
102
|
+
- **Concurrency Handling**: ETag conflicts (HTTP 412) are retried automatically
|
|
93
103
|
|
|
94
104
|
## Operations
|
|
95
105
|
|
|
96
106
|
### Task
|
|
97
107
|
|
|
98
|
-
- **Create** - Create a new task
|
|
99
|
-
- **Get** - Get a task by ID
|
|
100
|
-
- **Get Many** - Get multiple tasks from a plan or bucket
|
|
101
|
-
- **Update** - Update an existing task
|
|
108
|
+
- **Create** - Create a new task (supports Checklist, Attachments, Labels, Preview Type, Order Hints)
|
|
102
109
|
- **Delete** - Delete a task
|
|
110
|
+
- **Get** - Get a task by ID (optionally include details)
|
|
111
|
+
- **Get Board Format** - Get the ordering of a task in the Bucket, Progress or Assigned To board view
|
|
103
112
|
- **Get Files** - Get all files attached to a task
|
|
113
|
+
- **Get Many** - Get multiple tasks from a plan, a bucket, the current user ("My Tasks") or another user (optionally with details, optionally excluding completed tasks)
|
|
114
|
+
- **Update** - Update an existing task (supports Checklist, Attachments, Labels, replacing/removing assignees, removing dates)
|
|
115
|
+
- **Update Board Format** - Change the ordering of a task in a board view
|
|
116
|
+
|
|
117
|
+
### Plan
|
|
118
|
+
|
|
119
|
+
- **Create** - Create a new plan in a group
|
|
120
|
+
- **Delete** - Delete a plan
|
|
121
|
+
- **Get** - Get a plan by ID (optionally include details)
|
|
122
|
+
- **Get Many** - Get all plans (My Plans, Group Plans or the plans of a specific user)
|
|
123
|
+
- **Update** - Update a plan (supports Title, Label Names, and Sharing)
|
|
124
|
+
|
|
125
|
+
### Bucket
|
|
126
|
+
|
|
127
|
+
- **Create** - Create a new bucket in a plan (optionally with order hint, optionally upsert by name)
|
|
128
|
+
- **Delete** - Delete a bucket
|
|
129
|
+
- **Get** - Get a bucket by ID
|
|
130
|
+
- **Get Many** - Get all buckets in a plan
|
|
131
|
+
- **Update** - Update a bucket name and order
|
|
132
|
+
|
|
133
|
+
### Comment
|
|
134
|
+
|
|
135
|
+
- **Create** - Create a new comment on a task
|
|
136
|
+
- **Get Many** - Get all comments from a task
|
|
104
137
|
|
|
105
138
|
## Usage
|
|
106
139
|
|
|
@@ -118,10 +151,14 @@ Optional fields:
|
|
|
118
151
|
- Important
|
|
119
152
|
- Medium (default)
|
|
120
153
|
- Low
|
|
121
|
-
- **Assigned To**: Comma-separated list of user emails (e.g., `user1@domain.com, user2@domain.com`)
|
|
154
|
+
- **Assigned To**: Comma-separated list of user emails or IDs (e.g., `user1@domain.com, user2@domain.com`)
|
|
155
|
+
- **Labels**: Labels to apply (the list shows the label names defined in the plan)
|
|
122
156
|
- **Due Date Time**: When the task should be completed
|
|
123
157
|
- **Start Date Time**: When work on the task should begin
|
|
124
158
|
- **Percent Complete**: Task completion percentage (0-100)
|
|
159
|
+
- **Checklist**: Add multiple checklist items with titles and checked status
|
|
160
|
+
- **Attachments**: Add external references/attachments with URLs, aliases, and types (Word, Excel, etc.)
|
|
161
|
+
- **Description**: Detailed task description (stored in task details)
|
|
125
162
|
|
|
126
163
|
### Getting Tasks
|
|
127
164
|
|
|
@@ -129,10 +166,12 @@ Optional fields:
|
|
|
129
166
|
- Enter the **Task ID** manually (no dropdown available for single task lookups)
|
|
130
167
|
|
|
131
168
|
**Get many tasks:**
|
|
132
|
-
- Choose filter type: **Plan** or **
|
|
133
|
-
- Enter the **Plan ID**
|
|
169
|
+
- Choose filter type: **Plan**, **Bucket**, **My Tasks** or **User**
|
|
170
|
+
- Enter the **Plan ID** (Plan / Bucket) or the **User** (email or ID)
|
|
134
171
|
- If filtering by Bucket: Select bucket from dropdown or enter Bucket ID manually
|
|
135
|
-
-
|
|
172
|
+
- Optional: **Include Details** (description, checklist, attachments for every task), **Exclude Completed Tasks**, **Select Properties**
|
|
173
|
+
|
|
174
|
+
Microsoft Graph does not support `$top`/`$filter` for Planner, so all tasks of the selected scope are returned (pagination is handled automatically).
|
|
136
175
|
|
|
137
176
|
### Updating a Task
|
|
138
177
|
|
|
@@ -143,10 +182,17 @@ To update a task:
|
|
|
143
182
|
- Description
|
|
144
183
|
- Priority (via dropdown)
|
|
145
184
|
- Assigned users (via email list)
|
|
146
|
-
- Due Date Time
|
|
147
|
-
- Start Date Time
|
|
148
|
-
- Percent Complete
|
|
149
|
-
- Move to different bucket
|
|
185
|
+
- **Due Date Time**
|
|
186
|
+
- **Start Date Time**
|
|
187
|
+
- **Percent Complete**
|
|
188
|
+
- **Move to different bucket**
|
|
189
|
+
- **Checklist**: Add new items or update existing ones (Operation Mode: Append / Replace), or remove items by ID
|
|
190
|
+
- **Attachments**: Add new references (Operation Mode: Append / Replace), or remove references by URL
|
|
191
|
+
- **Description**: Update the task description (an empty value clears it)
|
|
192
|
+
- **Labels to Add / Labels to Remove**
|
|
193
|
+
- **Assignment Mode**: Append (default) or Replace the assignees; **Remove Assignees** unassigns users
|
|
194
|
+
- **Remove Due Date / Remove Start Date**
|
|
195
|
+
- **Order Hint**, **Assignee Priority**, **Preview Type**, **Conversation Thread ID**
|
|
150
196
|
|
|
151
197
|
### Getting Files from a Task
|
|
152
198
|
|
|
@@ -163,6 +209,64 @@ To get all files attached to a task:
|
|
|
163
209
|
- **lastModifiedDateTime**: When the file reference was last modified
|
|
164
210
|
- **lastModifiedBy**: Who last modified the reference
|
|
165
211
|
|
|
212
|
+
### Creating a Comment
|
|
213
|
+
|
|
214
|
+
To create a comment on a task:
|
|
215
|
+
1. Select **Comment** as the resource
|
|
216
|
+
2. Choose **Create** operation
|
|
217
|
+
3. Enter the **Task ID** manually
|
|
218
|
+
4. Enter the **Content** of the comment
|
|
219
|
+
5. Optionally select **Content Type**:
|
|
220
|
+
- **Text** (default): Plain text that will be wrapped in HTML
|
|
221
|
+
- **HTML**: Custom HTML content
|
|
222
|
+
|
|
223
|
+
The comment will be created as a conversation thread in the Microsoft 365 Group associated with the plan. If the task doesn't have a conversation thread yet (or the linked thread was deleted), one will be created automatically. Plain text is HTML-escaped and line breaks are preserved.
|
|
224
|
+
|
|
225
|
+
### Getting Comments from a Task
|
|
226
|
+
|
|
227
|
+
To get all comments from a task:
|
|
228
|
+
1. Select **Comment** as the resource
|
|
229
|
+
2. Choose **Get Many** operation
|
|
230
|
+
3. Enter the **Task ID** manually
|
|
231
|
+
4. The operation returns:
|
|
232
|
+
- **taskId**: The task ID
|
|
233
|
+
- **commentCount**: Number of comments
|
|
234
|
+
- **comments**: Array of comment objects with:
|
|
235
|
+
- **id**: Comment ID
|
|
236
|
+
- **content**: Comment body (HTML)
|
|
237
|
+
- **from**: Author information
|
|
238
|
+
- **createdDateTime**: When the comment was created
|
|
239
|
+
- **lastModifiedDateTime**: When the comment was last modified
|
|
240
|
+
5. Enable **Split Into Items** to get one output item per comment instead
|
|
241
|
+
|
|
242
|
+
**Note**: Once a comment is posted in Planner, it cannot be deleted or edited via the Microsoft Graph API or the Planner UI (for Basic plans). This is a limitation of the Microsoft 365 Groups conversation system that Planner uses.
|
|
243
|
+
|
|
244
|
+
### Working with Plans
|
|
245
|
+
|
|
246
|
+
The **Plan** resource allows you to manage Microsoft Planner plans:
|
|
247
|
+
|
|
248
|
+
- **Create**: Requires an **Owner Group** (selected from dropdown or entered as ID) and a **Title**.
|
|
249
|
+
- **Get Many**:
|
|
250
|
+
- **My Plans**: Lists plans the authenticated user is a member of.
|
|
251
|
+
- **Group Plans**: Requires a **Group ID** to list plans owned by that specific group.
|
|
252
|
+
- **User**: Lists the plans a specific user (email or ID) is a member of.
|
|
253
|
+
- **Get**: Retrieve full plan metadata. Enable **Include Details** to get category descriptions (labels) and other metadata.
|
|
254
|
+
- **Update**:
|
|
255
|
+
- Change the plan **Title**.
|
|
256
|
+
- **Category Descriptions**: Update the names of the 25 color-coded labels (Category 01-25). An empty value removes the name.
|
|
257
|
+
- **Shared With**: Update plan members using a JSON mapping of user IDs.
|
|
258
|
+
- **Delete**: Permanently removes the plan.
|
|
259
|
+
|
|
260
|
+
### Working with Buckets
|
|
261
|
+
|
|
262
|
+
The **Bucket** resource manages the columns or categories within a plan:
|
|
263
|
+
|
|
264
|
+
- **Create**: Requires a **Plan ID** and a **Name**.
|
|
265
|
+
- **Upsert**: When enabled, the node will check if a bucket with the same name already exists in the plan and return that instead of creating a duplicate.
|
|
266
|
+
- **Get Many**: Lists all buckets within a specific **Plan ID**.
|
|
267
|
+
- **Update**: Change the bucket **Name** and its **Order Hint** (controlling the position in the UI).
|
|
268
|
+
- **Delete**: Removes the bucket from the plan.
|
|
269
|
+
|
|
166
270
|
### How to Find Plan IDs
|
|
167
271
|
|
|
168
272
|
You can find your Plan ID in several ways:
|
|
@@ -188,7 +292,26 @@ For Get/Update/Delete operations, you need to manually enter the Task ID.
|
|
|
188
292
|
|
|
189
293
|
## Compatibility
|
|
190
294
|
|
|
191
|
-
|
|
295
|
+
Built and linted with the official n8n community node tooling (`@n8n/node-cli` 0.55, `n8n-workflow` 2.16) for n8n 2.x. Recent n8n 1.x versions that support `NodeConnectionTypes` work as well.
|
|
296
|
+
|
|
297
|
+
## Development
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
# --ignore-scripts skips the native build of isolated-vm (a dependency of n8n-workflow
|
|
301
|
+
# that is not needed to build nodes and fails on Windows without build tools)
|
|
302
|
+
npm install --ignore-scripts
|
|
303
|
+
|
|
304
|
+
npm run dev # starts a local n8n with the node loaded (hot reload)
|
|
305
|
+
npm run lint # n8n community node lint rules (strict mode)
|
|
306
|
+
npm run build # compiles to dist/
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Releasing
|
|
310
|
+
|
|
311
|
+
Since May 1 2026, n8n requires community nodes to be published from GitHub Actions with npm provenance. The workflow in `.github/workflows/publish.yml` publishes the package whenever a version tag (e.g. `1.6.0`) is pushed.
|
|
312
|
+
|
|
313
|
+
1. One-time: configure npm **Trusted Publishing** for this repository (workflow `publish.yml`) or add an `NPM_TOKEN` repository secret
|
|
314
|
+
2. Run `npm run release` locally. It lints, builds, bumps the version, updates `CHANGELOG.md`, commits, tags and pushes
|
|
192
315
|
|
|
193
316
|
## Resources
|
|
194
317
|
|
|
@@ -198,6 +321,90 @@ Tested with n8n version 1.0.0 and above.
|
|
|
198
321
|
|
|
199
322
|
## Version History
|
|
200
323
|
|
|
324
|
+
### 1.6.0
|
|
325
|
+
- **Migrated to the current n8n community node tooling**
|
|
326
|
+
- `@n8n/node-cli` for build, lint, dev and release, ESLint 9 flat config, strict mode
|
|
327
|
+
- GitHub Actions workflows for CI and npm publishing with provenance (required by n8n since May 2026)
|
|
328
|
+
- Node is usable as an AI agent tool; correct item pairing (`pairedItem`) for all operations
|
|
329
|
+
- **New Features**
|
|
330
|
+
- Task labels (applied categories) on create and update; the label dropdown shows the plan's label names
|
|
331
|
+
- Get Many Tasks for **My Tasks** and **User**, optional **Include Details** and **Exclude Completed Tasks**
|
|
332
|
+
- Get Many Plans for a specific **User**
|
|
333
|
+
- Task **Get Board Format** / **Update Board Format** (Bucket, Progress, Assigned To views)
|
|
334
|
+
- Task update: Assignment Mode (Append/Replace), Remove Assignees, Remove Due/Start Date, remove checklist items by ID, remove attachments by URL
|
|
335
|
+
- Task: Order Hint, Assignee Priority, Preview Type and Conversation Thread ID fields
|
|
336
|
+
- Checklist items: Order Hint; attachments: Preview Priority
|
|
337
|
+
- Bucket create: Order Hint
|
|
338
|
+
- Comments: Split Into Items option, pagination for threads with many posts
|
|
339
|
+
- Search filter for the Bucket and Group dropdowns
|
|
340
|
+
- **Bug Fixes**
|
|
341
|
+
- Task update priority values were wrong ("Urgent" sent 0, "Important" sent 1, which Planner treats as urgent). Now 1/3/5/9, the same as on create
|
|
342
|
+
- Replying to an existing comment thread used an invalid endpoint (the conversation ID was taken from the thread). Now uses `/groups/{id}/threads/{id}/reply`
|
|
343
|
+
- Creating the first comment relied on `threads` in the create-conversation response, which Graph does not return
|
|
344
|
+
- Plain-text comments were not HTML-escaped (`<`, `&` broke the comment) and lost line breaks
|
|
345
|
+
- The OAuth scope was missing `User.Read` / `User.ReadBasic.All`, so assigning users by email could fail
|
|
346
|
+
- Plans are now created with `container` instead of the deprecated `owner` property
|
|
347
|
+
- Empty Attachments/Checklist sections no longer send an empty PATCH request
|
|
348
|
+
- The description can now be cleared on update
|
|
349
|
+
- Dates passed as Luxon DateTime/Date objects (e.g. `{{ $now }}`) were dropped
|
|
350
|
+
- Email addresses containing `'` broke the user lookup filter
|
|
351
|
+
- ETag conflicts (HTTP 412) are retried automatically instead of failing the workflow
|
|
352
|
+
- Errors now reference the failing item
|
|
353
|
+
|
|
354
|
+
### 1.5.5
|
|
355
|
+
- **Bug Fix: $select Duplication**
|
|
356
|
+
- Fixed an issue where the `$select` query parameter was sent twice during pagination, causing "Query option '$select' was specified more than once" error.
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
### 1.5.4
|
|
360
|
+
- **New Feature: $select Support**
|
|
361
|
+
- Added "Select Properties" field to "Get Many" operations for Tasks, Plans, Buckets, and Comments.
|
|
362
|
+
- **Improved Task Assignments**
|
|
363
|
+
- Fixed silent failures for task assignments.
|
|
364
|
+
- Added robust user lookup (ID, Email, UPN) and error reporting for missing users.
|
|
365
|
+
- Added support for Array inputs (expressions) in the "Assigned To" field.
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
### 1.5.3
|
|
369
|
+
- **UI Improvements for Attachments and Checklists**
|
|
370
|
+
- Refactored to use a grouped UI pattern for better usability
|
|
371
|
+
- Replaced separate fields with a unified structure using `fixedCollection`
|
|
372
|
+
- **Updated Logic for Updates**
|
|
373
|
+
- Replaced "Replace All" toggle with a clearer **Operation Mode** dropdown (Append vs Replace)
|
|
374
|
+
- Renamed "Mode" to "Input Mode" for better clarity between Manual and JSON inputs
|
|
375
|
+
- Fixed logic for replacing items with matching IDs during updates
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
### 1.5.2
|
|
379
|
+
- **Maintenance release**
|
|
380
|
+
- Removed runtime dependency on `n8n-core` to comply with n8n community node requirements
|
|
381
|
+
- No functional changes to node behavior
|
|
382
|
+
|
|
383
|
+
### 1.5.1
|
|
384
|
+
- **Maintenance release**
|
|
385
|
+
- Replaced deprecated `requestOAuth2` helper with `httpRequestWithAuthentication` in Microsoft Planner API requests
|
|
386
|
+
- Removed `console` logging from the Microsoft Planner node and helper to satisfy n8n community package scan requirements
|
|
387
|
+
|
|
388
|
+
### 1.5.0
|
|
389
|
+
- **Major feature release** (with contributions from United Workspace GmbH)
|
|
390
|
+
- **Added Comment Support**
|
|
391
|
+
- Create and retrieve comments on Planner tasks
|
|
392
|
+
- Automatic conversation thread management
|
|
393
|
+
- Support for both HTML and plain text comments
|
|
394
|
+
- **Enhanced Task Details**
|
|
395
|
+
- **Checklist Support**: Full support for adding and managing checklist items
|
|
396
|
+
- **Attachments (References)**: Support for adding external URLs and files to tasks
|
|
397
|
+
- **Replace All Options**: New toggles to replace existing checklists or attachments entirely
|
|
398
|
+
- **Plan Resource Support**
|
|
399
|
+
- CRUD operations for Plans
|
|
400
|
+
- Manage Category Labels (1-25)
|
|
401
|
+
- Manage Plan members (Shared With)
|
|
402
|
+
- **Bucket Resource Support**
|
|
403
|
+
- CRUD operations for Buckets
|
|
404
|
+
- Manage bucket names and positioning (Order Hint)
|
|
405
|
+
- **Robust Encoding**: Improved handling of special characters in attachment URLs
|
|
406
|
+
- **Internal Improvements**: Comprehensive build audit, improved error handling and data fetch reliability
|
|
407
|
+
|
|
201
408
|
### 1.4.0
|
|
202
409
|
- **Updated branding**
|
|
203
410
|
- New Planner icon/logo
|
|
@@ -307,17 +514,13 @@ Tested with n8n version 1.0.0 and above.
|
|
|
307
514
|
|
|
308
515
|
## Author
|
|
309
516
|
|
|
310
|
-
Developed by **Blickwerk Media UG**
|
|
311
|
-
|
|
312
|
-
### About Blickwerk Media
|
|
517
|
+
Developed and maintained by **Blickwerk Media UG**
|
|
313
518
|
|
|
314
|
-
|
|
519
|
+
## Credits
|
|
315
520
|
|
|
316
|
-
|
|
521
|
+
This node was invented and developed by [**Blickwerk Media UG**](https://github.com/blickwerk/n8n-nodes-microsoft-planner). **United Workspace GmbH** contributed to its further development – we thank them for their contributions.
|
|
317
522
|
|
|
318
|
-
|
|
319
|
-
- **LinkedIn**: [linkedin.com/company/blickwerkmedia](https://linkedin.com/company/blickwerkmedia)
|
|
320
|
-
- **Instagram**: [instagram.com/blickwerk.media](https://instagram.com/blickwerk.media)
|
|
523
|
+
**Web**: [blickwerk.media](https://blickwerk.media)
|
|
321
524
|
|
|
322
525
|
## Support
|
|
323
526
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ICredentialTestRequest, ICredentialType, Icon, INodeProperties } from 'n8n-workflow';
|
|
2
2
|
export declare class MicrosoftPlannerOAuth2Api implements ICredentialType {
|
|
3
3
|
name: string;
|
|
4
4
|
extends: string[];
|
|
5
5
|
displayName: string;
|
|
6
|
+
icon: Icon;
|
|
6
7
|
documentationUrl: string;
|
|
7
8
|
properties: INodeProperties[];
|
|
8
|
-
authenticate: IAuthenticateGeneric;
|
|
9
9
|
test: ICredentialTestRequest;
|
|
10
10
|
}
|
|
@@ -6,7 +6,11 @@ class MicrosoftPlannerOAuth2Api {
|
|
|
6
6
|
this.name = 'microsoftPlannerOAuth2Api';
|
|
7
7
|
this.extends = ['oAuth2Api'];
|
|
8
8
|
this.displayName = 'Microsoft Planner OAuth2 API';
|
|
9
|
-
this.
|
|
9
|
+
this.icon = {
|
|
10
|
+
light: 'file:../nodes/MicrosoftPlanner/planner.svg',
|
|
11
|
+
dark: 'file:../nodes/MicrosoftPlanner/planner.svg',
|
|
12
|
+
};
|
|
13
|
+
this.documentationUrl = 'https://github.com/blickwerk/n8n-nodes-microsoft-planner?tab=readme-ov-file#credentials';
|
|
10
14
|
this.properties = [
|
|
11
15
|
{
|
|
12
16
|
displayName: 'Grant Type',
|
|
@@ -17,22 +21,24 @@ class MicrosoftPlannerOAuth2Api {
|
|
|
17
21
|
{
|
|
18
22
|
displayName: 'Authorization URL',
|
|
19
23
|
name: 'authUrl',
|
|
20
|
-
type: '
|
|
24
|
+
type: 'string',
|
|
21
25
|
default: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
|
|
26
|
+
description: 'For single-tenant app registrations, replace "common" with your Directory (tenant) ID',
|
|
22
27
|
required: true,
|
|
23
28
|
},
|
|
24
29
|
{
|
|
25
30
|
displayName: 'Access Token URL',
|
|
26
31
|
name: 'accessTokenUrl',
|
|
27
|
-
type: '
|
|
32
|
+
type: 'string',
|
|
28
33
|
default: 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
|
|
34
|
+
description: 'For single-tenant app registrations, replace "common" with your Directory (tenant) ID',
|
|
29
35
|
required: true,
|
|
30
36
|
},
|
|
31
37
|
{
|
|
32
38
|
displayName: 'Scope',
|
|
33
39
|
name: 'scope',
|
|
34
40
|
type: 'hidden',
|
|
35
|
-
default: 'openid offline_access Tasks.ReadWrite Group.ReadWrite.All',
|
|
41
|
+
default: 'openid offline_access User.Read User.ReadBasic.All Tasks.ReadWrite Group.ReadWrite.All',
|
|
36
42
|
},
|
|
37
43
|
{
|
|
38
44
|
displayName: 'Auth URI Query Parameters',
|
|
@@ -46,32 +52,7 @@ class MicrosoftPlannerOAuth2Api {
|
|
|
46
52
|
type: 'hidden',
|
|
47
53
|
default: 'body',
|
|
48
54
|
},
|
|
49
|
-
{
|
|
50
|
-
displayName: 'Client ID',
|
|
51
|
-
name: 'clientId',
|
|
52
|
-
type: 'string',
|
|
53
|
-
default: '',
|
|
54
|
-
required: true,
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
displayName: 'Client Secret',
|
|
58
|
-
name: 'clientSecret',
|
|
59
|
-
type: 'string',
|
|
60
|
-
typeOptions: {
|
|
61
|
-
password: true,
|
|
62
|
-
},
|
|
63
|
-
default: '',
|
|
64
|
-
required: true,
|
|
65
|
-
},
|
|
66
55
|
];
|
|
67
|
-
this.authenticate = {
|
|
68
|
-
type: 'generic',
|
|
69
|
-
properties: {
|
|
70
|
-
headers: {
|
|
71
|
-
Authorization: '={{$credentials.tokenType}} {{$credentials.accessToken}}',
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
56
|
this.test = {
|
|
76
57
|
request: {
|
|
77
58
|
baseURL: 'https://graph.microsoft.com/v1.0',
|
|
@@ -81,3 +62,4 @@ class MicrosoftPlannerOAuth2Api {
|
|
|
81
62
|
}
|
|
82
63
|
}
|
|
83
64
|
exports.MicrosoftPlannerOAuth2Api = MicrosoftPlannerOAuth2Api;
|
|
65
|
+
//# sourceMappingURL=MicrosoftPlannerOAuth2Api.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MicrosoftPlannerOAuth2Api.credentials.js","sourceRoot":"","sources":["../../credentials/MicrosoftPlannerOAuth2Api.credentials.ts"],"names":[],"mappings":";;;AAEA,MAAa,yBAAyB;IAAtC;QACC,SAAI,GAAG,2BAA2B,CAAC;QAEnC,YAAO,GAAG,CAAC,WAAW,CAAC,CAAC;QAExB,gBAAW,GAAG,8BAA8B,CAAC;QAE7C,SAAI,GAAS;YACZ,KAAK,EAAE,4CAA4C;YACnD,IAAI,EAAE,4CAA4C;SAClD,CAAC;QAEF,qBAAgB,GACf,yFAAyF,CAAC;QAE3F,eAAU,GAAsB;YAC/B;gBACC,WAAW,EAAE,YAAY;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,mBAAmB;aAC5B;YACD;gBACC,WAAW,EAAE,mBAAmB;gBAChC,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,gEAAgE;gBACzE,WAAW,EACV,uFAAuF;gBACxF,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,kBAAkB;gBAC/B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,4DAA4D;gBACrE,WAAW,EACV,uFAAuF;gBACxF,QAAQ,EAAE,IAAI;aACd;YACD;gBACC,WAAW,EAAE,OAAO;gBACpB,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,QAAQ;gBACd,OAAO,EACN,wFAAwF;aACzF;YACD;gBACC,WAAW,EAAE,2BAA2B;gBACxC,IAAI,EAAE,qBAAqB;gBAC3B,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,qBAAqB;aAC9B;YACD;gBACC,WAAW,EAAE,gBAAgB;gBAC7B,IAAI,EAAE,gBAAgB;gBACtB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,MAAM;aACf;SACD,CAAC;QAEF,SAAI,GAA2B;YAC9B,OAAO,EAAE;gBACR,OAAO,EAAE,kCAAkC;gBAC3C,GAAG,EAAE,KAAK;aACV;SACD,CAAC;IACH,CAAC;CAAA;AAnED,8DAmEC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bucketFields = exports.bucketOperations = void 0;
|
|
4
|
+
exports.bucketOperations = [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Operation',
|
|
7
|
+
name: 'operation',
|
|
8
|
+
type: 'options',
|
|
9
|
+
noDataExpression: true,
|
|
10
|
+
displayOptions: {
|
|
11
|
+
show: {
|
|
12
|
+
resource: ['bucket'],
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
options: [
|
|
16
|
+
{
|
|
17
|
+
name: 'Create',
|
|
18
|
+
value: 'create',
|
|
19
|
+
description: 'Create a new bucket in a plan',
|
|
20
|
+
action: 'Create a bucket',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Delete',
|
|
24
|
+
value: 'delete',
|
|
25
|
+
description: 'Delete a bucket',
|
|
26
|
+
action: 'Delete a bucket',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'Get',
|
|
30
|
+
value: 'get',
|
|
31
|
+
description: 'Get a bucket',
|
|
32
|
+
action: 'Get a bucket',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: 'Get Many',
|
|
36
|
+
value: 'getAll',
|
|
37
|
+
description: 'Get many buckets in a plan',
|
|
38
|
+
action: 'Get many buckets',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'Update',
|
|
42
|
+
value: 'update',
|
|
43
|
+
description: 'Update a bucket',
|
|
44
|
+
action: 'Update a bucket',
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
default: 'getAll',
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
exports.bucketFields = [
|
|
51
|
+
{
|
|
52
|
+
displayName: 'Plan ID',
|
|
53
|
+
name: 'planId',
|
|
54
|
+
type: 'string',
|
|
55
|
+
required: true,
|
|
56
|
+
displayOptions: {
|
|
57
|
+
show: {
|
|
58
|
+
resource: ['bucket'],
|
|
59
|
+
operation: ['create', 'getAll'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
default: '',
|
|
63
|
+
description: 'The ID of the plan this bucket belongs to',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
displayName: 'Name',
|
|
67
|
+
name: 'name',
|
|
68
|
+
type: 'string',
|
|
69
|
+
required: true,
|
|
70
|
+
displayOptions: {
|
|
71
|
+
show: {
|
|
72
|
+
resource: ['bucket'],
|
|
73
|
+
operation: ['create'],
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
default: '',
|
|
77
|
+
description: 'Name of the bucket',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
displayName: 'Upsert',
|
|
81
|
+
name: 'upsert',
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
default: false,
|
|
84
|
+
displayOptions: {
|
|
85
|
+
show: {
|
|
86
|
+
resource: ['bucket'],
|
|
87
|
+
operation: ['create'],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
description: 'Whether to return the existing bucket if one with the same name already exists in the plan',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
displayName: 'Additional Fields',
|
|
94
|
+
name: 'additionalFields',
|
|
95
|
+
type: 'collection',
|
|
96
|
+
placeholder: 'Add Field',
|
|
97
|
+
default: {},
|
|
98
|
+
displayOptions: {
|
|
99
|
+
show: {
|
|
100
|
+
resource: ['bucket'],
|
|
101
|
+
operation: ['create'],
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
options: [
|
|
105
|
+
{
|
|
106
|
+
displayName: 'Order Hint',
|
|
107
|
+
name: 'orderHint',
|
|
108
|
+
type: 'string',
|
|
109
|
+
default: '',
|
|
110
|
+
description: 'Used to sort buckets in the plan (e.g. " !" to put the bucket first)',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
displayName: 'Additional Fields',
|
|
116
|
+
name: 'additionalFields',
|
|
117
|
+
type: 'collection',
|
|
118
|
+
placeholder: 'Add Field',
|
|
119
|
+
default: {},
|
|
120
|
+
displayOptions: {
|
|
121
|
+
show: {
|
|
122
|
+
resource: ['bucket'],
|
|
123
|
+
operation: ['getAll'],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
options: [
|
|
127
|
+
{
|
|
128
|
+
displayName: 'Select Properties',
|
|
129
|
+
name: 'select',
|
|
130
|
+
type: 'string',
|
|
131
|
+
default: '',
|
|
132
|
+
description: 'Comma-separated list of properties to specify which fields to return (e.g. name,orderHint). The ID is always returned.',
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
displayName: 'Bucket ID',
|
|
138
|
+
name: 'bucketId',
|
|
139
|
+
type: 'string',
|
|
140
|
+
required: true,
|
|
141
|
+
displayOptions: {
|
|
142
|
+
show: {
|
|
143
|
+
resource: ['bucket'],
|
|
144
|
+
operation: ['get', 'update', 'delete'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
default: '',
|
|
148
|
+
description: 'The ID of the bucket',
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
displayName: 'Update Fields',
|
|
152
|
+
name: 'updateFields',
|
|
153
|
+
type: 'collection',
|
|
154
|
+
placeholder: 'Add Field',
|
|
155
|
+
default: {},
|
|
156
|
+
displayOptions: {
|
|
157
|
+
show: {
|
|
158
|
+
resource: ['bucket'],
|
|
159
|
+
operation: ['update'],
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
options: [
|
|
163
|
+
{
|
|
164
|
+
displayName: 'Name',
|
|
165
|
+
name: 'name',
|
|
166
|
+
type: 'string',
|
|
167
|
+
default: '',
|
|
168
|
+
description: 'Name of the bucket',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
displayName: 'Order Hint',
|
|
172
|
+
name: 'orderHint',
|
|
173
|
+
type: 'string',
|
|
174
|
+
default: '',
|
|
175
|
+
description: 'Used to sort buckets in the plan',
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
},
|
|
179
|
+
];
|
|
180
|
+
//# sourceMappingURL=BucketDescription.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BucketDescription.js","sourceRoot":"","sources":["../../../nodes/MicrosoftPlanner/BucketDescription.ts"],"names":[],"mappings":"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"}
|