@blickwerk/n8n-nodes-microsoft-planner 1.1.1 → 1.2.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/README.md
CHANGED
|
@@ -84,6 +84,13 @@ Configure the Microsoft Planner OAuth2 API credentials in n8n:
|
|
|
84
84
|
4. Click **Connect my account**
|
|
85
85
|
5. Complete the OAuth flow
|
|
86
86
|
|
|
87
|
+
## Features
|
|
88
|
+
|
|
89
|
+
- **Dynamic Dropdowns**: Automatically loads and displays your Plans, Buckets, and Tasks - no need to manually copy IDs!
|
|
90
|
+
- **User Assignment**: Assign tasks to users by email address
|
|
91
|
+
- **Priority Management**: Easy-to-use priority dropdown (Urgent, Important, Medium, Low)
|
|
92
|
+
- **Full CRUD Operations**: Create, Read, Update, and Delete tasks
|
|
93
|
+
|
|
87
94
|
## Operations
|
|
88
95
|
|
|
89
96
|
### Task
|
|
@@ -98,10 +105,10 @@ Configure the Microsoft Planner OAuth2 API credentials in n8n:
|
|
|
98
105
|
|
|
99
106
|
### Creating a Task
|
|
100
107
|
|
|
101
|
-
To create a task
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
108
|
+
To create a task:
|
|
109
|
+
1. Select a **Plan** from the dropdown (automatically loaded from your Microsoft 365)
|
|
110
|
+
2. Select a **Bucket** from the dropdown (loads buckets from the selected plan)
|
|
111
|
+
3. Enter the **Title** of the task
|
|
105
112
|
|
|
106
113
|
Optional fields:
|
|
107
114
|
- **Description**: Detailed task description
|
|
@@ -117,14 +124,19 @@ Optional fields:
|
|
|
117
124
|
|
|
118
125
|
### Getting Tasks
|
|
119
126
|
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
|
|
123
|
-
|
|
127
|
+
**Get a single task:**
|
|
128
|
+
- Select the task from the dropdown (automatically loaded from your plans)
|
|
129
|
+
|
|
130
|
+
**Get many tasks:**
|
|
131
|
+
- Filter by **Plan** (select from dropdown)
|
|
132
|
+
- Or filter by **Bucket** (select from dropdown)
|
|
133
|
+
- Set a limit or return all tasks
|
|
124
134
|
|
|
125
135
|
### Updating a Task
|
|
126
136
|
|
|
127
|
-
To update a task
|
|
137
|
+
To update a task:
|
|
138
|
+
1. Select the **Task** from the dropdown
|
|
139
|
+
2. Update any of these fields:
|
|
128
140
|
- Title
|
|
129
141
|
- Description
|
|
130
142
|
- Priority (via dropdown)
|
|
@@ -134,15 +146,14 @@ To update a task, provide the Task ID and the fields you want to update. You can
|
|
|
134
146
|
- Percent Complete
|
|
135
147
|
- Move to different bucket
|
|
136
148
|
|
|
137
|
-
###
|
|
149
|
+
### How Dynamic Dropdowns Work
|
|
138
150
|
|
|
139
|
-
|
|
151
|
+
The node automatically fetches your data from Microsoft 365:
|
|
152
|
+
- **Plans**: Loaded from your account when you open the Plan dropdown
|
|
153
|
+
- **Buckets**: Dynamically loaded based on the selected Plan
|
|
154
|
+
- **Tasks**: Loaded from the selected Plan or Bucket
|
|
140
155
|
|
|
141
|
-
|
|
142
|
-
2. Sign in with your Microsoft account
|
|
143
|
-
3. Use these queries:
|
|
144
|
-
- Get all plans: `GET https://graph.microsoft.com/v1.0/me/planner/plans`
|
|
145
|
-
- Get buckets in a plan: `GET https://graph.microsoft.com/v1.0/planner/plans/{plan-id}/buckets`
|
|
156
|
+
No need to manually look up IDs anymore! Just select from the dropdown menus.
|
|
146
157
|
|
|
147
158
|
## Compatibility
|
|
148
159
|
|
|
@@ -156,6 +167,20 @@ Tested with n8n version 1.0.0 and above.
|
|
|
156
167
|
|
|
157
168
|
## Version History
|
|
158
169
|
|
|
170
|
+
### 1.2.0
|
|
171
|
+
- **Major UX Improvement**: Added dynamic dropdowns for Plans, Buckets, and Tasks
|
|
172
|
+
- No more manual ID lookup - select from dropdown menus
|
|
173
|
+
- Plans load automatically from your Microsoft 365 account
|
|
174
|
+
- Buckets load dynamically based on selected Plan
|
|
175
|
+
- Tasks load from selected Plan or Bucket
|
|
176
|
+
- Improved user experience with clearer field labels
|
|
177
|
+
|
|
178
|
+
### 1.1.1
|
|
179
|
+
- Fixed startDateTime not being set (was returning null)
|
|
180
|
+
- Fixed user assignment by adding User.Read.All permission requirement
|
|
181
|
+
- Added error logging for failed user lookups
|
|
182
|
+
- Improved README documentation with all required permissions
|
|
183
|
+
|
|
159
184
|
### 1.1.0
|
|
160
185
|
- Added priority dropdown (Urgent, Important, Medium, Low) instead of number input
|
|
161
186
|
- Added user assignment functionality (assign tasks by email)
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
1
|
+
import { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
|
|
2
2
|
export declare class MicrosoftPlanner implements INodeType {
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
|
+
methods: {
|
|
5
|
+
loadOptions: {
|
|
6
|
+
getPlans(this: ILoadOptionsFunctions): Promise<any>;
|
|
7
|
+
getBuckets(this: ILoadOptionsFunctions): Promise<any>;
|
|
8
|
+
getTasks(this: ILoadOptionsFunctions): Promise<any>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
4
11
|
execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
|
|
5
12
|
}
|
|
@@ -43,6 +43,47 @@ class MicrosoftPlanner {
|
|
|
43
43
|
...TaskDescription_1.taskFields,
|
|
44
44
|
],
|
|
45
45
|
};
|
|
46
|
+
this.methods = {
|
|
47
|
+
loadOptions: {
|
|
48
|
+
async getPlans() {
|
|
49
|
+
const plans = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', '/me/planner/plans');
|
|
50
|
+
return plans.map((plan) => ({
|
|
51
|
+
name: plan.title,
|
|
52
|
+
value: plan.id,
|
|
53
|
+
}));
|
|
54
|
+
},
|
|
55
|
+
async getBuckets() {
|
|
56
|
+
const planId = this.getNodeParameter('planId', 0);
|
|
57
|
+
if (!planId) {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const buckets = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', `/planner/plans/${planId}/buckets`);
|
|
61
|
+
return buckets.map((bucket) => ({
|
|
62
|
+
name: bucket.name,
|
|
63
|
+
value: bucket.id,
|
|
64
|
+
}));
|
|
65
|
+
},
|
|
66
|
+
async getTasks() {
|
|
67
|
+
const planId = this.getNodeParameter('planId', 0);
|
|
68
|
+
const bucketId = this.getNodeParameter('bucketId', 0);
|
|
69
|
+
let endpoint = '';
|
|
70
|
+
if (bucketId) {
|
|
71
|
+
endpoint = `/planner/buckets/${bucketId}/tasks`;
|
|
72
|
+
}
|
|
73
|
+
else if (planId) {
|
|
74
|
+
endpoint = `/planner/plans/${planId}/tasks`;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
const tasks = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', endpoint);
|
|
80
|
+
return tasks.map((task) => ({
|
|
81
|
+
name: task.title,
|
|
82
|
+
value: task.id,
|
|
83
|
+
}));
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
};
|
|
46
87
|
}
|
|
47
88
|
async execute() {
|
|
48
89
|
const items = this.getInputData();
|
|
@@ -52,9 +52,12 @@ exports.taskFields = [
|
|
|
52
52
|
// task:create
|
|
53
53
|
// ----------------------------------
|
|
54
54
|
{
|
|
55
|
-
displayName: 'Plan
|
|
55
|
+
displayName: 'Plan',
|
|
56
56
|
name: 'planId',
|
|
57
|
-
type: '
|
|
57
|
+
type: 'options',
|
|
58
|
+
typeOptions: {
|
|
59
|
+
loadOptionsMethod: 'getPlans',
|
|
60
|
+
},
|
|
58
61
|
required: true,
|
|
59
62
|
displayOptions: {
|
|
60
63
|
show: {
|
|
@@ -63,12 +66,15 @@ exports.taskFields = [
|
|
|
63
66
|
},
|
|
64
67
|
},
|
|
65
68
|
default: '',
|
|
66
|
-
description: 'The
|
|
69
|
+
description: 'The plan to which the task belongs',
|
|
67
70
|
},
|
|
68
71
|
{
|
|
69
|
-
displayName: 'Bucket
|
|
72
|
+
displayName: 'Bucket',
|
|
70
73
|
name: 'bucketId',
|
|
71
|
-
type: '
|
|
74
|
+
type: 'options',
|
|
75
|
+
typeOptions: {
|
|
76
|
+
loadOptionsMethod: 'getBuckets',
|
|
77
|
+
},
|
|
72
78
|
required: true,
|
|
73
79
|
displayOptions: {
|
|
74
80
|
show: {
|
|
@@ -77,7 +83,7 @@ exports.taskFields = [
|
|
|
77
83
|
},
|
|
78
84
|
},
|
|
79
85
|
default: '',
|
|
80
|
-
description: 'The
|
|
86
|
+
description: 'The bucket to which the task belongs',
|
|
81
87
|
},
|
|
82
88
|
{
|
|
83
89
|
displayName: 'Title',
|
|
@@ -176,9 +182,12 @@ exports.taskFields = [
|
|
|
176
182
|
// task:get
|
|
177
183
|
// ----------------------------------
|
|
178
184
|
{
|
|
179
|
-
displayName: 'Task
|
|
185
|
+
displayName: 'Task',
|
|
180
186
|
name: 'taskId',
|
|
181
|
-
type: '
|
|
187
|
+
type: 'options',
|
|
188
|
+
typeOptions: {
|
|
189
|
+
loadOptionsMethod: 'getTasks',
|
|
190
|
+
},
|
|
182
191
|
required: true,
|
|
183
192
|
displayOptions: {
|
|
184
193
|
show: {
|
|
@@ -187,7 +196,7 @@ exports.taskFields = [
|
|
|
187
196
|
},
|
|
188
197
|
},
|
|
189
198
|
default: '',
|
|
190
|
-
description: 'The
|
|
199
|
+
description: 'The task to operate on',
|
|
191
200
|
},
|
|
192
201
|
{
|
|
193
202
|
displayName: 'Additional Fields',
|
|
@@ -259,18 +268,24 @@ exports.taskFields = [
|
|
|
259
268
|
},
|
|
260
269
|
options: [
|
|
261
270
|
{
|
|
262
|
-
displayName: 'Plan
|
|
271
|
+
displayName: 'Plan',
|
|
263
272
|
name: 'planId',
|
|
264
|
-
type: '
|
|
273
|
+
type: 'options',
|
|
274
|
+
typeOptions: {
|
|
275
|
+
loadOptionsMethod: 'getPlans',
|
|
276
|
+
},
|
|
265
277
|
default: '',
|
|
266
|
-
description: 'Filter tasks by plan
|
|
278
|
+
description: 'Filter tasks by plan',
|
|
267
279
|
},
|
|
268
280
|
{
|
|
269
|
-
displayName: 'Bucket
|
|
281
|
+
displayName: 'Bucket',
|
|
270
282
|
name: 'bucketId',
|
|
271
|
-
type: '
|
|
283
|
+
type: 'options',
|
|
284
|
+
typeOptions: {
|
|
285
|
+
loadOptionsMethod: 'getBuckets',
|
|
286
|
+
},
|
|
272
287
|
default: '',
|
|
273
|
-
description: 'Filter tasks by bucket
|
|
288
|
+
description: 'Filter tasks by bucket',
|
|
274
289
|
},
|
|
275
290
|
],
|
|
276
291
|
},
|