• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

rwjdk / TrelloDotNet / 7308990850

23 Dec 2023 03:12PM UTC coverage: 63.815% (-2.5%) from 66.31%
7308990850

push

github

rwjdk
v1.9.7

890 of 1733 branches covered (0.0%)

Branch coverage included in aggregate %.

5 of 128 new or added lines in 7 files covered. (3.91%)

2 existing lines in 2 files now uncovered.

2332 of 3316 relevant lines covered (70.33%)

54.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.84
/TrelloDotNet/TrelloDotNet/TrelloClient.Cards.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text.Json;
5
using System.Threading;
6
using System.Threading.Tasks;
7
using TrelloDotNet.Control;
8
using TrelloDotNet.Model;
9
using TrelloDotNet.Model.Options;
10
using TrelloDotNet.Model.Options.GetCardOptions;
11
using TrelloDotNet.Model.Options.MoveCardToBoardOptions;
12
using TrelloDotNet.Model.Options.MoveCardToListOptions;
13

14
namespace TrelloDotNet
15
{
16
    public partial class TrelloClient
17
    {
18
        /// <summary>
19
        /// Add a Card
20
        /// </summary>
21
        /// <param name="card">The Card to Add</param>
22
        /// <param name="cancellationToken">Cancellation Token</param>
23
        /// <returns>The Added Card</returns>
24
        public async Task<Card> AddCardAsync(Card card, CancellationToken cancellationToken = default)
25
        {
26
            QueryParameter[] parameters = _queryParametersBuilder.GetViaQueryParameterAttributes(card);
59✔
27
            _queryParametersBuilder.AdjustForNamedPosition(parameters, card.NamedPosition);
59✔
28
            return await _apiRequestController.Post<Card>($"{UrlPaths.Cards}", cancellationToken, parameters);
59✔
29
        }
59✔
30

31
        /// <summary>
32
        /// Archive (Close) a Card
33
        /// </summary>
34
        /// <param name="cardId">The id of card that should be archived</param>
35
        /// <param name="cancellationToken">Cancellation Token</param>
36
        /// <returns>The Archived Card</returns>
37
        public async Task<Card> ArchiveCardAsync(string cardId, CancellationToken cancellationToken = default)
38
        {
39
            return await _apiRequestController.Put<Card>($"{UrlPaths.Cards}/{cardId}", cancellationToken, new QueryParameter("closed", true));
1✔
40
        }
1✔
41

42
        /// <summary>
43
        /// ReOpen (Send back to board) a Card
44
        /// </summary>
45
        /// <param name="cardId">The id of card that should be reopened</param>
46
        /// <param name="cancellationToken">Cancellation Token</param>
47
        /// <returns>The ReOpened Card</returns>
48
        public async Task<Card> ReOpenCardAsync(string cardId, CancellationToken cancellationToken = default)
49
        {
50
            return await _apiRequestController.Put<Card>($"{UrlPaths.Cards}/{cardId}", cancellationToken, new QueryParameter("closed", false));
1✔
51
        }
1✔
52

53
        /// <summary>
54
        /// Update a Card
55
        /// </summary>
56
        /// <param name="cardWithChanges">The card with the changes</param>
57
        /// <param name="cancellationToken">Cancellation Token</param>
58
        /// <returns>The Updated Card</returns>
59
        public async Task<Card> UpdateCardAsync(Card cardWithChanges, CancellationToken cancellationToken = default)
60
        {
61
            var parameters = _queryParametersBuilder.GetViaQueryParameterAttributes(cardWithChanges).ToList();
9✔
62
            CardCover cardCover = cardWithChanges.Cover;
9✔
63
            _queryParametersBuilder.AdjustForNamedPosition(parameters, cardWithChanges.NamedPosition);
9✔
64
            var payload = GeneratePayloadForCoverUpdate(cardCover, parameters);
9✔
65
            return await _apiRequestController.PutWithJsonPayload<Card>($"{UrlPaths.Cards}/{cardWithChanges.Id}", cancellationToken, payload, parameters.ToArray());
9✔
66
        }
9✔
67

68
        private static string GeneratePayloadForCoverUpdate(CardCover cardCover, List<QueryParameter> parameters)
69
        {
70
            //Special code for Cover
71
            string payload = string.Empty;
10✔
72
            if (cardCover == null)
10✔
73
            {
74
                //Remove cover
75
                parameters.Add(new QueryParameter("cover", ""));
1✔
76
            }
77
            else
78
            {
79
                cardCover.PrepareForAddUpdate();
9✔
80
                if (cardCover.Color != null || cardCover.BackgroundImageId != null)
9✔
81
                {
82
                    QueryParameter queryParameter = parameters.FirstOrDefault(x => x.Name == "idAttachmentCover");
29✔
83
                    if (queryParameter != null)
3✔
84
                    {
85
                        parameters.Remove(queryParameter); //This parameter can't be there while a cover is added
2✔
86
                    }
87
                }
88

89
                payload = $"{{\"cover\":{JsonSerializer.Serialize(cardCover)}}}";
9✔
90
            }
91

92
            return payload;
10✔
93
        }
94

95
        /// <summary>
96
        /// Archive all cards on in a List
97
        /// </summary>
98
        /// <param name="listId">The id of the List that should have its cards archived</param>
99
        /// <param name="cancellationToken">Cancellation Token</param>
100
        public async Task ArchiveAllCardsInListAsync(string listId, CancellationToken cancellationToken = default)
101
        {
102
            await _apiRequestController.Post<List>($"{UrlPaths.Lists}/{listId}/archiveAllCards", cancellationToken);
1✔
103
        }
1✔
104

105
        /// <summary>
106
        /// Move all cards of a list to another list
107
        /// </summary>
108
        /// <param name="currentListId">The id of the List that should have its cards moved</param>
109
        /// <param name="newListId">The id of the new List that should receive the cards</param>
110
        /// <param name="cancellationToken">Cancellation Token</param>
111
        public async Task MoveAllCardsInListAsync(string currentListId, string newListId, CancellationToken cancellationToken = default)
112
        {
113
            var newList = await GetListAsync(newListId, cancellationToken); //Get the new list's BoardId so the user do not need to provide it.
1✔
114
            await _apiRequestController.Post($"{UrlPaths.Lists}/{currentListId}/moveAllCards", cancellationToken,
1✔
115
                0,
1✔
116
                new QueryParameter("idBoard", newList.BoardId),
1✔
117
                new QueryParameter("idList", newListId)
1✔
118
            );
1✔
119
        }
1✔
120

121
        /// <summary>
122
        /// Delete a Card (WARNING: THERE IS NO WAY GOING BACK!!!). Alternative use ArchiveCardAsync() for non-permanency
123
        /// </summary>
124
        /// <param name="cardId">The id of the Card to Delete</param>
125
        /// <param name="cancellationToken">Cancellation Token</param>
126
        public async Task DeleteCardAsync(string cardId, CancellationToken cancellationToken = default)
127
        {
128
            await _apiRequestController.Delete($"{UrlPaths.Cards}/{cardId}", cancellationToken, 0);
1✔
129
        }
1✔
130

131
        /// <summary>
132
        /// Get a Card by its Id
133
        /// </summary>
134
        /// <param name="cardId">Id of the Card</param>
135
        /// <param name="cancellationToken">Cancellation Token</param>
136
        /// <returns>The Card</returns>
137
        public async Task<Card> GetCardAsync(string cardId, CancellationToken cancellationToken = default)
138
        {
139
            return await _apiRequestController.Get<Card>(GetUrlBuilder.GetCard(cardId), cancellationToken,
51✔
140
                new QueryParameter("customFieldItems", Options.IncludeCustomFieldsInCardGetMethods),
51✔
141
                new QueryParameter("attachments", Options.IncludeAttachmentsInCardGetMethods)
51✔
142
            );
51✔
143
        }
51✔
144

145
        /// <summary>
146
        /// Get a Card by its Id
147
        /// </summary>
148
        /// <param name="cardId">Id of the Card</param>
149
        /// <param name="options">Options on how and what should be included on the cards (Example only a few fields to increase performance or more nested data to avoid more API calls)</param>
150
        /// <param name="cancellationToken">Cancellation Token</param>
151
        /// <returns>The Card</returns>
152
        public async Task<Card> GetCardAsync(string cardId, GetCardOptions options, CancellationToken cancellationToken = default)
153
        {
154
            return await _apiRequestController.Get<Card>(GetUrlBuilder.GetCard(cardId), cancellationToken, options.GetParameters());
58✔
155
        }
58✔
156

157
        /// <summary>
158
        /// Get all open cards on un-archived lists on a board
159
        /// </summary>
160
        /// <param name="boardId">Id of the Board (in its long or short version)</param>
161
        /// <param name="cancellationToken">CancellationToken</param>
162
        /// <returns>List of Cards</returns>
163
        public async Task<List<Card>> GetCardsOnBoardAsync(string boardId, CancellationToken cancellationToken = default)
164
        {
165
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsOnBoard(boardId), cancellationToken,
6✔
166
                new QueryParameter("customFieldItems", Options.IncludeCustomFieldsInCardGetMethods),
6✔
167
                new QueryParameter("attachments", Options.IncludeAttachmentsInCardGetMethods)
6✔
168
            );
6✔
169
        }
6✔
170

171
        /// <summary>
172
        /// Get all open cards on un-archived lists on a board
173
        /// </summary>
174
        /// <param name="boardId">Id of the Board (in its long or short version)</param>
175
        /// <param name="options">Options on how and what should be included on the cards (Example only a few fields to increase performance or more nested data to avoid more API calls)</param>
176
        /// <param name="cancellationToken">CancellationToken</param>
177
        /// <returns>List of Cards</returns>
178
        public async Task<List<Card>> GetCardsOnBoardAsync(string boardId, GetCardOptions options, CancellationToken cancellationToken = default)
179
        {
180
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsOnBoard(boardId), cancellationToken, options.GetParameters());
×
181
        }
