void IssueList_UpdateItem(ListViewItem Item, IssueData Issue, DateTime Midnight)
 {
     Item.SubItems[IdHeader.Index].Text          = Issue.Id.ToString();
     Item.SubItems[CreatedHeader.Index].Text     = FormatIssueDateTime(Issue.CreatedAt.ToLocalTime(), Midnight);
     Item.SubItems[ResolvedHeader.Index].Text    = Issue.ResolvedAt.HasValue ? FormatIssueDateTime(Issue.ResolvedAt.Value.ToLocalTime(), Midnight) : "Unresolved";
     Item.SubItems[TimeToFixHeader.Index].Text   = Issue.ResolvedAt.HasValue ? Utility.FormatDurationMinutes(Issue.ResolvedAt.Value - Issue.CreatedAt) : "-";
     Item.SubItems[OwnerHeader.Index].Text       = (Issue.Owner == null) ? "-" : Utility.FormatUserName(Issue.Owner);
     Item.SubItems[DescriptionHeader.Index].Text = Issue.Summary;
 }
Exemple #2
0
        public IssueAlertWindow(IssueMonitor IssueMonitor, IssueData Issue, IssueAlertReason Reason)
        {
            this.IssueMonitor = IssueMonitor;
            this.Issue        = Issue;

            InitializeComponent();

            SetIssue(Issue, Reason);
        }
        private void IssueListView_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            ListViewHitTestInfo HitTest = IssueListView.HitTest(e.Location);

            if (HitTest.Item != null)
            {
                IssueData Issue = (IssueData)HitTest.Item.Tag;
                ShowIssue(Issue);
            }
        }
        void IssueList_InsertItem(int ItemIdx, IssueData Issue, DateTime Midnight)
        {
            ListViewItem Item = new ListViewItem("");

            for (int Idx = 0; Idx < IssueListView.Columns.Count - 1; Idx++)
            {
                Item.SubItems.Add("");
            }
            Item.Tag = Issue;
            IssueList_UpdateItem(Item, Issue, Midnight);
            IssueListView.Items.Insert(ItemIdx, Item);
        }
        void UpdateIssueList()
        {
            // Get the time at midnight
            DateTime Now      = DateTime.Now;
            DateTime Midnight = (Now - Now.TimeOfDay).ToUniversalTime();

            // Update the table
            int ItemIdx = 0;

            IssueListView.BeginUpdate();
            foreach (IssueData Issue in Issues)
            {
                if (FilterProjectName == null || Issue.Project == FilterProjectName)
                {
                    for (;;)
                    {
                        if (ItemIdx == IssueListView.Items.Count)
                        {
                            IssueList_InsertItem(ItemIdx, Issue, Midnight);
                            break;
                        }

                        ListViewItem ExistingItem  = IssueListView.Items[ItemIdx];
                        IssueData    ExistingIssue = (IssueData)ExistingItem.Tag;
                        if (ExistingIssue == null || ExistingIssue.Id < Issue.Id)
                        {
                            IssueList_InsertItem(ItemIdx, Issue, Midnight);
                            break;
                        }
                        else if (ExistingIssue.Id == Issue.Id)
                        {
                            IssueList_UpdateItem(ExistingItem, Issue, Midnight);
                            break;
                        }
                        else
                        {
                            IssueListView.Items.RemoveAt(ItemIdx);
                            continue;
                        }
                    }
                    ItemIdx++;
                }
            }
            while (ItemIdx < IssueListView.Items.Count)
            {
                IssueListView.Items.RemoveAt(ItemIdx);
            }
            IssueListView.EndUpdate();

            // Update the maximum number of results
            StatusLabel.Text = (IssueListView.Items.Count == Issues.Count)? String.Format("Showing {0} results matching project '{1}'.", Issues.Count, FilterProjectName) : String.Format("Showing {0}/{1} results matching project '{2}'.", IssueListView.Items.Count, Issues.Count, FilterProjectName);
        }
 private void ShowIssue(IssueData Issue)
 {
     try
     {
         Issue.Builds = RESTApi.GET <List <IssueBuildData> >(IssueMonitor.ApiUrl, String.Format("issues/{0}/builds", Issue.Id));
     }
     catch (Exception Ex)
     {
         MessageBox.Show(Owner, Ex.ToString(), "Error querying builds", MessageBoxButtons.OK);
         return;
     }
     IssueDetailsWindow.Show(Owner, IssueMonitor, ServerAndPort, UserName, ServerTimeOffset, Issue, Log, CurrentStream);
 }
        private void IssueListView_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
        {
            IssueData Issue = (IssueData)e.Item.Tag;

            if (e.ColumnIndex == IconHeader.Index)
            {
                if (!Issue.ResolvedAt.HasValue && Issue.FixChange == 0)
                {
                    IssueListView.DrawIcon(e.Graphics, e.Bounds, WorkspaceControl.BadBuildIcon);
                }
                else
                {
                    IssueListView.DrawIcon(e.Graphics, e.Bounds, WorkspaceControl.GoodBuildIcon);
                }
            }
            else
            {
                IssueListView.DrawNormalSubItem(e);
            }
        }
