/// <summary> /// Updates the content of the synchronized OneNote page to reflect the given list of ToDo /// objects. /// </summary> /// <param name="todos">The list of todos to synchronize with OneNote.</param> /// <returns></returns> public async Task UpdateToDoList(List <ToDo> todos) { // First get the page that we are syncing with from OneNote. var client = GraphServiceHelper.GetAuthenticatedClient(); var pages = await OneNoteService.GetMyPages(client); var todoPage = pages.Where(page => page.Title == todoPageTitle).SingleOrDefault(); if (todoPage == null) { throw new Exception("Cannot update todo list. Failed to get OneNote page to update."); } // Load the HTML content of the page with OneNote IDs. Stream contentStream = await OneNoteService.GetPageContent(client, todoPage, includeIds : true); var pageContent = new HtmlDocument(); using (StreamReader reader = new StreamReader(contentStream)) { string stringContent = reader.ReadToEnd(); pageContent.LoadHtml(stringContent); } // The container of our todos will be the first <div> tag on the page. var targetDiv = pageContent.DocumentNode.Descendants("div").FirstOrDefault(); if (targetDiv == null) { throw new Exception("Cannot update todo list. Text content on a OneNote page must be contained within a div tag."); } // The div's ID will be used to identify the target on the page that we want to update. var targetDivId = targetDiv.ChildAttributes("id").FirstOrDefault(); if (targetDivId == null) { throw new Exception("Cannot update todo list. Target div tag does not have an id."); } // Regenerate HTML content for current todos. targetDiv.RemoveAllChildren(); foreach (ToDo todo in todos) { string dataTag = todo.Done ? "to-do:completed" : "to-do"; targetDiv.AppendChild(HtmlNode.CreateNode($"<p data-tag=\"{dataTag}\">{todo.Task}</p>")); } // Update the OneNote page. await OneNoteService.UpdatePage(client, todoPage, targetDivId.Value, targetDiv.InnerHtml); }
/// <summary> /// Reads the synchronized page in OneNote and translates the content into a list of todo objects. /// </summary> /// <returns>The list of todos synchronized with OneNote.</returns> public async Task <List <ToDo> > GetToDoList() { // First get the synchronized page. If it doesn't exist, create it. var client = GraphServiceHelper.GetAuthenticatedClient(); var pages = await OneNoteService.GetMyPages(client); var todoPage = pages.Where(page => page.Title == todoPageTitle).SingleOrDefault(); if (todoPage == null) { todoPage = await CreateToDoPage(client); } // Read the HTML content of the synchronized page and translate that into ToDo objects. List <ToDo> result = new List <ToDo>(); Stream contentStream = await OneNoteService.GetPageContent(client, todoPage); using (StreamReader reader = new StreamReader(contentStream)) { string pageContent = reader.ReadToEnd(); var document = new HtmlDocument(); document.LoadHtml(pageContent); // A OneNote todo list is a sequence of <p> tags with the data-tag attribute set // to "to-do" or "to-do:completed". foreach (var node in document.DocumentNode.Descendants("p").Where( p => p.GetAttributeValue("data-tag", "not-to-do") != "not-to-do")) { string dataTag = node.Attributes["data-tag"].Value; if (dataTag != "to-do" && dataTag != "to-do:completed") { continue; // node is not a OneNote todo } result.Add(new ToDo { Task = node.InnerText, Done = dataTag == "to-do:completed" }); } } return(result); }
private async Task <OnenotePage> CreateToDoPage(GraphServiceClient client) { var sections = await OneNoteService.GetMySections(client); var todoSection = sections.Where(section => section.DisplayName == todoSectionTitle).SingleOrDefault(); if (todoSection == null) { todoSection = await CreateToDoSection(client); } await OneNoteService.CreatePage(client, todoPageTitle, todoSection); // There can be a small delay between successful creation of a new page and that page appearing in GET requests. // We won't return from this method until the new page can be retrieved with a GET or we timeout. var stopwatch = new Stopwatch(); while (true) { try { var pages = await OneNoteService.GetMyPages(client); var todoPage = pages.Where(page => page.Title == todoPageTitle).SingleOrDefault(); if (todoPage != null) { return(todoPage); } if (stopwatch.ElapsedMilliseconds > 10000) { throw new Exception("Failed to create synchronized OneNote page."); } } catch { // Catch any errors in the GET and retry until we timeout. Thread.Sleep(500); } } }