×
182

183
        /// <summary>
184
        /// Get all open cards on a specific list
185
        /// </summary>
186
        /// <param name="listId">Id of the List</param>
187
        /// <param name="cancellationToken">Cancellation Token</param>
188
        /// <returns>List of Cards</returns>
189
        public async Task<List<Card>> GetCardsInListAsync(string listId, CancellationToken cancellationToken = default)
190
        {
191
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsInList(listId), cancellationToken,
9✔
192
                new QueryParameter("customFieldItems", Options.IncludeCustomFieldsInCardGetMethods),
9✔
193
                new QueryParameter("attachments", Options.IncludeAttachmentsInCardGetMethods));
9✔
194
        }
9✔
195

196
        /// <summary>
197
        /// Get all open cards on a specific list
198
        /// </summary>
199
        /// <param name="listId">Id of the List</param>
200
        /// <param name="options">Options on how and what should be included on the cards (Example only a few fields to increase performance or more nested data to avoid more API calls)</param>
201
        /// <param name="cancellationToken">Cancellation Token</param>
202
        /// <returns>List of Cards</returns>
203
        public async Task<List<Card>> GetCardsInListAsync(string listId, GetCardOptions options, CancellationToken cancellationToken = default)
204
        {
205
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsInList(listId), cancellationToken, options.GetParameters());
×
206
        }
