From 89edbb8c5e53d868038ed8537bf2e1bfa033dd28 Mon Sep 17 00:00:00 2001 From: Beau Cameron Date: Thu, 4 Jan 2024 16:39:13 -0700 Subject: [PATCH 1/2] V4 Onenote Adding full Notes functionality Adding Tests Adding Documentation --- docs/graph/onenote.md | 453 +++++++++++++++++++++++++++ packages/graph/onenote/groups.ts | 14 + packages/graph/onenote/index.ts | 9 +- packages/graph/onenote/sites.ts | 14 + packages/graph/onenote/types.ts | 237 +++++++++++--- packages/graph/operations/onenote.ts | 14 + test/graph/onenote.ts | 219 +++++++++++++ 7 files changed, 917 insertions(+), 43 deletions(-) create mode 100644 docs/graph/onenote.md create mode 100644 packages/graph/onenote/groups.ts create mode 100644 packages/graph/onenote/sites.ts create mode 100644 packages/graph/operations/onenote.ts create mode 100644 test/graph/onenote.ts diff --git a/docs/graph/onenote.md b/docs/graph/onenote.md new file mode 100644 index 000000000..87712ade0 --- /dev/null +++ b/docs/graph/onenote.md @@ -0,0 +1,453 @@ +# Graph OneNote (Notes) +Provides capabilities of working with OneNote files. + +Most of the following methods are available on users, groups, and sites. There may be exceptions, so please refer to the link below for more information. Most of the samples here will be using the .me endpoint for reference. + +More information can be found in the official Graph documentation: + +- [OneNote Resource Type](https://docs.microsoft.com/en-us/graph/api/resources/onenote-api-overview?view=graph-rest-1.0) + + +## Notebook, INoteBook, Notebooks, INotebooks, OneNote, IOneNote, Page, IPage, Pages, IPages, Section, ISection, Sections, ISections, Resources, IResources +[![Selective Imports Banner](https://img.shields.io/badge/Selective%20Imports-informational.svg)](../concepts/selective-imports.md) + +## Notebooks + +### Get Users Notebooks +Retrieves a list of notebooks for a user. +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const notebooks = await graph.me.onenote.notebooks() +``` +### Get Group Notebooks +Retrieves a list of notebooks for a group +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/groups"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const notebooks = await graph.groups.getById('3dfbeaa7-a097-4032-8965-cd387a79537f').onenote.notebooks() +``` +### Get Site Notebooks +Retrieves a list of notebooks for a site +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/sites"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const notebooks = await graph.sites.getById('contoso.sharepoint.com,91dd2418-8fb9-4e0e-919d-c1b31e938386,285cc5a1-cf50-4e4d-8d93-5ba5a8e76e01').onenote.notebooks() +``` +### Get User's most recent Notebooks +Retrieves the most recent notebooks for the logged in user. Not available on Sites or Groups. +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const notebooks = await graph.me.onenote.notebooks.recent(); +``` +### Create a Notebook +Create a new new notebook + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const userNotebookAdd = await graph.me.onenote.notebooks.add("New Notebook"); + +``` +### Get a Notebook +Retrieve the properties of a notebook by id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const noteBook = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83')(); + +``` +### Copy a Notebook +Copies a notebook to the Notebooks folder in the Documents library of a User or Group. The folder is created if it doesn't exist. + +Available for Users and Groups (not Sites). + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +// copy user notebook +const copyOperation = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83').copy({renameAs: "New Notebook Name"}); + +``` +## Sections +### List sections in OneNote +Retrieves a list of OneNote section objects + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sections = await graph.me.onenote.sections(); + +``` +### List sections in a Notebook +Retrieve a list of section objects from specified notebook + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sections = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83').sections(); + +``` +### Get a Section +Retrieve a specified Section + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const section = await graph.me.onenote.sections.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517')(); + +``` + +### Create a new section in a Notebook +Creates a new section in a specified notebook + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const section = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83').sections.add("New Section"); + +``` +### Copy a section to a Notebook +Copies a section to a specified notebook. +For Copy operations, you follow an asynchronous calling pattern: First call the Copy action, and then poll the operation endpoint for the result. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const notebookIdToCopyTo = '1742ad48-23cb-4106-b8ab-8e214283d61a'; + +const copyOperation = await graph.me.onenote.sections.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517').copyToNotebook({id:notebookIdToCopyTo, renameAs:'New Section' }); + +``` +### Copy a section to a Section Group +Copies a section to a specified Section Group. +For Copy operations, you follow an asynchronous calling pattern: First call the Copy action, and then poll the operation endpoint for the result. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sectionGroupToCopyTo = 'ea12ea17-ac6c-478b-bb6c-76fde6142892'; + +const copyOperation = await graph.me.onenote.sections.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517').copyToSectionGroup({id:sectionGroupToCopyTo, renameAs:'New Section' }); + +``` + +## Section Groups +### List section groups +Retrieves a list of OneNote sectionGroup objects + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sectionGroups = await graph.me.onenote.sectionsGroups(); + +``` +### List section groups in a Notebook +Retrieves a list of OneNote sectionGroup objects + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sectionGroups = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83').sectionsGroups(); + +``` +### Get a Section Group +Retrieves a section group by id + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sectionGroup = await graph.me.onenote.sectionsGroups.getById('15ef5f24-ca07-4d74-80c9-a4b7cb1cd7a4')(); + +``` +### Create a Section Group in a Notebook +Creates a new Section Group in a specified Notebook + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const section = await graph.me.onenote.notebooks.getById('eddc09e2-2d4f-4ca3-aadb-89e9a7305d83').sections.add('New Section Group'); + +``` +### List Sections in a Section Group +Retrieves a list of sections in a specified Section Group + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sections = await graph.me.onenote.sectionGroups.getById('15ef5f24-ca07-4d74-80c9-a4b7cb1cd7a4').sections(); + +``` +### Create a Section in a Section Group +Creates a new section in a specified Section Group + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const section = await graph.me.onenote.sectionGroups.getById('15ef5f24-ca07-4d74-80c9-a4b7cb1cd7a4').sections.add("New Section"); + +``` +## Pages +### List Pages in default OneNote +Retrieves a list of OneNote page objects + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const pages = await graph.me.onenote.pages(); + +``` +### List Pages in a Section +Retrieves a list of OneNote pages in a specified Section + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const pages = await graph.me.onenote.sections.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517').pages(); + +``` + +### Get a Page +Retrieve a specified Page + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const page = await graph.me.onenote.pages.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517')(); + +``` +### Get Contents of a Page +Retrieves HTML content from a specified page. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const pageHtml = await graph.me.onenote.pages.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517').content(); + +``` + +### Create a page +Create a new OneNote page in the default section of the default notebook. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + + var pageData =` + + + + A page with <i>rendered</i> images and an <b>attached</b> file + + + +