Exemple #8
0
        static bool ApplyPendingUpdate(List <IssueData> Issues, IssueUpdateData Update)
        {
            bool bUpdated = false;

            for (int Idx = 0; Idx < Issues.Count; Idx++)
            {
                IssueData Issue = Issues[Idx];
                if (Update.Id == Issue.Id)
                {
                    if (Update.Owner != null && Update.Owner != Issue.Owner)
                    {
                        Issue.Owner = Update.Owner;
                        bUpdated    = true;
                    }
                    if (Update.NominatedBy != null && Update.NominatedBy != Issue.NominatedBy)
                    {
                        Issue.NominatedBy = Update.NominatedBy;
                        bUpdated          = true;
                    }
                    if (Update.Acknowledged.HasValue && Update.Acknowledged.Value != Issue.AcknowledgedAt.HasValue)
                    {
                        Issue.AcknowledgedAt = Update.Acknowledged.Value? (DateTime?)DateTime.UtcNow : null;
                        bUpdated             = true;
                    }
                    if (Update.FixChange.HasValue)
                    {
                        Issue.FixChange = Update.FixChange.Value;
                        if (Issue.FixChange != 0)
                        {
                            Issues.RemoveAt(Idx);
                        }
                        bUpdated = true;
                    }
                    break;
                }
            }
            return(bUpdated);
        }
        private void IssueListView_DrawItem(object sender, DrawListViewItemEventArgs e)
        {
            if (e.Item.Selected)
            {
                IssueListView.DrawSelectedBackground(e.Graphics, e.Bounds);
            }
            else if (e.ItemIndex == IssueListView.HoverItem)
            {
                IssueListView.DrawTrackedBackground(e.Graphics, e.Bounds);
            }
            else if (e.Item.Tag is IssueData)
            {
                IssueData Issue = (IssueData)e.Item.Tag;

                Color BackgroundColor;
                if (Issue.ResolvedAt.HasValue)
                {
                    BackgroundColor = SystemColors.Window;                    //Color.FromArgb(248, 254, 246);
                }
                else if (Issue.FixChange > 0)
                {
                    BackgroundColor = Color.FromArgb(245, 245, 245);
                }
                else
                {
                    BackgroundColor = Color.FromArgb(254, 248, 246);
                }

                using (SolidBrush Brush = new SolidBrush(BackgroundColor))
                {
                    e.Graphics.FillRectangle(Brush, e.Bounds);
                }
            }
            else
            {
                IssueListView.DrawDefaultBackground(e.Graphics, e.Bounds);
            }
        }
Exemple #10
0
        bool ReadCurrentIssues()
        {
            try
            {
                Stopwatch Timer = Stopwatch.StartNew();
                LogWriter.WriteLine();
                LogWriter.WriteLine("Polling for notifications at {0}...", DateTime.Now.ToString());

                // Get the initial number of issues. We won't post updates if this stays at zero.
                int InitialNumIssues = Issues.Count;

                // Fetch the new issues
                List <IssueData> NewIssues = RESTApi.GET <List <IssueData> >(ApiUrl, String.Format("issues?user={0}", UserName));

                // Check if we're tracking a particular issue. If so, we want updates even when it's resolved.
                long[] LocalTrackingIssueIds;
                lock (LockObject)
                {
                    LocalTrackingIssueIds = TrackingIssueIds.Distinct().ToArray();
                }
                foreach (long LocalTrackingIssueId in LocalTrackingIssueIds)
                {
                    if (!NewIssues.Any(x => x.Id == LocalTrackingIssueId))
                    {
                        try
                        {
                            IssueData Issue = RESTApi.GET <IssueData>(ApiUrl, String.Format("issues/{0}", LocalTrackingIssueId));
                            if (Issue != null)
                            {
                                NewIssues.Add(Issue);
                            }
                        }
                        catch (Exception Ex)
                        {
                            LogWriter.WriteException(Ex, "Exception while fetching tracked issue");
                        }
                    }
                }

                // Update all the builds for each issue
                foreach (IssueData NewIssue in NewIssues)
                {
                    NewIssue.Builds = RESTApi.GET <List <IssueBuildData> >(ApiUrl, String.Format("issues/{0}/builds", NewIssue.Id));
                }

                // Apply any pending updates to this issue list, and update it
                lock (LockObject)
                {
                    foreach (IssueUpdateData PendingUpdate in PendingUpdates)
                    {
                        ApplyPendingUpdate(NewIssues, PendingUpdate);
                    }
                    Issues = NewIssues;
                }

                // Update the main thread
                if (InitialNumIssues > 0 || Issues.Count > 0)
                {
                    if (OnIssuesChanged != null)
                    {
                        OnIssuesChanged();
                    }
                }

                // Update the stats
                LastStatusMessage = String.Format("Last update took {0}ms", Timer.ElapsedMilliseconds);
                LogWriter.WriteLine("Done in {0}ms.", Timer.ElapsedMilliseconds);
                return(true);
            }
            catch (Exception Ex)
            {
                LogWriter.WriteException(Ex, "Failed with exception.");
                LastStatusMessage = String.Format("Last update failed: ({0})", Ex.ToString());
                return(false);
            }
        }
