Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhances 'spo page set' command Closes #4840 #5502

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions docs/docs/cmd/spo/page/page-set.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ m365 spo page set [options]

`--title [title]`
: The title to set for the page.

`--content [content]`
: JSON string containing page content
```

<Global />
Expand All @@ -52,6 +55,20 @@ If you try to create a page with a name of a page that already exists, you will

If you choose to promote the page using the `promoteAs` option or enable page comments, you will see the result only after publishing the page.

Running this command from the Windows Command Shell (cmd.exe) or PowerShell for Windows OS XP, 7, 8, 8.1 without bash installed might require additional formatting for command options that have JSON, XML or JavaScript values because the command shell treat quotes differently. For example, this is how you can add page content from the Windows cmd.exe:

```sh
m365 spo page set --name page.aspx --webUrl https://contoso.sharepoint.com/sites/a-team --content '[{\"controlType\": 4,\"id\": \"42b8afe8-dafe-4c11-bfbf-df5ef5b1feb7\",\"position\": {\"layoutIndex\": 1,\"zoneIndex\": 1,\"sectionIndex\": 1,\"sectionFactor\": 12,\"controlIndex\": 1},\"addedFromPersistedData\": true,\"innerHTML\":\"<p>Hello World</p>\"}]'
```

Note, how the content option has escaped double quotes `'[{\"controlType\": 4,\"id\": \"42b8afe8-dafe-4c11-bfbf-df5ef5b1feb7\",\"position\": {\"layoutIndex\": 1,\"zoneIndex\": 1,\"sectionIndex\": 1,\"sectionFactor\": 12,\"controlIndex\": 1},\"addedFromPersistedData\": true,\"innerHTML\":\"<p>Hello World</p>\"}]'` compared to execution from bash `''[{"controlType": 4,"id": "42b8afe8-dafe-4c11-bfbf-df5ef5b1feb7","position": {"layoutIndex": 1,"zoneIndex": 1,"sectionIndex": 1,"sectionFactor": 12,"controlIndex": 1},"addedFromPersistedData": true,"innerHTML":"<p>Hello World</p>"}]'`.

:::caution Escaping JSON in PowerShell

When using the `--content` option it's possible to enter a JSON string. In PowerShell 5 to 7.2 [specific escaping rules](./../../../user-guide/using-cli.mdx#escaping-double-quotes-in-powershell) apply due to an issue. Remember that you can also use [file tokens](./../../../user-guide/using-cli.mdx#passing-complex-content-into-cli-options) instead.

:::

## Examples

Change the layout of the existing page to _Article_
Expand Down Expand Up @@ -102,6 +119,12 @@ Set page description
m365 spo page set --name page.aspx --webUrl https://contoso.sharepoint.com/sites/a-team --description "Description to add for the page"
```

Set page content

```sh
m365 spo page set --name page.aspx --webUrl https://contoso.sharepoint.com/sites/a-team --content '[{\"controlType\": 4,\"id\": \"42b8afe8-dafe-4c11-bfbf-df5ef5b1feb7\",\"position\": {\"layoutIndex\": 1,\"zoneIndex\": 1,\"sectionIndex\": 1,\"sectionFactor\": 12,\"controlIndex\": 1},\"addedFromPersistedData\": true,\"innerHTML\":\"<p>Hello World</p>\"}]'
```

## Response

The command won't return a response on success.
57 changes: 57 additions & 0 deletions src/m365/spo/commands/page/page-set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,53 @@ describe(commands.PAGE_SET, () => {
await command.action(logger, { options: { debug: true, name: 'page.aspx', webUrl: 'https://contoso.sharepoint.com/sites/team-a', title: newPageTitle } });
});

it('updates page content', async () => {
sinonUtil.restore([request.post]);

const newContent = [{
"controlType": 4,
"position": {
"layoutIndex": 1,
"zoneIndex": 1,
"sectionIndex": 1,
"sectionFactor": 12,
"controlIndex": 1
},
"addedFromPersistedData": true,
"innerHTML": "<p>Text content</p>"
}];

const initialPage = {
Title: "article",
Id: 1,
TopicHeader: "TopicHeader",
AuthorByline: "AuthorByline",
Description: "Description",
BannerImageUrl: {
Description: '/_layouts/15/images/sitepagethumbnail.png',
Url: `https://contoso.sharepoint.com/_layouts/15/images/sitepagethumbnail.png`
},
CanvasContent1: "{}",
LayoutWebpartsContent: "{}"
};

