Skip to content

Commit 1cad8b7

Browse files
[Documents] - highlight editable elements is missing (#3776)
* added the highlight editable draft version * updated styles * Automatic frontend build * added the icon and moved it in the sidebar * updated styles * added tranlsations * Automatic frontend build * updated the icon * updated the HighlightEditablesButton styles * updated the translation key value * updated the sdk export of the InheritanceOverlay * Automatic frontend build --------- Co-authored-by: ValeriaMaltseva <11871778+ValeriaMaltseva@users.noreply.github.com>
1 parent 2af7106 commit 1cad8b7

784 files changed

Lines changed: 30556 additions & 91 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

assets/js/src/core/app/public-api/document-editor-iframe/editable-data/editable-data.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,17 @@ export interface DocumentEditableApi {
2828
getEditableDefinitions: () => AbstractDocumentEditableDefinition[]
2929
registerDynamicEditables: (editables: AbstractDocumentEditableDefinition[]) => void
3030
unregisterDynamicEditables: (editableIds: string[]) => void
31+
getHighlightEditables: () => boolean
32+
setHighlightEditables: (highlight: boolean) => void
33+
subscribeHighlightEditables: (listener: (highlight: boolean) => void) => () => void
3134
}
3235

3336
class DocumentEditableApiImpl implements DocumentEditableApi {
3437
private values: Record<string, ValueType> = {}
3538
private inheritanceState: Record<string, boolean> = {}
3639
private dynamicEditables: Record<string, AbstractDocumentEditableDefinition> = {}
40+
private highlightEditables = false
41+
private readonly highlightListeners = new Set<(highlight: boolean) => void>()
3742

3843
getValues (forApi: boolean = false): Record<string, ValueType> {
3944
if (!forApi) {
@@ -86,6 +91,33 @@ class DocumentEditableApiImpl implements DocumentEditableApi {
8691
Object.assign(this.inheritanceState, inheritanceState)
8792
}
8893

94+
getHighlightEditables (): boolean {
95+
return this.highlightEditables
96+
}
97+
98+
setHighlightEditables (highlight: boolean): void {
99+
if (this.highlightEditables === highlight) {
100+
return
101+
}
102+
103+
this.highlightEditables = highlight
104+
this.highlightListeners.forEach((listener) => {
105+
try {
106+
listener(highlight)
107+
} catch (error) {
108+
console.warn('Could not notify highlight-editables listener:', error)
109+
}
110+
})
111+
}
112+
113+
subscribeHighlightEditables (listener: (highlight: boolean) => void): () => void {
114+
this.highlightListeners.add(listener)
115+
116+
return () => {
117+
this.highlightListeners.delete(listener)
118+
}
119+
}
120+
89121
registerDynamicEditables (editables: AbstractDocumentEditableDefinition[]): void {
90122
for (const editable of editables) {
91123
this.dynamicEditables[editable.id] = editable

assets/js/src/core/app/public-api/document/document-api.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { markDocumentEditablesAsModified, selectDocumentById } from '@Pimcore/mo
1313
import { iframeDocumentEditorRegistry } from './iframe-registry'
1414
import { documentSaveService, SaveTaskType } from '@Pimcore/modules/document/services'
1515
import { debounce, isNil } from 'lodash'
16-
import { type AreablockGroupedTypes, setDocumentAreablockTypes, mergeDocumentAreablockTypes, setDocumentTimeSliderVisible } from '@Pimcore/modules/document/document-editor-slice'
16+
import { type AreablockGroupedTypes, setDocumentAreablockTypes, mergeDocumentAreablockTypes, setDocumentTimeSliderVisible, setDocumentHighlightEditables, selectDocumentHighlightEditables } from '@Pimcore/modules/document/document-editor-slice'
1717
import { type PublicApiDocumentEditorIframe } from '../document-editor-iframe'
1818
import { type IframeRef } from '@Pimcore/components/iframe/iframe'
1919

@@ -31,6 +31,8 @@ export interface DocumentApi {
3131
notifyAreablockTypes: (documentId: number, editableTypeId: string, areablockTypes: AreablockGroupedTypes) => void
3232
mergeAreablockTypes: (documentId: number, editableTypeId: string, areablockTypes: AreablockGroupedTypes) => void
3333
notifyTimeSliderVisible: (documentId: number, visible: boolean) => void
34+
setHighlightEditables: (documentId: number, highlight: boolean) => void
35+
getHighlightEditables: (documentId: number) => boolean
3436
isIframeReady: (documentId: number) => boolean
3537
onReady: (documentId: number, callback: () => void) => void
3638
}
@@ -120,6 +122,22 @@ class DocumentApiImpl implements DocumentApi {
120122
store.dispatch(setDocumentTimeSliderVisible({ documentId, visible }))
121123
}
122124

125+
setHighlightEditables (documentId: number, highlight: boolean): void {
126+
store.dispatch(setDocumentHighlightEditables({ documentId, highlight }))
127+
128+
if (iframeDocumentEditorRegistry.isIframeRegistered(documentId)) {
129+
try {
130+
this.getIframeApi(documentId).documentEditable.setHighlightEditables(highlight)
131+
} catch (error) {
132+
console.warn(`Could not push highlight-editables state to iframe for document ${documentId}:`, error)
133+
}
134+
}
135+
}
136+
137+
getHighlightEditables (documentId: number): boolean {
138+
return selectDocumentHighlightEditables(store.getState(), documentId)
139+
}
140+
123141
isIframeReady (documentId: number): boolean {
124142
return iframeDocumentEditorRegistry.isIframeReady(documentId)
125143
}
Lines changed: 10 additions & 0 deletions
Loading
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* This source file is available under the terms of the
3+
* Pimcore Open Core License (POCL)
4+
* Full copyright and license information is available in
5+
* LICENSE.md which is distributed with this source code.
6+
*
7+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
8+
* @license Pimcore Open Core License (POCL)
9+
*/
10+
11+
import { createStyles } from '@Pimcore/modules/ant-design/styles/create-styles'
12+
13+
export const useStyles = createStyles(({ token, css }) => {
14+
return {
15+
highlightEditablesButton: css`
16+
&:hover {
17+
background-color: ${token.colorFillAlter} !important;
18+
}
19+
`,
20+
21+
highlightEditablesButtonActive: css`
22+
background-color: ${token.colorFillAlter} !important;
23+
`
24+
}
25+
})
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* This source file is available under the terms of the
3+
* Pimcore Open Core License (POCL)
4+
* Full copyright and license information is available in
5+
* LICENSE.md which is distributed with this source code.
6+
*
7+
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
8+
* @license Pimcore Open Core License (POCL)
9+
*/
10+
11+
import React, { useContext } from 'react'
12+
import { useTranslation } from 'react-i18next'
13+
import cn from 'classnames'
14+
import { IconButton } from '@Pimcore/components/icon-button/icon-button'
15+
import { DocumentContext } from '@Pimcore/modules/document/document-provider'
16+
import { useDocumentDraft } from '@Pimcore/modules/document/hooks/use-document-draft'
17+
import { useAppSelector } from '@Pimcore/app/store'
18+
import { selectDocumentHighlightEditables } from '@Pimcore/modules/document/document-editor-slice'
19+
import { getPimcoreStudioApi } from '@Pimcore/app/public-api/helpers/api-helper'
20+
import { useStyles } from './highlight-editables-button.styles'
21+
22+
const TYPES_WITH_EDITABLES = ['page', 'snippet', 'email']
23+
24+
export const HighlightEditablesButton = (): React.JSX.Element | null => {
25+
const { t } = useTranslation()
26+
const { styles } = useStyles()
27+
28+
const { id } = useContext(DocumentContext)
29+
const { document } = useDocumentDraft(id)
30+
const isHighlighted = useAppSelector((state) => selectDocumentHighlightEditables(state, id))
31+
32+
if (document?.type === undefined || !TYPES_WITH_EDITABLES.includes(document.type)) {
33+
return null
34+
}
35+
36+
const toggleHighlight = (): void => {
37+
try {
38+
const { document: documentApi } = getPimcoreStudioApi()
39+
documentApi.setHighlightEditables(id, !isHighlighted)
40+
} catch (error) {
41+
console.warn('Could not toggle highlight-editables state:', error)
42+
}
43+
}
44+
45+
return (
46+
<IconButton
47+
className={ cn(styles.highlightEditablesButton, { [styles.highlightEditablesButtonActive]: isHighlighted }) }
48+
icon={ { value: 'highlight', colorToken: 'colorPrimary' } }
49+
onClick={ toggleHighlight }
50+
tooltip={ { title: t('document.highlight-editables'), placement: 'left' } }
51+
type="link"
52+
/>
53+
)
54+
}

assets/js/src/core/modules/document/document-editor-slice.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ export type AreablockGroupedTypes = Record<string, AreablockTypeEntry[]>
2525
export interface DocumentEditorState {
2626
documentAreablocks: Record<number, Record<string, AreablockGroupedTypes>>
2727
timeSliderVisible: Record<number, boolean>
28+
highlightEditables: Record<number, boolean>
2829
}
2930

3031
const initialState: DocumentEditorState = {
3132
documentAreablocks: {},
32-
timeSliderVisible: {}
33+
timeSliderVisible: {},
34+
highlightEditables: {}
3335
}
3436

3537
const documentEditorSlice = createSlice({
@@ -64,6 +66,9 @@ const documentEditorSlice = createSlice({
6466
setDocumentTimeSliderVisible: (state, action: PayloadAction<{ documentId: number, visible: boolean }>) => {
6567
state.timeSliderVisible[action.payload.documentId] = action.payload.visible
6668
},
69+
setDocumentHighlightEditables: (state, action: PayloadAction<{ documentId: number, highlight: boolean }>) => {
70+
state.highlightEditables[action.payload.documentId] = action.payload.highlight
71+
},
6772
removeDocument: (state, action: PayloadAction<number>) => {
6873
const documentId = action.payload
6974
if (state.documentAreablocks[documentId] !== undefined) {
@@ -74,15 +79,20 @@ const documentEditorSlice = createSlice({
7479
const { [documentId]: removed, ...remainingTimeSliderVisible } = state.timeSliderVisible
7580
state.timeSliderVisible = remainingTimeSliderVisible
7681
}
82+
if (state.highlightEditables[documentId] !== undefined) {
83+
const { [documentId]: removed, ...remainingHighlightEditables } = state.highlightEditables
84+
state.highlightEditables = remainingHighlightEditables
85+
}
7786
},
7887
clearAllDocuments: (state) => {
7988
state.documentAreablocks = {}
8089
state.timeSliderVisible = {}
90+
state.highlightEditables = {}
8191
}
8292
}
8393
})
8494

85-
export const { setDocumentAreablockTypes, mergeDocumentAreablockTypes, setDocumentTimeSliderVisible, removeDocument, clearAllDocuments } = documentEditorSlice.actions
95+
export const { setDocumentAreablockTypes, mergeDocumentAreablockTypes, setDocumentTimeSliderVisible, setDocumentHighlightEditables, removeDocument, clearAllDocuments } = documentEditorSlice.actions
8696

8797
export const selectDocumentEditorState = (state: any): DocumentEditorState => state['document-editor']
8898

@@ -122,6 +132,13 @@ export const selectDocumentTimeSliderVisible = createSelector(
122132
}
123133
)
124134

135+
export const selectDocumentHighlightEditables = createSelector(
136+
[selectDocumentEditorState, (_state: any, documentId: number) => documentId],
137+
(documentEditorState, documentId) => {
138+
return documentEditorState.highlightEditables[documentId] ?? false
139+
}
140+
)
141+
125142
export const selectDocumentHasAreablocks = createSelector(
126143
[selectDocumentAreablockGroupedTypes],
127144
(areablockGroupedTypes) => {

assets/js/src/core/modules/document/editor/shared-tab-manager/sidebar-definitions.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,13 @@
1010

1111
import React from 'react'
1212
import { Icon } from '@Pimcore/components/icon/icon'
13-
import { type ISidebarEntry } from '@Pimcore/modules/element/sidebar/sidebar-manager'
13+
import { type ISidebarButton, type ISidebarEntry } from '@Pimcore/modules/element/sidebar/sidebar-manager'
1414
import { type IDocumentContext } from '@Pimcore/modules/document/document-provider'
15-
import {
16-
ContentSettingsSidebar
17-
} from '../sidebar/tabs/content-settings/content-settings-sidebar'
18-
import {
19-
AreablockTypesSidebar
20-
} from '../sidebar/tabs/areablock-types/areablock-types-sidebar'
21-
import {
22-
NavigationSidebar
23-
} from '../sidebar/tabs/navigation/navigation-sidebar'
24-
import {
25-
DocumentConfigurationSidebar
26-
} from '../sidebar/tabs/document-configuration/document-configuration-sidebar'
15+
import { HighlightEditablesButton } from '@Pimcore/modules/document/actions/highlight-editables/highlight-editables-button'
16+
import { ContentSettingsSidebar } from '../sidebar/tabs/content-settings/content-settings-sidebar'
17+
import { AreablockTypesSidebar } from '../sidebar/tabs/areablock-types/areablock-types-sidebar'
18+
import { NavigationSidebar } from '../sidebar/tabs/navigation/navigation-sidebar'
19+
import { DocumentConfigurationSidebar } from '../sidebar/tabs/document-configuration/document-configuration-sidebar'
2720
import { checkAreablockTypesVisibility } from '../sidebar/visibility/areablock-types-visibility'
2821
import { checkSettingsVisibility } from '../sidebar/visibility/content-settings-visibility'
2922
import { checkNavigationVisibility } from '../sidebar/visibility/navigation-visibility'
@@ -59,3 +52,9 @@ export const SIDEBAR_DOCUMENT_CONFIGURATION: ISidebarEntry<IDocumentContext> = {
5952
tooltip: 'document-configuration.sidebar-title',
6053
isVisible: checkSettingsVisibility
6154
}
55+
56+
export const SIDEBAR_HIGHLIGHT_EDITABLES: ISidebarButton = {
57+
key: 'highlight-editables',
58+
icon: <Icon value="highlight" />,
59+
component: <HighlightEditablesButton />
60+
}

assets/js/src/core/modules/document/editor/shared-tab-manager/tabs/edit/components/editables-renderer/editables-loader.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const EditablesLoader = ({ editableDefinitions }: EditablesLoaderProps):
2626
const documentEditableRegistry = useInjection<DynamicTypeDocumentEditableRegistry>(serviceIds['DynamicTypes/DocumentEditableRegistry'])
2727
const apiInitialized = useRef(false)
2828
const [isInitialized, setIsInitialized] = useState(false)
29-
const { initializeData, notifyReady, initializeInheritanceState } = useDocumentEditor()
29+
const { initializeData, notifyReady, initializeInheritanceState, initializeHighlightEditables } = useDocumentEditor()
3030
const { id: documentId } = useContext(DocumentContext)
3131

3232
const getInitialData = (editableDefinitions: AbstractDocumentEditableDefinition[]): Record<string, { type: string, data: any }> => {
@@ -54,10 +54,12 @@ export const EditablesLoader = ({ editableDefinitions }: EditablesLoaderProps):
5454
if (!apiInitialized.current) {
5555
initializeData(getInitialData(editableDefinitions))
5656
initializeInheritanceState(getInitialInheritanceState(editableDefinitions))
57+
initializeHighlightEditables()
58+
5759
apiInitialized.current = true
5860
setIsInitialized(true)
5961
}
60-
}, [editableDefinitions, initializeData, initializeInheritanceState])
62+
}, [editableDefinitions, initializeData, initializeInheritanceState, initializeHighlightEditables])
6163

6264
useEffect(() => {
6365
if (apiInitialized.current) {

assets/js/src/core/modules/document/editor/shared-tab-manager/tabs/edit/hooks/use-document-editor.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export interface DocumentEditorContextProps {
2525
getInheritanceState: (key: string) => boolean
2626
setInheritanceState: (key: string, inherited: boolean) => void
2727
initializeInheritanceState: (inheritanceState: Record<string, boolean>) => void
28+
initializeHighlightEditables: () => void
2829
}
2930

3031
export const useDocumentEditor = (): DocumentEditorContextProps => {
@@ -89,6 +90,16 @@ export const useDocumentEditor = (): DocumentEditorContextProps => {
8990
getDocumentEditableApi().initializeInheritanceState(inheritanceState)
9091
}
9192

93+
const initializeHighlightEditables = (): void => {
94+
try {
95+
const { document: documentApi } = getPimcoreStudioApi()
96+
97+
getDocumentEditableApi().setHighlightEditables(documentApi.getHighlightEditables(id))
98+
} catch (error) {
99+
console.warn('Could not initialize highlight-editables state from parent:', error)
100+
}
101+
}
102+
92103
const triggerSaveAndReload = useCallback((): void => {
93104
try {
94105
const { document: documentApi } = getPimcoreStudioApi()
@@ -121,6 +132,7 @@ export const useDocumentEditor = (): DocumentEditorContextProps => {
121132
notifyReady,
122133
getInheritanceState,
123134
setInheritanceState,
124-
initializeInheritanceState
135+
initializeInheritanceState,
136+
initializeHighlightEditables
125137
}
126138
}

assets/js/src/core/modules/document/editor/types/email/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import { Icon } from '@Pimcore/components/icon/icon'
2626
import {
2727
SIDEBAR_AREABLOCK_TYPES,
2828
SIDEBAR_CONTENT_SETTINGS,
29-
SIDEBAR_DOCUMENT_CONFIGURATION
29+
SIDEBAR_DOCUMENT_CONFIGURATION,
30+
SIDEBAR_HIGHLIGHT_EDITABLES
3031
} from '../../shared-tab-manager/sidebar-definitions'
3132
import {
3233
EmailSettingsSidebar
@@ -58,5 +59,7 @@ moduleSystem.registerModule({
5859
})
5960
emailSidebarManager.registerEntry(SIDEBAR_CONTENT_SETTINGS)
6061
emailSidebarManager.registerEntry(SIDEBAR_DOCUMENT_CONFIGURATION)
62+
63+
emailSidebarManager.registerButton(SIDEBAR_HIGHLIGHT_EDITABLES)
6164
}
6265
})

0 commit comments

Comments
 (0)