1 | type Asana = { |
2 | token: string; |
3 | }; |
4 | |
5 | * Update a project |
6 | * A specific, existing project can be updated by making a PUT request on |
7 | the URL for that project. Only the fields provided in the `data` block |
8 | will be updated; any unspecified fields will remain unchanged. |
9 |
|
10 | When using this method, it is best to specify only those fields you wish |
11 | to change, or else you may overwrite changes made by another user since |
12 | you last retrieved the task. |
13 |
|
14 | Returns the complete updated project record. |
15 | */ |
16 | export async function main( |
17 | auth: Asana, |
18 | project_gid: string, |
19 | opt_pretty: string | undefined, |
20 | opt_fields: string | undefined, |
21 | body: { |
22 | data?: (({ gid?: string; resource_type?: string; [k: string]: unknown } & { |
23 | name?: string; |
24 | [k: string]: unknown; |
25 | }) & { |
26 | archived?: boolean; |
27 | color?: |
28 | | "dark-pink" |
29 | | "dark-green" |
30 | | "dark-blue" |
31 | | "dark-red" |
32 | | "dark-teal" |
33 | | "dark-brown" |
34 | | "dark-orange" |
35 | | "dark-purple" |
36 | | "dark-warm-gray" |
37 | | "light-pink" |
38 | | "light-green" |
39 | | "light-blue" |
40 | | "light-red" |
41 | | "light-teal" |
42 | | "light-brown" |
43 | | "light-orange" |
44 | | "light-purple" |
45 | | "light-warm-gray"; |
46 | created_at?: string; |
47 | current_status?: (({ |
48 | gid?: string; |
49 | resource_type?: string; |
50 | [k: string]: unknown; |
51 | } & { title?: string; [k: string]: unknown }) & { |
52 | color: "green" | "yellow" | "red" | "blue"; |
53 | html_text?: string; |
54 | text: string; |
55 | [k: string]: unknown; |
56 | }) & { |
57 | author?: { |
58 | gid?: string; |
59 | resource_type?: string; |
60 | [k: string]: unknown; |
61 | } & { name?: string; [k: string]: unknown }; |
62 | created_at?: string; |
63 | created_by?: { |
64 | gid?: string; |
65 | resource_type?: string; |
66 | [k: string]: unknown; |
67 | } & { name?: string; [k: string]: unknown }; |
68 | modified_at?: string; |
69 | [k: string]: unknown; |
70 | }; |
71 | current_status_update?: { |
72 | gid?: string; |
73 | resource_type?: string; |
74 | [k: string]: unknown; |
75 | } & { |
76 | resource_subtype?: |
77 | | "project_status_update" |
78 | | "portfolio_status_update" |
79 | | "goal_status_update"; |
80 | title?: string; |
81 | [k: string]: unknown; |
82 | }; |
83 | custom_field_settings?: (({ |
84 | gid?: string; |
85 | resource_type?: string; |
86 | [k: string]: unknown; |
87 | } & { [k: string]: unknown }) & { |
88 | custom_field?: ((({ |
89 | gid?: string; |
90 | resource_type?: string; |
91 | [k: string]: unknown; |
92 | } & { |
93 | date_value?: { |
94 | date?: string; |
95 | date_time?: string; |
96 | [k: string]: unknown; |
97 | }; |
98 | display_value?: string; |
99 | enabled?: boolean; |
100 | enum_options?: ({ |
101 | gid?: string; |
102 | resource_type?: string; |
103 | [k: string]: unknown; |
104 | } & { |
105 | color?: string; |
106 | enabled?: boolean; |
107 | name?: string; |
108 | [k: string]: unknown; |
109 | })[]; |
110 | enum_value?: ({ |
111 | gid?: string; |
112 | resource_type?: string; |
113 | [k: string]: unknown; |
114 | } & { |
115 | color?: string; |
116 | enabled?: boolean; |
117 | name?: string; |
118 | [k: string]: unknown; |
119 | }) & { [k: string]: unknown }; |
120 | multi_enum_values?: ({ |
121 | gid?: string; |
122 | resource_type?: string; |
123 | [k: string]: unknown; |
124 | } & { |
125 | color?: string; |
126 | enabled?: boolean; |
127 | name?: string; |
128 | [k: string]: unknown; |
129 | })[]; |
130 | name?: string; |
131 | number_value?: number; |
132 | resource_subtype?: |
133 | | "text" |
134 | | "enum" |
135 | | "multi_enum" |
136 | | "number" |
137 | | "date" |
138 | | "people"; |
139 | text_value?: string; |
140 | type?: "text" | "enum" | "multi_enum" | "number"; |
141 | [k: string]: unknown; |
142 | }) & { |
143 | asana_created_field?: |
144 | | "a_v_requirements" |
145 | | "account_name" |
146 | | "actionable" |
147 | | "align_shipping_link" |
148 | | "align_status" |
149 | | "allotted_time" |
150 | | "appointment" |
151 | | "approval_stage" |
152 | | "approved" |
153 | | "article_series" |
154 | | "board_committee" |
155 | | "browser" |
156 | | "campaign_audience" |
157 | | "campaign_project_status" |
158 | | "campaign_regions" |
159 | | "channel_primary" |
160 | | "client_topic_type" |
161 | | "complete_by" |
162 | | "contact" |
163 | | "contact_email_address" |
164 | | "content_channels" |
165 | | "content_channels_needed" |
166 | | "content_stage" |
167 | | "content_type" |
168 | | "contract" |
169 | | "contract_status" |
170 | | "cost" |
171 | | "creation_stage" |
172 | | "creative_channel" |
173 | | "creative_needed" |
174 | | "creative_needs" |
175 | | "data_sensitivity" |
176 | | "deal_size" |
177 | | "delivery_appt" |
178 | | "delivery_appt_date" |
179 | | "department" |
180 | | "department_responsible" |
181 | | "design_request_needed" |
182 | | "design_request_type" |
183 | | "discussion_category" |
184 | | "do_this_task" |
185 | | "editorial_content_status" |
186 | | "editorial_content_tag" |
187 | | "editorial_content_type" |
188 | | "effort" |
189 | | "effort_level" |
190 | | "est_completion_date" |
191 | | "estimated_time" |
192 | | "estimated_value" |
193 | | "expected_cost" |
194 | | "external_steps_needed" |
195 | | "favorite_idea" |
196 | | "feedback_type" |
197 | | "financial" |
198 | | "funding_amount" |
199 | | "grant_application_process" |
200 | | "hiring_candidate_status" |
201 | | "idea_status" |
202 | | "ids_link" |
203 | | "ids_patient_link" |
204 | | "implementation_stage" |
205 | | "insurance" |
206 | | "interview_area" |
207 | | "interview_question_score" |
208 | | "itero_scan_link" |
209 | | "job_s_applied_to" |
210 | | "lab" |
211 | | "launch_status" |
212 | | "lead_status" |
213 | | "localization_language" |
214 | | "localization_market_team" |
215 | | "localization_status" |
216 | | "meeting_minutes" |
217 | | "meeting_needed" |
218 | | "minutes" |
219 | | "mrr" |
220 | | "must_localize" |
221 | | "name_of_foundation" |
222 | | "need_to_follow_up" |
223 | | "next_appointment" |
224 | | "next_steps_sales" |
225 | | "num_people" |
226 | | "number_of_user_reports" |
227 | | "office_location" |
228 | | "onboarding_activity" |
229 | | "owner" |
230 | | "participants_needed" |
231 | | "patient_date_of_birth" |
232 | | "patient_email" |
233 | | "patient_phone" |
234 | | "patient_status" |
235 | | "phone_number" |
236 | | "planning_category" |
237 | | "point_of_contact" |
238 | | "position" |
239 | | "post_format" |
240 | | "prescription" |
241 | | "priority" |
242 | | "priority_level" |
243 | | "product" |
244 | | "product_stage" |
245 | | "progress" |
246 | | "project_size" |
247 | | "project_status" |
248 | | "proposed_budget" |
249 | | "publish_status" |
250 | | "reason_for_scan" |
251 | | "referral" |
252 | | "request_type" |
253 | | "research_status" |
254 | | "responsible_department" |
255 | | "responsible_team" |
256 | | "risk_assessment_status" |
257 | | "room_name" |
258 | | "sales_counterpart" |
259 | | "sentiment" |
260 | | "shipping_link" |
261 | | "social_channels" |
262 | | "stage" |
263 | | "status" |
264 | | "status_design" |
265 | | "status_of_initiative" |
266 | | "system_setup" |
267 | | "task_progress" |
268 | | "team" |
269 | | "team_marketing" |
270 | | "team_responsible" |
271 | | "time_it_takes_to_complete_tasks" |
272 | | "timeframe" |
273 | | "treatment_type" |
274 | | "type_work_requests_it" |
275 | | "use_agency" |
276 | | "user_name" |
277 | | "vendor_category" |
278 | | "vendor_type" |
279 | | "word_count"; |
280 | currency_code?: string; |
281 | custom_label?: string; |
282 | custom_label_position?: "prefix" | "suffix"; |
283 | description?: string; |
284 | enum_options?: ({ |
285 | gid?: string; |
286 | resource_type?: string; |
287 | [k: string]: unknown; |
288 | } & { |
289 | color?: string; |
290 | enabled?: boolean; |
291 | name?: string; |
292 | [k: string]: unknown; |
293 | })[]; |
294 | format?: "currency" | "identifier" | "percentage" | "custom" | "none"; |
295 | has_notifications_enabled?: boolean; |
296 | is_global_to_workspace?: boolean; |
297 | precision?: number; |
298 | [k: string]: unknown; |
299 | }) & { |
300 | created_by?: { |
301 | gid?: string; |
302 | resource_type?: string; |
303 | [k: string]: unknown; |
304 | } & { name?: string; [k: string]: unknown }; |
305 | people_value?: ({ |
306 | gid?: string; |
307 | resource_type?: string; |
308 | [k: string]: unknown; |
309 | } & { name?: string; [k: string]: unknown })[]; |
310 | [k: string]: unknown; |
311 | }) & { [k: string]: unknown }; |
312 | is_important?: boolean; |
313 | parent?: ({ |
314 | gid?: string; |
315 | resource_type?: string; |
316 | [k: string]: unknown; |
317 | } & { name?: string; [k: string]: unknown }) & { [k: string]: unknown }; |
318 | project?: ({ |
319 | gid?: string; |
320 | resource_type?: string; |
321 | [k: string]: unknown; |
322 | } & { name?: string; [k: string]: unknown }) & { [k: string]: unknown }; |
323 | [k: string]: unknown; |
324 | })[]; |
325 | default_view?: "list" | "board" | "calendar" | "timeline"; |
326 | due_date?: string; |
327 | due_on?: string; |
328 | html_notes?: string; |
329 | is_template?: boolean; |
330 | members?: ({ |
331 | gid?: string; |
332 | resource_type?: string; |
333 | [k: string]: unknown; |
334 | } & { name?: string; [k: string]: unknown })[]; |
335 | modified_at?: string; |
336 | notes?: string; |
337 | public?: boolean; |
338 | start_on?: string; |
339 | workspace?: ({ |
340 | gid?: string; |
341 | resource_type?: string; |
342 | [k: string]: unknown; |
343 | } & { name?: string; [k: string]: unknown }) & { [k: string]: unknown }; |
344 | [k: string]: unknown; |
345 | }) & { |
346 | custom_fields?: { [k: string]: string }; |
347 | followers?: string; |
348 | owner?: string; |
349 | team?: string; |
350 | [k: string]: unknown; |
351 | }; |
352 | [k: string]: unknown; |
353 | } |
354 | ) { |
355 | const url = new URL(`https://app.asana.com/api/1.0/projects/${project_gid}`); |
356 | for (const [k, v] of [ |
357 | ["opt_pretty", opt_pretty], |
358 | ["opt_fields", opt_fields], |
359 | ]) { |
360 | if (v !== undefined && v !== "") { |
361 | url.searchParams.append(k, v); |
362 | } |
363 | } |
364 | const response = await fetch(url, { |
365 | method: "PUT", |
366 | headers: { |
367 | "Content-Type": "application/json", |
368 | Authorization: "Bearer " + auth.token, |
369 | }, |
370 | body: JSON.stringify(body), |
371 | }); |
372 | if (!response.ok) { |
373 | const text = await response.text(); |
374 | throw new Error(`${response.status} ${text}`); |
375 | } |
376 | return await response.json(); |
377 | } |
378 |
|