let data: string = '';
sinon.stub(request, 'post').callsFake(async (opts) => {
if ((opts.url as string).includes(`/_api/sitepages/pages/GetByUrl('sitepages/page.aspx')/checkoutpage`)) {
return initialPage;
}
if ((opts.url as string).includes(`/_api/SitePages/Pages(1)/SavePage`) ||
(opts.url as string).includes(`/_api/SitePages/Pages(1)/SavePageAsDraft`)) {
data = opts.data.CanvasContent1;
return {};
}
throw 'Invalid request';
});

await command.action(logger, { options: { debug: true, name: 'page.aspx', webUrl: 'https://contoso.sharepoint.com/sites/team-a', content: JSON.stringify(newContent) } });
assert.deepStrictEqual(JSON.parse(data), newContent);
});

it('publishes page', async () => {
sinonUtil.restore([request.post]);

Expand Down Expand Up @@ -780,4 +827,14 @@ describe(commands.PAGE_SET, () => {
const actual = await command.validate({ options: { name: 'page.aspx', webUrl: 'https://contoso.sharepoint.com', commentsEnabled: false } }, commandInfo);
assert.strictEqual(actual, true);
});

it('fails validation if content is not valid JSON', async () => {
const actual = await command.validate({ options: { name: 'page.aspx', webUrl: 'https://contoso.sharepoint.com', content: "foo" } }, commandInfo);
assert.notStrictEqual(actual, true);
});

it('passes validation if content is valid JSON', async () => {
const actual = await command.validate({ options: { name: 'page.aspx', webUrl: 'https://contoso.sharepoint.com', content: "[]" } }, commandInfo);
assert.strictEqual(actual, true);
});
});
18 changes: 16 additions & 2 deletions src/m365/spo/commands/page/page-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface Options extends GlobalOptions {
description?: string;
title?: string;
demoteFrom?: string;
content?: string;
}

class SpoPageSetCommand extends SpoCommand {
Expand Down Expand Up @@ -59,7 +60,8 @@ class SpoPageSetCommand extends SpoCommand {
publish: args.options.publish || false,
publishMessage: typeof args.options.publishMessage !== 'undefined',
description: typeof args.options.description !== 'undefined',
title: typeof args.options.title !== 'undefined'
title: typeof args.options.title !== 'undefined',
content: typeof args.options.content !== 'undefined'
});
});
}
Expand Down Expand Up @@ -99,6 +101,9 @@ class SpoPageSetCommand extends SpoCommand {
},
{
option: '--title [title]'
},
{
option: '--content [content]'
}
);
}
Expand Down Expand Up @@ -138,6 +143,15 @@ class SpoPageSetCommand extends SpoCommand {
return 'You can only promote article pages as news article';
}

if (args.options.content) {
try {
JSON.parse(args.options.content);
}
catch (e) {
return `Specified content is not a valid JSON string. Input: ${args.options.content}. Error: ${e}`;
}
}

return true;
}
);
Expand Down Expand Up @@ -174,7 +188,7 @@ class SpoPageSetCommand extends SpoCommand {
pageId = page.Id;

bannerImageUrl = page.BannerImageUrl;
canvasContent1 = page.CanvasContent1;
canvasContent1 = args.options.content || page.CanvasContent1;
layoutWebpartsContent = page.LayoutWebpartsContent;
pageDescription = pageDescription || page.Description;
topicHeader = page.TopicHeader;
Expand Down