Here's an image from an online source:

+ an image on the page +

Here's an image uploaded as binary data:

+ an image on the page +

Here's a file attachment:

+ + + `; + +const page = await graph.me.onenote.pages.add(pageData); + +``` +### Create a page in a Section +Create a new OneNote page in a specified section + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + + var pageData =` + + + + A page with <i>rendered</i> images and an <b>attached</b> file + + + +

Here's an image from an online source:

+ an image on the page +

Here's an image uploaded as binary data:

+ an image on the page +

Here's a file attachment:

+ + + `; + +const page = await graph.me.onenote.sections.getById('107542cd-a4da-4bf6-8afc-5cbeb3f9a517').pages.add(pageData); + +``` +### Copy a page to a Section +Copy a page to specified section +For copy operations, you follow an asynchronous calling pattern: First call the Copy action, and then poll the operation endpoint for the result. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const sectionToCopyTo = 'ea12ea17-ac6c-478b-bb6c-76fde6142892'; +await graph.me.onenote.pages.getById('6bd3eace-14a2-4859-8855-02724f3e4539').copyToSection({id:sectionToCopyTo, renameAs:'New Copied Page'}); + +``` + +### Update a page +Update the content of a OneNote page. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +const oneNotePageUpdate = await graph.me.onenote.pages.getById('6bd3eace-14a2-4859-8855-02724f3e4539').update( + [ + { + 'target':'#para-id', + 'action':'Insert', + 'position':'Before', + 'content':'image-alt-text' + }, + { + 'target':'#list-id', + 'action':'Append', + 'content':'
  • new-page-content
  • ' + } + ] +); + +``` +### Delete a page +Delete a OneNote page. + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +await graph.me.onenote.pages.getById('6bd3eace-14a2-4859-8855-02724f3e4539').delete() + +``` +## Resources +### Get a Resource +Retrieve the binary data of a file or image resource object. Returned as a Blob + +```TypeScript +import { graphfi } from "@pnp/graph"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; + +const graph = graphfi(...); + +// Example of getting a resource +const resourceBlob = await graph.me.onenote.resources.getById('1-b2bce3f55b5d4864be426d7cce66b239!1-5137fae1-07eb-4383-bc8b-0c0c6cf0af39')(); + +``` diff --git a/packages/graph/onenote/groups.ts b/packages/graph/onenote/groups.ts new file mode 100644 index 000000000..4dd91ae06 --- /dev/null +++ b/packages/graph/onenote/groups.ts @@ -0,0 +1,14 @@ +import { addProp } from "@pnp/queryable"; +import { _Group } from "../groups/types.js"; +import { IOneNote, OneNote } from "./types.js"; + +declare module "../groups/types" { + interface _Group { + readonly onenote: IOneNote; + } + interface IGroup { + readonly onenote: IOneNote; + } +} + +addProp(_Group, "onenote", OneNote); diff --git a/packages/graph/onenote/index.ts b/packages/graph/onenote/index.ts index 5580cd60b..dec8f5774 100644 --- a/packages/graph/onenote/index.ts +++ b/packages/graph/onenote/index.ts @@ -1,16 +1,21 @@ +import "./groups.js"; import "./users.js"; +import "./sites.js"; export { INotebook, - INotebookAddResult, INotebooks, IOneNote, + IPages, + IResources, ISection, - ISectionAddResult, ISections, Notebook, Notebooks, OneNote, + Page, + Pages, + Resources, Section, Sections, } from "./types.js"; diff --git a/packages/graph/onenote/sites.ts b/packages/graph/onenote/sites.ts new file mode 100644 index 000000000..42615d692 --- /dev/null +++ b/packages/graph/onenote/sites.ts @@ -0,0 +1,14 @@ +import { addProp } from "@pnp/queryable"; +import { _Site } from "../sites/types.js"; +import { IOneNote, OneNote } from "./types.js"; + +declare module "../sites/types" { + interface _Site { + readonly onenote: IOneNote; + } + interface ISite { + readonly onenote: IOneNote; + } +} + +addProp(_Site, "onenote", OneNote); diff --git a/packages/graph/onenote/types.ts b/packages/graph/onenote/types.ts index 491041a7c..3162fcfc4 100644 --- a/packages/graph/onenote/types.ts +++ b/packages/graph/onenote/types.ts @@ -1,15 +1,27 @@ -import { body } from "@pnp/queryable"; -import { Notebook as INotebookType, Onenote as IOnenoteType, OnenoteSection as ISectionType, OnenotePage as IOnenotePageType } from "@microsoft/microsoft-graph-types"; +import { BlobParse, InjectHeaders, TextParse, body } from "@pnp/queryable"; +import { + Notebook as INotebookType, + Onenote as IOnenoteType, + OnenoteSection as IOnenoteSectionType, + OnenotePage as IOnenotePageType, + SectionGroup as ISectionGroupType, + RecentNotebook as IRecentNotebookType, + Operation as IOperationType, + OnenotePatchContentCommand as IOnenotePatchContentCommand, +} from "@microsoft/microsoft-graph-types"; import { - GraphCollection, _GraphInstance, _GraphCollection, - IGraphCollection, + _GraphQueryable, graphInvokableFactory, + GraphQueryable, graphPost, + graphGet, + graphPatch, } from "../graphqueryable.js"; -import { defaultPath, getById, IGetById } from "../decorators.js"; +import { defaultPath, deleteable, getById, IDeleteable, IGetById } from "../decorators.js"; +type Combine = T & U; /** * Represents a onenote entity */ @@ -20,28 +32,47 @@ export class _OneNote extends _GraphInstance { return Notebooks(this); } - public get sections(): ISections { + public get pages(): IPages { + return Pages(this); + } + + public get resources(): IResources { + return Resources(this); + } + + public get sections(): Combine<_GraphCollection, Omit> { return Sections(this); } - public get pages(): IGraphCollection { - return GraphCollection(this, "pages"); + public get sectionGroups(): Combine<_GraphCollection, Omit> { + return SectionGroups(this); } } -export interface IOneNote extends _OneNote {} +export interface IOneNote extends _OneNote { } export const OneNote = graphInvokableFactory(_OneNote); - /** * Describes a notebook instance * */ export class _Notebook extends _GraphInstance { - public get sections(): ISections { + public get sections(): Combine<_GraphCollection, Pick> { return Sections(this); } + + public get sectionGroups(): Combine<_GraphCollection, Pick> { + return SectionGroups(this); + } + + /** + * Copy notebook + * @param props of type ICopyProps. groupId (id of group to copy to. Use only when copying to M365 group), renameAs name of the copy. + */ + public async copy(props: ICopyProps): Promise { + return graphPost(GraphQueryable(this, "copyNoteBook"), body(props)); + } } -export interface INotebook extends _Notebook {} +export interface INotebook extends _Notebook { } export const Notebook = graphInvokableFactory(_Notebook); /** @@ -56,64 +87,188 @@ export class _Notebooks extends _GraphCollection { * * @param displayName Notebook display name */ - public async add(displayName: string): Promise { - - const data = await graphPost(this, body({ displayName })); + public async add(displayName: string): Promise { + return graphPost(this, body({ displayName })); + } - return { - data, - notebook: (this).getById(data.id), - }; + /** + * Get a list of recent notebooks for the sign-in user + * @param includePersonalNotebooks Include notebooks owned by the user. Set to true to include notebooks owned by the user; otherwise, set to false. + */ + public async recent(includePersonalNotebooks = false): Promise { + return graphGet(GraphQueryable(this, `getRecentNotebooks(includePersonalNotebooks=${includePersonalNotebooks})`)); } } -export interface INotebooks extends _Notebooks, IGetById {} +export interface INotebooks extends _Notebooks, IGetById { } export const Notebooks = graphInvokableFactory(_Notebooks); - /** - * Describes a sections instance + * Describes a OneNote sections instance */ -export class _Section extends _GraphInstance { } +export class _Section extends _GraphInstance { + + public get pages(): IPages { + return Pages(this); + } + + /** + * Copy section to notebook + * @param props of type ICopySectionProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. + */ + public async copyToNotebook(props: ICopySectionProps): Promise { + return graphPost(GraphQueryable(this, "copyToNoteBook"), body(props)); + } + + /** + * Copy section group + * @param props of type ICopySectionProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. + */ + public async copyToSectionGroup(props: ICopySectionProps): Promise { + return graphPost(GraphQueryable(this, "copyToNoteBook"), body(props)); + } +} export interface ISection extends _Section { } export const Section = graphInvokableFactory(_Section); /** - * Describes a collection of Sections objects + * Describes a collection of onenote sections objects * */ @defaultPath("sections") @getById(Section) -export class _Sections extends _GraphCollection { +export class _Sections extends _GraphCollection { /** * Adds a new section * * @param displayName New section display name */ - public async add(displayName: string): Promise { + public async add(displayName: string): Promise { + return graphPost(this, body({ displayName })); + } +} +export interface ISections extends _Sections, IGetById { } +export const Sections = graphInvokableFactory(_Sections); + +/** + * Describes a root onenote sections group instance + */ +export class _SectionGroup extends _GraphInstance { + public get sections(): ISections { + return Sections(this); + } +} +export interface ISectionGroup extends _SectionGroup { } +export const SectionGroup = graphInvokableFactory(_SectionGroup); + +/** + * Describes a collection of Sections objects + * + */ +@defaultPath("sectiongroups") +@getById(SectionGroup) +export class _SectionGroups extends _GraphCollection { + /** + * Adds a new section group + * @param displayName New section group display name + */ + public async add(displayName: string): Promise { + return graphPost(this, body({ displayName })); + } + + public get sections(): ISections { + return Sections(this); + } +} +export interface ISectionGroups extends _SectionGroups, IGetById { } +export const SectionGroups = graphInvokableFactory(_SectionGroups); + +/** + * Describes a page instance + * + */ +@deleteable() +export class _Page extends _GraphInstance { + /** + * Copy page to section + * @param props of type ICopyPageProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook + */ + public async copyToSection(props: ICopyPageProps): Promise { + return graphPost(GraphQueryable(this, "copyToSection"), body(props)); + } - const data = await graphPost(this, body({ displayName })); + /** + * Gets contents of a page + * + * @param includeIDs page html body + */ + public async content(includeIDs = false): Promise { + return Page(this, `content?includeIDs=${includeIDs}`).using(TextParse())(); + } - return { - data, - section: (this).getById(data.id), - }; + /** + * Copy page to section + * @param props of type IOnenotePatchContentCommand. + */ + public async update(props: IOnenotePatchContentCommand[]): Promise { + return graphPatch(GraphQueryable(this, "content"), body(props)); } } -export interface ISections extends _Sections, IGetById {} -export const Sections = graphInvokableFactory(_Sections); +export interface IPage extends _Page, IDeleteable { } +export const Page = graphInvokableFactory(_Page); /** - * INotebookAddResult + * Describes a collection of page objects + * */ -export interface INotebookAddResult { - data: any; - notebook: INotebook; +@defaultPath("pages") +@getById(Page) +export class _Pages extends _GraphCollection { + /** + * Create a new page as specified in the request body. + * + * @param html page html body + */ + public async add(html: string): Promise { + const q = GraphQueryable(this); + q.using(InjectHeaders({ + "Content-Type": "text/html", + })); + + return graphPost(q, { body: html }); + } } +export interface IPages extends _Pages, IGetById { } +export const Pages = graphInvokableFactory(_Pages); /** - * ISectionAddResult + * Describes a resources + * */ -export interface ISectionAddResult { - data: any; - section: ISection; +@defaultPath("resources") +export class _Resources extends _GraphInstance { + /** + * getById returns a Blob. API does not support getting JSON representation. + * @param id id of the resource in a OneNote page + * @returns Blob of the resource from a OneNote page + */ + public getById(id: string): _GraphQueryable { + return GraphQueryable(this, `${id}/content`).using(BlobParse()); + } +} +export interface IResources extends _Resources { } +export const Resources = graphInvokableFactory(_Resources); + + +export interface ICopyProps { + groupId?: string; + renameAs?: string; +} + +export interface ICopySectionProps extends ICopyProps { + id: string; +} + +export interface ICopyPageProps { + groupId?: string; + id: string; } diff --git a/packages/graph/operations/onenote.ts b/packages/graph/operations/onenote.ts new file mode 100644 index 000000000..37c3bdd23 --- /dev/null +++ b/packages/graph/operations/onenote.ts @@ -0,0 +1,14 @@ +import { addProp } from "@pnp/queryable"; +import { _OneNote } from "../onenote/types.js"; +import { IOperations, Operations } from "./types.js"; + +declare module "../onenote/types" { + interface _OneNote { + readonly operations: IOperations; + } + interface IOneNote { + readonly operations: IOperations; + } +} + +addProp(_OneNote, "operations", Operations); diff --git a/test/graph/onenote.ts b/test/graph/onenote.ts new file mode 100644 index 000000000..a5be833e3 --- /dev/null +++ b/test/graph/onenote.ts @@ -0,0 +1,219 @@ +import { expect } from "chai"; +import { getRandomString, stringIsNullOrEmpty } from "@pnp/core"; +import { pnpTest } from "../pnp-test.js"; +import "@pnp/graph/groups"; +import "@pnp/graph/sites"; +import "@pnp/graph/users"; +import "@pnp/graph/onenote"; +import { Notebook } from "@microsoft/microsoft-graph-types"; +import getValidUser from "./utilities/getValidUser.js"; + +describe("OneNote", function () { + let notebook: Notebook; + let testUserName: string; + + before(async function () { + + if (!this.pnp.settings.enableWebTests || stringIsNullOrEmpty(this.pnp.settings.testUser)) { + this.skip(); + } + + const userInfo = await getValidUser.call(this); + testUserName = userInfo.userPrincipalName; + notebook = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.add(getRandomString(10)); + + if(!notebook.id){ + this.skip(); + } + }); + + it("onenote - list notebooks", pnpTest("9d0fe4b3-dc62-4699-be83-cc6f72daa62", async function () { + const oneNoteNoteBooks = await this.pnp.graph.users.getById(testUserName).onenote.notebooks(); + return expect(oneNoteNoteBooks).to.be.an("array"); + })); + + it.skip("onenote - list recent notebooks", pnpTest("769fbaf2-d92b-47aa-a2f5-6fccfc569b4d", async function () { + const oneNoteNoteBooks = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.recent(); + return expect(oneNoteNoteBooks).to.be.an("array"); + })); + + it("onenote - notebooks getById()", pnpTest("9e75f0cf-9940-4988-b05f-2aff019e8296", async function () { + const notebookById = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id)(); + return expect(notebookById.id).is.not.null; + })); + + it("onenote - add notebook", pnpTest("81c342d9-d943-4a18-a8c3-828ef090d447", async function () { + const oneNodeNotebooksAdd = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.add(getRandomString(10)); + return expect(oneNodeNotebooksAdd.id).is.not.null; + })); + + it("onenote - list sections", pnpTest("ca8871f8-c90e-48e4-8909-39f42884ea2c", async function () { + const sections = await this.pnp.graph.users.getById(testUserName).onenote.sections(); + return expect(sections).to.be.an("array"); + })); + + it("onenote - notebook copy", pnpTest("aa57039b-4c75-437d-92ae-bb2a06c7b802", async function () { + const notebooks = await this.pnp.graph.users.getById(testUserName).onenote.notebooks(); + if(notebooks.length > 0){ + const copy = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebooks[0].id).copy({renameAs:getRandomString(10)}); + return expect(copy.id).is.not.null; + } + this.skip(); + })); + + it("onenote - section copyToNotebook()", pnpTest("b5cc2f9b-0a19-4d42-a041-1a68a2cfd915", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + if(section){ + const copy = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).copyToNotebook({id:notebook.id, renameAs:getRandomString(10)}); + return expect(copy.id).is.not.null; + } + this.skip(); + })); + + it("onenote - section copyToSectionGroup()", pnpTest("b48e5d00-7806-4bde-96fe-1650dea1e1e4", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + const group = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sectionGroups.add(getRandomString(10)); + if(section.id && group.id){ + const copy = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).copyToSectionGroup({id:group.id, renameAs:getRandomString(5)}); + return expect(copy.id).is.not.null; + } + this.skip(); + })); + + // doesn't work well with large onenotes. + it.skip("onenote - list pages", pnpTest("77d47760-0371-4045-898d-6a95d8e42cca", async function () { + const pages = await this.pnp.graph.users.getById(testUserName).onenote.pages(); + return expect(pages).to.be.an("array"); + })); + + // doesn't work well with large onenotes. + it.skip("onenote - pages getById()", pnpTest("fcd78bde-69a0-4331-8aa4-389bba222963", async function () { + const pages = await this.pnp.graph.users.getById(testUserName).onenote.pages(); + if(pages.length > 0){ + const page = await this.pnp.graph.users.getById(testUserName).onenote.pages.getById(pages[0].id)(); + return expect(page.id).is.not.null; + } + this.skip(); + })); + + it("onenote - pages copyToSection", pnpTest("e8c21973-8d90-4bc4-947f-ef39198832dd", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + const pages = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).pages(); + if(section.id && pages.length > 0) { + const pageCopy = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).pages.getById(pages[0].id).copyToSection({id:section.id}); + return expect(pageCopy).to.be.fulfilled; + } + + this.skip(); + })); + + it("onenote - add page", pnpTest("60a4fd91-3f6b-4f6f-a5bb-e11f57186eaf", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + if(section.id){ + const pageData =` + + + A page with <i>rendered</i> images and an <b>attached</b> file + + + +

    Here's an image from an online source:

    + an image on the page +

    Here's an image uploaded as binary data:

    + an image on the page +

    Here's a file attachment:

    + + + `; + const page = await this.pnp.graph.users.getById(testUserName).onenote.pages.add(pageData); + return expect(page.id).is.not.null; + } + this.skip(); + })); + + it("onenote - sections list pages", pnpTest("5f44bc04-6119-432e-ac92-602085c4dc91", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + if(section.id){ + const pages = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).pages(); + return expect(pages).to.be.an("array"); + } + this.skip(); + })); + + + it("onenote - sections add page", pnpTest("48744c5a-999a-40fb-9ab8-9d06e0b544a2", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + if(section.id){ + const pageData =` + + + A page with <i>rendered</i> images and an <b>attached</b> file + + + +

    Here's an image from an online source:

    + an image on the page +

    Here's an image uploaded as binary data:

    + an image on the page +

    Here's a file attachment:

    + + + `; + const page = await this.pnp.graph.users.getById(testUserName).onenote.sections.getById(section.id).pages.add(pageData); + return expect(page.id).is.not.null; + } + this.skip(); + })); + + it("onenote - list section groups", pnpTest("df461253-a206-4ebf-b993-5b7a76d2ee5b", async function () { + const sectionGroups = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups(); + return expect(sectionGroups).to.be.an("array"); + })); + + it("onenote - sectionGroups getById()", pnpTest("4dd65bad-d8db-4b05-984a-ec06cd650c62", async function () { + const sectionGroups = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups(); + if(sectionGroups.length > 0){ + const section = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups.getById(sectionGroups[0].id)(); + return expect(section.id).is.not.null; + } + this.skip(); + })); + + it("onenote - list section groups sections", pnpTest("ef961253-a206-4ebf-b993-5a1a76d2ff5b", async function () { + const sectionGroups = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups(); + if(sectionGroups.length > 0){ + const sections = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups.getById(sectionGroups[0].id).sections(); + return expect(sections).to.be.an("array"); + } + this.skip(); + })); + + it("onenote - create section in section group", pnpTest("4959895e-404f-4068-bf5f-85b0d2db9bcf", async function () { + const sectionGroups = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups(); + if(sectionGroups.length > 0){ + const section = await this.pnp.graph.users.getById(testUserName).onenote.sectionGroups.getById(sectionGroups[0].id).sections.add(getRandomString(10)); + return expect(section.id).is.not.null; + } + this.skip(); + })); + + it("notebook - list sections", pnpTest("b746d08e-f07d-4df2-82a3-7e1c7522bef8", async function () { + const sections = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections(); + return expect(sections).to.be.an("array"); + })); + + it("notebook - add section", pnpTest("1298ee0d-0566-4144-ab56-d8e3c89654c7", async function () { + const section = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sections.add(getRandomString(10)); + return expect(section.id).is.not.null; + })); + + it("notebook - list section groups", pnpTest("66f3aeaa-e9d2-4b26-8894-6ed226e1f180", async function () { + const sectionGroups = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sectionGroups(); + return expect(sectionGroups).to.be.an("array"); + })); + + it("notebook - add section group", pnpTest("cb1d6d80-d5dc-4879-ac5a-288a5f0249ba", async function () { + const sectionGroup = await this.pnp.graph.users.getById(testUserName).onenote.notebooks.getById(notebook.id).sectionGroups.add(getRandomString(10)); + return expect(sectionGroup.id).is.not.null; + })); +}); From a7143dbb817e25da3632f78bd92aefb7d188b95b Mon Sep 17 00:00:00 2001 From: Beau Cameron Date: Mon, 8 Jan 2024 20:22:44 -0700 Subject: [PATCH 2/2] Clean up extra interfaces --- packages/graph/onenote/types.ts | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/graph/onenote/types.ts b/packages/graph/onenote/types.ts index 3162fcfc4..94f4e12dc 100644 --- a/packages/graph/onenote/types.ts +++ b/packages/graph/onenote/types.ts @@ -68,7 +68,7 @@ export class _Notebook extends _GraphInstance { * Copy notebook * @param props of type ICopyProps. groupId (id of group to copy to. Use only when copying to M365 group), renameAs name of the copy. */ - public async copy(props: ICopyProps): Promise { + public async copy(props: Pick): Promise { return graphPost(GraphQueryable(this, "copyNoteBook"), body(props)); } } @@ -113,17 +113,17 @@ export class _Section extends _GraphInstance { /** * Copy section to notebook - * @param props of type ICopySectionProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. + * @param props of type ICopyProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. */ - public async copyToNotebook(props: ICopySectionProps): Promise { + public async copyToNotebook(props: ICopyProps): Promise { return graphPost(GraphQueryable(this, "copyToNoteBook"), body(props)); } /** * Copy section group - * @param props of type ICopySectionProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. + * @param props of type ICopyProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook, renameAs name of the copy. */ - public async copyToSectionGroup(props: ICopySectionProps): Promise { + public async copyToSectionGroup(props: ICopyProps): Promise { return graphPost(GraphQueryable(this, "copyToNoteBook"), body(props)); } } @@ -192,7 +192,7 @@ export class _Page extends _GraphInstance { * Copy page to section * @param props of type ICopyPageProps. groupId (id of group to copy to. Use only when copying to M365 group), id of destination notebook */ - public async copyToSection(props: ICopyPageProps): Promise { + public async copyToSection(props: Pick): Promise { return graphPost(GraphQueryable(this, "copyToSection"), body(props)); } @@ -258,17 +258,8 @@ export class _Resources extends _GraphInstance { export interface IResources extends _Resources { } export const Resources = graphInvokableFactory(_Resources); - export interface ICopyProps { groupId?: string; renameAs?: string; -} - -export interface ICopySectionProps extends ICopyProps { - id: string; -} - -export interface ICopyPageProps { - groupId?: string; id: string; }