UNPKG

@craftercms/studio-ui

Version:

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

407 lines (405 loc) 16.9 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 React, { useRef, useState } from 'react'; import DialogBody from '../DialogBody/DialogBody'; import DialogFooter from '../DialogFooter/DialogFooter'; import SecondaryButton from '../SecondaryButton'; import PrimaryButton from '../PrimaryButton'; import { FormattedMessage, useIntl } from 'react-intl'; import MediaCard from '../MediaCard/MediaCard'; import { useStyles } from './styles'; import SearchBar from '../SearchBar/SearchBar'; import MediaSkeletonCard from './MediaSkeletonCard'; import EmptyState from '../EmptyState/EmptyState'; import Pagination from '../Pagination'; import FolderBrowserTreeView from '../FolderBrowserTreeView'; import Box from '@mui/material/Box'; import Divider from '@mui/material/Divider'; import Select from '@mui/material/Select'; import MenuItem from '@mui/material/MenuItem'; import { filtersMessages } from '../SiteSearchSortBy'; import { camelize } from '../../utils/string'; import Toolbar from '@mui/material/Toolbar'; import IconButton from '@mui/material/IconButton'; import Tooltip from '@mui/material/Tooltip'; import RefreshIcon from '@mui/icons-material/Refresh'; import UploadFileIcon from '@mui/icons-material/UploadFile'; import Paper from '@mui/material/Paper'; import Button from '@mui/material/Button'; import Menu from '@mui/material/Menu'; import FilterListIcon from '@mui/icons-material/FilterList'; import FormControl from '@mui/material/FormControl'; import InputLabel from '@mui/material/InputLabel'; import { inputBaseClasses } from '@mui/material/InputBase'; import ListViewIcon from '@mui/icons-material/ViewStreamRounded'; import GridViewIcon from '@mui/icons-material/GridOnRounded'; import ReorderRoundedIcon from '@mui/icons-material/ReorderRounded'; import { SORT_AUTO } from '../Search/utils'; export function BrowseFilesDialogUI(props) { // region const { ... } = props; const { items, guestBase, selectedCard, selectedArray, multiSelect = false, path, currentPath, searchParameters, setSearchParameters, limit, offset, keyword, total, numOfLoaderItems = 12, sortKeys, onCardSelected, onPreviewImage, onCheckboxChecked, handleSearchKeyword, onPathSelected, onSelectButtonClick, onChangePage, onChangeRowsPerPage, onCloseButtonClick, onRefresh, onUpload, allowUpload = true, viewMode = 'card', onToggleViewMode } = props; // endregion const { classes, cx: clsx } = useStyles(); const { formatMessage } = useIntl(); const [sortMenuOpen, setSortMenuOpen] = useState(false); const buttonRef = useRef(); return React.createElement( React.Fragment, null, React.createElement( DialogBody, { className: classes.dialogBody }, React.createElement( Box, { display: 'flex', className: classes.dialogContent }, React.createElement( Box, { className: classes.leftWrapper, display: 'flex', flexDirection: 'column', rowGap: '20px' }, React.createElement(FolderBrowserTreeView, { rootPath: path, onPathSelected: onPathSelected, selectedPath: currentPath }) ), React.createElement( 'section', { className: classes.rightWrapper }, React.createElement( Paper, { className: classes.actionsBar }, React.createElement( Toolbar, { disableGutters: true, variant: 'dense' }, React.createElement( Box, { sx: { flexGrow: 1, display: 'flex' } }, React.createElement( Tooltip, { title: React.createElement(FormattedMessage, { id: 'word.refresh', defaultMessage: 'Refresh' }) }, React.createElement(IconButton, { onClick: onRefresh }, React.createElement(RefreshIcon, null)) ), allowUpload && React.createElement( Tooltip, { title: React.createElement(FormattedMessage, { id: 'word.upload', defaultMessage: 'Upload' }) }, React.createElement( IconButton, { onClick: onUpload, sx: { mr: 1 } }, React.createElement(UploadFileIcon, null) ) ), React.createElement(Divider, { orientation: 'vertical', flexItem: true, className: classes.actionsBarDivider }), React.createElement(SearchBar, { keyword: keyword, onChange: handleSearchKeyword, showDecoratorIcon: true, showActionButton: Boolean(keyword), classes: { root: classes.searchRoot, inputInput: classes.searchInput } }), React.createElement(Divider, { orientation: 'vertical', flexItem: true, className: classes.actionsBarDivider }), React.createElement( Button, { id: 'sort-button', 'aria-haspopup': 'true', 'aria-controls': sortMenuOpen ? 'sort-menu' : undefined, 'aria-expanded': sortMenuOpen ? 'true' : undefined, onClick: () => setSortMenuOpen(!sortMenuOpen), ref: buttonRef, sx: { ml: 1, mr: 1 }, startIcon: React.createElement(FilterListIcon, null) }, React.createElement(FormattedMessage, { id: 'words.sorting', defaultMessage: 'Sorting' }) ), React.createElement( Menu, { id: 'sort-menu', anchorEl: buttonRef.current, open: sortMenuOpen, onClose: () => setSortMenuOpen(false), MenuListProps: { 'aria-labelledby': 'sort-button' } }, React.createElement( MenuItem, null, React.createElement( FormControl, { fullWidth: true }, React.createElement( InputLabel, null, React.createElement(FormattedMessage, { id: 'BrowseFilesDialog.sortBy', defaultMessage: 'Sort By' }) ), React.createElement( Select, { fullWidth: true, value: searchParameters.sortBy, onChange: ({ target }) => { setSearchParameters({ sortBy: target.value }); }, size: 'small', className: classes.sortingSelect, label: React.createElement(FormattedMessage, { id: 'BrowseFilesDialog.sortBy', defaultMessage: 'Sort By' }) }, React.createElement( MenuItem, { value: SORT_AUTO }, React.createElement(FormattedMessage, { defaultMessage: 'Auto' }) ), React.createElement( MenuItem, { value: '_score' }, React.createElement(FormattedMessage, { id: 'words.relevance', defaultMessage: 'Relevance' }) ), React.createElement( MenuItem, { value: 'internalName' }, React.createElement(FormattedMessage, { id: 'words.name', defaultMessage: 'Name' }) ), sortKeys.map((name, i) => React.createElement( MenuItem, { value: name, key: i }, formatMessage(filtersMessages[camelize(name)]) ) ) ) ) ), searchParameters.sortBy && SORT_AUTO !== searchParameters.sortBy && React.createElement( MenuItem, null, React.createElement( FormControl, { fullWidth: true }, React.createElement( InputLabel, null, React.createElement(FormattedMessage, { id: 'words.order', defaultMessage: 'Order' }) ), React.createElement( Select, { fullWidth: true, value: searchParameters.sortOrder, onChange: ({ target }) => { setSearchParameters({ sortOrder: target.value }); }, size: 'small', className: classes.sortingSelect, label: React.createElement(FormattedMessage, { id: 'words.order', defaultMessage: 'Order' }) }, React.createElement( MenuItem, { value: 'asc' }, searchParameters.sortBy === '_score' ? React.createElement(FormattedMessage, { id: 'browseFilesDialog.lessRelevantFirst', defaultMessage: 'Less relevant first' }) : React.createElement(FormattedMessage, { id: 'words.ascending', defaultMessage: 'Ascending' }) ), React.createElement( MenuItem, { value: 'desc' }, searchParameters.sortBy === '_score' ? React.createElement(FormattedMessage, { id: 'browseFilesDialog.mostRelevantFirst', defaultMessage: 'Most relevant first' }) : React.createElement(FormattedMessage, { id: 'words.descending', defaultMessage: 'Descending' }) ) ) ) ) ), React.createElement(Divider, { orientation: 'vertical', flexItem: true, className: classes.actionsBarDivider }) ), React.createElement( Box, { sx: { display: 'flex', flexGrow: 0 } }, React.createElement( Tooltip, { title: React.createElement(FormattedMessage, { defaultMessage: 'Switch view mode' }) }, React.createElement( IconButton, { onClick: onToggleViewMode, sx: { mr: 1 } }, viewMode === 'card' ? React.createElement(ListViewIcon, null) : viewMode === 'compact' ? React.createElement(ReorderRoundedIcon, null) : React.createElement(GridViewIcon, null) ) ), React.createElement(Divider, { orientation: 'vertical', flexItem: true, className: classes.actionsBarDivider }), items && React.createElement(Pagination, { sxs: { toolbar: { pl: 0 }, root: { [`.${inputBaseClasses.root}`]: { marginRight: (theme) => theme.spacing(1), backgroundColor: (theme) => theme.palette.background[theme.palette.mode === 'dark' ? 'default' : 'paper'] } } }, count: total, rowsPerPage: limit, page: Math.ceil(offset / limit), onPageChange: (e, page) => onChangePage(page), onRowsPerPageChange: onChangeRowsPerPage }) ) ) ), React.createElement( Box, { className: classes.cardsContainer, sx: [viewMode === 'row' && { display: 'flex !important', flexFlow: 'wrap' }] }, items ? items.map((item) => React.createElement(MediaCard, { viewMode: viewMode, classes: { root: clsx(classes.mediaCardRoot, item.path === selectedCard?.path && classes.selectedCard) }, key: item.path, item: item, selected: multiSelect ? selectedArray : null, onSelect: multiSelect ? onCheckboxChecked : null, onPreview: onPreviewImage ? () => onPreviewImage(item) : null, previewAppBaseUri: guestBase, onClick: () => onCardSelected(item), showPath: true }) ) : new Array(numOfLoaderItems).fill(null).map((x, i) => React.createElement(MediaSkeletonCard, { key: i })) ), items && items.length === 0 && React.createElement(EmptyState, { styles: { root: { flexGrow: 1 } }, title: React.createElement(FormattedMessage, { id: 'browseFilesDialog.noResults', defaultMessage: 'No items found.' }) }) ) ) ), React.createElement( DialogFooter, null, React.createElement( SecondaryButton, { onClick: onCloseButtonClick }, React.createElement(FormattedMessage, { id: 'words.cancel', defaultMessage: 'Cancel' }) ), React.createElement( PrimaryButton, { disabled: !Boolean(selectedArray.length) && !selectedCard, onClick: onSelectButtonClick }, React.createElement(FormattedMessage, { id: 'words.select', defaultMessage: 'Select' }) ) ) ); } export default BrowseFilesDialogUI;