public static async Task <Dictionary <int, AgilefantTeam> > GetTeams(AgilefantSession session) { var response = await session.Get("ajax/retrieveAllProductsWithStandalone.action"); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); var summaries = JsonConvert.DeserializeObject <AgilefantBacklogProductSummary[]>(json); var menu = await AgilefantMenuData.GetMenuData(session); var teams = new Dictionary <int, AgilefantTeam>(); foreach (var summary in summaries) { var data = menu.FirstOrDefault(menuData => menuData.Title == summary.Name); if (data == null) { continue; } var sprintData = await AgilefantSprint.GetSprints(data.Children[0].Id, session); var sprints = sprintData.Select(sprint => new Sprint(sprint.Name, sprint.Description, sprint.Id, sprint.StartDate, sprint.EndTime)).ToList(); sprints.Sort((a, b) => { var ai = Regex.Match(a.Name, "[0-9]+"); var bi = Regex.Match(b.Name, "[0-9]+"); if (!ai.Success || !bi.Success) { return(string.Compare(a.Name, b.Name, StringComparison.Ordinal)); } return(int.Parse(ai.Value).CompareTo(int.Parse(bi.Value))); }); var sprint0 = Regex.Match(sprints.First().Name, "[0-9]+"); if (sprint0.Success && int.Parse(sprint0.Value) == 0) { sprints.RemoveAt(0); } var assignees = sprintData[0].Assignees; for (var i = 1; i < sprintData.Length && assignees.Length == 0; i++) { assignees = sprintData[i].Assignees; // sprint 0 sometimes does not have assignees } var name = summary.Name; var match = Regex.Match(name, @"^\s*[0-9]+\s*[.:]"); if (match.Success) { name = name.Substring(match.Length); } teams.Add(summary.Id, new AgilefantTeam(name.Trim(), summary.Description, summary.Id, assignees, sprints.ToArray())); } return(teams); }
/// <summary> /// Gets the data that would normally be in the left-hand menu of Agilefant. /// </summary> /// <param name="session">The current login session for Agilefant.</param> /// <returns>An array of the items in the menu.</returns> internal static async Task <AgilefantMenuData[]> GetMenuData(AgilefantSession session) { var response = await session.Get("ajax/menuData.action"); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); return(JsonConvert.DeserializeObject <AgilefantMenuData[]>(json)); }
/// <summary> /// Downloads the burndown image for a sprint. /// </summary> /// <param name="sprintId">ID of sprint to get burndown for.</param> /// <param name="session">Agilefant login session to use.</param> /// <returns>The burndown image.</returns> public static async Task <Image> GenerateBurndownImage(int sprintId, AgilefantSession session) { var url = $"drawIterationBurndown.action?backlogId={sprintId}&timeZoneOffset=720"; var response = await session.Get(url); response.EnsureSuccessStatusCode(); var stream = await response.Content.ReadAsStreamAsync(); return(Image.FromStream(stream)); }
/// <summary> /// Gets details about a sprint with a specified ID. /// </summary> /// <param name="sprintId">ID of the sprint to get.</param> /// <param name="session">Agilefant login session to use.</param> /// <returns>Details of the specified sprint.</returns> public static async Task <AgilefantSprint> GetSprint(int sprintId, AgilefantSession session) { var url = $"ajax/iterationData.action?iterationId={sprintId}"; var response = await session.Get(url); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); return(JsonConvert.DeserializeObject <AgilefantSprint>(json)); }
internal static async Task <AgilefantUser[]> GetAgilefantUsers(AgilefantSession session) { var response = await session.Post("ajax/userChooserData.action"); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); var wrappers = JsonConvert.DeserializeObject <AgilefantUserWrapper[]>(json); return((from wrapper in wrappers select wrapper.OriginalObject).ToArray()); }
/// <summary> /// Gets all sprints for a project. /// </summary> /// <param name="projectId">ID of the project to get sprint for.</param> /// <param name="session">Session to use.</param> /// <returns>All sprints.</returns> public static async Task <AgilefantSprint[]> GetSprints(int projectId, AgilefantSession session) { var response = await session.Post("ajax/projectIterations.action", new FormUrlEncodedContent(new Dictionary <string, string> { { "projectId", projectId.ToString() } })); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); return(JsonConvert.DeserializeObject <AgilefantSprint[]>(json)); }
internal static async Task <AgilefantTime> GetTimes(int teamNumber, int backlogId, int sprintId, int userId, AgilefantSession session) { var data = new FormUrlEncodedContent(new Dictionary <string, string> { { "backlogSelectionType", "0" }, { "productIds", teamNumber.ToString() }, { "projectIds", backlogId.ToString() }, { "iterationIds", sprintId.ToString() }, { "interval", "NO_INTERVAL" }, { "startDate", "" }, { "endDate", "" }, { "userIds", userId.ToString() }, }); var response = await session.Post("generateTree.action", data); response.EnsureSuccessStatusCode(); var content = await response.Content.ReadAsStringAsync(); return(ParseHtmlToTimes(content)); }
/// <summary> /// Gets the burndown image for this sprint. /// </summary> /// <param name="session">Agilefant session to use to get burndown image.</param> /// <returns>The burndown image.</returns> public async Task <Image> GetBurndownImage(AgilefantSession session) { return(await GenerateBurndownImage(Id, session)); }
/// <summary> /// Creates a new Agilefant Client /// </summary> /// <param name="session"></param> public AgilefantClient(AgilefantSession session) { Session = session; }
/// <summary> /// Logs time against an backlog item /// </summary> /// <param name="against">The item to log against</param> /// <param name="entryDate">The entry date</param> /// <param name="minutesSpent">The minutes spent</param> /// <param name="description">A description of the work done</param> /// <param name="users">The users to log time for</param> /// <param name="session">The session</param> internal static System.Threading.Tasks.Task LogTime(IAgilefantLoggable against, DateTime entryDate, int minutesSpent, string description, IEnumerable <AgilefantUser> users, AgilefantSession session) { return(LogTime(against.Id, entryDate, minutesSpent, description, from user in users select user.Id, session)); }
/// <summary> /// Gets all the effort entries for a backlog /// </summary> /// <param name="from">The backlog item to get the effort entries for</param> /// <param name="session">The session</param> /// <returns>The effort entries</returns> internal static async Task <IEnumerable <AgilefantEffortEntry> > GetEffortEntries(int from, AgilefantSession session) { var query = $"ajax/retrieveTaskHourEntries.action?parentObjectId={@from}&limited=false"; var response = await session.Get(query); var json = await response.Content.ReadAsStringAsync(); var entries = JsonConvert.DeserializeObject <AgilefantEffortEntry[]>(json); return(entries); }
/// <summary> /// Gets all the effort entries for a backlog /// </summary> /// <param name="from">The backlog item to get the effort entries for</param> /// <param name="session">The session</param> /// <returns>The effort entries</returns> internal static Task <IEnumerable <AgilefantEffortEntry> > GetEffortEntries(IAgilefantLoggable from, AgilefantSession session) { return(GetEffortEntries(from.Id, session)); }
/// <summary> /// Updates an existing effort entry /// </summary> /// <param name="entry">The effort entry to update. This *MUST* have the correct id</param> /// <param name="session">The session</param> internal static System.Threading.Tasks.Task UpdateEffortEntry(AgilefantEffortEntry entry, AgilefantSession session) { var content = new FormUrlEncodedContent(new Dictionary <string, string> { { "hourEntry.minutesSpent", entry.MinutesSpent.ToString() }, { "hourEntry.date", entry.LogTimeMilliseconds.ToString() }, { "hourEntry.description", entry.Comment }, { "hourEntryId", entry.Id.ToString() }, }); return(session.Post("ajax/storeEffortEntry.action", content)); }
/// <summary> /// Adds an effort entry to the specified loggable /// </summary> /// <param name="parentObjectId">The id of the object to log against</param> /// <param name="entryDate">The date of the entry</param> /// <param name="minutesSpent">The time spent, in minutes</param> /// <param name="description">A description of the entry</param> /// <param name="users">The users to log against</param> /// <param name="session">The session</param> internal static async System.Threading.Tasks.Task LogTime(int parentObjectId, DateTime entryDate, int minutesSpent, string description, IEnumerable <int> users, AgilefantSession session) { //Get the time in milliseconds since the epoch var timeSinceEpoch = (long)(entryDate - new DateTime(1970, 1, 1)).TotalMilliseconds; var content = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("parentObjectId", parentObjectId.ToString()), new KeyValuePair <string, string>("hourEntry.date", timeSinceEpoch.ToString()), new KeyValuePair <string, string>("hourEntry.minutesSpent", minutesSpent.ToString()), new KeyValuePair <string, string>("hourEntry.description", description), }; content.AddRange(users.Select(user => new KeyValuePair <string, string>("userIds", user.ToString()))); var postData = new FormUrlEncodedContent(content); await session.Post("ajax/logTaskEffort.action", postData); }
/// <summary> /// Gets an array of the backlogs for a team /// </summary> /// <param name="teamNumber">The team to get the backlog for</param> /// <param name="session">The session to operate within</param> /// <returns>The backlogs</returns> internal static async Task <AgilefantBacklog[]> GetAgilefantBacklogs(int teamNumber, AgilefantSession session) { var response = await session.Post("ajax/retrieveSubBacklogs.action", new FormUrlEncodedContent(new Dictionary <string, string> { { "backlogId", teamNumber.ToString() } })); response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); return(JsonConvert.DeserializeObject <AgilefantBacklog[]>(json)); }