×
207

208
        /// <summary>
209
        /// Get the cards on board based on their status regardless if they are on archived lists
210
        /// </summary>
211
        /// <param name="boardId">Id of the Board (in its long or short version)</param>
212
        /// <param name="filter">The Selected Filter</param>
213
        /// <param name="cancellationToken">Cancellation Token</param>
214
        /// <returns>List of Cards</returns>
215
        public async Task<List<Card>> GetCardsOnBoardFilteredAsync(string boardId, CardsFilter filter, CancellationToken cancellationToken = default)
216
        {
217
            return await _apiRequestController.Get<List<Card>>($"{GetUrlBuilder.GetCardsOnBoard(boardId)}/{filter.GetJsonPropertyName()}", cancellationToken,
1✔
218
                new QueryParameter("customFieldItems", Options.IncludeCustomFieldsInCardGetMethods),
1✔
219
                new QueryParameter("attachments", Options.IncludeAttachmentsInCardGetMethods));
1✔
220
        }
1✔
221

222
        /// <summary>
223
        /// Get the cards on board based on their status regardless if they are on archived lists
224
        /// </summary>
225
        /// <param name="boardId">Id of the Board (in its long or short version)</param>
226
        /// <param name="filter">The Selected Filter</param>
227
        /// <param name="options">Options on how and what should be included on the cards (Example only a few fields to increase performance or more nested data to avoid more API calls)</param> 
