From 15fda95d397f11b757a0f827550362cb5a1dea99 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Fri, 2 Dec 2022 17:09:28 -0600 Subject: [PATCH 01/22] Added EditFrame for react --- .../src/components/EditFrame.tsx | 287 ++++++++++++++++++ packages/sitecore-jss-react/src/index.ts | 9 + 2 files changed, 296 insertions(+) create mode 100644 packages/sitecore-jss-react/src/components/EditFrame.tsx diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx new file mode 100644 index 0000000000..aac9ad7451 --- /dev/null +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -0,0 +1,287 @@ +import PropTypes from 'prop-types'; +import React, { PropsWithChildren } from 'react'; +import { useSitecoreContext } from '../enhancers/withSitecoreContext'; + +type EditFrameButton = { + isDivider: boolean; + click: string; + header: string; + icon: string; + tooltip: string | null; + type: string | null; +}; + +const DefaultEditFrameButtonIds = { + edit: '{70C4EED5-D4CD-4D7D-9763-80C42504F5E7}', +}; + +export const DefaultEditFrameButton = { + insert: { + header: 'Insert New', + icon: '/~/icon/Office/16x16/insert_from_template.png', + click: 'webedit:new', + tooltip: 'Insert a new item', + }, + editRelatedItem: { + header: 'Edit the related item', + icon: '/~/icon/Office/16x16/cubes.png', + click: 'webedit:open', // Command in Sitecore, 'chrome:common:edititem({command:"webedit:open"})', + tooltip: 'Edit the related item in the Content Editor.', + }, + edit: { + header: 'Edit Item', + icon: '/~/icon/people/16x16/cubes_blue.png', + fields: ['Title', 'Text'], + tooltip: 'Edit the item fields.', + }, +}; + +export const DefaultEditFrameButtons = [ + DefaultEditFrameButton.editRelatedItem, + DefaultEditFrameButton.insert, + DefaultEditFrameButton.edit, +]; + +/** + * @param {WebEditButton | FieldEditButton} button the button to determine the type of + */ +function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { + return (button as WebEditButton).click !== undefined; +} + +export type EditFrameDataSource = { + itemId: string; + databaseName?: string; + language?: string; +}; + +export type FieldEditButton = { + header: string; + icon: string; + fields: string[]; + tooltip: string; +}; + +export type WebEditButton = { + header: string; + icon: string; + click: string; + tooltip: string; + parameters?: Record; + type?: string; +}; + +/** + * @param {WebEditButton } button the button to build a EditFrameButton for + * @param {string} itemId the ID of the item the EditFrame is associated with + * @param {Record} frameParameters additional parameters passed to the EditFrame + */ +function commandBuilder( + button: WebEditButton, + itemId?: string, + frameParameters?: Record +): EditFrameButton { + if (!button.click) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else if (button.click.startsWith('javascript:') || button.click.startsWith('chrome:')) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else { + if (!itemId) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else { + let message = button.click; + let parameters: Record = {}; + + const length = button.click.indexOf('('); + if (length >= 0) { + const end = button.click.indexOf(')'); + if (end < 0) { + throw new Error('Message with arguments must end with ")".'); + } + parameters = button.click + .substring(length + 1, end) + .split(',') + .map((_) => _.trim()) + .reduce((previous: Record, current) => { + const parts = current.split('='); + if (parts.length < 2) { + previous[parts[0]] = ''; + } else { + previous[parts[0]] = parts[1]; + } + return previous; + }, {}); + message = button.click.substring(0, length); + } + + parameters.id = itemId; + + if (button.parameters) { + Object.keys(button.parameters).forEach((_) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + parameters[_] = button.parameters![_]?.toString() || ''; + }); + } + + if (frameParameters) { + Object.keys(frameParameters).forEach((_) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + parameters[_] = frameParameters![_]?.toString() || ''; + }); + } + + const parameterString = Object.keys(parameters) + .map((_) => `${_}=${parameters[_]}`) + .join(', '); + + const click = `${message}(${parameterString})`; + + return { + isDivider: false, + click: `javascript:Sitecore.PageModes.PageEditor.postRequest('${click}',null,false)`, + header: button.header, + icon: button.icon, + tooltip: button.tooltip, + type: button.type || null, + }; + } + } +} + +export interface EditFrameProps { + dataSource?: EditFrameDataSource; + buttons?: (FieldEditButton | WebEditButton | '|')[]; + title?: string; + tooltip?: string; + cssClass?: string; + parameters?: Record; +} + +export const EditFrame: React.FC> = ({ + children, + dataSource, + buttons, + title, + tooltip, + cssClass, + parameters, +}: PropsWithChildren): JSX.Element => { + const { sitecoreContext } = useSitecoreContext(); + + if (!sitecoreContext.pageEditing) { + return <>; + } + + const commandData: Record = { + displayName: title, + expandedDisplayName: tooltip, + }; + + const frameProps: Record = {}; + frameProps.class = 'scLooseFrameZone'; + if (cssClass) { + frameProps.class = `${frameProps.class} ${cssClass}`; + } + + // item uri for edit frame target + if (dataSource) { + const databaseName = dataSource.databaseName || sitecoreContext.route?.databaseName; + const language = dataSource.language || sitecoreContext.language; + frameProps.sc_item = `sitecore://${databaseName}/${dataSource.itemId}?lang=${language}`; + commandData.contextItemUri = frameProps.sc_item; + } + + commandData.commands = buttons?.map( + (value): EditFrameButton => { + if (value === '|') { + return { + click: 'chrome:dummy', + header: 'Separator', + icon: '', + isDivider: false, + tooltip: null, + type: 'separator', + }; + } else if (isWebEditButton(value)) { + return commandBuilder(value, dataSource?.itemId, parameters); + } else { + const fieldsString = value.fields.join('|'); + const editButton: WebEditButton = { + click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, + ...value, + }; + + return commandBuilder(editButton, dataSource?.itemId, parameters); + } + } + ); + + return ( +
+ {JSON.stringify(commandData)} + {children} +
+ ); +}; + +EditFrame.defaultProps = { + dataSource: undefined, + buttons: [], + title: 'Edit', +}; + +export interface EditFrameProps { + dataSource?: EditFrameDataSource; + buttons?: (FieldEditButton | WebEditButton | '|')[]; + title?: string; + tooltip?: string; + cssClass?: string; + parameters?: Record; +} + +EditFrame.propTypes = { + dataSource: PropTypes.oneOf([ + undefined, + PropTypes.shape({ + itemId: PropTypes.string.isRequired, + databaseName: PropTypes.string, + language: PropTypes.string, + }), + ]), + buttons: PropTypes.arrayOf( + PropTypes.oneOf([ + PropTypes.shape({ + header: PropTypes.string, + icon: PropTypes.string, + fields: PropTypes.arrayOf(PropTypes.string).isRequired, + tooltip: PropTypes.string, + }), + PropTypes.shape({ + header: PropTypes.string.isRequired, + icon: PropTypes.string.isRequired, + click: PropTypes.string.isRequired, + tooltip: PropTypes.string, + parameters: PropTypes.string.isRequired, + type: PropTypes.string, + }), + '|', + ]) + ), + title: PropTypes.string, + tooltip: PropTypes.string, + cssClass: PropTypes.string, +}; + +EditFrame.displayName = 'Edit Frame'; diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index e53f2ce001..d9cb840f93 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -67,3 +67,12 @@ export { export { withEditorChromes } from './enhancers/withEditorChromes'; export { withPlaceholder } from './enhancers/withPlaceholder'; export { withDatasourceCheck } from './enhancers/withDatasourceCheck'; +export { + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, + EditFrameProps, + EditFrame, +} from './components/EditFrame'; From 84864c041e4d870423b87f31e81ca862e6911143 Mon Sep 17 00:00:00 2001 From: Mike Date: Mon, 5 Dec 2022 22:41:57 -0600 Subject: [PATCH 02/22] Initial work on vue component. --- packages/sitecore-jss-nextjs/src/index.ts | 11 +- .../src/components/EditFrame.tsx | 233 ++++-------------- packages/sitecore-jss-react/src/index.ts | 15 +- .../src/components/EditFrame.ts | 86 +++++++ packages/sitecore-jss/src/utils/edit-frame.ts | 158 ++++++++++++ packages/sitecore-jss/src/utils/index.ts | 11 + 6 files changed, 316 insertions(+), 198 deletions(-) create mode 100644 packages/sitecore-jss-vue/src/components/EditFrame.ts create mode 100644 packages/sitecore-jss/src/utils/edit-frame.ts diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index c027bfb619..589e05e2ec 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -9,7 +9,16 @@ export { NativeDataFetcherConfig, enableDebug, } from '@sitecore-jss/sitecore-jss'; -export { isEditorActive, resetEditorChromes, resolveUrl } from '@sitecore-jss/sitecore-jss/utils'; +export { + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, + isEditorActive, + resetEditorChromes, + resolveUrl +} from '@sitecore-jss/sitecore-jss/utils'; export { LayoutService, LayoutServiceData, diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx index aac9ad7451..ce84562acb 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -1,164 +1,15 @@ -import PropTypes from 'prop-types'; +// import PropTypes from 'prop-types'; import React, { PropsWithChildren } from 'react'; import { useSitecoreContext } from '../enhancers/withSitecoreContext'; - -type EditFrameButton = { - isDivider: boolean; - click: string; - header: string; - icon: string; - tooltip: string | null; - type: string | null; -}; - -const DefaultEditFrameButtonIds = { - edit: '{70C4EED5-D4CD-4D7D-9763-80C42504F5E7}', -}; - -export const DefaultEditFrameButton = { - insert: { - header: 'Insert New', - icon: '/~/icon/Office/16x16/insert_from_template.png', - click: 'webedit:new', - tooltip: 'Insert a new item', - }, - editRelatedItem: { - header: 'Edit the related item', - icon: '/~/icon/Office/16x16/cubes.png', - click: 'webedit:open', // Command in Sitecore, 'chrome:common:edititem({command:"webedit:open"})', - tooltip: 'Edit the related item in the Content Editor.', - }, - edit: { - header: 'Edit Item', - icon: '/~/icon/people/16x16/cubes_blue.png', - fields: ['Title', 'Text'], - tooltip: 'Edit the item fields.', - }, -}; - -export const DefaultEditFrameButtons = [ - DefaultEditFrameButton.editRelatedItem, - DefaultEditFrameButton.insert, - DefaultEditFrameButton.edit, -]; - -/** - * @param {WebEditButton | FieldEditButton} button the button to determine the type of - */ -function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { - return (button as WebEditButton).click !== undefined; -} - -export type EditFrameDataSource = { - itemId: string; - databaseName?: string; - language?: string; -}; - -export type FieldEditButton = { - header: string; - icon: string; - fields: string[]; - tooltip: string; -}; - -export type WebEditButton = { - header: string; - icon: string; - click: string; - tooltip: string; - parameters?: Record; - type?: string; -}; - -/** - * @param {WebEditButton } button the button to build a EditFrameButton for - * @param {string} itemId the ID of the item the EditFrame is associated with - * @param {Record} frameParameters additional parameters passed to the EditFrame - */ -function commandBuilder( - button: WebEditButton, - itemId?: string, - frameParameters?: Record -): EditFrameButton { - if (!button.click) { - return { - isDivider: false, - type: button.type || null, - ...button, - }; - } else if (button.click.startsWith('javascript:') || button.click.startsWith('chrome:')) { - return { - isDivider: false, - type: button.type || null, - ...button, - }; - } else { - if (!itemId) { - return { - isDivider: false, - type: button.type || null, - ...button, - }; - } else { - let message = button.click; - let parameters: Record = {}; - - const length = button.click.indexOf('('); - if (length >= 0) { - const end = button.click.indexOf(')'); - if (end < 0) { - throw new Error('Message with arguments must end with ")".'); - } - parameters = button.click - .substring(length + 1, end) - .split(',') - .map((_) => _.trim()) - .reduce((previous: Record, current) => { - const parts = current.split('='); - if (parts.length < 2) { - previous[parts[0]] = ''; - } else { - previous[parts[0]] = parts[1]; - } - return previous; - }, {}); - message = button.click.substring(0, length); - } - - parameters.id = itemId; - - if (button.parameters) { - Object.keys(button.parameters).forEach((_) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - parameters[_] = button.parameters![_]?.toString() || ''; - }); - } - - if (frameParameters) { - Object.keys(frameParameters).forEach((_) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - parameters[_] = frameParameters![_]?.toString() || ''; - }); - } - - const parameterString = Object.keys(parameters) - .map((_) => `${_}=${parameters[_]}`) - .join(', '); - - const click = `${message}(${parameterString})`; - - return { - isDivider: false, - click: `javascript:Sitecore.PageModes.PageEditor.postRequest('${click}',null,false)`, - header: button.header, - icon: button.icon, - tooltip: button.tooltip, - type: button.type || null, - }; - } - } -} +import { + DefaultEditFrameButtonIds, + EditFrameDataSource, + EditFrameButton, + FieldEditButton, + WebEditButton, + isWebEditButton, + commandBuilder +} from '@sitecore-jss/sitecore-jss/utils'; export interface EditFrameProps { dataSource?: EditFrameDataSource; @@ -251,37 +102,37 @@ export interface EditFrameProps { parameters?: Record; } -EditFrame.propTypes = { - dataSource: PropTypes.oneOf([ - undefined, - PropTypes.shape({ - itemId: PropTypes.string.isRequired, - databaseName: PropTypes.string, - language: PropTypes.string, - }), - ]), - buttons: PropTypes.arrayOf( - PropTypes.oneOf([ - PropTypes.shape({ - header: PropTypes.string, - icon: PropTypes.string, - fields: PropTypes.arrayOf(PropTypes.string).isRequired, - tooltip: PropTypes.string, - }), - PropTypes.shape({ - header: PropTypes.string.isRequired, - icon: PropTypes.string.isRequired, - click: PropTypes.string.isRequired, - tooltip: PropTypes.string, - parameters: PropTypes.string.isRequired, - type: PropTypes.string, - }), - '|', - ]) - ), - title: PropTypes.string, - tooltip: PropTypes.string, - cssClass: PropTypes.string, -}; +// EditFrame.propTypes = { +// dataSource: PropTypes.oneOf([ +// undefined, +// PropTypes.shape({ +// itemId: PropTypes.string.isRequired, +// databaseName: PropTypes.string, +// language: PropTypes.string, +// }), +// ]), +// buttons: PropTypes.arrayOf( +// PropTypes.oneOf([ +// PropTypes.shape({ +// header: PropTypes.string, +// icon: PropTypes.string, +// fields: PropTypes.arrayOf(PropTypes.string).isRequired, +// tooltip: PropTypes.string, +// }), +// PropTypes.shape({ +// header: PropTypes.string.isRequired, +// icon: PropTypes.string.isRequired, +// click: PropTypes.string.isRequired, +// tooltip: PropTypes.string, +// parameters: PropTypes.string.isRequired, +// type: PropTypes.string, +// }), +// '|', +// ]) +// ), +// title: PropTypes.string, +// tooltip: PropTypes.string, +// cssClass: PropTypes.string, +// }; EditFrame.displayName = 'Edit Frame'; diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index d9cb840f93..3442e35256 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -1,5 +1,13 @@ export { constants, enableDebug } from '@sitecore-jss/sitecore-jss'; -export { isEditorActive, resetEditorChromes } from '@sitecore-jss/sitecore-jss/utils'; +export { + isEditorActive, + resetEditorChromes, + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, +} from '@sitecore-jss/sitecore-jss/utils'; export { LayoutService, LayoutServiceData, @@ -68,11 +76,6 @@ export { withEditorChromes } from './enhancers/withEditorChromes'; export { withPlaceholder } from './enhancers/withPlaceholder'; export { withDatasourceCheck } from './enhancers/withDatasourceCheck'; export { - DefaultEditFrameButton, - DefaultEditFrameButtons, - EditFrameDataSource, - FieldEditButton, - WebEditButton, EditFrameProps, EditFrame, } from './components/EditFrame'; diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts new file mode 100644 index 0000000000..c428e7ea14 --- /dev/null +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -0,0 +1,86 @@ +import { h, defineComponent, PropType, getCurrentInstance } from 'vue'; +import { + EditFrameDataSource, + FieldEditButton, + WebEditButton, + EditFrameButton, + DefaultEditFrameButtonIds, + isWebEditButton, + commandBuilder +} from '@sitecore-jss/sitecore-jss/utils'; + +export const RichText = defineComponent({ + props: { + dataSource: { type: Object as PropType }, + buttons: { type: Object as PropType<(FieldEditButton | WebEditButton | '|')[]> }, + title: { type: String }, + tooltip: { type: String }, + cssClass: { type: String }, + parameters: { type: Object as PropType> }, + }, + methods: {}, + render() { + const instance = getCurrentInstance(); + const sitecoreContext = instance.appContext.config.globalProperties.$jss.sitecoreContext(); + if (!sitecoreContext.pageEditing) { + return null; + } + + const commandData: Record = { + displayName: this.$props.title, + expandedDisplayName: this.$props.tooltip, + }; + + const frameProps: Record = {}; + frameProps.class = 'scLooseFrameZone'; + if (this.$props.cssClass) { + frameProps.class = `${frameProps.class} ${this.$props.cssClass}`; + } + + // item uri for edit frame target + if (this.$props.dataSource) { + const route = instance.appContext.config.globalProperties.$jss.route(); + const databaseName = this.$props.dataSource.databaseName || route?.databaseName; + const language = this.$props.dataSource.language || sitecoreContext.language; + frameProps.sc_item = `sitecore://${databaseName}/${this.$props.dataSource.itemId}?lang=${language}`; + commandData.contextItemUri = frameProps.sc_item; + } + + commandData.commands = this.$props.buttons?.map( + (value): EditFrameButton => { + if (value === '|') { + return { + click: 'chrome:dummy', + header: 'Separator', + icon: '', + isDivider: false, + tooltip: null, + type: 'separator', + }; + } else if (isWebEditButton(value)) { + return commandBuilder(value, this.$props.dataSource?.itemId, this.$props.parameters); + } else { + const fieldsString = value.fields.join('|'); + const editButton: WebEditButton = { + click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, + ...value, + }; + + return commandBuilder(editButton, this.$props.dataSource?.itemId, this.$props.parameters); + } + } + ); + + const children = this.$slots.default; + if (children) { + const childElements = h(null, { }, children()); + const chromeData = h('span', { class: 'scChromeData' }, JSON.stringify(commandData)); + + return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData, childElements]); + } else { + const chromeData = h('span', { class: 'scChromeData' }, JSON.stringify(commandData)); + + return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData]); + } + } +}); \ No newline at end of file diff --git a/packages/sitecore-jss/src/utils/edit-frame.ts b/packages/sitecore-jss/src/utils/edit-frame.ts new file mode 100644 index 0000000000..aab9edca13 --- /dev/null +++ b/packages/sitecore-jss/src/utils/edit-frame.ts @@ -0,0 +1,158 @@ + +export type EditFrameButton = { + isDivider: boolean; + click: string; + header: string; + icon: string; + tooltip: string | null; + type: string | null; +}; + +export const DefaultEditFrameButtonIds = { + edit: '{70C4EED5-D4CD-4D7D-9763-80C42504F5E7}', +}; + +export const DefaultEditFrameButton = { + insert: { + header: 'Insert New', + icon: '/~/icon/Office/16x16/insert_from_template.png', + click: 'webedit:new', + tooltip: 'Insert a new item', + }, + editRelatedItem: { + header: 'Edit the related item', + icon: '/~/icon/Office/16x16/cubes.png', + click: 'webedit:open', // Command in Sitecore, 'chrome:common:edititem({command:"webedit:open"})', + tooltip: 'Edit the related item in the Content Editor.', + }, + edit: { + header: 'Edit Item', + icon: '/~/icon/people/16x16/cubes_blue.png', + fields: ['Title', 'Text'], + tooltip: 'Edit the item fields.', + }, +}; + +export const DefaultEditFrameButtons = [ + DefaultEditFrameButton.editRelatedItem, + DefaultEditFrameButton.insert, + DefaultEditFrameButton.edit, +]; + +/** + * @param {WebEditButton | FieldEditButton} button the button to determine the type of + */ +export function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { + return (button as WebEditButton).click !== undefined; +} + +export type EditFrameDataSource = { + itemId: string; + databaseName?: string; + language?: string; +}; + +export type FieldEditButton = { + header: string; + icon: string; + fields: string[]; + tooltip: string; +}; + +export type WebEditButton = { + header: string; + icon: string; + click: string; + tooltip: string; + parameters?: Record; + type?: string; +}; + +/** + * @param {WebEditButton } button the button to build a EditFrameButton for + * @param {string} itemId the ID of the item the EditFrame is associated with + * @param {Record} frameParameters additional parameters passed to the EditFrame + */ +export function commandBuilder( + button: WebEditButton, + itemId?: string, + frameParameters?: Record +): EditFrameButton { + if (!button.click) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else if (button.click.startsWith('javascript:') || button.click.startsWith('chrome:')) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else { + if (!itemId) { + return { + isDivider: false, + type: button.type || null, + ...button, + }; + } else { + let message = button.click; + let parameters: Record = {}; + + const length = button.click.indexOf('('); + if (length >= 0) { + const end = button.click.indexOf(')'); + if (end < 0) { + throw new Error('Message with arguments must end with ")".'); + } + parameters = button.click + .substring(length + 1, end) + .split(',') + .map((_) => _.trim()) + .reduce((previous: Record, current) => { + const parts = current.split('='); + if (parts.length < 2) { + previous[parts[0]] = ''; + } else { + previous[parts[0]] = parts[1]; + } + return previous; + }, {}); + message = button.click.substring(0, length); + } + + parameters.id = itemId; + + if (button.parameters) { + Object.keys(button.parameters).forEach((_) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + parameters[_] = button.parameters![_]?.toString() || ''; + }); + } + + if (frameParameters) { + Object.keys(frameParameters).forEach((_) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + parameters[_] = frameParameters![_]?.toString() || ''; + }); + } + + const parameterString = Object.keys(parameters) + .map((_) => `${_}=${parameters[_]}`) + .join(', '); + + const click = `${message}(${parameterString})`; + + return { + isDivider: false, + click: `javascript:Sitecore.PageModes.PageEditor.postRequest('${click}',null,false)`, + header: button.header, + icon: button.icon, + tooltip: button.tooltip, + type: button.type || null, + }; + } + } +} \ No newline at end of file diff --git a/packages/sitecore-jss/src/utils/index.ts b/packages/sitecore-jss/src/utils/index.ts index 7539a87eb7..7271053166 100644 --- a/packages/sitecore-jss/src/utils/index.ts +++ b/packages/sitecore-jss/src/utils/index.ts @@ -7,3 +7,14 @@ export { resetEditorChromes, handleEditorAnchors, } from './editing'; +export { + DefaultEditFrameButton, + DefaultEditFrameButtons, + DefaultEditFrameButtonIds, + EditFrameDataSource, + EditFrameButton, + FieldEditButton, + WebEditButton, + commandBuilder, + isWebEditButton +} from './edit-frame'; \ No newline at end of file From 202371bcabe44b320d67081ef2696ac37de1a99e Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Wed, 7 Dec 2022 15:30:38 -0600 Subject: [PATCH 03/22] More work on EditFrame for Vue. --- packages/sitecore-jss-vue/src/components/EditFrame.ts | 11 +++++------ packages/sitecore-jss-vue/src/index.ts | 6 ++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts index c428e7ea14..0cbf1e587e 100644 --- a/packages/sitecore-jss-vue/src/components/EditFrame.ts +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -9,7 +9,7 @@ import { commandBuilder } from '@sitecore-jss/sitecore-jss/utils'; -export const RichText = defineComponent({ +export const EditFrame = defineComponent({ props: { dataSource: { type: Object as PropType }, buttons: { type: Object as PropType<(FieldEditButton | WebEditButton | '|')[]> }, @@ -18,7 +18,6 @@ export const RichText = defineComponent({ cssClass: { type: String }, parameters: { type: Object as PropType> }, }, - methods: {}, render() { const instance = getCurrentInstance(); const sitecoreContext = instance.appContext.config.globalProperties.$jss.sitecoreContext(); @@ -39,7 +38,7 @@ export const RichText = defineComponent({ // item uri for edit frame target if (this.$props.dataSource) { - const route = instance.appContext.config.globalProperties.$jss.route(); + const route = instance.appContext.config.globalProperties.$jss.routeData(); const databaseName = this.$props.dataSource.databaseName || route?.databaseName; const language = this.$props.dataSource.language || sitecoreContext.language; frameProps.sc_item = `sitecore://${databaseName}/${this.$props.dataSource.itemId}?lang=${language}`; @@ -73,7 +72,7 @@ export const RichText = defineComponent({ const children = this.$slots.default; if (children) { - const childElements = h(null, { }, children()); + const childElements = h(null, {}, children()); const chromeData = h('span', { class: 'scChromeData' }, JSON.stringify(commandData)); return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData, childElements]); @@ -82,5 +81,5 @@ export const RichText = defineComponent({ return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData]); } - } -}); \ No newline at end of file + }, +}); diff --git a/packages/sitecore-jss-vue/src/index.ts b/packages/sitecore-jss-vue/src/index.ts index b9de9db833..739bce36df 100644 --- a/packages/sitecore-jss-vue/src/index.ts +++ b/packages/sitecore-jss-vue/src/index.ts @@ -2,6 +2,11 @@ export { isEditorActive, resetEditorChromes, handleEditorAnchors, + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, } from '@sitecore-jss/sitecore-jss/utils'; export { constants, enableDebug } from '@sitecore-jss/sitecore-jss'; export { @@ -34,6 +39,7 @@ export { RestDictionaryService, } from '@sitecore-jss/sitecore-jss/i18n'; export { mediaApi } from '@sitecore-jss/sitecore-jss/media'; +export { EditFrame } from './components/EditFrame'; export { Placeholder } from './components/Placeholder'; export { Image } from './components/Image'; export { RichText } from './components/RichText'; From bd241208ccc8654473970e86b08588b7abc12f54 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Wed, 7 Dec 2022 21:20:01 -0600 Subject: [PATCH 04/22] Fix markup for vue. --- .../sitecore-jss-vue/src/components/EditFrame.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts index 0cbf1e587e..c5deadf64b 100644 --- a/packages/sitecore-jss-vue/src/components/EditFrame.ts +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -72,14 +72,20 @@ export const EditFrame = defineComponent({ const children = this.$slots.default; if (children) { - const childElements = h(null, {}, children()); - const chromeData = h('span', { class: 'scChromeData' }, JSON.stringify(commandData)); + const childElements = h('div', null, children()); + const chromeData = h('span', { + class: 'scChromeData', + innerHTML: JSON.stringify(commandData), + }); - return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData, childElements]); + return h('div', frameProps, [chromeData, childElements]); } else { - const chromeData = h('span', { class: 'scChromeData' }, JSON.stringify(commandData)); + const chromeData = h('span', { + class: 'scChromeData', + innerHTML: JSON.stringify(commandData), + }); - return h('div', { class: 'scLooseFrameZone', ...frameProps }, [chromeData]); + return h('div', frameProps, [chromeData]); } }, }); From ab638c6a8ea854fe3d688ff6fd1d6e519a86b229 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Wed, 7 Dec 2022 21:23:56 -0600 Subject: [PATCH 05/22] Fix linting issues. --- packages/sitecore-jss/src/utils/edit-frame.ts | 3 +-- packages/sitecore-jss/src/utils/index.ts | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/sitecore-jss/src/utils/edit-frame.ts b/packages/sitecore-jss/src/utils/edit-frame.ts index aab9edca13..570d4e12fc 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.ts @@ -1,4 +1,3 @@ - export type EditFrameButton = { isDivider: boolean; click: string; @@ -155,4 +154,4 @@ export function commandBuilder( }; } } -} \ No newline at end of file +} diff --git a/packages/sitecore-jss/src/utils/index.ts b/packages/sitecore-jss/src/utils/index.ts index 7271053166..afb689ffdd 100644 --- a/packages/sitecore-jss/src/utils/index.ts +++ b/packages/sitecore-jss/src/utils/index.ts @@ -7,7 +7,7 @@ export { resetEditorChromes, handleEditorAnchors, } from './editing'; -export { +export { DefaultEditFrameButton, DefaultEditFrameButtons, DefaultEditFrameButtonIds, @@ -16,5 +16,5 @@ export { FieldEditButton, WebEditButton, commandBuilder, - isWebEditButton -} from './edit-frame'; \ No newline at end of file + isWebEditButton, +} from './edit-frame'; From f50266fc71353c6a27c5eaf1dfa2e8a38a2679a6 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Wed, 7 Dec 2022 21:38:24 -0600 Subject: [PATCH 06/22] Fix more linting issues --- .../src/components/EditFrame.ts | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts index c5deadf64b..e2d5fa82f8 100644 --- a/packages/sitecore-jss-vue/src/components/EditFrame.ts +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -6,17 +6,23 @@ import { EditFrameButton, DefaultEditFrameButtonIds, isWebEditButton, - commandBuilder + commandBuilder, } from '@sitecore-jss/sitecore-jss/utils'; export const EditFrame = defineComponent({ props: { - dataSource: { type: Object as PropType }, - buttons: { type: Object as PropType<(FieldEditButton | WebEditButton | '|')[]> }, - title: { type: String }, - tooltip: { type: String }, - cssClass: { type: String }, - parameters: { type: Object as PropType> }, + dataSource: { type: Object as PropType, default: undefined }, + buttons: { + type: Object as PropType<(FieldEditButton | WebEditButton | '|')[]>, + default: undefined, + }, + title: { type: String, default: undefined }, + tooltip: { type: String, default: undefined }, + cssClass: { type: String, default: undefined }, + parameters: { + type: Object as PropType>, + default: undefined, + }, }, render() { const instance = getCurrentInstance(); From a05de301ca284116a772884c21da4826dc882b26 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Wed, 7 Dec 2022 21:56:36 -0600 Subject: [PATCH 07/22] More linting. --- packages/sitecore-jss-react/src/components/EditFrame.tsx | 4 ++-- packages/sitecore-jss-react/src/index.ts | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx index ce84562acb..447e3886db 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -1,14 +1,14 @@ // import PropTypes from 'prop-types'; import React, { PropsWithChildren } from 'react'; import { useSitecoreContext } from '../enhancers/withSitecoreContext'; -import { +import { DefaultEditFrameButtonIds, EditFrameDataSource, EditFrameButton, FieldEditButton, WebEditButton, isWebEditButton, - commandBuilder + commandBuilder, } from '@sitecore-jss/sitecore-jss/utils'; export interface EditFrameProps { diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index 3442e35256..849cfbbd26 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -75,7 +75,4 @@ export { export { withEditorChromes } from './enhancers/withEditorChromes'; export { withPlaceholder } from './enhancers/withPlaceholder'; export { withDatasourceCheck } from './enhancers/withDatasourceCheck'; -export { - EditFrameProps, - EditFrame, -} from './components/EditFrame'; +export { EditFrameProps, EditFrame } from './components/EditFrame'; From 010ddf0d7a03a7b0d60e6ac952bedee3c6841df5 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Thu, 8 Dec 2022 09:26:25 -0600 Subject: [PATCH 08/22] Some more linting. --- packages/sitecore-jss-react/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index 849cfbbd26..1e592cf2ac 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -1,5 +1,5 @@ export { constants, enableDebug } from '@sitecore-jss/sitecore-jss'; -export { +export { isEditorActive, resetEditorChromes, DefaultEditFrameButton, From eda7be9be763a2a60756330e903ea4cf1fdcfd31 Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Thu, 8 Dec 2022 09:37:30 -0600 Subject: [PATCH 09/22] Linting fixes. --- packages/sitecore-jss-nextjs/src/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index 589e05e2ec..7069c8a777 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -9,15 +9,15 @@ export { NativeDataFetcherConfig, enableDebug, } from '@sitecore-jss/sitecore-jss'; -export { - DefaultEditFrameButton, - DefaultEditFrameButtons, - EditFrameDataSource, - FieldEditButton, - WebEditButton, +export { + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, isEditorActive, resetEditorChromes, - resolveUrl + resolveUrl, } from '@sitecore-jss/sitecore-jss/utils'; export { LayoutService, From 47964fe061748f7e01f044f38d7cb56cb0e825cc Mon Sep 17 00:00:00 2001 From: Mike Jarosch Date: Thu, 8 Dec 2022 21:52:13 -0600 Subject: [PATCH 10/22] Angular implementation --- .../src/components/editframe.component.ts | 91 +++++++++++++++++++ .../sitecore-jss-angular/src/lib.module.ts | 3 + .../sitecore-jss-angular/src/public_api.ts | 5 + 3 files changed, 99 insertions(+) create mode 100644 packages/sitecore-jss-angular/src/components/editframe.component.ts diff --git a/packages/sitecore-jss-angular/src/components/editframe.component.ts b/packages/sitecore-jss-angular/src/components/editframe.component.ts new file mode 100644 index 0000000000..16ef1d4fd7 --- /dev/null +++ b/packages/sitecore-jss-angular/src/components/editframe.component.ts @@ -0,0 +1,91 @@ +import { Component, Input, OnChanges } from '@angular/core'; +import { + EditFrameDataSource, + FieldEditButton, + WebEditButton, + EditFrameButton, + DefaultEditFrameButtonIds, + isWebEditButton, + commandBuilder, +} from '@sitecore-jss/sitecore-jss/utils'; +import { LayoutServiceContextData, RouteData } from '@sitecore-jss/sitecore-jss/layout'; + +@Component({ + selector: 'sc-edit-frame,[sc-edit-frame]', + template: + '
{{chromeData}}
', +}) +export class EditFrameComponent implements OnChanges { + @Input() dataSource: EditFrameDataSource; + + @Input() buttons: (FieldEditButton | WebEditButton | '|')[]; + + @Input() title: string; + + @Input() tooltip: string; + + @Input() cssClass: string; + + @Input() parameters: Record; + + @Input() sitecore: LayoutServiceContextData & { + route: RouteData | null; + }; + + isEditing = false; + frameProps: Record = {}; + chromeData = ''; + + ngOnChanges() { + this.isEditing = this.sitecore.context.pageEditing || false; + if (!this.isEditing) { + return; + } + + const commandData: Record = { + displayName: this.title, + expandedDisplayName: this.tooltip, + }; + + this.frameProps.class = 'scLooseFrameZone'; + if (this.cssClass) { + this.frameProps.class = `${this.frameProps.class} ${this.cssClass}`; + } + + // item uri for edit frame target + if (this.dataSource) { + const route = this.sitecore.route; + const databaseName = this.dataSource.databaseName || route?.databaseName; + const language = this.dataSource.language || this.sitecore.context.language; + this.frameProps.sc_item = `sitecore://${databaseName}/${this.dataSource.itemId}?lang=${language}`; + commandData.contextItemUri = this.frameProps.sc_item; + } + + commandData.commands = this.buttons?.map( + (value): EditFrameButton => { + if (value === '|') { + return { + click: 'chrome:dummy', + header: 'Separator', + icon: '', + isDivider: false, + tooltip: null, + type: 'separator', + }; + } else if (isWebEditButton(value)) { + return commandBuilder(value, this.dataSource?.itemId, this.parameters); + } else { + const fieldsString = value.fields.join('|'); + const editButton: WebEditButton = { + click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, + ...value, + }; + + return commandBuilder(editButton, this.dataSource?.itemId, this.parameters); + } + } + ); + + this.chromeData = JSON.stringify(commandData); + } +} diff --git a/packages/sitecore-jss-angular/src/lib.module.ts b/packages/sitecore-jss-angular/src/lib.module.ts index 414b4d82fb..b0f610f72a 100644 --- a/packages/sitecore-jss-angular/src/lib.module.ts +++ b/packages/sitecore-jss-angular/src/lib.module.ts @@ -19,6 +19,7 @@ import { MissingComponentComponent } from './components/missing-component.compon import { HiddenRenderingComponent } from './components/hidden-rendering.component'; import { PlaceholderLoadingDirective } from './components/placeholder-loading.directive'; import { PlaceholderComponent } from './components/placeholder.component'; +import { EditFrameComponent } from './components/editframe.component'; import { ComponentNameAndModule, ComponentNameAndType, @@ -58,6 +59,7 @@ import { JssComponentFactoryService } from './jss-component-factory.service'; TextDirective, MissingComponentComponent, HiddenRenderingComponent, + EditFrameComponent, ], exports: [ FileDirective, @@ -74,6 +76,7 @@ import { JssComponentFactoryService } from './jss-component-factory.service'; PlaceholderLoadingDirective, RichTextDirective, TextDirective, + EditFrameComponent, ], entryComponents: [RawComponent, MissingComponentComponent], }) diff --git a/packages/sitecore-jss-angular/src/public_api.ts b/packages/sitecore-jss-angular/src/public_api.ts index b1d6eac3dd..8a73c4f695 100644 --- a/packages/sitecore-jss-angular/src/public_api.ts +++ b/packages/sitecore-jss-angular/src/public_api.ts @@ -54,6 +54,11 @@ export { isEditorActive, resetEditorChromes, handleEditorAnchors, + DefaultEditFrameButton, + DefaultEditFrameButtons, + EditFrameDataSource, + FieldEditButton, + WebEditButton, } from '@sitecore-jss/sitecore-jss/utils'; export { trackingApi, From 7e1db85645f455e6edeebf7c9061b9fa325cd35b Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 13 Dec 2022 20:58:53 -0600 Subject: [PATCH 11/22] Add commandBuilder tests --- .../sitecore-jss/src/utils/edit-frame.test.ts | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 packages/sitecore-jss/src/utils/edit-frame.test.ts diff --git a/packages/sitecore-jss/src/utils/edit-frame.test.ts b/packages/sitecore-jss/src/utils/edit-frame.test.ts new file mode 100644 index 0000000000..5b2222b18d --- /dev/null +++ b/packages/sitecore-jss/src/utils/edit-frame.test.ts @@ -0,0 +1,78 @@ +/* eslint-disable no-unused-expressions */ +import { expect } from 'chai'; +import { commandBuilder, DefaultEditFrameButton } from '.'; + +describe('commandBuilder', () => { + it('should handle no click', () => { + const input = { + click: '', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input); + + expect(output.click).to.be.equal(''); + }); + + it('should handle javascript', () => { + const input = { + click: 'javascript:test', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input); + + expect(output.click).to.be.equal('javascript:test'); + }); + + it('should handle chrome', () => { + const input = { + click: 'chrome:test', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input); + + expect(output.click).to.be.equal('chrome:test'); + }); + + it('should handle no item', () => { + const input = { + click: 'item:new', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input); + + expect(output.click).to.be.equal('item:new'); + }); + + it('should build a button', () => { + const input = { + click: 'item:new', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input, '123'); + + expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123)',null,false)"); + }); + + it('should handle button parameters', () => { + const input = { + click: 'item:new', + parameters: { + Navigate: 0, + }, + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input, '123'); + + expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, Navigate=0)',null,false)"); + }); + + it('should handle frame parameters', () => { + const input = { + click: 'item:new', + ...DefaultEditFrameButton.edit + }; + const output = commandBuilder(input, '123', {extra: 'Value'}); + + expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, extra=Value)',null,false)"); + }); +}); From 55bdffa77d095216f434f75f7516b7dcd3e56082 Mon Sep 17 00:00:00 2001 From: Mike Date: Tue, 13 Dec 2022 22:22:08 -0600 Subject: [PATCH 12/22] Add tests for core and react. Added some comments. --- .../src/components/EditFrame.test.tsx | 154 ++++++++++++++++++ .../src/components/EditFrame.tsx | 7 +- packages/sitecore-jss-react/src/index.ts | 1 + packages/sitecore-jss-vue/src/index.ts | 1 + .../sitecore-jss/src/utils/edit-frame.test.ts | 30 ++-- packages/sitecore-jss/src/utils/edit-frame.ts | 5 + packages/sitecore-jss/src/utils/index.ts | 1 + 7 files changed, 184 insertions(+), 15 deletions(-) create mode 100644 packages/sitecore-jss-react/src/components/EditFrame.test.tsx diff --git a/packages/sitecore-jss-react/src/components/EditFrame.test.tsx b/packages/sitecore-jss-react/src/components/EditFrame.test.tsx new file mode 100644 index 0000000000..8ee6b5fea5 --- /dev/null +++ b/packages/sitecore-jss-react/src/components/EditFrame.test.tsx @@ -0,0 +1,154 @@ +import { expect } from 'chai'; +import { mount } from 'enzyme'; +import React from 'react'; +import { EditFrame } from './EditFrame'; +import { ComponentFactory } from './sharedTypes'; +import { SitecoreContext } from './SitecoreContext'; +import { LayoutServiceData } from '../index'; +import { DefaultEditFrameButton, EditButtonTypes } from '@sitecore-jss/sitecore-jss/utils'; + +const components = new Map(); +const mockComponentFactory: ComponentFactory = (name) => components.get(name); + +const mockLayoutData: LayoutServiceData = { + sitecore: { + context: { + pageEditing: false, + site: { + name: 'JssTestWeb', + }, + language: 'en', + }, + route: { + name: 'styleguide', + placeholders: { + 'JssTestWeb-jss-main': [], + }, + itemId: 'testitemid', + }, + }, +}; + +const mockEditingLayoutData: LayoutServiceData = { + sitecore: { + context: { + pageEditing: true, + site: { + name: 'JssTestWeb', + }, + language: 'en', + }, + route: { + name: 'styleguide', + placeholders: { + 'JssTestWeb-jss-main': [], + }, + itemId: 'testitemid', + }, + }, +}; + +describe('', () => { + it('should render nothing when not in pageEditing mode', () => { + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal('Test'); + }); + + it('should render a frame when in pageEditing mode', () => { + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal( + '
{"displayName":"Edit","commands":[]}Test
' + ); + }); + + it('should render the title and tooltip', () => { + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal( + '
{"displayName":"Test Title","expandedDisplayName":"Test Tooltip","commands":[]}Test
' + ); + }); + + it('should render the added class', () => { + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal( + '
{"displayName":"Edit","commands":[]}Test
' + ); + }); + + it('should render the datasource', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal( + '
{"displayName":"Edit","contextItemUri":"sitecore://master/testItemId?lang=en","commands":[]}Test
' + ); + }); + + it('should render the buttons', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + const mockButtons: EditButtonTypes[] = [ + DefaultEditFrameButton.insert, + '|', + DefaultEditFrameButton.edit, + ]; + const rendered = mount( + + + Test + + + ) + .childAt(0) + .html(); + expect(rendered).to.be.equal( + '
{"displayName":"Edit","contextItemUri":"sitecore://master/testItemId?lang=en","commands":[{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:new(id=testItemId)\',null,false)","header":"Insert New","icon":"/~/icon/Office/16x16/insert_from_template.png","tooltip":"Insert a new item","type":null},{"click":"chrome:dummy","header":"Separator","icon":"","isDivider":false,"tooltip":null,"type":"separator"},{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:fieldeditor(command={70C4EED5-D4CD-4D7D-9763-80C42504F5E7}, fields=Title|Text, id=testItemId)\',null,false)","header":"Edit Item","icon":"/~/icon/people/16x16/cubes_blue.png","tooltip":"Edit the item fields.","type":null}]}Test
' + ); + }); +}); diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx index 447e3886db..9e176e4b87 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -7,13 +7,14 @@ import { EditFrameButton, FieldEditButton, WebEditButton, + EditButtonTypes, isWebEditButton, commandBuilder, } from '@sitecore-jss/sitecore-jss/utils'; export interface EditFrameProps { dataSource?: EditFrameDataSource; - buttons?: (FieldEditButton | WebEditButton | '|')[]; + buttons?: EditButtonTypes[]; title?: string; tooltip?: string; cssClass?: string; @@ -28,11 +29,11 @@ export const EditFrame: React.FC> = ({ tooltip, cssClass, parameters, -}: PropsWithChildren): JSX.Element => { +}: PropsWithChildren) => { const { sitecoreContext } = useSitecoreContext(); if (!sitecoreContext.pageEditing) { - return <>; + return <>{children}; } const commandData: Record = { diff --git a/packages/sitecore-jss-react/src/index.ts b/packages/sitecore-jss-react/src/index.ts index 1e592cf2ac..a9a72c5058 100644 --- a/packages/sitecore-jss-react/src/index.ts +++ b/packages/sitecore-jss-react/src/index.ts @@ -7,6 +7,7 @@ export { EditFrameDataSource, FieldEditButton, WebEditButton, + EditButtonTypes, } from '@sitecore-jss/sitecore-jss/utils'; export { LayoutService, diff --git a/packages/sitecore-jss-vue/src/index.ts b/packages/sitecore-jss-vue/src/index.ts index 739bce36df..d9d9cc3b5b 100644 --- a/packages/sitecore-jss-vue/src/index.ts +++ b/packages/sitecore-jss-vue/src/index.ts @@ -7,6 +7,7 @@ export { EditFrameDataSource, FieldEditButton, WebEditButton, + EditButtonTypes, } from '@sitecore-jss/sitecore-jss/utils'; export { constants, enableDebug } from '@sitecore-jss/sitecore-jss'; export { diff --git a/packages/sitecore-jss/src/utils/edit-frame.test.ts b/packages/sitecore-jss/src/utils/edit-frame.test.ts index 5b2222b18d..d2c82e919a 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.test.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.test.ts @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-expressions */ +/* eslint-disable quotes */ import { expect } from 'chai'; import { commandBuilder, DefaultEditFrameButton } from '.'; @@ -6,7 +6,7 @@ describe('commandBuilder', () => { it('should handle no click', () => { const input = { click: '', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input); @@ -16,7 +16,7 @@ describe('commandBuilder', () => { it('should handle javascript', () => { const input = { click: 'javascript:test', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input); @@ -26,7 +26,7 @@ describe('commandBuilder', () => { it('should handle chrome', () => { const input = { click: 'chrome:test', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input); @@ -36,7 +36,7 @@ describe('commandBuilder', () => { it('should handle no item', () => { const input = { click: 'item:new', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input); @@ -46,11 +46,13 @@ describe('commandBuilder', () => { it('should build a button', () => { const input = { click: 'item:new', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input, '123'); - expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123)',null,false)"); + expect(output.click).to.be.equal( + "javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123)',null,false)" + ); }); it('should handle button parameters', () => { @@ -59,20 +61,24 @@ describe('commandBuilder', () => { parameters: { Navigate: 0, }, - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; const output = commandBuilder(input, '123'); - expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, Navigate=0)',null,false)"); + expect(output.click).to.be.equal( + "javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, Navigate=0)',null,false)" + ); }); it('should handle frame parameters', () => { const input = { click: 'item:new', - ...DefaultEditFrameButton.edit + ...DefaultEditFrameButton.edit, }; - const output = commandBuilder(input, '123', {extra: 'Value'}); + const output = commandBuilder(input, '123', { extra: 'Value' }); - expect(output.click).to.be.equal("javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, extra=Value)',null,false)"); + expect(output.click).to.be.equal( + "javascript:Sitecore.PageModes.PageEditor.postRequest('item:new(id=123, extra=Value)',null,false)" + ); }); }); diff --git a/packages/sitecore-jss/src/utils/edit-frame.ts b/packages/sitecore-jss/src/utils/edit-frame.ts index 570d4e12fc..7b12a87688 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.ts @@ -1,3 +1,4 @@ +// The button fields required for chrome data export type EditFrameButton = { isDivider: boolean; click: string; @@ -67,7 +68,11 @@ export type WebEditButton = { type?: string; }; +// We are using the | divider indicator, provide a type so it isn't seend as a string +export type EditButtonTypes = WebEditButton | FieldEditButton | '|'; + /** + * Build an EditFrameButton from a web edit button. Merging the parameters from the button, frame and id * @param {WebEditButton } button the button to build a EditFrameButton for * @param {string} itemId the ID of the item the EditFrame is associated with * @param {Record} frameParameters additional parameters passed to the EditFrame diff --git a/packages/sitecore-jss/src/utils/index.ts b/packages/sitecore-jss/src/utils/index.ts index afb689ffdd..155109806b 100644 --- a/packages/sitecore-jss/src/utils/index.ts +++ b/packages/sitecore-jss/src/utils/index.ts @@ -15,6 +15,7 @@ export { EditFrameButton, FieldEditButton, WebEditButton, + EditButtonTypes, commandBuilder, isWebEditButton, } from './edit-frame'; From bf5a54933a9e5d94d1ed5a5a6479a17223430c3d Mon Sep 17 00:00:00 2001 From: Mike Date: Thu, 15 Dec 2022 21:44:03 -0600 Subject: [PATCH 13/22] Edit frame code cleanup --- .../src/components/editframe.component.ts | 42 ++++----------- .../src/components/EditFrame.tsx | 37 +++---------- .../src/components/EditFrame.ts | 52 ++++++------------- .../sitecore-jss/src/utils/edit-frame.test.ts | 3 +- packages/sitecore-jss/src/utils/edit-frame.ts | 46 +++++++++++++--- packages/sitecore-jss/src/utils/index.ts | 5 +- 6 files changed, 77 insertions(+), 108 deletions(-) diff --git a/packages/sitecore-jss-angular/src/components/editframe.component.ts b/packages/sitecore-jss-angular/src/components/editframe.component.ts index 16ef1d4fd7..9e6b240f60 100644 --- a/packages/sitecore-jss-angular/src/components/editframe.component.ts +++ b/packages/sitecore-jss-angular/src/components/editframe.component.ts @@ -1,12 +1,9 @@ import { Component, Input, OnChanges } from '@angular/core'; import { EditFrameDataSource, - FieldEditButton, - WebEditButton, - EditFrameButton, - DefaultEditFrameButtonIds, - isWebEditButton, - commandBuilder, + ChromeCommand, + EditButtonTypes, + mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/utils'; import { LayoutServiceContextData, RouteData } from '@sitecore-jss/sitecore-jss/layout'; @@ -18,7 +15,7 @@ import { LayoutServiceContextData, RouteData } from '@sitecore-jss/sitecore-jss/ export class EditFrameComponent implements OnChanges { @Input() dataSource: EditFrameDataSource; - @Input() buttons: (FieldEditButton | WebEditButton | '|')[]; + @Input() buttons: EditButtonTypes[]; @Input() title: string; @@ -42,7 +39,7 @@ export class EditFrameComponent implements OnChanges { return; } - const commandData: Record = { + const chromeData: Record = { displayName: this.title, expandedDisplayName: this.tooltip, }; @@ -58,34 +55,15 @@ export class EditFrameComponent implements OnChanges { const databaseName = this.dataSource.databaseName || route?.databaseName; const language = this.dataSource.language || this.sitecore.context.language; this.frameProps.sc_item = `sitecore://${databaseName}/${this.dataSource.itemId}?lang=${language}`; - commandData.contextItemUri = this.frameProps.sc_item; + chromeData.contextItemUri = this.frameProps.sc_item; } - commandData.commands = this.buttons?.map( - (value): EditFrameButton => { - if (value === '|') { - return { - click: 'chrome:dummy', - header: 'Separator', - icon: '', - isDivider: false, - tooltip: null, - type: 'separator', - }; - } else if (isWebEditButton(value)) { - return commandBuilder(value, this.dataSource?.itemId, this.parameters); - } else { - const fieldsString = value.fields.join('|'); - const editButton: WebEditButton = { - click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, - ...value, - }; - - return commandBuilder(editButton, this.dataSource?.itemId, this.parameters); - } + chromeData.commands = this.buttons?.map( + (value): ChromeCommand => { + return mapButtonToCommand(value, this.dataSource?.itemId, this.parameters); } ); - this.chromeData = JSON.stringify(commandData); + this.chromeData = JSON.stringify(chromeData); } } diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx index 9e176e4b87..dfc91fc9e1 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -2,14 +2,12 @@ import React, { PropsWithChildren } from 'react'; import { useSitecoreContext } from '../enhancers/withSitecoreContext'; import { - DefaultEditFrameButtonIds, EditFrameDataSource, - EditFrameButton, + ChromeCommand, FieldEditButton, WebEditButton, EditButtonTypes, - isWebEditButton, - commandBuilder, + mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/utils'; export interface EditFrameProps { @@ -36,7 +34,7 @@ export const EditFrame: React.FC> = ({ return <>{children}; } - const commandData: Record = { + const chromeData: Record = { displayName: title, expandedDisplayName: tooltip, }; @@ -52,37 +50,18 @@ export const EditFrame: React.FC> = ({ const databaseName = dataSource.databaseName || sitecoreContext.route?.databaseName; const language = dataSource.language || sitecoreContext.language; frameProps.sc_item = `sitecore://${databaseName}/${dataSource.itemId}?lang=${language}`; - commandData.contextItemUri = frameProps.sc_item; + chromeData.contextItemUri = frameProps.sc_item; } - commandData.commands = buttons?.map( - (value): EditFrameButton => { - if (value === '|') { - return { - click: 'chrome:dummy', - header: 'Separator', - icon: '', - isDivider: false, - tooltip: null, - type: 'separator', - }; - } else if (isWebEditButton(value)) { - return commandBuilder(value, dataSource?.itemId, parameters); - } else { - const fieldsString = value.fields.join('|'); - const editButton: WebEditButton = { - click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, - ...value, - }; - - return commandBuilder(editButton, dataSource?.itemId, parameters); - } + chromeData.commands = buttons?.map( + (value): ChromeCommand => { + return mapButtonToCommand(value, dataSource?.itemId, parameters); } ); return (
- {JSON.stringify(commandData)} + {JSON.stringify(chromeData)} {children}
); diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts index e2d5fa82f8..62ab290521 100644 --- a/packages/sitecore-jss-vue/src/components/EditFrame.ts +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -1,19 +1,16 @@ import { h, defineComponent, PropType, getCurrentInstance } from 'vue'; import { EditFrameDataSource, - FieldEditButton, - WebEditButton, - EditFrameButton, - DefaultEditFrameButtonIds, - isWebEditButton, - commandBuilder, + ChromeCommand, + EditButtonTypes, + mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/utils'; export const EditFrame = defineComponent({ props: { dataSource: { type: Object as PropType, default: undefined }, buttons: { - type: Object as PropType<(FieldEditButton | WebEditButton | '|')[]>, + type: Object as PropType, default: undefined, }, title: { type: String, default: undefined }, @@ -31,7 +28,7 @@ export const EditFrame = defineComponent({ return null; } - const commandData: Record = { + const chromeData: Record = { displayName: this.$props.title, expandedDisplayName: this.$props.tooltip, }; @@ -48,50 +45,31 @@ export const EditFrame = defineComponent({ const databaseName = this.$props.dataSource.databaseName || route?.databaseName; const language = this.$props.dataSource.language || sitecoreContext.language; frameProps.sc_item = `sitecore://${databaseName}/${this.$props.dataSource.itemId}?lang=${language}`; - commandData.contextItemUri = frameProps.sc_item; + chromeData.contextItemUri = frameProps.sc_item; } - commandData.commands = this.$props.buttons?.map( - (value): EditFrameButton => { - if (value === '|') { - return { - click: 'chrome:dummy', - header: 'Separator', - icon: '', - isDivider: false, - tooltip: null, - type: 'separator', - }; - } else if (isWebEditButton(value)) { - return commandBuilder(value, this.$props.dataSource?.itemId, this.$props.parameters); - } else { - const fieldsString = value.fields.join('|'); - const editButton: WebEditButton = { - click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, - ...value, - }; - - return commandBuilder(editButton, this.$props.dataSource?.itemId, this.$props.parameters); - } + chromeData.commands = this.$props.buttons?.map( + (value): ChromeCommand => { + return mapButtonToCommand(value, this.$props.dataSource?.itemId, this.$props.parameters); } ); const children = this.$slots.default; if (children) { const childElements = h('div', null, children()); - const chromeData = h('span', { + const chromeSpan = h('span', { class: 'scChromeData', - innerHTML: JSON.stringify(commandData), + innerHTML: JSON.stringify(chromeData), }); - return h('div', frameProps, [chromeData, childElements]); + return h('div', frameProps, [chromeSpan, childElements]); } else { - const chromeData = h('span', { + const chromeSpan = h('span', { class: 'scChromeData', - innerHTML: JSON.stringify(commandData), + innerHTML: JSON.stringify(chromeData), }); - return h('div', frameProps, [chromeData]); + return h('div', frameProps, [chromeSpan]); } }, }); diff --git a/packages/sitecore-jss/src/utils/edit-frame.test.ts b/packages/sitecore-jss/src/utils/edit-frame.test.ts index d2c82e919a..a61cbf06b9 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.test.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.test.ts @@ -1,6 +1,7 @@ /* eslint-disable quotes */ import { expect } from 'chai'; -import { commandBuilder, DefaultEditFrameButton } from '.'; +import { DefaultEditFrameButton } from '.'; +import { commandBuilder } from './edit-frame'; describe('commandBuilder', () => { it('should handle no click', () => { diff --git a/packages/sitecore-jss/src/utils/edit-frame.ts b/packages/sitecore-jss/src/utils/edit-frame.ts index 7b12a87688..d985154483 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.ts @@ -1,5 +1,5 @@ -// The button fields required for chrome data -export type EditFrameButton = { +// The fields for a command in the chrome data +export type ChromeCommand = { isDivider: boolean; click: string; header: string; @@ -42,7 +42,7 @@ export const DefaultEditFrameButtons = [ /** * @param {WebEditButton | FieldEditButton} button the button to determine the type of */ -export function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { +function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { return (button as WebEditButton).click !== undefined; } @@ -72,8 +72,41 @@ export type WebEditButton = { export type EditButtonTypes = WebEditButton | FieldEditButton | '|'; /** - * Build an EditFrameButton from a web edit button. Merging the parameters from the button, frame and id - * @param {WebEditButton } button the button to build a EditFrameButton for + * Map the edit button types to chrome data + * @param {EditButtonTypes } button the edit button to build a ChromeCommand for + * @param {string} itemId the ID of the item the EditFrame is associated with + * @param {Record} frameParameters additional parameters passed to the EditFrame + */ +export function mapButtonToCommand( + button: EditButtonTypes, + itemId?: string, + frameParameters?: Record +): ChromeCommand { + if (button === '|') { + return { + click: 'chrome:dummy', + header: 'Separator', + icon: '', + isDivider: false, + tooltip: null, + type: 'separator', + }; + } else if (isWebEditButton(button)) { + return commandBuilder(button, itemId, frameParameters); + } else { + const fieldsString = button.fields.join('|'); + const editButton: WebEditButton = { + click: `webedit:fieldeditor(command=${DefaultEditFrameButtonIds.edit},fields=${fieldsString})`, + ...button, + }; + + return commandBuilder(editButton, itemId, frameParameters); + } +} + +/** + * Build a ChromeCommand from a web edit button. Merging the parameters from the button, frame and id + * @param {WebEditButton } button the web edit button to build a ChromeCommand for * @param {string} itemId the ID of the item the EditFrame is associated with * @param {Record} frameParameters additional parameters passed to the EditFrame */ @@ -81,7 +114,7 @@ export function commandBuilder( button: WebEditButton, itemId?: string, frameParameters?: Record -): EditFrameButton { +): ChromeCommand { if (!button.click) { return { isDivider: false, @@ -105,6 +138,7 @@ export function commandBuilder( let message = button.click; let parameters: Record = {}; + // Extract any parameters already in the command const length = button.click.indexOf('('); if (length >= 0) { const end = button.click.indexOf(')'); diff --git a/packages/sitecore-jss/src/utils/index.ts b/packages/sitecore-jss/src/utils/index.ts index 155109806b..49dd35e287 100644 --- a/packages/sitecore-jss/src/utils/index.ts +++ b/packages/sitecore-jss/src/utils/index.ts @@ -12,10 +12,9 @@ export { DefaultEditFrameButtons, DefaultEditFrameButtonIds, EditFrameDataSource, - EditFrameButton, + ChromeCommand, FieldEditButton, WebEditButton, EditButtonTypes, - commandBuilder, - isWebEditButton, + mapButtonToCommand, } from './edit-frame'; From dded274e7ba4332434645e6355040a7ada91987e Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Wed, 8 Feb 2023 08:07:18 -0500 Subject: [PATCH 14/22] editframe example for nextjs styleguide - first draft --- .../data/routes/styleguide/en.yml | 8 +++ .../Styleguide-EditFrame.sitecore.ts | 21 +++++++ .../src/components/Styleguide-EditFrame.tsx | 55 +++++++++++++++++++ packages/sitecore-jss-nextjs/src/index.ts | 12 +--- packages/sitecore-jss/src/utils/edit-frame.ts | 38 ++++++++----- 5 files changed, 110 insertions(+), 24 deletions(-) create mode 100644 packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts create mode 100644 packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml index 0b22a59299..d0d1675f31 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml @@ -240,3 +240,11 @@ placeholders: fields: heading: Translation Patterns sample: This text can be translated in en.yml + - componentName: Styleguide-Section + fields: + heading: Multilingual Patterns + placeholders: + <%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section: + - componentName: Styleguide-EditFrame + fields: + heading: Edit frame example diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts new file mode 100644 index 0000000000..8ae8f4cd75 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts @@ -0,0 +1,21 @@ +// eslint-disable-next-line no-unused-vars +import { CommonFieldTypes, SitecoreIcon, Manifest } from '@sitecore-jss/sitecore-jss-dev-tools'; + +/** + * Adds the Styleguide-EditFrame component to the disconnected manifest. + * This function is invoked by convention (*.sitecore.ts) when 'jss manifest' is run. + * @param {Manifest} manifest Manifest instance to add components to + */ +export default function StyleguideEditFrame(manifest: Manifest): void { + manifest.addComponent({ + name: 'Styleguide-EditFrame', + icon: SitecoreIcon.DocumentTag, + fields: [{ name: 'heading', type: CommonFieldTypes.SingleLineText }], + templateName: '<%- helper.getAppPrefix(appPrefix, appName) %>Styleguide-EditFrame', + /* + If the component implementation uses or withPlaceholder to expose a placeholder, + register it here, or components added to that placeholder will not be returned by Sitecore: + placeholders: ['exposed-placeholder-name'] + */ + }); +} diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx new file mode 100644 index 0000000000..3212bbcf53 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx @@ -0,0 +1,55 @@ +import { Field, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs'; +import { ComponentProps } from 'lib/component-props'; +import { EditFrame } from '@sitecore-jss/sitecore-jss-nextjs'; + +type StyleguideEditFrameProps = ComponentProps & { + fields: { + heading: Field; + }; + children: React.ReactNode; +}; + +const StyleguideEditFrame = (props: StyleguideEditFrameProps): JSX.Element => ( +
+

Styleguide-EditFrame Component

+ + Who framed Roger Rabbit? Who knows. But JSS can now edit frame any content on your page in + editing mode. + {props.children} + +
+); + +const getEditFrameProps = (dataSource?: string) => { + return { + dataSource: dataSource + ? { + itemId: dataSource, + // databaseName: 'web', + // language: 'en', // optional params you can also set for datasource + } + : undefined, // datasource will set the item to be edited by edit frame + buttons: editFrameButtons, // add custom editing functionality or edit field sets with buttons + title: 'JSS edit frame', + tooltip: 'Perform editing anywhere while not tied to a rendering, placeholder or field', + cssClass: 'jss-edit-frame', // customize edit frame appearance through CSS + parameters: {}, // set additional parameters when needed + }; +}; + +const editFrameButtons = [ + { + header: 'WebEditButton', + icon: './icon.png', + click: 'alert("you clicked an edit fram button")', + tooltip: 'Doesnt do much, just a web edit button example', + }, + { + header: 'FieldEditButton', + icon: './icon.png', + fields: ['heading'], + tooltip: 'Allows you to open field editor for specified fields', + }, +]; + +export default withDatasourceCheck()(StyleguideEditFrame); diff --git a/packages/sitecore-jss-nextjs/src/index.ts b/packages/sitecore-jss-nextjs/src/index.ts index 039c0a6a96..574b10ca23 100644 --- a/packages/sitecore-jss-nextjs/src/index.ts +++ b/packages/sitecore-jss-nextjs/src/index.ts @@ -10,16 +10,7 @@ export { NativeDataFetcherConfig, enableDebug, } from '@sitecore-jss/sitecore-jss'; -export { - DefaultEditFrameButton, - DefaultEditFrameButtons, - EditFrameDataSource, - FieldEditButton, - WebEditButton, - isEditorActive, - resetEditorChromes, - resolveUrl, -} from '@sitecore-jss/sitecore-jss/utils'; +export { isEditorActive, resetEditorChromes, resolveUrl } from '@sitecore-jss/sitecore-jss/utils'; export { LayoutService, LayoutServiceData, @@ -135,6 +126,7 @@ export { Text, TextField, DateField, + EditFrame, FEaaSComponent, FEaaSComponentProps, File, diff --git a/packages/sitecore-jss/src/utils/edit-frame.ts b/packages/sitecore-jss/src/utils/edit-frame.ts index d985154483..761f9f8100 100644 --- a/packages/sitecore-jss/src/utils/edit-frame.ts +++ b/packages/sitecore-jss/src/utils/edit-frame.ts @@ -42,7 +42,7 @@ export const DefaultEditFrameButtons = [ /** * @param {WebEditButton | FieldEditButton} button the button to determine the type of */ -function isWebEditButton(button: WebEditButton | FieldEditButton): button is WebEditButton { +function isWebEditButton(button: EditButtonTypes): button is WebEditButton { return (button as WebEditButton).click !== undefined; } @@ -52,18 +52,19 @@ export type EditFrameDataSource = { language?: string; }; -export type FieldEditButton = { - header: string; - icon: string; +export type BaseEditButton = { + isDivider?: boolean; + header?: string; + icon?: string; + tooltip?: string; +}; + +export type FieldEditButton = BaseEditButton & { fields: string[]; - tooltip: string; }; -export type WebEditButton = { - header: string; - icon: string; +export type WebEditButton = BaseEditButton & { click: string; - tooltip: string; parameters?: Record; type?: string; }; @@ -82,12 +83,12 @@ export function mapButtonToCommand( itemId?: string, frameParameters?: Record ): ChromeCommand { - if (button === '|') { + if (button === '|' || button.isDivider) { return { click: 'chrome:dummy', header: 'Separator', icon: '', - isDivider: false, + isDivider: true, tooltip: null, type: 'separator', }; @@ -119,12 +120,18 @@ export function commandBuilder( return { isDivider: false, type: button.type || null, + header: button.header || '', + icon: button.icon || '', + tooltip: button.tooltip || '', ...button, }; } else if (button.click.startsWith('javascript:') || button.click.startsWith('chrome:')) { return { isDivider: false, type: button.type || null, + header: button.header || '', + icon: button.icon || '', + tooltip: button.tooltip || '', ...button, }; } else { @@ -132,6 +139,9 @@ export function commandBuilder( return { isDivider: false, type: button.type || null, + header: button.header || '', + icon: button.icon || '', + tooltip: button.tooltip || '', ...button, }; } else { @@ -186,9 +196,9 @@ export function commandBuilder( return { isDivider: false, click: `javascript:Sitecore.PageModes.PageEditor.postRequest('${click}',null,false)`, - header: button.header, - icon: button.icon, - tooltip: button.tooltip, + header: button.header || '', + icon: button.icon || '', + tooltip: button.tooltip || '', type: button.type || null, }; } From cdc52abb22edc89d04bb1ff09f07a34021877a75 Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Mon, 13 Feb 2023 14:44:16 -0500 Subject: [PATCH 15/22] Edit frame productized --- .../angular/data/routes/styleguide/en.yml | 9 + .../styleguide-edit-frame.sitecore.ts | 15 ++ .../styleguide-edit-frame.component.html | 15 ++ .../styleguide-edit-frame.component.ts | 67 ++++++ .../data/routes/styleguide/en.yml | 2 +- .../Styleguide-EditFrame.sitecore.ts | 5 - .../{ => styleguide}/Styleguide-EditFrame.tsx | 12 +- .../react/data/routes/styleguide/en.yml | 8 + .../Styleguide-EditFrame.sitecore.js | 15 ++ .../components/Styleguide-EditFrame/index.js | 47 ++++ .../vue/data/routes/styleguide/en.yml | 8 + .../Styleguide-EditFrame.sitecore.js | 16 ++ .../Styleguide/Styleguide-EditFrame.vue | 60 +++++ .../components/editframe.component.spec.ts | 211 ++++++++++++++++++ .../src/components/editframe.component.ts | 16 +- .../src/components/EditFrame.test.tsx | 16 +- .../src/components/EditFrame.tsx | 41 ---- .../src/components/EditFrame.test.ts | 128 +++++++++++ .../src/components/EditFrame.ts | 21 +- 19 files changed, 646 insertions(+), 66 deletions(-) create mode 100644 packages/create-sitecore-jss/src/templates/angular/sitecore/definitions/components/styleguide-edit-frame.sitecore.ts create mode 100644 packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html create mode 100644 packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.ts rename packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/{ => styleguide}/Styleguide-EditFrame.sitecore.ts (73%) rename packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/{ => styleguide}/Styleguide-EditFrame.tsx (85%) create mode 100644 packages/create-sitecore-jss/src/templates/react/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js create mode 100644 packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js create mode 100644 packages/create-sitecore-jss/src/templates/vue/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js create mode 100644 packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue create mode 100644 packages/sitecore-jss-angular/src/components/editframe.component.spec.ts create mode 100644 packages/sitecore-jss-vue/src/components/EditFrame.test.ts diff --git a/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml index b51235cf35..d816fa7d08 100644 --- a/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml @@ -251,3 +251,12 @@ placeholders: - componentName: StyleguideAngularLazyLoading fields: heading: Lazy Loading + - componentName: Styleguide-Section + fields: + heading: Editing + placeholders: + <%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section: + - componentName: StyleguideEditFrame + fields: + heading: Edit frame example + diff --git a/packages/create-sitecore-jss/src/templates/angular/sitecore/definitions/components/styleguide-edit-frame.sitecore.ts b/packages/create-sitecore-jss/src/templates/angular/sitecore/definitions/components/styleguide-edit-frame.sitecore.ts new file mode 100644 index 0000000000..8fee8653cf --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/angular/sitecore/definitions/components/styleguide-edit-frame.sitecore.ts @@ -0,0 +1,15 @@ +import { CommonFieldTypes, SitecoreIcon, Manifest } from '@sitecore-jss/sitecore-jss-dev-tools'; + +/** + * Adds the Styleguide-EditFrame component to the disconnected manifest. + * This function is invoked by convention (*.sitecore.ts) when `jss manifest` is run. + */ +export default function StyleguideEditFrame(manifest: Manifest) { + manifest.addComponent({ + name: 'StyleguideEditFrame', + icon: SitecoreIcon.DocumentTag, + fields: [ + { name: 'heading', type: CommonFieldTypes.SingleLineText }, + ], + }); +} diff --git a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html new file mode 100644 index 0000000000..13311a1a83 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html @@ -0,0 +1,15 @@ + +

+ + Who framed Roger Rabbit? Can't say.
+ But JSS now allows to edit frame any piece of content on a page in editing mode.
+ You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it + +
+
| null; + }; + + editFrameProps: EditFrameProps; + + constructor(private jssContext: JssContextService) { } + + ngOnInit() { + this.jssContext.state.subscribe((state) => { + this.context = state.sitecore; + }); + this.editFrameProps = this.getEditFrameProps(this.rendering.dataSource); + } + + getEditFrameProps(dataSource: string) { + return { + dataSource: dataSource + ? { + itemId: dataSource, + // databaseName: 'web', + // language: 'en', // optional params you can also set for datasource + } + : undefined, // datasource will set the item to be edited by edit frame + buttons: this.editFrameButtons, // add custom editing functionality or edit field sets with buttons + title: 'JSS edit frame', + tooltip: 'Perform editing anywhere while not tied to a rendering, placeholder or field', + cssClass: 'jss-edit-frame', // customize edit frame appearance through CSS + parameters: {}, // set additional parameters when needed + sitecore: this.context, + }; + }; + + editFrameButtons = [ + { + header: 'WebEditButton', + icon: '/~/icon/Office/16x16/document_selection.png', + click: 'javascript:alert("An edit frame button was just clicked!")', + tooltip: 'Doesnt do much, just a web edit button example', + }, // use javascript:, webedit: or chrome: commands for webedit buttons + { + header: 'FieldEditButton', + icon: '/~/icon/Office/16x16/pencil.png', + fields: ['heading'], + tooltip: 'Allows you to open field editor for specified fields', + }, // or use field edit buttons to open Field Editor + ]; +} diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml index d0d1675f31..097220ad6a 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml @@ -242,7 +242,7 @@ placeholders: sample: This text can be translated in en.yml - componentName: Styleguide-Section fields: - heading: Multilingual Patterns + heading: Editing placeholders: <%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section: - componentName: Styleguide-EditFrame diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-EditFrame.sitecore.ts similarity index 73% rename from packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts rename to packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-EditFrame.sitecore.ts index 8ae8f4cd75..a5c896ce5b 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/Styleguide-EditFrame.sitecore.ts +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/sitecore/definitions/components/styleguide/Styleguide-EditFrame.sitecore.ts @@ -12,10 +12,5 @@ export default function StyleguideEditFrame(manifest: Manifest): void { icon: SitecoreIcon.DocumentTag, fields: [{ name: 'heading', type: CommonFieldTypes.SingleLineText }], templateName: '<%- helper.getAppPrefix(appPrefix, appName) %>Styleguide-EditFrame', - /* - If the component implementation uses or withPlaceholder to expose a placeholder, - register it here, or components added to that placeholder will not be returned by Sitecore: - placeholders: ['exposed-placeholder-name'] - */ }); } diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx similarity index 85% rename from packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx rename to packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx index 3212bbcf53..122e1db1ef 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/Styleguide-EditFrame.tsx +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx @@ -10,14 +10,14 @@ type StyleguideEditFrameProps = ComponentProps & { }; const StyleguideEditFrame = (props: StyleguideEditFrameProps): JSX.Element => ( -
-

Styleguide-EditFrame Component

+ +

{props.fields.heading}

Who framed Roger Rabbit? Who knows. But JSS can now edit frame any content on your page in editing mode. {props.children} -
+ ); const getEditFrameProps = (dataSource?: string) => { @@ -40,13 +40,13 @@ const getEditFrameProps = (dataSource?: string) => { const editFrameButtons = [ { header: 'WebEditButton', - icon: './icon.png', - click: 'alert("you clicked an edit fram button")', + icon: '/~/icon/Office/16x16/document_selection.png', + click: 'javascript:alert("An edit frame button was just clicked!")', tooltip: 'Doesnt do much, just a web edit button example', }, { header: 'FieldEditButton', - icon: './icon.png', + icon: '/~/icon/Office/16x16/pencil.png', fields: ['heading'], tooltip: 'Allows you to open field editor for specified fields', }, diff --git a/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml index 6d0f80ea3c..c07b069085 100644 --- a/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml @@ -244,4 +244,12 @@ placeholders: fields: heading: Translation Patterns sample: This text can be translated in en.yml + - componentName: Styleguide-Section + fields: + heading: Editing + placeholders: + React-jss-styleguide-section: + - componentName: Styleguide-EditFrame + fields: + heading: Edit Frame Component diff --git a/packages/create-sitecore-jss/src/templates/react/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js b/packages/create-sitecore-jss/src/templates/react/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js new file mode 100644 index 0000000000..f4701b3f68 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/react/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js @@ -0,0 +1,15 @@ +// eslint-disable-next-line no-unused-vars +import { CommonFieldTypes, SitecoreIcon, Manifest } from '@sitecore-jss/sitecore-jss-dev-tools'; + +/** + * Adds the StyleguideEditFrame component to the disconnected manifest. + * This function is invoked by convention (*.sitecore.js) when 'jss manifest' is run. + * @param {Manifest} manifest Manifest instance to add components to + */ +export default function (manifest) { + manifest.addComponent({ + name: 'Styleguide-EditFrame', + icon: SitecoreIcon.DocumentTag, + fields: [{ name: 'heading', type: CommonFieldTypes.SingleLineText }], + }); +} diff --git a/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js new file mode 100644 index 0000000000..565b4c3f4a --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js @@ -0,0 +1,47 @@ +import React from 'react'; +import { Text, EditFrame } from '@sitecore-jss/sitecore-jss-react'; + +const StyleguideEditFrame = (props) => ( +
+

{props.fields.heading}

+ + Who framed Roger Rabbit? Can't say. + But JSS now allows to edit frame any piece of content on a page in editing mode. + {props.children} + +
+); + +const getEditFrameProps = (dataSource) => { + return { + dataSource: dataSource + ? { + itemId: dataSource, + // databaseName: 'web', + // language: 'en', // optional params you can also set for datasource + } + : undefined, // datasource will set the item to be edited by edit frame + buttons: editFrameButtons, // add custom editing functionality or edit field sets with buttons + title: 'JSS edit frame', + tooltip: 'Perform editing anywhere while not tied to a rendering, placeholder or field', + cssClass: 'jss-edit-frame', // customize edit frame appearance through CSS + parameters: {}, // set additional parameters when needed + }; +}; + +const editFrameButtons = [ + { + header: 'WebEditButton', + icon: '/~/icon/Office/16x16/document_selection.png', + click: 'javascript:alert("An edit frame button was just clicked!")', + tooltip: 'Doesnt do much, just a web edit button example', + }, // use javascript:, webedit: or chrome: commands for webedit buttons + { + header: 'FieldEditButton', + icon: '/~/icon/Office/16x16/pencil.png', + fields: ['heading'], + tooltip: 'Allows you to open field editor for specified fields', + }, // or use field edit buttons to open Field Editor +]; + +export default StyleguideEditFrame; diff --git a/packages/create-sitecore-jss/src/templates/vue/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/vue/data/routes/styleguide/en.yml index 2bcea3f56a..3282cb5162 100644 --- a/packages/create-sitecore-jss/src/templates/vue/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/vue/data/routes/styleguide/en.yml @@ -245,3 +245,11 @@ placeholders: fields: heading: Translation Patterns sample: This text can be translated in en.yml + - componentName: Styleguide-Section + fields: + heading: Editing + placeholders: + Vue-jss-styleguide-section: + - componentName: Styleguide-EditFrame + fields: + heading: Edit Frame diff --git a/packages/create-sitecore-jss/src/templates/vue/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js b/packages/create-sitecore-jss/src/templates/vue/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js new file mode 100644 index 0000000000..0bd712526e --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/vue/sitecore/definitions/components/Styleguide-EditFrame.sitecore.js @@ -0,0 +1,16 @@ +// eslint-disable-next-line no-unused-vars +import { CommonFieldTypes, SitecoreIcon, Manifest } from '@sitecore-jss/sitecore-jss-dev-tools'; + +/** + * Adds the Styleguide-EditFrame component to the disconnected manifest. + * This function is invoked by convention (*.sitecore.js) when 'jss manifest' is run. + * @param {Manifest} manifest Manifest instance to add components to + */ +export default function (manifest) { + manifest.addComponent({ + name: 'Styleguide-EditFrame', + templateName: 'Vue-Styleguide-EditFrame', + icon: SitecoreIcon.DocumentTag, + fields: [{ name: 'heading', type: CommonFieldTypes.SingleLineText }], + }); +} diff --git a/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue b/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue new file mode 100644 index 0000000000..6649542b82 --- /dev/null +++ b/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue @@ -0,0 +1,60 @@ + + + diff --git a/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts b/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts new file mode 100644 index 0000000000..f83a27a967 --- /dev/null +++ b/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts @@ -0,0 +1,211 @@ +import { Component, DebugElement, Input } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; + +import { EditFrameComponent } from './editframe.component'; +import { DefaultEditFrameButton, EditButtonTypes, EditFrameDataSource } from '@sitecore-jss/sitecore-jss/utils'; +import { LayoutServiceContextData, RouteData } from '@sitecore-jss/sitecore-jss/layout'; +import { RouterTestingModule } from '@angular/router/testing'; + +const editingContext = { + context: { + pageEditing: true, + }, + route: { + name: 'styleguide', + placeholders: { + 'JssTestWeb-jss-main': [], + }, + itemId: 'testitemid', + }, +} + +const normalContext = { + context: { + pageEditing: false, + }, + route: { + name: 'styleguide', + placeholders: { + 'JssTestWeb-jss-main': [], + }, + itemId: 'testitemid', + }, +} + +@Component({ + selector: 'test-editframe', + template: ` +
+ + Wrapped text + +
+ `, + }) + class TestComponent { + @Input() dataSource: EditFrameDataSource; + + @Input() buttons: EditButtonTypes[]; + + @Input() title: string; + + @Input() tooltip: string; + + @Input() cssClass: string; + + @Input() parameters: Record; + + @Input() sitecore: LayoutServiceContextData & { + route: RouteData | null; + }; + + ngOnInit() { + this.sitecore = normalContext; + } + } + + describe('', () => { + + let fixture: ComponentFixture; + let de: DebugElement; + let editFrameComp: TestComponent; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [EditFrameComponent, TestComponent], + imports: [ + RouterTestingModule, + ], + }); + + fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + de = fixture.debugElement.query(By.css('sc-edit-frame')); + editFrameComp = fixture.componentInstance; + editFrameComp.sitecore = normalContext; + editingContext.context; + }); + + + it('should render nothing when not in pageEditing mode', () => { + editFrameComp.sitecore = normalContext; + fixture.detectChanges(); + + const rendered = de.nativeElement.textContent.trim(); + expect(rendered).toBe('Wrapped text'); + }); + + it('should render a frame when in pageEditing mode', () => { + editFrameComp.sitecore = editingContext; + fixture.detectChanges(); + + const frameDiv = de.query(By.css('div.scLooseFrameZone')).nativeElement; + const frameSpan = de.query(By.css('div.scLooseFrameZone > span.scChromeData')).nativeElement; + expect(frameDiv).toBeDefined(); + expect(frameSpan).toBeDefined(); + console.log(frameSpan); + expect(frameSpan.textContent).toBe( + '{}' + ); + }); + + it('should render child content within a frame when in pageEditing mode', () => { + editFrameComp.sitecore = editingContext; + fixture.detectChanges(); + + const frameDiv = de.query(By.css('div.scLooseFrameZone')).nativeElement; + expect(frameDiv.textContent).toContain('Wrapped text'); + }); + + it('should render the title and tooltip', () => { + editFrameComp.sitecore = editingContext; + editFrameComp.title = 'Test Title'; + editFrameComp.tooltip = 'Test Tooltip'; + fixture.detectChanges(); + + const frameSpan = de.query(By.css('div.scLooseFrameZone > span.scChromeData')).nativeElement; + expect(frameSpan.textContent).toBe( + '{"displayName":"Test Title","expandedDisplayName":"Test Tooltip"}' + ); + + }); + + it('should render the added class', () => { + editFrameComp.sitecore = editingContext; + editFrameComp.cssClass = 'topClass'; + fixture.detectChanges(); + + const frameDiv = de.query(By.css('div.scLooseFrameZone')).nativeElement; + const classDiv = de.query(By.css('div.topClass')).nativeElement; + expect(frameDiv).toBe(classDiv); + + }); + + it('should render the datasource', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + + editFrameComp.sitecore = editingContext; + editFrameComp.dataSource = mockDatasource; + fixture.detectChanges(); + + const frameDiv = de.query(By.css('div.scLooseFrameZone')).nativeElement; + const frameSpan = de.query(By.css('div.scLooseFrameZone > span.scChromeData')).nativeElement; + expect(frameDiv.getAttribute('sc_item')).toBe('sitecore://master/testItemId?lang=en'); + expect(frameSpan.textContent).toContain('"contextItemUri":"sitecore://master/testItemId?lang=en"'); + }); + + it('should render the buttons', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + const mockButtons: EditButtonTypes[] = [ + DefaultEditFrameButton.insert, + '|', + DefaultEditFrameButton.edit, + ]; + + editFrameComp.sitecore = editingContext; + editFrameComp.dataSource = mockDatasource; + editFrameComp.buttons = mockButtons; + fixture.detectChanges(); + + const frameSpan = de.query(By.css('div.scLooseFrameZone > span.scChromeData')).nativeElement; + + expect(frameSpan.textContent).toContain(` + "commands": + [{"isDivider":false, + "click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:new(id=testItemId)\',null,false)", + "header":"Insert New", + "icon":"/~/icon/Office/16x16/insert_from_template.png", + "tooltip":"Insert a new item", + "type":null}, + {"click":"chrome:dummy", + "header":"Separator", + "icon":"", + "isDivider":true, + "tooltip":null, + "type":"separator"}, + {"isDivider":false, + "click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:fieldeditor(command={70C4EED5-D4CD-4D7D-9763-80C42504F5E7}, fields=Title|Text, id=testItemId)\',null,false)", + "header":"Edit Item", + "icon":"/~/icon/people/16x16/cubes_blue.png", + "tooltip":"Edit the item fields.", + "type":null} + ]`.replace(/(\r\n|\n|\r|[\s]{2,})/gm, "")); // ensure expected output is readable for both human and runtime + }); + }); diff --git a/packages/sitecore-jss-angular/src/components/editframe.component.ts b/packages/sitecore-jss-angular/src/components/editframe.component.ts index 9e6b240f60..d8a98bae4d 100644 --- a/packages/sitecore-jss-angular/src/components/editframe.component.ts +++ b/packages/sitecore-jss-angular/src/components/editframe.component.ts @@ -9,8 +9,18 @@ import { LayoutServiceContextData, RouteData } from '@sitecore-jss/sitecore-jss/ @Component({ selector: 'sc-edit-frame,[sc-edit-frame]', - template: - '
{{chromeData}}
', + template: ` + + + +
+ {{chromeData}} + +
+ + + + `, }) export class EditFrameComponent implements OnChanges { @Input() dataSource: EditFrameDataSource; @@ -26,7 +36,7 @@ export class EditFrameComponent implements OnChanges { @Input() parameters: Record; @Input() sitecore: LayoutServiceContextData & { - route: RouteData | null; + route: RouteData | null; }; isEditing = false; diff --git a/packages/sitecore-jss-react/src/components/EditFrame.test.tsx b/packages/sitecore-jss-react/src/components/EditFrame.test.tsx index 8ee6b5fea5..7c8ff34ce0 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.test.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.test.tsx @@ -73,7 +73,7 @@ describe('', () => { .childAt(0) .html(); expect(rendered).to.be.equal( - '
{"displayName":"Edit","commands":[]}Test
' + '
{}Test
' ); }); @@ -88,7 +88,7 @@ describe('', () => { .childAt(0) .html(); expect(rendered).to.be.equal( - '
{"displayName":"Test Title","expandedDisplayName":"Test Tooltip","commands":[]}Test
' + '
{"displayName":"Test Title","expandedDisplayName":"Test Tooltip"}Test
' ); }); @@ -103,7 +103,7 @@ describe('', () => { .childAt(0) .html(); expect(rendered).to.be.equal( - '
{"displayName":"Edit","commands":[]}Test
' + '
{}Test
' ); }); @@ -123,7 +123,7 @@ describe('', () => { .childAt(0) .html(); expect(rendered).to.be.equal( - '
{"displayName":"Edit","contextItemUri":"sitecore://master/testItemId?lang=en","commands":[]}Test
' + '
{"contextItemUri":"sitecore://master/testItemId?lang=en"}Test
' ); }); @@ -148,7 +148,13 @@ describe('', () => { .childAt(0) .html(); expect(rendered).to.be.equal( - '
{"displayName":"Edit","contextItemUri":"sitecore://master/testItemId?lang=en","commands":[{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:new(id=testItemId)\',null,false)","header":"Insert New","icon":"/~/icon/Office/16x16/insert_from_template.png","tooltip":"Insert a new item","type":null},{"click":"chrome:dummy","header":"Separator","icon":"","isDivider":false,"tooltip":null,"type":"separator"},{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:fieldeditor(command={70C4EED5-D4CD-4D7D-9763-80C42504F5E7}, fields=Title|Text, id=testItemId)\',null,false)","header":"Edit Item","icon":"/~/icon/people/16x16/cubes_blue.png","tooltip":"Edit the item fields.","type":null}]}Test
' + `
+ + {"contextItemUri":"sitecore://master/testItemId?lang=en","commands":[{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:new(id=testItemId)\',null,false)","header":"Insert New","icon":"/~/icon/Office/16x16/insert_from_template.png","tooltip":"Insert a new item","type":null},{"click":"chrome:dummy","header":"Separator","icon":"","isDivider":true,"tooltip":null,"type":"separator"},{"isDivider":false,"click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:fieldeditor(command={70C4EED5-D4CD-4D7D-9763-80C42504F5E7}, fields=Title|Text, id=testItemId)\',null,false)","header":"Edit Item","icon":"/~/icon/people/16x16/cubes_blue.png","tooltip":"Edit the item fields.","type":null}]} + + Test +
+ `.replace(/(\r\n|\n|\r|[\s]{2,})/gm, "") ); }); }); diff --git a/packages/sitecore-jss-react/src/components/EditFrame.tsx b/packages/sitecore-jss-react/src/components/EditFrame.tsx index dfc91fc9e1..07de0b14a3 100644 --- a/packages/sitecore-jss-react/src/components/EditFrame.tsx +++ b/packages/sitecore-jss-react/src/components/EditFrame.tsx @@ -67,12 +67,6 @@ export const EditFrame: React.FC> = ({ ); }; -EditFrame.defaultProps = { - dataSource: undefined, - buttons: [], - title: 'Edit', -}; - export interface EditFrameProps { dataSource?: EditFrameDataSource; buttons?: (FieldEditButton | WebEditButton | '|')[]; @@ -81,38 +75,3 @@ export interface EditFrameProps { cssClass?: string; parameters?: Record; } - -// EditFrame.propTypes = { -// dataSource: PropTypes.oneOf([ -// undefined, -// PropTypes.shape({ -// itemId: PropTypes.string.isRequired, -// databaseName: PropTypes.string, -// language: PropTypes.string, -// }), -// ]), -// buttons: PropTypes.arrayOf( -// PropTypes.oneOf([ -// PropTypes.shape({ -// header: PropTypes.string, -// icon: PropTypes.string, -// fields: PropTypes.arrayOf(PropTypes.string).isRequired, -// tooltip: PropTypes.string, -// }), -// PropTypes.shape({ -// header: PropTypes.string.isRequired, -// icon: PropTypes.string.isRequired, -// click: PropTypes.string.isRequired, -// tooltip: PropTypes.string, -// parameters: PropTypes.string.isRequired, -// type: PropTypes.string, -// }), -// '|', -// ]) -// ), -// title: PropTypes.string, -// tooltip: PropTypes.string, -// cssClass: PropTypes.string, -// }; - -EditFrame.displayName = 'Edit Frame'; diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.test.ts b/packages/sitecore-jss-vue/src/components/EditFrame.test.ts new file mode 100644 index 0000000000..854e79b202 --- /dev/null +++ b/packages/sitecore-jss-vue/src/components/EditFrame.test.ts @@ -0,0 +1,128 @@ + +import { mount } from '@vue/test-utils'; +import { defineComponent, h } from 'vue'; +import { EditFrame } from './EditFrame'; +import { DefaultEditFrameButton, EditButtonTypes } from '@sitecore-jss/sitecore-jss/utils'; + +const normalContext = { + pageEditing: false, + }; + + const editingContext = { + pageEditing: true, + }; + +const EditFrameWithText = defineComponent({ + props: { + context: { + type: Object, + default: normalContext + } + }, + render() { + return h(EditFrame, {context: this.$props.context}, () => "Test text"); + } +}) + + +describe('', () => { + it('should render nothing when not in pageEditing mode', () => { + const rendered = mount(EditFrame, {props: { + context: normalContext, + }}); + expect(rendered.html()).toBe(''); + }); + + it('should render a frame when in pageEditing mode', () => { + const rendered = mount(EditFrame, {props: { + context: editingContext, + }}); + expect(rendered.html()).toBe('
{}
'); + }); + + it('should render child content within a frame when in pageEditing mode', () => { + const rendered = mount(EditFrameWithText, {props: { + context: editingContext, + }}); + expect(rendered.find('div.scLooseFrameZone').text()).toContain('Test text'); + }); + }); + + it('should render the title and tooltip', () => { + const rendered = mount(EditFrame, {props: { + context: editingContext, + title: 'Test Title', + tooltip: 'Test Tooltip', + }}); + const editSpan = rendered.find('.scLooseFrameZone > span.scChromeData'); + expect(editSpan.text()).toBe('{"displayName":"Test Title","expandedDisplayName":"Test Tooltip"}'); + }); + + + it('should render the added class', () => { + const rendered = mount(EditFrame, {props: { + context: editingContext, + cssClass: 'topClass', + }}); + const editDiv = rendered.find('div.scLooseFrameZone'); + expect(editDiv.element.classList.contains('topClass')).toBe(true); + }); + + it('should render the datasource', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + const rendered = mount(EditFrame, {props: { + context: editingContext, + dataSource: mockDatasource, + }}); + const editDiv = rendered.find('div.scLooseFrameZone'); + const editSpan = rendered.find('.scLooseFrameZone > span.scChromeData'); + expect(editDiv.attributes('sc_item') ).toBe('sitecore://master/testItemId?lang=en'); + expect(editSpan.text().includes('"contextItemUri":"sitecore://master/testItemId?lang=en"')).toBe(true); + }); + + it('should render the buttons', () => { + const mockDatasource = { + itemId: 'testItemId', + databaseName: 'master', + language: 'en', + }; + const mockButtons: EditButtonTypes[] = [ + DefaultEditFrameButton.insert, + '|', + DefaultEditFrameButton.edit, + ]; + const rendered = mount(EditFrame, {props: { + context: editingContext, + dataSource: mockDatasource, + buttons: mockButtons, + }}); + const editSpan = rendered.find('.scLooseFrameZone > span.scChromeData'); + + expect(editSpan.text().includes(` + "commands": + [{"isDivider":false, + "click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:new(id=testItemId)\',null,false)", + "header":"Insert New", + "icon":"/~/icon/Office/16x16/insert_from_template.png", + "tooltip":"Insert a new item", + "type":null}, + {"click":"chrome:dummy", + "header":"Separator", + "icon":"", + "isDivider":true, + "tooltip":null, + "type":"separator"}, + {"isDivider":false, + "click":"javascript:Sitecore.PageModes.PageEditor.postRequest(\'webedit:fieldeditor(command={70C4EED5-D4CD-4D7D-9763-80C42504F5E7}, fields=Title|Text, id=testItemId)\',null,false)", + "header":"Edit Item", + "icon":"/~/icon/people/16x16/cubes_blue.png", + "tooltip":"Edit the item fields.", + "type":null} + ]`.replace(/(\r\n|\n|\r|[\s]{2,})/gm, ""))).toBe(true); + + }); + diff --git a/packages/sitecore-jss-vue/src/components/EditFrame.ts b/packages/sitecore-jss-vue/src/components/EditFrame.ts index 62ab290521..88298239f9 100644 --- a/packages/sitecore-jss-vue/src/components/EditFrame.ts +++ b/packages/sitecore-jss-vue/src/components/EditFrame.ts @@ -5,6 +5,7 @@ import { EditButtonTypes, mapButtonToCommand, } from '@sitecore-jss/sitecore-jss/utils'; +import { RouteData } from '@sitecore-jss/sitecore-jss/layout'; export const EditFrame = defineComponent({ props: { @@ -20,12 +21,23 @@ export const EditFrame = defineComponent({ type: Object as PropType>, default: undefined, }, + context: { + type: Object, + default: undefined + }, + routeData: { + type: Object as () => RouteData, + }, }, render() { const instance = getCurrentInstance(); - const sitecoreContext = instance.appContext.config.globalProperties.$jss.sitecoreContext(); + const children = this.$slots.default; + // similar to placeholder implementation, try reading context locally first before retrieving it from global + const sitecoreContext = this.$props.context || instance.appContext.config.globalProperties.$jss?.sitecoreContext(); if (!sitecoreContext.pageEditing) { - return null; + if (children) + return children(); + return ''; } const chromeData: Record = { @@ -41,7 +53,7 @@ export const EditFrame = defineComponent({ // item uri for edit frame target if (this.$props.dataSource) { - const route = instance.appContext.config.globalProperties.$jss.routeData(); + const route = this.$props.routeData || instance.appContext.config.globalProperties.$jss?.routeData(); const databaseName = this.$props.dataSource.databaseName || route?.databaseName; const language = this.$props.dataSource.language || sitecoreContext.language; frameProps.sc_item = `sitecore://${databaseName}/${this.$props.dataSource.itemId}?lang=${language}`; @@ -53,8 +65,7 @@ export const EditFrame = defineComponent({ return mapButtonToCommand(value, this.$props.dataSource?.itemId, this.$props.parameters); } ); - - const children = this.$slots.default; + if (children) { const childElements = h('div', null, children()); const chromeSpan = h('span', { From ce99798a63a34d4fef7a5d9ae763b91521a9a744 Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Mon, 13 Feb 2023 16:46:13 -0500 Subject: [PATCH 16/22] Consistency, lint, cleanup --- .../angular/data/routes/styleguide/en.yml | 4 +- .../styleguide-edit-frame.component.html | 4 +- .../styleguide-edit-frame.component.ts | 51 +++++++++++-------- .../data/routes/styleguide/en.yml | 2 +- .../react/data/routes/styleguide/en.yml | 2 +- .../components/Styleguide-EditFrame/index.js | 6 ++- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml index d816fa7d08..2a7519fdcd 100644 --- a/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/angular/data/routes/styleguide/en.yml @@ -251,12 +251,12 @@ placeholders: - componentName: StyleguideAngularLazyLoading fields: heading: Lazy Loading - - componentName: Styleguide-Section + - componentName: StyleguideSection fields: heading: Editing placeholders: <%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section: - componentName: StyleguideEditFrame fields: - heading: Edit frame example + heading: Edit Frame diff --git a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html index 13311a1a83..70374ee52c 100644 --- a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html +++ b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html @@ -9,7 +9,7 @@

[sitecore]="context"> Who framed Roger Rabbit? Can't say.
But JSS now allows to edit frame any piece of content on a page in editing mode.
- You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it + You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it. - \ No newline at end of file diff --git a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.ts b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.ts index d64fd940c3..893ff779a7 100644 --- a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.ts +++ b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.ts @@ -1,14 +1,21 @@ import { Component, OnInit, Input } from '@angular/core'; -import { ComponentRendering, EditFrameDataSource, FieldEditButton, LayoutServiceContextData, RouteData, WebEditButton } from '@sitecore-jss/sitecore-jss-angular'; +import { + ComponentRendering, + EditFrameDataSource, + FieldEditButton, + LayoutServiceContextData, + RouteData, + WebEditButton +} from '@sitecore-jss/sitecore-jss-angular'; import { JssContextService } from '../../jss-context.service'; interface EditFrameProps { - dataSource: EditFrameDataSource, - buttons: (FieldEditButton | WebEditButton | '|')[], - title: string, - tooltip: string, - cssClass: string, - parameters: object, + dataSource: EditFrameDataSource; + buttons: (FieldEditButton | WebEditButton | '|')[]; + title: string; + tooltip: string; + cssClass: string; + parameters: object; } @Component({ @@ -23,6 +30,21 @@ export class StyleguideEditFrameComponent implements OnInit { editFrameProps: EditFrameProps; + editFrameButtons = [ + { + header: 'WebEditButton', + icon: '/~/icon/Office/16x16/document_selection.png', + click: 'javascript:alert("An edit frame button was just clicked!")', + tooltip: 'Doesnt do much, just a web edit button example', + }, // use javascript:, webedit: or chrome: commands for webedit buttons + { + header: 'FieldEditButton', + icon: '/~/icon/Office/16x16/pencil.png', + fields: ['heading'], + tooltip: 'Allows you to open field editor for specified fields', + }, // or use field edit buttons to open Field Editor + ]; + constructor(private jssContext: JssContextService) { } ngOnInit() { @@ -49,19 +71,4 @@ export class StyleguideEditFrameComponent implements OnInit { sitecore: this.context, }; }; - - editFrameButtons = [ - { - header: 'WebEditButton', - icon: '/~/icon/Office/16x16/document_selection.png', - click: 'javascript:alert("An edit frame button was just clicked!")', - tooltip: 'Doesnt do much, just a web edit button example', - }, // use javascript:, webedit: or chrome: commands for webedit buttons - { - header: 'FieldEditButton', - icon: '/~/icon/Office/16x16/pencil.png', - fields: ['heading'], - tooltip: 'Allows you to open field editor for specified fields', - }, // or use field edit buttons to open Field Editor - ]; } diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml index 097220ad6a..76494ba4d1 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/data/routes/styleguide/en.yml @@ -247,4 +247,4 @@ placeholders: <%- helper.getAppPrefix(appPrefix, appName) %>jss-styleguide-section: - componentName: Styleguide-EditFrame fields: - heading: Edit frame example + heading: Edit Frame diff --git a/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml b/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml index c07b069085..c6e010c9c4 100644 --- a/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml +++ b/packages/create-sitecore-jss/src/templates/react/data/routes/styleguide/en.yml @@ -251,5 +251,5 @@ placeholders: React-jss-styleguide-section: - componentName: Styleguide-EditFrame fields: - heading: Edit Frame Component + heading: Edit Frame diff --git a/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js index 565b4c3f4a..c3fcbe7ec4 100644 --- a/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js +++ b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js @@ -5,8 +5,10 @@ const StyleguideEditFrame = (props) => (

{props.fields.heading}

- Who framed Roger Rabbit? Can't say. - But JSS now allows to edit frame any piece of content on a page in editing mode. + Who framed Roger Rabbit? Can't say.
+ But JSS now allows to edit frame any piece of content on a page in editing mode.
+ You can add web edit or field edit buttons, modify edit frame's style through CSS class and + put the frame wherever you need it. {props.children}
From da967a28ff45fdf6c384dde76446325e823c59f5 Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Tue, 14 Feb 2023 17:12:01 -0500 Subject: [PATCH 17/22] editframe - misc changes --- .../src/components/editframe.component.spec.ts | 3 +-- packages/sitecore-jss-angular/src/public_api.ts | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts b/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts index f83a27a967..1695c07bdc 100644 --- a/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts +++ b/packages/sitecore-jss-angular/src/components/editframe.component.spec.ts @@ -96,7 +96,7 @@ const normalContext = { }); - it('should render nothing when not in pageEditing mode', () => { + it('should render wrapped element when not in pageEditing mode', () => { editFrameComp.sitecore = normalContext; fixture.detectChanges(); @@ -112,7 +112,6 @@ const normalContext = { const frameSpan = de.query(By.css('div.scLooseFrameZone > span.scChromeData')).nativeElement; expect(frameDiv).toBeDefined(); expect(frameSpan).toBeDefined(); - console.log(frameSpan); expect(frameSpan.textContent).toBe( '{}' ); diff --git a/packages/sitecore-jss-angular/src/public_api.ts b/packages/sitecore-jss-angular/src/public_api.ts index 6dc8916577..3785f30dfb 100644 --- a/packages/sitecore-jss-angular/src/public_api.ts +++ b/packages/sitecore-jss-angular/src/public_api.ts @@ -9,6 +9,7 @@ export { RenderEachDirective } from './components/render-each.directive'; export { RenderEmptyDirective } from './components/render-empty.directive'; export { RenderComponentComponent } from './components/render-component.component'; export { DateDirective } from './components/date.directive'; +export { EditFrameComponent } from './components/editframe.component'; export { ComponentNameAndType, DYNAMIC_COMPONENT, From c7a0f5e53d1ab2a77ba21b07a5991786ec006e52 Mon Sep 17 00:00:00 2001 From: Artem Alexeyenko Date: Wed, 15 Feb 2023 15:08:28 -0500 Subject: [PATCH 18/22] finalize styleguide examples on all frameworks --- .../styleguide-edit-frame.component.html | 3 +-- .../components/styleguide/Styleguide-EditFrame.tsx | 7 ++++--- .../src/components/Styleguide-EditFrame/index.js | 10 +++++----- .../components/Styleguide/Styleguide-EditFrame.vue | 14 +++++++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html index 70374ee52c..7dacc9d1c9 100644 --- a/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html +++ b/packages/create-sitecore-jss/src/templates/angular/src/app/components/styleguide-edit-frame/styleguide-edit-frame.component.html @@ -1,5 +1,4 @@ -

[cssClass]="editFrameProps.cssClass" [parameters]="editFrameProps.parameters" [sitecore]="context"> - Who framed Roger Rabbit? Can't say.
+ Who framed Roger Rabbit? Hard to say.
But JSS now allows to edit frame any piece of content on a page in editing mode.
You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it. diff --git a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx index 122e1db1ef..c91208ec66 100644 --- a/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx +++ b/packages/create-sitecore-jss/src/templates/nextjs-styleguide/src/components/styleguide/Styleguide-EditFrame.tsx @@ -1,6 +1,7 @@ import { Field, withDatasourceCheck } from '@sitecore-jss/sitecore-jss-nextjs'; import { ComponentProps } from 'lib/component-props'; import { EditFrame } from '@sitecore-jss/sitecore-jss-nextjs'; +import StyleguideSpecimen from './Styleguide-Specimen'; type StyleguideEditFrameProps = ComponentProps & { fields: { @@ -11,10 +12,10 @@ type StyleguideEditFrameProps = ComponentProps & { const StyleguideEditFrame = (props: StyleguideEditFrameProps): JSX.Element => ( -

{props.fields.heading}

- Who framed Roger Rabbit? Who knows. But JSS can now edit frame any content on your page in - editing mode. + Who framed Roger Rabbit? Hard to say.
+ But JSS now allows to edit frame any piece of content on a page in editing mode.
+ You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it. {props.children}
diff --git a/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js index c3fcbe7ec4..f696f82b36 100644 --- a/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js +++ b/packages/create-sitecore-jss/src/templates/react/src/components/Styleguide-EditFrame/index.js @@ -1,17 +1,17 @@ import React from 'react'; -import { Text, EditFrame } from '@sitecore-jss/sitecore-jss-react'; +import { EditFrame } from '@sitecore-jss/sitecore-jss-react'; +import StyleguideSpecimen from '../Styleguide-Specimen'; const StyleguideEditFrame = (props) => ( -
-

{props.fields.heading}

+ - Who framed Roger Rabbit? Can't say.
+ Who framed Roger Rabbit? Hard to say.
But JSS now allows to edit frame any piece of content on a page in editing mode.
You can add web edit or field edit buttons, modify edit frame's style through CSS class and put the frame wherever you need it. {props.children}
-
+ ); const getEditFrameProps = (dataSource) => { diff --git a/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue b/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue index 6649542b82..47a226f05e 100644 --- a/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue +++ b/packages/create-sitecore-jss/src/templates/vue/src/components/Styleguide/Styleguide-EditFrame.vue @@ -1,13 +1,16 @@