/// <summary> /// Simply create a dictionary of substitution values from all the fields /// of the work item. /// </summary> /// <param name="workItem"></param> /// <returns></returns> private Dictionary <String, Object> CreateDictionaryFromWorkItem(WorkItem workItem) { var retValue = new Dictionary <String, Object>(StringComparer.OrdinalIgnoreCase); retValue["title"] = workItem.Title; retValue["id"] = workItem.Id; //Some help to avoid forcing the user to use System.AssignedTo etc for most commonly used fields. retValue["description"] = new HtmlSubstitution(workItem.EmbedHtmlContent(workItem.Description)); retValue["assignedto"] = workItem.Fields["System.AssignedTo"].Value?.ToString() ?? String.Empty; retValue["createdby"] = workItem.Fields["System.CreatedBy"].Value?.ToString() ?? String.Empty; HashSet <String> specialFields = new HashSet <string>(StringComparer.OrdinalIgnoreCase) { "description", }; //All the fields will be set in raw format. foreach (Field field in workItem.Fields) { if (specialFields.Contains(field.Name)) { continue; //This is a special field, ignore. } var value = GetValue(field); retValue[field.Name] = field.Value?.ToString() ?? String.Empty; retValue[field.ReferenceName] = field.Value?.ToString() ?? String.Empty; } //ok some of the historical value could be of interests, as an example the last user timestamp for each state change //is an information that can be interesting if (workItem.Revisions.Count > 0) { foreach (Revision revision in workItem.Revisions) { var fieldsChanged = revision .Fields .OfType <Field>() .Where(f => f.IsChangedInRevision) .ToList(); var changedBy = revision.Fields["Changed By"].Value; var changedDate = revision.Fields["Changed Date"].Value; foreach (var field in fieldsChanged) { if (field.ReferenceName.Equals("system.state", StringComparison.OrdinalIgnoreCase)) { retValue[$"statechange.{field.Value.ToString().ToLower()}.author"] = changedBy; retValue[$"statechange.{field.Value.ToString().ToLower()}.date"] = ((DateTime)changedDate).ToShortDateString(); } else if (field.ReferenceName.Equals("system.areapath", StringComparison.OrdinalIgnoreCase)) { retValue[$"lastareapathchange.author"] = changedBy; retValue[$"lastareapathchange.date"] = ((DateTime)changedDate).ToShortDateString(); } } } } return(retValue); }
/// <summary> /// From a <see cref="WorkItem"/> creates a dictionary with the name of the field as key and /// value of the field as value. Some special fields, like description, are converted to html /// images are downloaded and embedded (if requested). /// </summary> /// <param name="workItem"></param> /// <param name="dictionary"></param> /// <param name="prefix"></param> /// <param name="skipHtmlFields">If true, the caller does not want to retrieve HTML field /// with full content, like images embedded. It is true when we are creating dictionary for /// excel, since we cannot embed images in excel.</param> public static void FillPropertyDictionary( this WorkItem workItem, Dictionary <string, object> dictionary, String prefix, Boolean skipHtmlFields) { Log.Logger.Debug("Filling dictionary information for work item {id}", workItem.Id); var tempDictionary = new Dictionary <String, Object>(); tempDictionary["title"] = workItem.Title; tempDictionary["id"] = workItem.Id; //Some help to avoid forcing the user to use System.AssignedTo etc for most commonly used fields. if (skipHtmlFields) { tempDictionary["description"] = GetTxtFromHtmlContent(workItem.Description); } else { tempDictionary["description"] = new HtmlSubstitution(workItem.GenerateHtmlForWordEmbedding(workItem.Description, Registry.Options.NormalizeFontInDescription)); } tempDictionary["description.txt"] = GetTxtFromHtmlContent(workItem.Description); tempDictionary["assignedto"] = workItem.Fields["System.AssignedTo"].Value?.ToString() ?? String.Empty; tempDictionary["createdby"] = workItem.Fields["System.CreatedBy"].Value?.ToString() ?? String.Empty; HashSet <String> specialFields = new HashSet <string>(StringComparer.OrdinalIgnoreCase) { "description", }; //All the fields will be set in raw format. foreach (Field field in workItem.Fields) { if (specialFields.Contains(field.Name)) { continue; //This is a special field, ignore. } tempDictionary[field.Name] = tempDictionary[field.ReferenceName] = GetValue(field); } var comments = ConnectionManager.Instance .WorkItemTrackingHttpClient .GetCommentsAsync(workItem.Id).Result; if (comments.Count > 0) { StringBuilder htmlComment = new StringBuilder(); foreach (var comment in comments.Comments) { htmlComment.Append($"<b>Author:</b>{comment.RevisedBy.Name} in date {comment.RevisedDate.ToString("yyyy/MM/dd hh:mm")}"); htmlComment.Append("<br>"); htmlComment.Append(comment.Text); } if (skipHtmlFields) { tempDictionary["comments"] = GetTxtFromHtmlContent(htmlComment.ToString()); } else { var commentsInHtml = workItem.GenerateHtmlForWordEmbedding(htmlComment.ToString(), Registry.Options.NormalizeFontInDescription); tempDictionary["comments"] = new HtmlSubstitution(commentsInHtml); } } else { tempDictionary["comments"] = ""; } //ok some of the historical value could be of interests, as an example the last user timestamp for each state change //is an information that can be interesting if (workItem.Revisions.Count > 0) { foreach (Revision revision in workItem.Revisions) { var fieldsChanged = revision .Fields .OfType <Field>() .Where(f => f.IsChangedInRevision) .ToList(); var changedBy = revision.Fields["Changed By"].Value; var changedDate = revision.Fields["Changed Date"].Value; foreach (var field in fieldsChanged) { if (field.ReferenceName.Equals("system.state", StringComparison.OrdinalIgnoreCase)) { tempDictionary[$"statechange.{field.Value.ToString().ToLower()}.author"] = changedBy; tempDictionary[$"statechange.{field.Value.ToString().ToLower()}.date"] = ((DateTime)changedDate).ToShortDateString(); } else if (field.ReferenceName.Equals("system.areapath", StringComparison.OrdinalIgnoreCase)) { tempDictionary["lastareapathchange.author"] = changedBy; tempDictionary["lastareapathchange.date"] = ((DateTime)changedDate).ToShortDateString(); } } } } foreach (var element in tempDictionary) { dictionary[$"{prefix}{element.Key}"] = element.Value; } }