228
        /// <param name="cancellationToken">Cancellation Token</param>
229
        /// <returns>List of Cards</returns>
230
        public async Task<List<Card>> GetCardsOnBoardFilteredAsync(string boardId, CardsFilter filter, GetCardOptions options, CancellationToken cancellationToken = default)
231
        {
232
            return await _apiRequestController.Get<List<Card>>($"{GetUrlBuilder.GetCardsOnBoard(boardId)}/{filter.GetJsonPropertyName()}", cancellationToken, options.GetParameters());
×
233
        }
×
234

235
        /// <summary>
236
        /// Get all Cards a Member is on (across multiple boards)
237
        /// </summary>
238
        /// <param name="memberId">Id of Member</param>
239
        /// <param name="cancellationToken">Cancellation Token</param>
240
        /// <returns></returns>
241
        public async Task<List<Card>> GetCardsForMemberAsync(string memberId, CancellationToken cancellationToken = default)
242
        {
243
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsForMember(memberId), cancellationToken);
1✔
244
        }
1✔
245

246
        /// <summary>
247
        /// Get all Cards a Member is on (across multiple boards)
248
        /// </summary>
249
        /// <param name="memberId">Id of Member</param>
250
        /// <param name="options">Options on how and what should be included on the cards (Example only a few fields to increase performance or more nested data to avoid more API calls)</param>
251
        /// <param name="cancellationToken">Cancellation Token</param>
252
        /// <returns></returns>
253
        public async Task<List<Card>> GetCardsForMemberAsync(string memberId, GetCardOptions options, CancellationToken cancellationToken = default)
254
        {
255
            return await _apiRequestController.Get<List<Card>>(GetUrlBuilder.GetCardsForMember(memberId), cancellationToken, options.GetParameters());
×
256
        }
×
257

258
        /// <summary>
259
        /// Set Due Date on a card
260
        /// </summary>
261
        /// <param name="cardId">Id of the Card</param>
262
        /// <param name="dueDate">The Due Date (In UTC Time)</param>
263
        /// <param name="dueComplete">If Due is complete</param>
264
        /// <param name="cancellationToken">Cancellation Token</param>
265
        public async Task<Card> SetDueDateOnCardAsync(string cardId, DateTimeOffset dueDate, bool dueComplete = false, CancellationToken cancellationToken = default)
266
        {
267
            return await UpdateCardAsync(cardId, new List<QueryParameter>
1✔
268
            {
1✔
269
                new QueryParameter(CardFieldsType.Due.GetJsonPropertyName(), dueDate),
1✔
270
                new QueryParameter(CardFieldsType.DueComplete.GetJsonPropertyName(), dueComplete)
1✔
271
            }, cancellationToken);
1✔
272
        }
