Example #1
0
		/// <summary>
		/// Populates one row of data with the details of the passed change list.
		/// Used when displaying the list of change lists in review. Called for both
		/// the CLs where the user is the reviewer, as well as the reviewee.
		/// </summary>
		/// <param name="changeList"> The change list to process. </param>
		private TableRow GetReviewRow(ChangeList changeList, bool includeUserName, bool includeCloseButton = false)
		{
			TableRow row = new TableRow();
			if (changeList.Stage != 0)
				row.AppendCSSClass("Closed");

			// Added by CBOBO
			if (!includeUserName && includeCloseButton)
			{
				if (changeList.Stage == 2) // 2 = Closed
				{
					LiteralControl literalControl = new LiteralControl("Closed");
					TableCell cell = new TableCell();
					cell.Controls.Add(literalControl);
					cell.Width = 60;
					row.Cells.Add(cell);
				}
				else
				{
					switch(GetChangeListStatus(changeList))
					{
						case ChangeListStatus.Pending:
							row.Cells
								.Add(new TableCell() { CssClass = "Pending" }
								.Add("Pending".As(HtmlTextWriterTag.Span)));
							break;
						case ChangeListStatus.NeedsWork:
							row.Cells
								.Add(new TableCell() { CssClass = "NeedsWork" }
								.Add("Needs Work".As(HtmlTextWriterTag.Span)));
							break;
						case ChangeListStatus.Closable:
							HyperLink closeBtn = new HyperLink();
							closeBtn.NavigateUrl = Request.FilePath + "?cid=" + changeList.Id + "&action=close";
							closeBtn.Text = "[Close]";
							TableCell cell = new TableCell();
							cell.Controls.Add(closeBtn);
							cell.Width = 60;
							row.Cells.Add(cell);
							break;
					}
				}
			}
			// End Added by CBOBO

			// Time stamp
			row.Cells.Add(new TableCell() { CssClass = "ShortDate" }
				.Add(changeList.TimeStamp.ToShortDateString().As(HtmlTextWriterTag.Span)));

			// Author
			if (includeUserName)
			{
				row.Cells.Add(new TableCell() { CssClass = "Author" }
					.Add(changeList.UserName.As(HtmlTextWriterTag.Span)));
			}

			// Change list ID
			row.Cells.Add(new TableCell() { CssClass = "ChangeListName" }
				.Add(new HyperLink()
					{
						NavigateUrl = Request.FilePath + "?cid=" + changeList.Id,
						Text = Server.HtmlEncode(changeList.CL)
					}.As(HtmlTextWriterTag.Div)));

			// Description
			row.Cells.Add(new TableCell() { CssClass = "Description" }
				.Add(Server.HtmlEncode(changeList.Description).As(HtmlTextWriterTag.Span)));

			return row;
		}
Example #2
0
		/// <summary>
		/// Returns a row with title and body as two cells.
		/// </summary>
		/// <param name="title"> The text for the first cell (usually, a description). </param>
		/// <param name="body"> The text for the second cell (usually, the information). </param>
		private TableRow GetChangeDescriptionRow(string title, string body)
		{
			TableRow row = new TableRow();
			row.AppendCSSClass("CssTopAligned");

			TableCell cell = new TableCell() { Text = title };
			row.Cells.Add(cell);
			cell.AppendCSSClass("CssTitle");

			cell = new TableCell() { Text = "<pre>" + body + "</pre>" };
			row.Cells.Add(cell);
			cell.AppendCSSClass("CssBody");

			return row;
		}
