@pnp/cli-microsoft365
Version:
Manage Microsoft 365 and SharePoint Framework projects on any platform
374 lines • 19.1 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _SpoPageSectionAddCommand_instances, _SpoPageSectionAddCommand_initTelemetry, _SpoPageSectionAddCommand_initOptions, _SpoPageSectionAddCommand_initValidators, _SpoPageSectionAddCommand_initTypes;
import { v4 } from 'uuid';
import request from '../../../../request.js';
import { formatting } from '../../../../utils/formatting.js';
import { validation } from '../../../../utils/validation.js';
import SpoCommand from '../../../base/SpoCommand.js';
import commands from '../../commands.js';
import { CanvasSectionTemplate } from './clientsidepages.js';
class SpoPageSectionAddCommand extends SpoCommand {
get name() {
return commands.PAGE_SECTION_ADD;
}
get description() {
return 'Adds section to modern page';
}
constructor() {
super();
_SpoPageSectionAddCommand_instances.add(this);
this.sectionTemplate = ['OneColumn', 'OneColumnFullWidth', 'TwoColumn', 'ThreeColumn', 'TwoColumnLeft', 'TwoColumnRight', 'Vertical'];
this.zoneEmphasis = ['None', 'Neutral', 'Soft', 'Strong', 'Image', 'Gradient'];
this.iconAlignment = ['Left', 'Right'];
this.fillMode = ['ScaleToFill', 'ScaleToFit', 'Tile', 'OriginalSize'];
__classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initTelemetry).call(this);
__classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initOptions).call(this);
__classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initValidators).call(this);
__classPrivateFieldGet(this, _SpoPageSectionAddCommand_instances, "m", _SpoPageSectionAddCommand_initTypes).call(this);
}
async commandAction(logger, args) {
let pageFullName = args.options.pageName.toLowerCase();
if (!pageFullName.endsWith('.aspx')) {
pageFullName += '.aspx';
}
let canvasContent;
if (this.verbose) {
await logger.logToStderr(`Retrieving page information...`);
}
try {
let requestOptions = {
url: `${args.options.webUrl}/_api/sitepages/pages/GetByUrl('sitepages/${formatting.encodeQueryParameter(pageFullName)}')?$select=CanvasContent1,IsPageCheckedOutToCurrentUser`,
headers: {
'accept': 'application/json;odata=nometadata'
},
responseType: 'json'
};
const res = await request.get(requestOptions);
canvasContent = JSON.parse(res.CanvasContent1 || "[{\"controlType\":0,\"pageSettingsSlice\":{\"isDefaultDescription\":true,\"isDefaultThumbnail\":true}}]");
if (!res.IsPageCheckedOutToCurrentUser) {
requestOptions = {
url: `${args.options.webUrl}/_api/sitepages/pages/GetByUrl('sitepages/${formatting.encodeQueryParameter(pageFullName)}')/checkoutpage`,
headers: {
'accept': 'application/json;odata=nometadata'
},
responseType: 'json'
};
await request.post(requestOptions);
}
// get columns
const columns = canvasContent
.filter(c => typeof c.controlType === 'undefined');
// get unique zoneIndex values given each section can have 1 or more
// columns each assigned to the zoneIndex of the corresponding section
const zoneIndices = columns
.map(c => c.position.zoneIndex)
.filter((value, index, array) => {
return array.indexOf(value) === index;
})
.sort();
// zoneIndex for the new section to add
const zoneIndex = this.getSectionIndex(zoneIndices, args.options.order);
let zoneId;
let backgroundControlToAdd = undefined;
if (args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) {
zoneId = v4();
// get background control based on control type 14
const backgroundControl = canvasContent.find(c => c.controlType === 14);
backgroundControlToAdd = this.setBackgroundControl(zoneId, backgroundControl, args);
if (!backgroundControl) {
canvasContent.push(backgroundControlToAdd);
}
}
// get the list of columns to insert based on the selected template
const columnsToAdd = this.getColumns(zoneIndex, args, zoneId);
// insert the column in the right place in the array so that
// it stays sorted ascending by zoneIndex
let pos = canvasContent.findIndex(c => typeof c.controlType === 'undefined' && c.position && c.position.zoneIndex > zoneIndex);
if (pos === -1) {
pos = canvasContent.length - 1;
}
canvasContent.splice(pos, 0, ...columnsToAdd);
requestOptions = {
url: `${args.options.webUrl}/_api/sitepages/pages/GetByUrl('sitepages/${formatting.encodeQueryParameter(pageFullName)}')/savepage`,
headers: {
'accept': 'application/json;odata=nometadata',
'content-type': 'application/json;odata=nometadata'
},
data: {
CanvasContent1: JSON.stringify(canvasContent)
},
responseType: 'json'
};
await request.post(requestOptions);
}
catch (err) {
this.handleRejectedODataJsonPromise(err);
}
}
getSectionIndex(zoneIndices, order) {
// zoneIndex of the first column on the page
const minIndex = zoneIndices.length === 0 ? 0 : zoneIndices[0];
// zoneIndex of the last column on the page
const maxIndex = zoneIndices.length === 0 ? 0 : zoneIndices[zoneIndices.length - 1];
if (!order || order > zoneIndices.length) {
// no order specified, add section to the end
return maxIndex === 0 ? 1 : maxIndex * 2;
}
// add to the beginning
if (order === 1) {
return minIndex / 2;
}
return zoneIndices[order - 2] + ((zoneIndices[order - 1] - zoneIndices[order - 2]) / 2);
}
getColumns(zoneIndex, args, zoneId) {
const columns = [];
let sectionIndex = 1;
switch (args.options.sectionTemplate) {
case 'OneColumnFullWidth':
columns.push(this.getColumn(zoneIndex, sectionIndex++, 0, args, zoneId));
break;
case 'TwoColumn':
columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, args, zoneId));
columns.push(this.getColumn(zoneIndex, sectionIndex++, 6, args, zoneId));
break;
case 'ThreeColumn':
columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
break;
case 'TwoColumnLeft':
columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, args, zoneId));
columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
break;
case 'TwoColumnRight':
columns.push(this.getColumn(zoneIndex, sectionIndex++, 4, args, zoneId));
columns.push(this.getColumn(zoneIndex, sectionIndex++, 8, args, zoneId));
break;
case 'Vertical':
columns.push(this.getVerticalColumn(args, zoneId));
break;
case 'OneColumn':
default:
columns.push(this.getColumn(zoneIndex, sectionIndex++, 12, args, zoneId));
break;
}
return columns;
}
getColumn(zoneIndex, sectionIndex, sectionFactor, args, zoneId) {
const { zoneEmphasis, isCollapsibleSection, isExpanded, showDivider, iconAlignment, collapsibleTitle } = args.options;
const columnValue = {
displayMode: 2,
position: {
zoneIndex: zoneIndex,
sectionIndex: sectionIndex,
sectionFactor: sectionFactor,
layoutIndex: 1,
zoneId: zoneId
},
emphasis: {}
};
if (zoneEmphasis && ['none', 'neutral', 'soft', 'strong'].includes(zoneEmphasis?.toLocaleLowerCase())) {
// Just these zoneEmphasis values should be added to column emphasis
const zoneEmphasisValue = ['none', 'neutral', 'soft', 'strong'].indexOf(zoneEmphasis.toLocaleLowerCase());
columnValue.emphasis = { zoneEmphasis: zoneEmphasisValue };
}
if (isCollapsibleSection) {
columnValue.zoneGroupMetadata = {
type: 1,
isExpanded: !!isExpanded,
showDividerLine: !!showDivider,
iconAlignment: iconAlignment && iconAlignment.toLocaleLowerCase() === "right" ? "right" : "left",
displayName: collapsibleTitle
};
}
return columnValue;
}
getVerticalColumn(args, zoneId) {
const columnValue = this.getColumn(1, 1, 12, args, zoneId);
columnValue.position.isLayoutReflowOnTop = args.options.isLayoutReflowOnTop !== undefined;
columnValue.position.layoutIndex = 2;
columnValue.position.controlIndex = 1;
return columnValue;
}
setBackgroundControl(zoneId, backgroundControl, args) {
const { overlayColor, overlayOpacity, useLightText, imageUrl } = args.options;
const backgroundDetails = this.getBackgroundDetails(args);
if (!backgroundControl) {
backgroundControl = {
controlType: 14,
webPartData: {
properties: {
zoneBackground: {}
},
serverProcessedContent: {
htmlStrings: {},
searchablePlainTexts: {},
imageSources: {},
links: {}
},
dataVersion: "1.0"
}
};
}
backgroundControl.webPartData.properties.zoneBackground[zoneId] = {
...backgroundDetails,
useLightText: !!useLightText,
overlay: {
color: overlayColor ? overlayColor : "#FFFFFF",
opacity: overlayOpacity ? overlayOpacity : 60
}
};
if (imageUrl && backgroundControl.webPartData.serverProcessedContent.imageSources) {
backgroundControl.webPartData.serverProcessedContent.imageSources[`zoneBackground.${zoneId}.imageData.url`] = imageUrl;
}
return backgroundControl;
}
getBackgroundDetails(args) {
const { gradientText, imageUrl, imageHeight, imageWidth, fillMode } = args.options;
const backgroundDetails = {};
if (gradientText) {
backgroundDetails.type = "gradient";
backgroundDetails.gradient = gradientText;
}
if (imageUrl) {
backgroundDetails.type = "image";
backgroundDetails.imageData = {
source: 2,
fileName: "sectionbackground.jpg",
height: imageHeight ? imageHeight : 955,
width: imageWidth ? imageWidth : 555
};
backgroundDetails.fillMode = fillMode ? this.fillMode.indexOf(fillMode) : 0;
}
return backgroundDetails;
}
}
_SpoPageSectionAddCommand_instances = new WeakSet(), _SpoPageSectionAddCommand_initTelemetry = function _SpoPageSectionAddCommand_initTelemetry() {
this.telemetry.push((args) => {
Object.assign(this.telemetryProperties, {
order: typeof args.options.order !== 'undefined',
zoneEmphasis: typeof args.options.zoneEmphasis !== 'undefined',
isLayoutReflowOnTop: !!args.options.isLayoutReflowOnTop,
isCollapsibleSection: !!args.options.isCollapsibleSection,
showDivider: !!typeof args.options.showDivider,
iconAlignment: typeof args.options.iconAlignment !== 'undefined',
isExpanded: !!args.options.isExpanded,
gradientText: typeof args.options.gradientText !== 'undefined',
imageUrl: typeof args.options.imageUrl !== 'undefined',
imageHeight: typeof args.options.imageHeight !== 'undefined',
imageWidth: typeof args.options.imageWidth !== 'undefined',
fillMode: typeof args.options.fillMode !== 'undefined',
useLightText: !!args.options.useLightText,
overlayColor: typeof args.options.overlayColor !== 'undefined',
overlayOpacity: typeof args.options.overlayOpacity !== 'undefined',
collapsibleTitle: typeof args.options.collapsibleTitle !== 'undefined'
});
});
}, _SpoPageSectionAddCommand_initOptions = function _SpoPageSectionAddCommand_initOptions() {
this.options.unshift({
option: '-n, --pageName <pageName>'
}, {
option: '-u, --webUrl <webUrl>'
}, {
option: '-t, --sectionTemplate <sectionTemplate>',
autocomplete: this.sectionTemplate
}, {
option: '--order [order]'
}, {
option: '--zoneEmphasis [zoneEmphasis]',
autocomplete: this.zoneEmphasis
}, {
option: '--isLayoutReflowOnTop'
}, {
option: '--isCollapsibleSection'
}, {
option: '--showDivider'
}, {
option: '--iconAlignment [iconAlignment]',
autocomplete: this.iconAlignment
}, {
option: '--isExpanded'
}, {
option: '--gradientText [gradientText]'
}, {
option: '--imageUrl [imageUrl]'
}, {
option: '--imageHeight [imageHeight]'
}, {
option: '--imageWidth [imageWidth]'
}, {
option: '--fillMode [fillMode]',
autocomplete: this.fillMode
}, {
option: '--useLightText'
}, {
option: '--overlayColor [overlayColor]'
}, {
option: '--overlayOpacity [overlayOpacity]'
}, {
option: '--collapsibleTitle [collapsibleTitle]'
});
}, _SpoPageSectionAddCommand_initValidators = function _SpoPageSectionAddCommand_initValidators() {
this.validators.push(async (args) => {
if (!(args.options.sectionTemplate in CanvasSectionTemplate)) {
return `${args.options.sectionTemplate} is not a valid section template. Allowed values are OneColumn|OneColumnFullWidth|TwoColumn|ThreeColumn|TwoColumnLeft|TwoColumnRight|Vertical`;
}
if (typeof args.options.order !== 'undefined') {
if (!Number.isInteger(args.options.order) || args.options.order < 1) {
return 'The value of parameter order must be 1 or higher';
}
}
if (typeof args.options.zoneEmphasis !== 'undefined') {
if (!this.zoneEmphasis.some(zoneEmphasisValue => zoneEmphasisValue.toLocaleLowerCase() === args.options.zoneEmphasis?.toLowerCase())) {
return `The value of parameter zoneEmphasis must be ${this.zoneEmphasis.join(', ')}`;
}
}
if (typeof args.options.isLayoutReflowOnTop !== 'undefined') {
if (args.options.sectionTemplate !== 'Vertical') {
return 'Specify isLayoutReflowOnTop when the sectionTemplate is set to Vertical.';
}
}
if (typeof args.options.iconAlignment !== 'undefined') {
if (!this.iconAlignment.some(iconAlignmentValue => iconAlignmentValue.toLocaleLowerCase() === args.options.iconAlignment?.toLowerCase())) {
return `The value of parameter iconAlignment must be ${this.iconAlignment.join(', ')}`;
}
}
if (typeof args.options.fillMode !== 'undefined') {
if (!this.fillMode.some(fillModeValue => fillModeValue.toLocaleLowerCase() === args.options.fillMode?.toLowerCase())) {
return `The value of parameter fillMode must be ${this.fillMode.join(', ')}`;
}
}
if (args.options.zoneEmphasis?.toLocaleLowerCase() !== 'image' && (args.options.imageUrl || args.options.imageWidth ||
args.options.imageHeight || args.options.fillMode)) {
return 'Specify imageUrl, imageWidth, imageHeight or fillMode only when zoneEmphasis is set to Image';
}
if (args.options.zoneEmphasis?.toLocaleLowerCase() === 'image' && !args.options.imageUrl) {
return 'Specify imageUrl when zoneEmphasis is set to Image';
}
if (args.options.zoneEmphasis?.toLowerCase() !== 'gradient' && args.options.gradientText) {
return 'Specify gradientText only when zoneEmphasis is set to Gradient';
}
if (args.options.zoneEmphasis?.toLowerCase() === 'gradient' && !args.options.gradientText) {
return 'Specify gradientText when zoneEmphasis is set to Gradient';
}
if (args.options.overlayOpacity && (args.options.overlayOpacity < 0 || args.options.overlayOpacity > 100)) {
return 'The value of parameter overlayOpacity must be between 0 and 100';
}
if (args.options.overlayColor && !/^#[0-9a-f]{6}$/i.test(args.options.overlayColor)) {
return 'The value of parameter overlayColor must be a valid hex color';
}
if (!(args.options.zoneEmphasis && ['image', 'gradient'].includes(args.options.zoneEmphasis.toLowerCase())) && (args.options.overlayColor || args.options.overlayOpacity || args.options.useLightText)) {
return 'Specify overlayColor or overlayOpacity only when zoneEmphasis is set to Image or Gradient';
}
return validation.isValidSharePointUrl(args.options.webUrl);
});
}, _SpoPageSectionAddCommand_initTypes = function _SpoPageSectionAddCommand_initTypes() {
this.types.string = ['pageName', 'webUrl', 'sectionTemplate', 'zoneEmphasis', 'iconAlignment', 'gradientText', 'imageUrl', 'fillMode', 'overlayColor', 'collapsibleTitle'];
this.types.boolean = ['isLayoutReflowOnTop', 'isCollapsibleSection', 'showDivider', 'isExpanded', 'useLightText'];
};
export default new SpoPageSectionAddCommand();
//# sourceMappingURL=page-section-add.js.map