1✔
273

274
        /// <summary>
275
        /// Set Due Date on a card
276
        /// </summary>
277
        /// <param name="cardId">Id of the Card</param>
278
        /// <param name="startDate">The Start Date (In UTC Time)</param>
279
        /// <param name="cancellationToken">Cancellation Token</param>
280
        public async Task<Card> SetStartDateOnCardAsync(string cardId, DateTimeOffset startDate, CancellationToken cancellationToken = default)
281
        {
282
            return await UpdateCardAsync(cardId, new List<QueryParameter>
1✔
283
            {
1✔
284
                new QueryParameter(CardFieldsType.Start.GetJsonPropertyName(), startDate)
1✔
285
            }, cancellationToken);
1✔
286
        }
1✔
287

288
        /// <summary>
289
        /// Set Start and Due Date on a card
290
        /// </summary>
291
        /// <param name="cardId">Id of the Card</param>
292
        /// <param name="startDate">The Start Date (In UTC Time)</param>
293
        /// <param name="dueDate">The Due Date (In UTC Time)</param>
294
        /// <param name="dueComplete">If Due is complete</param>
295
        /// <param name="cancellationToken">Cancellation Token</param> 
296
        public async Task<Card> SetStartDateAndDueDateOnCardAsync(string cardId, DateTimeOffset startDate, DateTimeOffset dueDate, bool dueComplete = false, CancellationToken cancellationToken = default)
297
        {
298
            return await UpdateCardAsync(cardId, new List<QueryParameter>
1✔
299
            {
1✔
300
                new QueryParameter(CardFieldsType.Start.GetJsonPropertyName(), startDate),
1✔
301
                new QueryParameter(CardFieldsType.Due.GetJsonPropertyName(), dueDate),
1✔
302
                new QueryParameter(CardFieldsType.DueComplete.GetJsonPropertyName(), dueComplete),
1✔
303
            }, cancellationToken);
1✔
304
        }
1✔
305

306
        /// <summary>
307
        /// Move a Card to a new list on the same board
308
        /// </summary>
309
        /// <param name="cardId">Id of the Card</param>
310
        /// <param name="newListId">Id of the List you wish to move it to</param>
311
        /// <param name="cancellationToken">Cancellation Token</param>
312
        /// <returns></returns>
313
        public async Task<Card> MoveCardToListAsync(string cardId, string newListId, CancellationToken cancellationToken = default)
314
        {
315
            return await UpdateCardAsync(cardId, new List<QueryParameter>
1✔
316
            {
1✔
317
                new QueryParameter(CardFieldsType.ListId.GetJsonPropertyName(), newListId)
1✔
318
            }, cancellationToken);
1✔
319
        }
1✔
320

321
        /// <summary>
322
        /// Move a Card to a new list on the same board
323
        /// </summary>
324
        /// <param name="cardId">Id of the Card</param>
325
        /// <param name="newListId">Id of the List you wish to move it to</param>
326
        /// <param name="options">Additional optional Options for the Move</param>
327
        /// <param name="cancellationToken">Cancellation Token</param>
328
        /// <returns></returns>
329
        public async Task<Card> MoveCardToListAsync(string cardId, string newListId, MoveCardToListOptions options, CancellationToken cancellationToken = default)
330
        {
NEW
331
            var parameters = new List<QueryParameter> { new QueryParameter(CardFieldsType.ListId.GetJsonPropertyName(), newListId) };
×
NEW
332
            if (options.NamedPositionOnNewList.HasValue)
×
333
            {
NEW
334
                switch (options.NamedPositionOnNewList.Value)
×
335
                {
336
                    case NamedPosition.Top:
NEW
337
                        parameters.Add(new QueryParameter("pos", "top"));
×
NEW
338
                        break;
×
339
                    case NamedPosition.Bottom:
NEW
340
                        parameters.Add(new QueryParameter("pos", "bottom"));
×
NEW
341
                        break;
×
342
                }
343
            }
NEW
344
            else if (options.PositionOnNewList.HasValue)
×
345
            {
NEW
346
                parameters.Add(new QueryParameter(CardFieldsType.Position.GetJsonPropertyName(), options.PositionOnNewList.Value));
×
347
            }
348

NEW
349
            return await UpdateCardAsync(cardId, parameters, cancellationToken);
×
NEW
350
        }
