Azure / Microsoft365R

R SDK for interacting with Microsoft 365 APIs
Other
308 stars 41 forks source link

Add support for SharePoint Pages #190

Open schuffr opened 8 months ago

schuffr commented 8 months ago

Hello, I'd like to be able to create/update a SharePoint page/pages with output from rmarkdown however it seems that the only way to modify page content for a sharepoint page is through the current beta graph API for pages. Can support for SharePoint Pages be added?

hongooi73 commented 5 months ago

https://learn.microsoft.com/en-us/graph/api/resources/sitepage?view=graph-rest-beta

hongooi73 commented 5 months ago

I don't have access to a business MS365 account, so Sharepoint enhancements are difficult for me to add. @elipousson would you be interested in adding this to sharepointr?

elipousson commented 5 months ago

@hongooi73 Potentially! Your tip about how to use do_operation really helped me figure out how to apply the API documentation. I'm still not entirely sure how to add new methods to the package (I'm just less familiar with R6 in general so any guidance on convention or structure are welcome).

The script below shows how to list pages and get the contents of a page which is mostly straightforward. The structure of the canvasLayout elements is pretty complicated though so implementing the API for creating pages or updating pages probably isn't something I can prioritize unless a good excuse pops up in the future.

If a limited implementation is still helpful, @schuffr, I'm happy to work on it. If modifying pages is a key requirement, you may need to build on this example yourself.

library(Microsoft365R)
library(tidyverse)

# Helper function for transforming list columns to character columns
list_cols_to_char <- function(data) {
  data |> 
  mutate(
    across(
      where(is.list),
      \(var) {
        if (all(map_lgl(var, \(x) {
          length(x) == 1
        }))) {
          var <- as.character(var)
        }

        var
      }
    )
  )
}

# Helper function for transformed list to dataframe
list_to_df <- function(.list, list_cols_to_chr = TRUE) {
  .list <- .list |>
    map(
      \(val) {
        val |>
          enframe() |>
          pivot_wider()
      }
    ) |>
    list_rbind()

  if (!list_cols_to_chr) {
    return(.list)
  }

  .list |>
    list_cols_to_char()
}

# Get site
site <- Microsoft365R::get_sharepoint_site(
  tenant = "bmore",
  site_url = "https://bmore.sharepoint.com/sites/WorkdayTeamBaltimore"
)
#> Loading Microsoft Graph login for tenant 'bmore.onmicrosoft.com'

# List site pages
# https://learn.microsoft.com/en-us/graph/api/sitepage-list?view=graph-rest-beta&tabs=http#http-request
page_list <- site$do_operation(
  "pages/microsoft.graph.sitePage"
)

# Convert site page list to data frame
pages <- list_to_df(page_list$value)

# Get page information 
# https://learn.microsoft.com/en-us/graph/api/sitepage-get?view=graph-rest-beta&tabs=http#example-1-get-a-page-in-the-site-pages-list-of-a-site
page_info <- site$do_operation(
  paste0(
    "pages/",
    pages$id[[1]],
    "/microsoft.graph.sitePage"
  )
)

# Get page contents
# https://learn.microsoft.com/en-us/graph/api/sitepage-get?view=graph-rest-beta&tabs=http#example-3-get-a-page-with-page-content
page_contents <- site$do_operation(
  paste0(
    "pages/",
    pages$id[[1]],
    "/microsoft.graph.sitePage?expand=canvasLayout"
  )
)

# Transform list to data frame
page_contents <- page_contents |> 
  enframe() |>
  pivot_wider() |> 
  list_cols_to_char()

