Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / WPF

Microsoft Office Addins (Outlook & Project) for YouTrack

4.89/5 (4 votes)
5 Feb 2015CPOL3 min read 17.3K   245  
Create YouTrack issues from Outlook and manage your issues from Microsoft Project

Introduction

JetBrains' YouTrack issue tracker is a fantastic tool. Here are 2 Microsoft Office Add-ins to facilitate the work of the support people who receive e-mails that have to be entered in YouTrack or the project manager who does not want to synchronize manually YouTrack issues and Microsoft Project Tasks.

Using the Code

Warnings

  1. The code of the sample project is unfortunately not great: I'm now IT Manager and don't have the luxury to make it perfect. Please accept all my apologies for the hard-coded bits ;-)
  2. The Outlook Add-in was created using the VSTO for Office 10. The Microsoft Project Add-in uses VSTO for Office 13.
  3. This code contained in the zip file won't probably even compile in your environment. It is intended to help you reduce the waste of time that involves understanding 2 world-apart technologies. Therefore, please take it as a copy-paste source!
  4. The Microsoft Project Add-in assumes that you are using LDAP /AD integration on both sides.
  5. YouTrack services are provided by the YouTrackSharp project from Hadi Hariri (many, many thanks to him). Unfortunately, this project and its dependencies are not Strongly Signed which lead me to get the sources and include them in the attached solution for signing.
  6. I did not manage to use the "Attachment" feature of YouTrackSharp. So I implemented a work around (leading to use mixed technics in the same project) which I'm not particularly proud of...

Outlook Add-in

  1. Create a project for Outlook
  2. Add a Ribbon and change the property OfficeRibbon.RibbonType for Microsoft.Outlook.Mail.Read.
  3. Change the property of the Ribbon RibbonTab.ControlId.ControlIdType for Office and RibbonTab.ControlId.OfficeId for TabReadMessage.
  4. To create a YouTrack Issue from a Mail, you can do the following:

    First, add a Button to the Ribbon and implement the Click event:

    C#
    using Microsoft.Office.Interop.MSProject;
    using Microsoft.Office.Tools.Ribbon;

    Then, store the elements of the Mail into a MailItem object:

    C#
    Application application = Globals.ThisAddIn.Application;
    Inspector inspector = application.ActiveInspector();
    MailItem myMailItem = (MailItem) inspector.CurrentItem;
    
    string mailSubject = myMailItem.Subject;
    string mailBody = myMailItem.Body;
    IEnumerable<Attachment> attachments = myMailItem.Attachments.Cast<Attachment>();
    
    string localTempDirectory = string.Concat(Environment.GetFolderPath
                    (Environment.SpecialFolder.ApplicationData),
                                    @"\TempYouTrackAttachments\",
                                    Guid.NewGuid(),
                                    "\\");
    Directory.CreateDirectory(localTempDirectory);
    
    //Save all the attachments in the temp directory
    List<MailAttachment> mailAttachments = new List<MailAttachment>();
    
    foreach (Attachment attachment in attachments)
    {
        MailAttachment mailAttachment = new MailAttachment();
        mailAttachments.Add(mailAttachment);
        mailAttachment.DisplayName = attachment.DisplayName;
        mailAttachment.FilePath = string.Concat(localTempDirectory, attachment.FileName);
        attachment.SaveAsFile(mailAttachment.FilePath);
    }
    
    //Save the mail itself in the temp directory
    MailAttachment mail = new MailAttachment();
    mailAttachments.Add(mail);
    mail.DisplayName = "Mail";
    mail.FilePath = string.Concat(localTempDirectory, "Mail.msg");
    myMailItem.SaveAs(mail.FilePath);

    Finally, call the user interface that will allow you to define your new YouTrack Issue:

    C#
    IConnection connection = new Connection("[YouTrack server]", 80);
    ProjectManagement projectManagement = new ProjectManagement(connection); 
        IssueManagement issueManagement = new IssueManagement(connection);
    
    IssueCreationViewModel viewModel = new IssueCreationViewModel
        (projectManagement, issueManagement, mailSubject, mailBody, mailAttachments);
    
    IssueCreationView view = new IssueCreationView(); view.ViewModel = viewModel; view.ShowDialog();

    Once the user interface closes, we'll delete the temporary directory containing the attachments:

    C#
    Directory.Delete(localTempDirectory, true);
  5. The user interface is initialized as such:
    C#
    Projects = _projectManagement.GetProjects();
    IssueTypes = _projectManagement.GetIssueTypes();
    Priorities = _projectManagement.GetPriorities();
    
    SelectedIssueType = IssueTypes.First();
    SelectedPriority = Priorities.First(p => p.Name == "Normal");

    Note that the Assignees depend on the Project. Therefore it is queried each time the selected project changes.

  6. This is how we create the new Issue:
    C#
    dynamic issue = new Issue();
    if (SelectedAssignee != null)
        issue.Assignee = SelectedAssignee.Login;
    
    issue.Summary = Summary;
    issue.Description = Description;
    issue.ProjectShortName = SelectedProject.ShortName;
    issue.Type = SelectedIssueType;
    issue.Department = SelectedDepartment.Value;
    issue.State = "Submitted";
    
    string issueId = _issueManagement.CreateIssue(issue);
    
    foreach (MailAttachment attachment in Attachments)
    _issueManagement.AttachFileToIssue(issueId, attachment.FilePath);