×
351

352
        /// <summary>
353
        /// Update one or more specific fields on a card (compared to a full update of all fields with UpdateCard)
354
        /// </summary>
355
        /// <param name="cardId">Id of the Card</param>
356
        /// <param name="parameters">The Specific Parameters to set</param>
357
        /// <param name="cancellationToken">CancellationToken</param>
358
        public async Task<Card> UpdateCardAsync(string cardId, List<QueryParameter> parameters, CancellationToken cancellationToken = default)
359
        {
360
            QueryParameter coverParameter = parameters.FirstOrDefault(x => x.Name == "cover");
78✔
361
            if (coverParameter != null && !string.IsNullOrWhiteSpace(coverParameter.GetRawStringValue()))
33✔
362
            {
363
                parameters.Remove(coverParameter);
1✔
364
                CardCover cover = JsonSerializer.Deserialize<CardCover>(coverParameter.GetRawStringValue());
1✔
365
                var payload = GeneratePayloadForCoverUpdate(cover, parameters);
1✔
366
                return await _apiRequestController.PutWithJsonPayload<Card>($"{UrlPaths.Cards}/{cardId}", cancellationToken, payload, parameters.ToArray());
1✔
367
            }
368

369
            //Special Cover Card
370
            return await _apiRequestController.Put<Card>($"{UrlPaths.Cards}/{cardId}", cancellationToken, parameters.ToArray());
32✔
371
        }
33✔
372

373
        /// <summary>
374
        /// Move the Card to the top of its current list
375
        /// </summary>
376
        /// <param name="cardId">Id of the Card</param>
377
        /// <param name="cancellationToken">Cancellation Token</param>
378
        /// <returns>The Card</returns>
379
        public async Task<Card> MoveCardToTopOfCurrentListAsync(string cardId, CancellationToken cancellationToken = default)
380
        {
NEW
381
            return await UpdateCardAsync(cardId, new List<QueryParameter>
×
NEW
382
            {
×
NEW
383
                new QueryParameter(CardFieldsType.Position.GetJsonPropertyName(), "top")
×
NEW
384
            }, cancellationToken);
×
NEW
385
        }
×
386

387
        /// <summary>
388
        /// Move the Card to the bottom of its current list
389
        /// </summary>
390
        /// <param name="cardId">Id of the Card</param>
391
        /// <param name="cancellationToken">Cancellation Token</param>
392
        /// <returns>The Card</returns>
393
        public async Task<Card> MoveCardToBottomOfCurrentListAsync(string cardId, CancellationToken cancellationToken = default)
394
        {
NEW
395
            return await UpdateCardAsync(cardId, new List<QueryParameter>
×
NEW
396
            {
×
NEW
397
                new QueryParameter(CardFieldsType.Position.GetJsonPropertyName(), "bottom")
×
NEW
398
            }, cancellationToken);
×
NEW
399
        }
×
400

401
        /// <summary>
402
        /// Move a Card to another board
403
        /// </summary>
404
        /// <param name="cardId">The Id of the Card to Move</param>
405
        /// <param name="newBoardId">The ID of the New Board that the card should be moved to</param>
406
        /// <param name="options">Additional Options for the move like what list the card should end up on the new board and what happens to labels and members</param>
407
        /// <param name="cancellationToken">Cancellation Token</param>
408
        /// <returns></returns>
409
        public async Task<Card> MoveCardToBoard(string cardId, string newBoardId, MoveCardToBoardOptions options, CancellationToken cancellationToken = default)