Example #3
0
		/// <summary>
		/// Displays the change list composition. This is called when the main table shows the details of one
		/// change list.
		/// </summary>
		/// <param name="cid"> Change Id. This is relative to the database, not source control. </param>
		/// <param name="userName"> User name. </param>
		private void DisplayChange(int cid, string userName)
		{
			var changeQuery = from ch in DataContext.ChangeLists where ch.Id == cid select ch;
			if (changeQuery.Count() != 1)
			{
				ErrorOut("Could not find this change in the system!");
				return;
			}

			HintsData.InChangeView = true;

			ChangeList changeList = changeQuery.Single();

			DisplayPageHeader("Change list " + changeList.CL);

			Table table = new Table();
			table.AppendCSSClass("CssChangeListDetail");

			ActivePage.Controls.Add(table);

			table.Rows.Add(GetChangeDescriptionRow("Date:", WrapTimeStamp(changeList.TimeStamp)));
			if (changeList.UserClient != null && changeList.UserClient != String.Empty)
				table.Rows.Add(GetChangeDescriptionRow("Client:", changeList.UserClient));
			var userRow = GetChangeDescriptionRow("User:"******"Status:", changeList.Stage == 0 ? "Pending" : "Submitted"));
			if (changeList.Description != null && changeList.Description != String.Empty)
				table.Rows.Add(GetChangeDescriptionRow("Description:", Server.HtmlEncode(changeList.Description)));
			table.Rows.Add(GetChangeDescriptionRow("Files:", ""));

			var latestReview = GetLatestUserReviewForChangeList(userName, cid);
			foreach (ChangeFile file in
				(from fl in DataContext.ChangeFiles where fl.ChangeListId == cid select fl))
			{
				var versions = GetVersionsAbstract(file.Id);
				bool hasTextBody = (from ver in versions where ver.HasTextBody select ver).Count() != 0;
				table.Rows.Add(GetChangeFileRow(file, versions.LastOrDefault(), hasTextBody, latestReview));
			}

			var attachments = (from ll in DataContext.Attachments 
							   where ll.ChangeListId == cid
							   orderby ll.TimeStamp
							   select ll);

			if (attachments.Count() > 0)
			{
				table.Rows.Add(GetChangeDescriptionRow("Links:", ""));

				foreach (Attachment a in attachments)
					AddAttachmentRow(table, a);
			}

			AddLabel("<h3>Review history</h3>");
			Table reviewResults = new Table();

			ActivePage.Controls.Add(reviewResults);

			reviewResults.AppendCSSClass("CssChangeListReviewHistory");

			var allReviewsQuery = from rr in DataContext.Reviews
								  where rr.ChangeListId == cid && rr.IsSubmitted
								  orderby rr.TimeStamp
								  select rr;

			foreach (Review review in allReviewsQuery)
			{
				TableRow row = new TableRow();
				reviewResults.Rows.Add(row);

				row.AppendCSSClass("CssTopAligned");

				TableCell dateCell = new TableCell();
				row.Cells.Add(dateCell);

				dateCell.AppendCSSClass("CssDate");
				dateCell.Text = WrapTimeStamp(review.TimeStamp);

				TableCell nameCell = new TableCell();
				row.Cells.Add(nameCell);

				nameCell.AppendCSSClass("CssName");
				nameCell.Text = review.UserName;

				TableCell verdictCell = new TableCell();
				row.Cells.Add(verdictCell);

				verdictCell.AppendCSSClass("CssScore");

				HyperLink reviewTarget = new HyperLink();
				verdictCell.Controls.Add(reviewTarget);

				if (review.OverallStatus == 0)
					HintsData.HaveNeedsWorkVotes = true;

				reviewTarget.Text = Malevich.Util.CommonUtils.ReviewStatusToString(review.OverallStatus);
				reviewTarget.NavigateUrl = Request.FilePath + "?rid=" + review.Id;

				if (review.CommentText != null)
				{
					TableCell abbreviatedCommentCell = new TableCell();
					row.Cells.Add(abbreviatedCommentCell);
					abbreviatedCommentCell.AppendCSSClass("CssComment");
					abbreviatedCommentCell.Text = AbbreviateToOneLine(review.CommentText, MaxReviewCommentLength);
				}
			}

			//Todo: modify stage logic, stage 1 is pending...
			if (changeList.Stage != 0)
			{
				HintsData.IsChangeInactive = true;

				AddLabel(String.Format("<br>This review has been {0}.", (changeList.Stage == 2 ? "closed" : "deleted")));
				return;
			}

			AddLabel("<h3>Vote so far</h3>");

			TableGen.Table reviewerVote = new TableGen.Table(2) { CssClass = "CssChangeListVoteHistory" };
			ActivePage.Controls.Add(reviewerVote);

			var reviewerQuery = from rv in DataContext.Reviewers where rv.ChangeListId == cid select rv;
			Reviewer[] reviewers = reviewerQuery.ToArray();
			bool iAmAReviewer = false;
			foreach (Reviewer reviewer in reviewers)
			{
				var row = reviewerVote.CreateRow();
				reviewerVote.AddItem(row);

				row[0].Text = reviewer.ReviewerAlias;

				if (userName.EqualsIgnoreCase(reviewer.ReviewerAlias))
				{
					DropDownList list = new DropDownList() { ID = "verdictlist" };
					row[1].Add(list);

					list.Items.Add(new ListItem() { Text = "Needs work" });				
					list.Items.Add(new ListItem() { Text = "LGTM with minor tweaks" });
					list.Items.Add(new ListItem() { Text = "LGTM" });
					list.Items.Add(new ListItem() { Text = "Non-scoring comment" });

					iAmAReviewer = true;
				}
				else if (!Page.IsPostBack)
				{
					Review review = GetLastReview(cid, reviewer.ReviewerAlias);
					if (review == null)
					{
						row[1].Text = "Have not looked";
					}
					else
					{
						row[1].Add(new HyperLink()
						{
							Text = Malevich.Util.CommonUtils.ReviewStatusToString(review.OverallStatus),
							NavigateUrl = Request.FilePath + "?rid=" + review.Id,
						});
					}
				}
			}

			bool iOwnTheChange = changeList.UserName.EqualsIgnoreCase(userName);
			if (!iAmAReviewer && !iOwnTheChange)
			{
				AddLabel("<br>");
				AddLink("I would like to review this change.", "?cid=" + changeList.Id + "&action=makemereviewer")
					.AppendCSSClass("button");
			}

			if (iOwnTheChange && changeList.Stage != 2 && /* 2 = closed */
				GetChangeListStatus(changeList) == ChangeListStatus.Closable)
			{
				AddLabel("<br>");
				AddLink("Close Review", "?cid=" + changeList.Id + "&action=close")
					.AppendCSSClass("button");
			}

			if (iOwnTheChange)
			{
				HintsData.IsChangeAuthor = true;
				AddLabel("<h3>My response</h3>");
			}
			else
			{
				HintsData.IsChangeReviewer = true;
				AddLabel("<h3>My comments</h3>");
			}

			TextBox commentTextBox = new TextBox();
			ActivePage.Controls.Add(commentTextBox);
			commentTextBox.TextMode = TextBoxMode.MultiLine;
			commentTextBox.AppendCSSClass("CssGeneralCommentInputBox");
			commentTextBox.ID = "reviewcommenttextbox";

			AddLabel("<br>");

			Button submitReviewButton =
				new Button() { ID = "submitreviewbutton", Text = "Submit", CssClass = "button" };
			ActivePage.Controls.Add(submitReviewButton.As(HtmlTextWriterTag.P));
			submitReviewButton.Click += new EventHandler(
				delegate(object sender, EventArgs e) { submitReview_Clicked(cid, sender, e); });

			AddLabel("<br>");

			int myReviewId = GetBaseReviewId(userName, cid);
			if (myReviewId == 0)
				return;

			DisplayReviewLineComments(myReviewId);
		}
Example #4
0
		/// <summary>
		/// Displays files from a change list by adding a row with details regarding the file to a table.
		/// </summary>
		/// <param name="file"> The top-level file data (names). </param>
		/// <param name="lastVersion"> The last version of the file. </param>
		/// <param name="hasTextBody"> Whether to display the file as a hyperlink </param>
		/// <param name="latestReview">The latest review that the user has submitted for this changelist. May be null.</param>
		private TableRow GetChangeFileRow(
			DataModel.ChangeFile file,
			AbstractedFileVersion lastVersion,
			bool hasTextBody,
			Review latestReview)
		{
			TableRow row = new TableRow();
			if (!file.IsActive)
				row.AppendCSSClass("CssInactiveFile");

			TableCell cell = new TableCell();
			// If the latest version of this file has a timestamp greater than the latest review,
			// then present a "new!" icon in the list to allow the user to quickly determine what
			// has changed since they last reviewed this change.
			if (latestReview != null &&
				lastVersion.TimeStamp != null &&
				latestReview.TimeStamp.CompareTo(lastVersion.TimeStamp) < 0)
			{
				cell.AppendCSSClass("CssNewIcon");
				cell.Controls.Add(new Image()
				{
					ImageUrl = "~/images/new_icon.png",
					AlternateText = "This file has changed since your last review submission."
				});
			}
			row.Cells.Add(cell);

			cell = new TableCell();
			row.Cells.Add(cell);

			string moniker = null;
			if (lastVersion == null)
			{
				moniker = file.ServerFileName + "#" + " (no versions found)";
			}
			else if (lastVersion.Action == SourceControlAction.DELETE)
			{
				moniker = file.ServerFileName + "#" + lastVersion.Revision + " DELETE";
			}
			else if (lastVersion.Action == SourceControlAction.BRANCH)
			{
				moniker = file.ServerFileName + "#" + lastVersion.Revision + " BRANCH";
			}
			else if (lastVersion.Action == SourceControlAction.INTEGRATE)
			{
				moniker = file.ServerFileName + "#" + lastVersion.Revision + " INTEGRATE";
			}
			else if (lastVersion.Action == SourceControlAction.RENAME)
			{
				moniker = file.ServerFileName + "#" + lastVersion.Revision + " RENAME";
			}
			else
			{
				moniker = file.ServerFileName + "#" + lastVersion.Revision +
					((lastVersion.Action == SourceControlAction.ADD) ? " ADD" : " EDIT");
			}

			if (hasTextBody)
			{
				HyperLink link = new HyperLink();
				cell.Controls.Add(link);
				link.NavigateUrl = Request.FilePath + "?fid=" + file.Id;
				link.Text = moniker;
			}
			else
			{
				cell.Text = moniker;
			}

			return row;
		}