Microsoft Project Add-in

  1. Create a project for Microsoft Project
  2. Add a Ribbon and with the property OfficeRibbon.RibbonType set to Microsoft.Project.Project.
  3. Change the property of the Ribbon RibbonTab.ControlId.ControlIdType for Office and RibbonTab.ControlId.OfficeId for TabTask.
  4. To sync the Issue from YouTrack to Microsoft Project, you can do the following:

    First, add a Button to the Ribbon and implement the Click event.

    C#
    using Microsoft.Office.Interop.MSProject;
    using Microsoft.Office.Tools.Ribbon;
    
    //Get Issues from YouTrack
    IConnection connection = new Connection("[YouTrack server]", 80);
    IssueManagement issueManagement = new IssueManagement(connection); 
    IEnumerable<Issue> issues = issueManagement.GetAllIssuesForProject("[my project code]");

    I'm using the following Microsoft Project fields to store YouTrack information:

    Microsoft Project YouTrack Comment
    Text1 Id Issue Id
    Work Estimation Estimation that will change through Microsoft Project changes
    Duration2 Estimation Initial Estimation that stays fix for further comparison
    Name Summary  
    ResourceNames AssigneeName  
    ActualWork SpentTime Time tracked in YouTrack

    Now, let's update Microsoft Project:

    C#
    //Get the MS Project Tasks Application application = Globals.ThisAddIn.Application;
    Project project = application.ActiveProject; 
    List<Task> tasks = project.Tasks.Cast<Task>().ToList();
    
    //For Each YouTrack Issue, we try to get the corresponding MS Project Task 
    //If none is found, we create one. 
    foreach (dynamic issue in issues) 
    {
         Task task = tasks.FirstOrDefault(t => t.Text1 == issue.Id);
    
         if (task == null) 
         {
             task = project.Tasks.Add();
             task.Text1 = issue.Id;
             task.Manual = false;
             task.Work = Convert.ToDouble(issue.Estimation);
             task.Duration2 = task.Work;
         }
    
         task.Name = issue.Summary;
         task.ResourceNames = GetResourceName(issue.AssigneeName); 
         task.ActualWork = Convert.ToDouble(issue.SpentTime); 
    }

    With the function GetResourceName defined as:

    C#
    private string GetResourceName(string assignee)
    {
         if (assignee == null)
              return string.Empty;
    
         Application application = Globals.ThisAddIn.Application;
         Project project = application.ActiveProject;
         List<Resource> resources = project.Resources.Cast<Resource>().ToList();
    
         Resource resource = resources.FirstOrDefault
        (r => r.WindowsUserAccount.ToLower().Contains(assignee));
         return resource != null? resource.Name : string.Empty;
    }
  5. To sync the Issue from Microsoft Project to YouTrack , you can do the following:

    I'm using the following YouTrack fields to store Microsoft Project information:

    YouTrack MS Project Comment
    Planned start date Start Custom YouTrack field
    Target date Finish Custom YouTrack field
    Assignee Resources[0]  

Now, let's update YouTrack:

C#
Application application = Globals.ThisAddIn.Application;
Project project = application.ActiveProject;

foreach (Task task in project.Tasks) 
{
     string issueId = task.Text1;

     if (string.IsNullOrEmpty(issueId))
           continue;

     // The POST method allows updating issue summary and/or description, only. 
     // To update issue fields, we need to apply a Command to the Isse.
      string command = string.Format("Planned Start Date {0} Target date {1} Assignee {2}",
      ((DateTime) task.Start).ToString("yyyy-MM-dd"),
      ((DateTime) task.Finish).ToString("yyyy-MM-dd"),
      GetYoutrackAssigneeName(task.Resources));

     issueManagement.ApplyCommand(issueId,command,"MS Project Update",true); }

With the function GetYoutrackAssigneeName defined as:

C#
private string GetYoutrackAssigneeName(Resources resources) 
{
     if (resources.Count == 0)
           return "Unassigned";

     Resource resource = resources.Cast<Resource>().First();
     string userAccountName = resource.WindowsUserAccount.Split('\\').GetValue(1).ToString();

     return userAccountName;
}

That's it, job done!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)