410
        {
NEW
411
            if (options == null)
×
412
            {
NEW
413
                throw new ArgumentNullException(nameof(options), "You need to pass an options object to confirm the various options that are invovled with moving a card between boards");
×
414
            }
415

NEW
416
            List<QueryParameter> parameters = new List<QueryParameter> { new QueryParameter(CardFieldsType.BoardId.GetJsonPropertyName(), newBoardId) };
×
NEW
417
            var newListId = options.NewListId;
×
NEW
418
            if (string.IsNullOrWhiteSpace(newListId))
×
419
            {
420
                //No list specified, so we need to find the first list on the board
NEW
421
                newListId = (await GetListsOnBoardAsync(newBoardId, cancellationToken)).OrderBy(x => x.Position).FirstOrDefault()?.Id;
×
422
            }
423

NEW
424
            parameters.Add(new QueryParameter(CardFieldsType.ListId.GetJsonPropertyName(), newListId));
×
425

NEW
426
            if (options.NamedPositionOnNewList.HasValue)
×
427
            {
NEW
428
                switch (options.NamedPositionOnNewList.Value)
×
429
                {
430
                    case NamedPosition.Top:
NEW
431
                        parameters.Add(new QueryParameter("pos", "top"));
×
NEW
432
                        break;
×
433
                    case NamedPosition.Bottom:
NEW
434
                        parameters.Add(new QueryParameter("pos", "bottom"));
×
NEW
435
                        break;
×
436
                }
437
            }
NEW
438
            else if (options.PositionOnNewList.HasValue)
×
439
            {
NEW
440
                parameters.Add(new QueryParameter(CardFieldsType.Position.GetJsonPropertyName(), options.PositionOnNewList.Value));
×
441
            }
442

NEW
443
            Card card = await GetCardAsync(cardId, new GetCardOptions
×
NEW
444
            {
×
NEW
445
                CardFields = new CardFields(CardFieldsType.MemberIds, CardFieldsType.LabelIds, CardFieldsType.Labels)
×
NEW
446
            }, cancellationToken);
×
447

NEW
448
            switch (options.MemberOptions)
×
449
            {
450
                case MoveCardToBoardOptionsMemberOptions.KeepMembersAlsoOnNewBoardAndRemoveRest:
NEW
451
                    var existingMemberIdsOnNewBoard = (await GetMembersOfBoardAsync(newBoardId, cancellationToken)).Select(x => x.Id);
×
NEW
452
                    card.MemberIds = card.MemberIds.Intersect(existingMemberIdsOnNewBoard).ToList();
×
NEW
453
                    break;
×
454
                case MoveCardToBoardOptionsMemberOptions.RemoveAllMembersOnCard:
NEW
455
                    card.MemberIds.Clear();
×
NEW
456
                    break;
×
457
                default:
NEW
458
                    throw new ArgumentOutOfRangeException();
×
459
            }
460

NEW
461
            if (card.LabelIds.Any())
×
462
            {
NEW
463
                card.LabelIds.Clear();
×
NEW
464
                switch (options.LabelOptions)
×
465
                {
466
                    case MoveCardToBoardOptionsLabelOptions.MigrateToLabelsOfSameNameAndColorAndCreateMissing:
467
                    {
NEW
468
                        var existingLabels = await GetLabelsOfBoardAsync(newBoardId, cancellationToken);
×
NEW
469
                        foreach (Label cardLabel in card.Labels)
×
470
                        {
NEW
471
                            Label existingLabel = existingLabels.FirstOrDefault(x => x.Name == cardLabel.Name && x.Color == cardLabel.Color);
×
NEW
472
                            if (existingLabel != null)
×
473
                            {
NEW
474
                                card.LabelIds.Add(existingLabel.Id);
×
475
                            }
476
                            else
477
                            {
478
                                //Label need to be added
NEW
479
                                Label newLabel = await AddLabelAsync(new Label(newBoardId, cardLabel.Name, cardLabel.Color), cancellationToken);
×
NEW
480
                                card.LabelIds.Add(newLabel.Id);
×
481
                            }
482
                        }
483

NEW
484
                        break;
×
485
                    }
486
                    case MoveCardToBoardOptionsLabelOptions.MigrateToLabelsOfSameNameAndColorAndRemoveMissing:
487
                    {
NEW
488
                        var existingLabels = await GetLabelsOfBoardAsync(newBoardId, cancellationToken);
×
NEW
489
                        foreach (Label cardLabel in card.Labels)
×
490
                        {
NEW
491
                            Label existingLabel = existingLabels.FirstOrDefault(x => x.Name == cardLabel.Name && x.Color == cardLabel.Color);
×
NEW
492
                            if (existingLabel != null)
×
493
                            {
NEW
494
                                card.LabelIds.Add(existingLabel.Id);
×
495
                            }
496
                        }
497

498
                        break;
499
                    }
500
                    case MoveCardToBoardOptionsLabelOptions.MigrateToLabelsOfSameNameAndCreateMissing:
501
                    {
NEW
502
                        var existingLabels = await GetLabelsOfBoardAsync(newBoardId, cancellationToken);
×
NEW
503
                        foreach (Label cardLabel in card.Labels)
×
504
                        {
NEW
505
                            Label existingLabel = existingLabels.FirstOrDefault(x => x.Name == cardLabel.Name);
×
NEW
506
                            if (existingLabel != null)
×
507
                            {
NEW
508
                                card.LabelIds.Add(existingLabel.Id);
×
509
                            }
510
                            else
511
                            {
512
                                //Label need to be added
NEW
513
                                Label newLabel = await AddLabelAsync(new Label(newBoardId, cardLabel.Name, cardLabel.Color), cancellationToken);
×
NEW
514
                                card.LabelIds.Add(newLabel.Id);
×
515
                            }
516
                        }
517

NEW
518
                        break;
×
519
                    }
520
                    case MoveCardToBoardOptionsLabelOptions.MigrateToLabelsOfSameNameAndRemoveMissing:
521
                    {
NEW
522
                        var existingLabels = await GetLabelsOfBoardAsync(newBoardId, cancellationToken);
×
NEW
523
                        foreach (Label cardLabel in card.Labels)
×
524
                        {
NEW
525
                            Label existingLabel = existingLabels.FirstOrDefault(x => x.Name == cardLabel.Name);
×
NEW
526
                            if (existingLabel != null)
×
527
                            {
NEW
528
                                card.LabelIds.Add(existingLabel.Id);
×
529
                            }
530
                        }
531

532
                        break;
533
                    }
534
                    case MoveCardToBoardOptionsLabelOptions.RemoveAllLabelsOnCard:
535
                        //No more Work needed
536
                        break;
537
                    default:
NEW
538
                        throw new ArgumentOutOfRangeException();
×
539
                }
540
            }
541

NEW
542
            parameters.Add(new QueryParameter(CardFieldsType.LabelIds.GetJsonPropertyName(), card.LabelIds));
×
NEW
543
            parameters.Add(new QueryParameter(CardFieldsType.MemberIds.GetJsonPropertyName(), card.MemberIds));
×
544

NEW
545
            if (options.RemoveDueDate)
×
546
            {
NEW
547
                parameters.Add(new QueryParameter(CardFieldsType.Due.GetJsonPropertyName(), (DateTimeOffset?)null));
×
548
            }
549

NEW
550
            if (options.RemoveStartDate)
×
551
            {
NEW
552
                parameters.Add(new QueryParameter(CardFieldsType.Start.GetJsonPropertyName(), (DateTimeOffset?)null));
×
553
            }
554

NEW
555
            return await UpdateCardAsync(cardId, parameters, cancellationToken);
×
NEW
556
        }
×
557
    }
558
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc