@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
395 lines (393 loc) • 16.2 kB
JavaScript
/*
* 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';
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,
compact = false,
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: '_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)])
)
)
)
)
),
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: 'Toggle compact view' }) },
React.createElement(
IconButton,
{ onClick: onToggleViewMode, sx: { mr: 1 } },
compact ? React.createElement(GridViewIcon, null) : React.createElement(ListViewIcon, 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(
'div',
{ className: classes.cardsContainer },
items
? items.map((item) =>
React.createElement(MediaCard, {
compact: compact,
classes: {
root: clsx(
classes.mediaCardRoot,
item.path === (selectedCard === null || selectedCard === void 0 ? void 0 : 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: false
})
)
: 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;