Exemple #11
0
        public void SetIssue(IssueData NewIssue, IssueAlertReason NewReason)
        {
            bool bNewStrongAlert = false;

            StringBuilder OwnerTextBuilder = new StringBuilder();

            if (NewIssue.Owner == null)
            {
                OwnerTextBuilder.Append("Currently unassigned.");
            }
            else
            {
                if (String.Compare(NewIssue.Owner, IssueMonitor.UserName, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (NewIssue.NominatedBy != null)
                    {
                        OwnerTextBuilder.AppendFormat("You have been nominated to fix this issue by {0}.", Utility.FormatUserName(NewIssue.NominatedBy));
                    }
                    else
                    {
                        OwnerTextBuilder.AppendFormat("Assigned to {0}.", Utility.FormatUserName(NewIssue.Owner));
                    }
                    bNewStrongAlert = true;
                }
                else
                {
                    OwnerTextBuilder.AppendFormat("Assigned to {0}", Utility.FormatUserName(NewIssue.Owner));
                    if (NewIssue.NominatedBy != null)
                    {
                        OwnerTextBuilder.AppendFormat(" by {0}", Utility.FormatUserName(NewIssue.NominatedBy));
                    }
                    if (!NewIssue.AcknowledgedAt.HasValue && (NewReason & IssueAlertReason.UnacknowledgedTimer) != 0)
                    {
                        OwnerTextBuilder.Append(" (not acknowledged)");
                    }
                    OwnerTextBuilder.Append(".");
                }
            }
            OwnerTextBuilder.AppendFormat(" Open for {0}.", Utility.FormatDurationMinutes((int)(NewIssue.RetrievedAt - NewIssue.CreatedAt).TotalMinutes));
            string OwnerText = OwnerTextBuilder.ToString();

            bool bNewIsWarning = Issue.Builds.Count > 0 && !Issue.Builds.Any(x => x.Outcome != IssueBuildOutcome.Warning);

            Issue = NewIssue;

            string Summary = NewIssue.Summary;

            int MaxLength = 128;

            if (Summary.Length > MaxLength)
            {
                Summary = Summary.Substring(0, MaxLength).TrimEnd() + "...";
            }

            if (Summary != SummaryLabel.Text || OwnerText != OwnerLabel.Text || Reason != NewReason || bIsWarning != bNewIsWarning || bStrongAlert != bNewStrongAlert)
            {
                Rectangle PrevBounds = Bounds;
                SuspendLayout();

                SummaryLabel.Text = Summary;
                OwnerLabel.Text   = OwnerText;

                bool bForceUpdateButtons = false;
                if (bStrongAlert != bNewStrongAlert)
                {
                    bStrongAlert = bNewStrongAlert;

                    if (bNewStrongAlert)
                    {
                        SummaryLabel.ForeColor         = Color.FromArgb(255, 255, 255);
                        SummaryLabel.LinkColor         = Color.FromArgb(255, 255, 255);
                        OwnerLabel.ForeColor           = Color.FromArgb(255, 255, 255);
                        DetailsBtn.Theme               = AlertButtonControl.AlertButtonTheme.Strong;
                        AcceptBtn.Theme                = AlertButtonControl.AlertButtonTheme.Strong;
                        LatestBuildLinkLabel.LinkColor = Color.FromArgb(255, 255, 255);
                    }
                    else
                    {
                        SummaryLabel.ForeColor         = Color.FromArgb(32, 32, 64);
                        SummaryLabel.LinkColor         = Color.FromArgb(32, 32, 64);
                        OwnerLabel.ForeColor           = Color.FromArgb(32, 32, 64);
                        DetailsBtn.Theme               = AlertButtonControl.AlertButtonTheme.Normal;
                        AcceptBtn.Theme                = AlertButtonControl.AlertButtonTheme.Green;
                        LatestBuildLinkLabel.LinkColor = Color.FromArgb(16, 102, 192);
                    }

                    bForceUpdateButtons = true;
                }

                if (bIsWarning != bNewIsWarning)
                {
                    bIsWarning = bNewIsWarning;
                }

                if (Reason != NewReason || bForceUpdateButtons)
                {
                    Reason = NewReason;

                    List <Button> Buttons = new List <Button>();
                    Buttons.Add(DetailsBtn);
                    if ((NewReason & IssueAlertReason.Owner) != 0)
                    {
                        AcceptBtn.Text = "Acknowledge";
                        Buttons.Add(AcceptBtn);
                    }
                    else if ((NewReason & IssueAlertReason.Normal) != 0)
                    {
                        AcceptBtn.Text = "Will Fix";
                        Buttons.Add(AcceptBtn);
                        DeclineBtn.Text = "Not Me";
                        Buttons.Add(DeclineBtn);
                    }
                    else
                    {
                        DeclineBtn.Text = "Dismiss";
                        Buttons.Add(DeclineBtn);
                    }

                    tableLayoutPanel3.ColumnCount = Buttons.Count;
                    tableLayoutPanel3.Controls.Clear();
                    for (int Idx = 0; Idx < Buttons.Count; Idx++)
                    {
                        tableLayoutPanel3.Controls.Add(Buttons[Idx], Idx, 0);
                    }
                }

                ResumeLayout(true);
                Location = new Point(PrevBounds.Right - Bounds.Width, PrevBounds.Y);
                Invalidate();
            }
        }
 private void ShowIssue(IssueData Issue)
 {
     IssueDetailsWindow.Show(Owner, IssueMonitor, ServerAndPort, UserName, ServerTimeOffset, Issue, Log, CurrentStream);
 }
        void UpdateIssueList()
        {
            // Get the time at midnight
            DateTime Now      = DateTime.Now;
            DateTime Midnight = (Now - Now.TimeOfDay).ToUniversalTime();

            // Get the regex for the selected filter
            Func <IssueData, bool> Filter;

            if (String.IsNullOrEmpty(FilterName))
            {
                Filter = x => true;
            }
            else if (!CustomFilters.TryGetValue(FilterName, out Filter))
            {
                Filter = x => x.Streams == null || x.Streams.Any(y => String.Equals(y, FilterName, StringComparison.OrdinalIgnoreCase));
            }

            // Update the table
            int ItemIdx = 0;

            IssueListView.BeginUpdate();
            foreach (IssueData Issue in Issues)
            {
                if (Filter(Issue))
                {
                    for (;;)
                    {
                        if (ItemIdx == IssueListView.Items.Count)
                        {
                            IssueList_InsertItem(ItemIdx, Issue, Midnight);
                            break;
                        }

                        ListViewItem ExistingItem  = IssueListView.Items[ItemIdx];
                        IssueData    ExistingIssue = (IssueData)ExistingItem.Tag;
                        if (ExistingIssue == null || ExistingIssue.Id < Issue.Id)
                        {
                            IssueList_InsertItem(ItemIdx, Issue, Midnight);
                            break;
                        }
                        else if (ExistingIssue.Id == Issue.Id)
                        {
                            IssueList_UpdateItem(ExistingItem, Issue, Midnight);
                            break;
                        }
                        else
                        {
                            IssueListView.Items.RemoveAt(ItemIdx);
                            continue;
                        }
                    }
                    ItemIdx++;
                }
            }
            while (ItemIdx < IssueListView.Items.Count)
            {
                IssueListView.Items.RemoveAt(ItemIdx);
            }
            IssueListView.EndUpdate();

            // Update the maximum number of results
            string FilterText = "";

            if (!String.IsNullOrEmpty(FilterName))
            {
                FilterText = String.Format(" matching filter '{0}'", FilterName);
            }
            StatusLabel.Text = (IssueListView.Items.Count == Issues.Count)? String.Format("Showing {0} results{1}.", Issues.Count, FilterText) : String.Format("Showing {0}/{1} results{2}.", IssueListView.Items.Count, Issues.Count, FilterText);
        }
Exemple #14
0
 private void ShowIssue(IssueData Issue)
 {
     Issue.Builds = RESTApi.GET <List <IssueBuildData> >(IssueMonitor.ApiUrl, String.Format("issues/{0}/builds", Issue.Id));
     IssueDetailsWindow.Show(Owner, IssueMonitor, ServerAndPort, UserName, ServerTimeOffset, Issue, Log, CurrentStream);
 }