# Page text and styling is in the canvasLayout element
str(page_contents$canvasLayout)
#> List of 1
#>  $ :List of 2
#>   ..$ horizontalSections@odata.context: chr "https://graph.microsoft.com/beta/$metadata#sites('bmore.sharepoint.com%2C2fa9068a-30b6-43d7-bfbe-e0da504d0101%2"| __truncated__
#>   ..$ horizontalSections              :List of 2
#>   .. ..$ :List of 5
#>   .. .. ..$ layout               : chr "oneColumn"
#>   .. .. ..$ id                   : chr "1"
#>   .. .. ..$ emphasis             : chr "none"
#>   .. .. ..$ columns@odata.context: chr "https://graph.microsoft.com/beta/$metadata#sites('bmore.sharepoint.com%2C2fa9068a-30b6-43d7-bfbe-e0da504d0101%2"| __truncated__
#>   .. .. ..$ columns              :List of 1
#>   .. .. .. ..$ :List of 4
#>   .. .. .. .. ..$ id                    : chr "1"
#>   .. .. .. .. ..$ width                 : int 12
#>   .. .. .. .. ..$ webparts@odata.context: chr "https://graph.microsoft.com/beta/$metadata#sites('bmore.sharepoint.com%2C2fa9068a-30b6-43d7-bfbe-e0da504d0101%2"| __truncated__
#>   .. .. .. .. ..$ webparts              :List of 1
#>   .. .. .. .. .. ..$ :List of 3
#>   .. .. .. .. .. .. ..$ @odata.type: chr "#microsoft.graph.textWebPart"
#>   .. .. .. .. .. .. ..$ id         : chr "1212fc8d-dd6b-408a-8d5d-9f1cc787efbb"
#>   .. .. .. .. .. .. ..$ innerHtml  : chr "<p>Workday delivers significant enhancements and new functionality twice a year during the second week of March"| __truncated__
#>   .. ..$ :List of 5
#>   .. .. ..$ layout               : chr "oneColumn"
#>   .. .. ..$ id                   : chr "2"
#>   .. .. ..$ emphasis             : chr "none"
#>   .. .. ..$ columns@odata.context: chr "https://graph.microsoft.com/beta/$metadata#sites('bmore.sharepoint.com%2C2fa9068a-30b6-43d7-bfbe-e0da504d0101%2"| __truncated__
#>   .. .. ..$ columns              :List of 1
#>   .. .. .. ..$ :List of 4
#>   .. .. .. .. ..$ id                    : chr "1"
#>   .. .. .. .. ..$ width                 : int 12
#>   .. .. .. .. ..$ webparts@odata.context: chr "https://graph.microsoft.com/beta/$metadata#sites('bmore.sharepoint.com%2C2fa9068a-30b6-43d7-bfbe-e0da504d0101%2"| __truncated__
#>   .. .. .. .. ..$ webparts              :List of 1
#>   .. .. .. .. .. ..$ :List of 4
#>   .. .. .. .. .. .. ..$ @odata.type: chr "#microsoft.graph.standardWebPart"
#>   .. .. .. .. .. .. ..$ id         : chr "3ed82e7e-1a30-4e9c-95bf-682b5065183e"
#>   .. .. .. .. .. .. ..$ webPartType: chr "d1d91016-032f-456d-98a4-721247c305e8"
#>   .. .. .. .. .. .. ..$ data       :List of 6
#>   .. .. .. .. .. .. .. ..$ audiences             : list()
#>   .. .. .. .. .. .. .. ..$ dataVersion           : chr "1.11"
#>   .. .. .. .. .. .. .. ..$ description           : chr "Add an image, picture or photo to your page including text overlays and ability to crop and resize images."
#>   .. .. .. .. .. .. .. ..$ title                 : chr "Image"
#>   .. .. .. .. .. .. .. ..$ properties            :List of 16
#>   .. .. .. .. .. .. .. .. ..$ imageSourceType     : int 2
#>   .. .. .. .. .. .. .. .. ..$ captionText         : chr ""
#>   .. .. .. .. .. .. .. .. ..$ altText             : chr ""
#>   .. .. .. .. .. .. .. .. ..$ linkUrl             : chr ""
#>   .. .. .. .. .. .. .. .. ..$ overlayText         : chr ""
#>   .. .. .. .. .. .. .. .. ..$ fileName            : chr "2024 Release Dates.jpg"
#>   .. .. .. .. .. .. .. .. ..$ siteId              : chr "2fa9068a-30b6-43d7-bfbe-e0da504d0101"
#>   .. .. .. .. .. .. .. .. ..$ webId               : chr "e6e7a0b2-250f-4b03-938f-44c39701d57d"
#>   .. .. .. .. .. .. .. .. ..$ listId              : chr "67272282-05d9-4e94-8fe1-1c1d66aed6c5"
#>   .. .. .. .. .. .. .. .. ..$ uniqueId            : chr "912ce694-761c-4c4c-81db-5e1a0947e490"
#>   .. .. .. .. .. .. .. .. ..$ imgWidth            : int 624
#>   .. .. .. .. .. .. .. .. ..$ imgHeight           : int 468
#>   .. .. .. .. .. .. .. .. ..$ isOverlayTextVisible: logi TRUE
#>   .. .. .. .. .. .. .. .. ..$ alignment           : chr "Center"
#>   .. .. .. .. .. .. .. .. ..$ fixAspectRatio      : logi FALSE
#>   .. .. .. .. .. .. .. .. ..$ overlayTextStyles   :List of 8
#>   .. .. .. .. .. .. .. .. .. ..$ @odata.type        : chr "#graph.Json"
#>   .. .. .. .. .. .. .. .. .. ..$ textColor          : chr "light"
#>   .. .. .. .. .. .. .. .. .. ..$ isBold             : logi FALSE
#>   .. .. .. .. .. .. .. .. .. ..$ isItalic           : logi FALSE
#>   .. .. .. .. .. .. .. .. .. ..$ textBoxColor       : chr "dark"
#>   .. .. .. .. .. .. .. .. .. ..$ textBoxOpacity     : num 0.54
#>   .. .. .. .. .. .. .. .. .. ..$ overlayColor       : chr "light"
#>   .. .. .. .. .. .. .. .. .. ..$ overlayTransparency: int 0
#>   .. .. .. .. .. .. .. ..$ serverProcessedContent:List of 5
#>   .. .. .. .. .. .. .. .. ..$ htmlStrings         : list()
#>   .. .. .. .. .. .. .. .. ..$ searchablePlainTexts: list()
#>   .. .. .. .. .. .. .. .. ..$ links               : list()
#>   .. .. .. .. .. .. .. .. ..$ imageSources        :List of 1
#>   .. .. .. .. .. .. .. .. .. ..$ :List of 2
#>   .. .. .. .. .. .. .. .. .. .. ..$ key  : chr "imageSource"
#>   .. .. .. .. .. .. .. .. .. .. ..$ value: chr "/sites/WorkdayTeamBaltimore/SiteAssets/SitePages/2024-Workday-Feature-Release-Timeline/1522907347-2024-Release-Dates.jpg"
#>   .. .. .. .. .. .. .. .. ..$ customMetadata      :List of 1
#>   .. .. .. .. .. .. .. .. .. ..$ :List of 2
#>   .. .. .. .. .. .. .. .. .. .. ..$ key  : chr "imageSource"
#>   .. .. .. .. .. .. .. .. .. .. ..$ value:List of 6
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ siteid  : chr "2fa9068a-30b6-43d7-bfbe-e0da504d0101"
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ webid   : chr "e6e7a0b2-250f-4b03-938f-44c39701d57d"
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ listid  : chr "67272282-05d9-4e94-8fe1-1c1d66aed6c5"
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ uniqueid: chr "912ce694-761c-4c4c-81db-5e1a0947e490"
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ width   : chr "624"
#>   .. .. .. .. .. .. .. .. .. .. .. ..$ height  : chr "468"
#>  - attr(*, "status")= int 200

Created on 2024-02-15 with reprex v2.1.0