All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.page_editor.app.components.MasterLayout.js Maven / Gradle / Ivy

The newest version!
/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

import classNames from 'classnames';
import {openToast} from 'frontend-js-components-web';
import PropTypes from 'prop-types';
import React, {useCallback, useEffect, useMemo, useRef} from 'react';
import {useDrop} from 'react-dnd';

import {
	LayoutDataPropTypes,
	getLayoutDataItemPropTypes,
} from '../../prop_types/index';
import {LAYOUT_DATA_ITEM_TYPES} from '../config/constants/layoutDataItemTypes';
import {useSelectItem} from '../contexts/ControlsContext';
import {useSelector, useSelectorRef} from '../contexts/StoreContext';
import Layout from './Layout';
import FragmentContent from './fragment_content/FragmentContent';
import {FormStep} from './layout_data_items/FormStep';
import {FormStepContainer} from './layout_data_items/FormStepContainer';
import hasDropZoneChild from './layout_data_items/hasDropZoneChild';
import {
	Collection,
	Column,
	Container,
	Form,
	Row,
} from './layout_data_items/index';

const LAYOUT_DATA_ITEMS = {
	[LAYOUT_DATA_ITEM_TYPES.collection]: Collection,
	[LAYOUT_DATA_ITEM_TYPES.collectionItem]: CollectionItem,
	[LAYOUT_DATA_ITEM_TYPES.column]: MasterColumn,
	[LAYOUT_DATA_ITEM_TYPES.container]: Container,
	[LAYOUT_DATA_ITEM_TYPES.form]: Form,
	[LAYOUT_DATA_ITEM_TYPES.formStep]: FormStep,
	[LAYOUT_DATA_ITEM_TYPES.formStepContainer]: FormStepContainer,
	[LAYOUT_DATA_ITEM_TYPES.dropZone]: DropZoneContainer,
	[LAYOUT_DATA_ITEM_TYPES.fragment]: Fragment,
	[LAYOUT_DATA_ITEM_TYPES.fragmentDropZone]: Root,
	[LAYOUT_DATA_ITEM_TYPES.root]: Root,
	[LAYOUT_DATA_ITEM_TYPES.row]: Row,
};

const MasterPage = React.memo(() => {
	const fragmentEntryLinks = useSelector((state) => state.fragmentEntryLinks);
	const masterLayoutData = useSelector(
		(state) => state.masterLayout?.masterLayoutData
	);

	const mainItem = masterLayoutData.items[masterLayoutData.rootItems.main];

	const [, targetRef] = useDrop({
		accept: Object.values(LAYOUT_DATA_ITEM_TYPES),
		drop: (_, monitor) => {
			const {x, y} = monitor.getClientOffset();

			const element = document.elementFromPoint(x, y);

			if (element.closest('.page-editor')) {
				return;
			}

			openToast({
				message: Liferay.Language.get(
					'fragments-and-widgets-cannot-be-placed-inside-this-area'
				),
				type: 'danger',
			});
		},
	});

	return (
		
); }); MasterPage.displayName = 'MasterPage'; export default MasterPage; function MasterLayoutDataItem({fragmentEntryLinks, item, layoutData}) { const Component = LAYOUT_DATA_ITEMS[item.type]; if (!Component) { return null; } return ( {item.children.map((childId) => { return ( ); })} ); } MasterLayoutDataItem.propTypes = { fragmentEntryLinks: PropTypes.object.isRequired, item: getLayoutDataItemPropTypes().isRequired, layoutData: LayoutDataPropTypes.isRequired, }; function DropZoneContainer() { const mainItemId = useSelector((state) => state.layoutData.rootItems.main); return ; } function Root({children}) { return
{children}
; } function CollectionItem({children}) { return
{children}
; } function Fragment({item, layoutData}) { const ref = useRef(null); const selectItem = useSelectItem(); const hasDropzoneChild = useMemo( () => hasDropZoneChild(item, layoutData), [item, layoutData] ); useEffect(() => { const element = ref.current; if (!element) { return; } const handler = (event) => { const element = event.target; if (element.closest('[href]')) { event.preventDefault(); } if (!event.target.closest('.page-editor')) { selectItem(null); } }; element.addEventListener('click', handler); if (!hasDropzoneChild) { element.setAttribute('inert', ''); } element.setAttribute('aria-hidden', 'true'); return () => { element.removeEventListener('click', handler); if (!hasDropzoneChild) { element.removeAttribute('inert'); } element.removeAttribute('aria-hidden'); }; }); const fragmentEntryLinksRef = useSelectorRef( (state) => state.fragmentEntryLinks ); const masterLayoutDataRef = useSelectorRef( (state) => state.masterLayout?.masterLayoutData ); const getPortals = useCallback( (element) => Array.from(element.querySelectorAll('lfr-drop-zone')).map( (dropZoneElement) => { const mainItemId = dropZoneElement.getAttribute('uuid') || ''; const Component = () => mainItemId ? ( ) : null; Component.displayName = `DropZone(${mainItemId})`; return { Component, element: dropZoneElement, }; } ), [fragmentEntryLinksRef, masterLayoutDataRef] ); return ( ); } Fragment.propTypes = { fragmentEntryLinks: PropTypes.object.isRequired, item: getLayoutDataItemPropTypes({ config: PropTypes.shape({ fragmentEntryLinkId: PropTypes.string.isRequired, }), }).isRequired, }; function MasterColumn({children, className, ...otherProps}) { return ( {children} ); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy