@blickwerk/n8n-nodes-microsoft-planner 1.2.1 → 1.2.3
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
|
@@ -106,8 +106,8 @@ Configure the Microsoft Planner OAuth2 API credentials in n8n:
|
|
|
106
106
|
### Creating a Task
|
|
107
107
|
|
|
108
108
|
To create a task:
|
|
109
|
-
1.
|
|
110
|
-
2. Select a **Bucket** from the dropdown (loads
|
|
109
|
+
1. Enter the **Plan ID** (you can find this in Microsoft Planner URL or via Graph Explorer)
|
|
110
|
+
2. Select a **Bucket** from the dropdown (loads automatically based on the Plan ID)
|
|
111
111
|
3. Enter the **Title** of the task
|
|
112
112
|
|
|
113
113
|
Optional fields:
|
|
@@ -146,14 +146,28 @@ To update a task:
|
|
|
146
146
|
- Percent Complete
|
|
147
147
|
- Move to different bucket
|
|
148
148
|
|
|
149
|
-
### How
|
|
149
|
+
### How to Find Plan IDs
|
|
150
150
|
|
|
151
|
-
|
|
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
|
|
151
|
+
You can find your Plan ID in several ways:
|
|
155
152
|
|
|
156
|
-
|
|
153
|
+
1. **From Planner URL**: Open Microsoft Planner in browser, the URL contains the Plan ID:
|
|
154
|
+
```
|
|
155
|
+
https://tasks.office.com/.../ planId=YOUR_PLAN_ID_HERE /...
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
2. **Via Microsoft Graph Explorer**:
|
|
159
|
+
- Go to https://developer.microsoft.com/graph/graph-explorer
|
|
160
|
+
- Sign in
|
|
161
|
+
- Run: `GET /me/planner/plans`
|
|
162
|
+
- Copy the `id` field from the plan you want
|
|
163
|
+
|
|
164
|
+
### Dynamic Dropdowns
|
|
165
|
+
|
|
166
|
+
Once you enter a Plan ID:
|
|
167
|
+
- **Buckets**: Automatically load for that plan
|
|
168
|
+
- **Tasks**: Load based on selected Plan/Bucket
|
|
169
|
+
|
|
170
|
+
You can also manually enter Bucket IDs and Task IDs if needed.
|
|
157
171
|
|
|
158
172
|
## Compatibility
|
|
159
173
|
|
|
@@ -167,6 +181,17 @@ Tested with n8n version 1.0.0 and above.
|
|
|
167
181
|
|
|
168
182
|
## Version History
|
|
169
183
|
|
|
184
|
+
### 1.2.3
|
|
185
|
+
- Improved error handling for Buckets and Tasks loading
|
|
186
|
+
- Better fallback values when data cannot be loaded
|
|
187
|
+
- Added console logging for debugging dropdown issues
|
|
188
|
+
|
|
189
|
+
### 1.2.2
|
|
190
|
+
- Removed Plan dropdown (Plans cannot be loaded via API)
|
|
191
|
+
- Plan ID is now manual input only
|
|
192
|
+
- Buckets and Tasks still have dynamic dropdowns
|
|
193
|
+
- Simplified and more reliable plan selection
|
|
194
|
+
|
|
170
195
|
### 1.2.1
|
|
171
196
|
- Fixed Plans not loading (improved API endpoint to fetch from groups)
|
|
172
197
|
- Allow manual ID input in all dropdown fields
|
|
@@ -3,10 +3,6 @@ export declare class MicrosoftPlanner implements INodeType {
|
|
|
3
3
|
description: INodeTypeDescription;
|
|
4
4
|
methods: {
|
|
5
5
|
loadOptions: {
|
|
6
|
-
getPlans(this: ILoadOptionsFunctions): Promise<{
|
|
7
|
-
name: any;
|
|
8
|
-
value: any;
|
|
9
|
-
}[]>;
|
|
10
6
|
getBuckets(this: ILoadOptionsFunctions): Promise<any>;
|
|
11
7
|
getTasks(this: ILoadOptionsFunctions): Promise<any>;
|
|
12
8
|
};
|
|
@@ -45,62 +45,53 @@ class MicrosoftPlanner {
|
|
|
45
45
|
};
|
|
46
46
|
this.methods = {
|
|
47
47
|
loadOptions: {
|
|
48
|
-
async
|
|
48
|
+
async getBuckets() {
|
|
49
49
|
try {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
plans.push(...groupPlans.value);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (error) {
|
|
61
|
-
// Skip groups without plans
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
50
|
+
const planId = this.getNodeParameter('planId', 0);
|
|
51
|
+
if (!planId) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
const buckets = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', `/planner/plans/${planId}/buckets`);
|
|
55
|
+
if (!buckets || buckets.length === 0) {
|
|
56
|
+
return [];
|
|
64
57
|
}
|
|
65
|
-
return
|
|
66
|
-
name:
|
|
67
|
-
value:
|
|
58
|
+
return buckets.map((bucket) => ({
|
|
59
|
+
name: bucket.name || bucket.id,
|
|
60
|
+
value: bucket.id,
|
|
68
61
|
}));
|
|
69
62
|
}
|
|
70
63
|
catch (error) {
|
|
71
|
-
console.error('Error loading
|
|
64
|
+
console.error('Error loading buckets:', error);
|
|
72
65
|
return [];
|
|
73
66
|
}
|
|
74
67
|
},
|
|
75
|
-
async getBuckets() {
|
|
76
|
-
const planId = this.getNodeParameter('planId', 0);
|
|
77
|
-
if (!planId) {
|
|
78
|
-
return [];
|
|
79
|
-
}
|
|
80
|
-
const buckets = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', `/planner/plans/${planId}/buckets`);
|
|
81
|
-
return buckets.map((bucket) => ({
|
|
82
|
-
name: bucket.name,
|
|
83
|
-
value: bucket.id,
|
|
84
|
-
}));
|
|
85
|
-
},
|
|
86
68
|
async getTasks() {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
69
|
+
try {
|
|
70
|
+
const planId = this.getNodeParameter('planId', 0);
|
|
71
|
+
const bucketId = this.getNodeParameter('bucketId', 0);
|
|
72
|
+
let endpoint = '';
|
|
73
|
+
if (bucketId) {
|
|
74
|
+
endpoint = `/planner/buckets/${bucketId}/tasks`;
|
|
75
|
+
}
|
|
76
|
+
else if (planId) {
|
|
77
|
+
endpoint = `/planner/plans/${planId}/tasks`;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
const tasks = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', endpoint);
|
|
83
|
+
if (!tasks || tasks.length === 0) {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
return tasks.map((task) => ({
|
|
87
|
+
name: task.title || task.id,
|
|
88
|
+
value: task.id,
|
|
89
|
+
}));
|
|
95
90
|
}
|
|
96
|
-
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error('Error loading tasks:', error);
|
|
97
93
|
return [];
|
|
98
94
|
}
|
|
99
|
-
const tasks = await GenericFunctions_1.microsoftApiRequestAllItems.call(this, 'value', 'GET', endpoint);
|
|
100
|
-
return tasks.map((task) => ({
|
|
101
|
-
name: task.title,
|
|
102
|
-
value: task.id,
|
|
103
|
-
}));
|
|
104
95
|
},
|
|
105
96
|
},
|
|
106
97
|
};
|
|
@@ -52,12 +52,9 @@ exports.taskFields = [
|
|
|
52
52
|
// task:create
|
|
53
53
|
// ----------------------------------
|
|
54
54
|
{
|
|
55
|
-
displayName: 'Plan',
|
|
55
|
+
displayName: 'Plan ID',
|
|
56
56
|
name: 'planId',
|
|
57
57
|
type: 'string',
|
|
58
|
-
typeOptions: {
|
|
59
|
-
loadOptionsMethod: 'getPlans',
|
|
60
|
-
},
|
|
61
58
|
required: true,
|
|
62
59
|
displayOptions: {
|
|
63
60
|
show: {
|
|
@@ -66,8 +63,8 @@ exports.taskFields = [
|
|
|
66
63
|
},
|
|
67
64
|
},
|
|
68
65
|
default: '',
|
|
69
|
-
description: 'The plan to which the task belongs
|
|
70
|
-
placeholder: '
|
|
66
|
+
description: 'The ID of the plan to which the task belongs',
|
|
67
|
+
placeholder: 'Enter Plan ID',
|
|
71
68
|
},
|
|
72
69
|
{
|
|
73
70
|
displayName: 'Bucket',
|
|
@@ -271,15 +268,12 @@ exports.taskFields = [
|
|
|
271
268
|
},
|
|
272
269
|
options: [
|
|
273
270
|
{
|
|
274
|
-
displayName: 'Plan',
|
|
271
|
+
displayName: 'Plan ID',
|
|
275
272
|
name: 'planId',
|
|
276
273
|
type: 'string',
|
|
277
|
-
typeOptions: {
|
|
278
|
-
loadOptionsMethod: 'getPlans',
|
|
279
|
-
},
|
|
280
274
|
default: '',
|
|
281
|
-
description: 'Filter tasks by
|
|
282
|
-
placeholder: '
|
|
275
|
+
description: 'Filter tasks by Plan ID',
|
|
276
|
+
placeholder: 'Enter Plan ID',
|
|
283
277
|
},
|
|
284
278
|
{
|
|
285
279
|
displayName: 'Bucket',
|