UNPKG

@craftercms/studio-ui

Version:

Services, components, models & utils to build CrafterCMS authoring extensions.

324 lines (322 loc) 12.1 kB
/* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ import MenuItem from '@mui/material/MenuItem'; import MenuList from '@mui/material/MenuList'; import EmptyState from '../EmptyState/EmptyState'; import { FormattedMessage } from 'react-intl'; import Typography from '@mui/material/Typography'; import ItemDisplay from '../ItemDisplay'; import ItemStateIcon from '../ItemStateIcon/ItemStateIcon'; import { getItemPublishingTargetText, getItemStateText, isInWorkflow } from '../ItemDisplay/utils'; import React from 'react'; import { makeStyles } from 'tss-react/mui'; import Popover from '@mui/material/Popover'; import palette from '../../styles/palette'; import Skeleton from '@mui/material/Skeleton'; import ItemPublishingTargetIcon from '../ItemPublishingTargetIcon/ItemPublishingTargetIcon'; const useStyles = makeStyles()( ( theme, { root, mainItem, actionsContainer, actionsColumn, emptyRoot, itemsList, itemInfo, itemInfoContentType, itemEdited, itemEditedText, itemState, infoItem, menuItem, itemDisplayRoot, itemTypeIcon, itemTypography, icon } = {} ) => ({ root: Object.assign({ maxWidth: 400, borderRadius: '12px' }, root), mainItem: Object.assign({ padding: '10px 20px' }, mainItem), actionsContainer: Object.assign({ display: 'flex', flexDirection: 'row', padding: '10px' }, actionsContainer), actionsColumn: Object.assign( { display: 'flex', flexDirection: 'column', flexBasis: '100%', flex: '1', '&:first-child': { marginRight: '60px' } }, actionsColumn ), emptyRoot: Object.assign({ display: 'block', padding: '10px', textAlign: 'center' }, emptyRoot), itemsList: Object.assign({ padding: 0 }, itemsList), itemInfo: Object.assign({ display: 'block', borderBottom: `1px solid ${palette.gray.light4}` }, itemInfo), itemInfoContentType: Object.assign( { color: theme.palette.text.secondary, marginBottom: '4px' }, itemInfoContentType ), itemEdited: Object.assign({ paddingTop: '12px', borderTop: `1px solid ${palette.gray.light4}` }, itemEdited), itemEditedText: Object.assign({ color: theme.palette.text.secondary, fontWeight: 600 }, itemEditedText), itemState: Object.assign( { '&> *': { marginRight: '5px' } }, itemState ), infoItem: Object.assign( { cursor: 'default', backgroundColor: 'inherit !important', '&:hover': { backgroundColor: 'inherit' } }, infoItem ), menuItem: Object.assign({ minWidth: '100px' }, menuItem), itemDisplayRoot: Object.assign({ marginBottom: 5 }, itemDisplayRoot), itemTypeIcon: Object.assign({ color: palette.teal.main, marginRight: '2px' }, itemTypeIcon), itemTypography: Object.assign({ color: theme.palette.text.primary }, itemTypography), icon: Object.assign({ fontSize: '0.8rem', verticalAlign: 'middle' }, icon) }) ); export function ItemMegaMenuUI(props) { const { open, styles, item, isLoading = false, numOfLoaderItems = 5, options, editorialOptions, nonEditorialOptions, anchorEl, anchorOrigin, anchorReference, anchorPosition, contentType, locale, onClose, onMenuItemClicked, classes: propClasses } = props; const { classes, cx } = useStyles(styles); const isFolder = (item === null || item === void 0 ? void 0 : item.systemType) === 'folder'; const inWorkflow = isInWorkflow(item === null || item === void 0 ? void 0 : item.stateMap); return React.createElement( Popover, { open: open, onClose: onClose, anchorEl: anchorEl, anchorOrigin: anchorOrigin, anchorReference: anchorReference, anchorPosition: anchorPosition, classes: Object.assign({ paper: classes.root }, propClasses) }, React.createElement( 'section', { className: cx(classes.itemInfo, classes.infoItem, classes.mainItem) }, React.createElement( Typography, { variant: 'body2', className: classes.itemInfoContentType }, isLoading ? React.createElement(Skeleton, { animation: 'wave' }) : contentType ), isLoading ? React.createElement(Skeleton, { animation: 'wave' }) : React.createElement(ItemDisplay, { item: item, labelComponent: 'h2', showPublishingTarget: false, showWorkflowState: false, classes: { root: classes.itemDisplayRoot, icon: classes.itemTypeIcon }, labelTypographyProps: { className: classes.itemTypography } }), isLoading ? React.createElement(Skeleton, { animation: 'wave' }) : React.createElement( 'div', { className: classes.itemState }, !isFolder && (inWorkflow ? React.createElement( React.Fragment, null, React.createElement(ItemStateIcon, { item: item, className: classes.icon }), React.createElement( Typography, { variant: 'body2', component: 'span' }, getItemStateText(item === null || item === void 0 ? void 0 : item.stateMap, { user: item === null || item === void 0 ? void 0 : item.lockOwner }) ) ) : React.createElement( React.Fragment, null, React.createElement(ItemPublishingTargetIcon, { item: item, className: classes.icon }), React.createElement( Typography, { variant: 'body2', component: 'span' }, getItemPublishingTargetText(item === null || item === void 0 ? void 0 : item.stateMap) ) )) ) ), isLoading ? React.createElement( 'div', { className: cx(classes.actionsContainer) }, new Array(2).fill(null).map((value, i) => React.createElement( MenuList, { key: i, className: cx(classes.actionsColumn, classes.itemsList) }, new Array(Math.ceil(numOfLoaderItems / 2)) .fill(null) .map((value, j) => React.createElement( MenuItem, { key: j, className: cx( classes.menuItem, propClasses === null || propClasses === void 0 ? void 0 : propClasses.menuItem ) }, React.createElement(Skeleton, { animation: 'wave', width: '100%' }) ) ) ) ) ) : options.flatMap((i) => i).length === 0 ? React.createElement(EmptyState, { title: React.createElement(FormattedMessage, { id: 'contextMenu.emptyOptionsMessage', defaultMessage: 'No options available to display.' }) }) : React.createElement( 'div', { className: cx(classes.actionsContainer) }, React.createElement( MenuList, { className: cx(classes.actionsColumn, classes.itemsList) }, editorialOptions.map((option, y) => React.createElement(MenuItem, { dense: true, autoFocus: y === 0, key: option.id, onClick: (e) => onMenuItemClicked(option.id, e), className: cx( classes.menuItem, propClasses === null || propClasses === void 0 ? void 0 : propClasses.menuItem ), children: option.label }) ) ), React.createElement( 'div', { className: classes.actionsColumn }, nonEditorialOptions.map((section, i) => React.createElement( MenuList, { key: i, className: classes.itemsList }, section.map((option, y) => React.createElement(MenuItem, { dense: true, key: option.id, divider: i !== nonEditorialOptions.length - 1 && y === section.length - 1, onClick: (e) => onMenuItemClicked(option.id, e), className: cx( classes.menuItem, propClasses === null || propClasses === void 0 ? void 0 : propClasses.menuItem ), children: option.label }) ) ) ) ) ), React.createElement( 'section', { className: cx(classes.itemEdited, classes.infoItem, classes.mainItem) }, isLoading ? React.createElement(Skeleton, { animation: 'wave', width: '100%' }) : React.createElement( React.Fragment, null, React.createElement( Typography, { variant: 'body2', color: 'text.secondary', title: item.path, noWrap: true }, item.path ), React.createElement( Typography, { variant: 'body2' }, React.createElement(FormattedMessage, { id: 'itemMegaMenu.editedBy', defaultMessage: '{edited} {date} {byLabel} {by}', values: { date: new Intl.DateTimeFormat(locale.localeCode, locale.dateTimeFormatOptions).format( new Date(item === null || item === void 0 ? void 0 : item.sandbox.dateModified) ), by: item === null || item === void 0 ? void 0 : item.sandbox.modifier, edited: React.createElement( 'span', { className: classes.itemEditedText }, React.createElement(FormattedMessage, { id: 'words.edited', defaultMessage: 'Edited' }) ), byLabel: (item === null || item === void 0 ? void 0 : item.sandbox.modifier) ? React.createElement( 'span', { className: classes.itemEditedText }, React.createElement(FormattedMessage, { id: 'words.by', defaultMessage: 'By' }) ) : '' } }) ) ) ) ); } export default ItemMegaMenuUI;