import React, { useCallback, useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import ViewItem from './view'; import ItemDropdownMenu from '../../components/dropdown-menu/item-dropdown-menu'; import toaster from '../../components/toast'; import NewView from './new-view'; import InlineNameEditor from './inline-name-editor'; import { useMetadata } from '../hooks'; import { PRIVATE_FILE_TYPE } from '../../constants'; import { Utils, isMobile } from '../../utils/utils'; import TextTranslation from '../../utils/text-translation'; import { validateName } from '../utils/validate'; import { METADATA_VIEWS_DRAG_DATA_KEY, METADATA_VIEWS_KEY, TREE_NODE_LEFT_INDENT, VIEW_TYPE, VIEWS_TYPE_FOLDER, VIEWS_TYPE_VIEW } from '../constants'; import { getNewViewMenuItem, KEY_ADD_VIEW_MAP } from '../../components/dir-view-mode/dir-views/new-view-menu'; const ViewsFolder = ({ leftIndent, folder, currentPath, userPerm, canDeleteView, getFoldersNames, getMoveableFolders, generateNewViewDefaultName, setDragMode, getDragMode, selectView, modifyView, }) => { const { idViewMap, collapsedFoldersIds, collapseFolder, expandFolder, modifyFolder, deleteFolder, deleteView, duplicateView, addView, moveView, } = useMetadata(); const { _id: folderId, name: folderName, children } = folder || {}; const [expanded, setExpanded] = useState(!collapsedFoldersIds.includes(folderId)); const [highlight, setHighlight] = useState(false); const [freeze, setFreeze] = useState(false); const [isRenaming, setRenaming] = useState(false); const [newView, setNewView] = useState(null); const [isDropShow, setDropShow] = useState(false); const canUpdate = useMemo(() => { if (userPerm !== 'rw' && userPerm !== 'admin') return false; return true; }, [userPerm]); const canDrop = useMemo(() => { if (Utils.isIEBrowser() || !canUpdate) return false; return true; }, [canUpdate]); const folderMoreOperationMenus = useMemo(() => { let menus = []; if (canUpdate) { menus.push( getNewViewMenuItem(), TextTranslation.RENAME, TextTranslation.DELETE, ); } return menus; }, [canUpdate]); const onMouseEnter = useCallback(() => { if (freeze) return; setHighlight(true); }, [freeze]); const onMouseOver = useCallback(() => { if (freeze) return; setHighlight(true); }, [freeze]); const onMouseLeave = useCallback(() => { if (freeze) return; setHighlight(false); }, [freeze]); const freezeItem = useCallback(() => { setFreeze(true); setHighlight(true); }, []); const unfreezeItem = useCallback(() => { setFreeze(false); setHighlight(false); }, []); const clickFolder = useCallback(() => { if (expanded) { collapseFolder(folderId); } else { expandFolder(folderId); } setExpanded(!expanded); }, [expanded, folderId, collapseFolder, expandFolder]); const prepareAddView = useCallback((viewType) => { setNewView({ key: viewType, type: viewType, default_name: generateNewViewDefaultName() }); }, [generateNewViewDefaultName]); const clickMenu = useCallback((operationKey) => { switch (operationKey) { case KEY_ADD_VIEW_MAP.ADD_TABLE: { prepareAddView(VIEW_TYPE.TABLE); return; } case KEY_ADD_VIEW_MAP.ADD_GALLERY: { prepareAddView(VIEW_TYPE.GALLERY); return; } case KEY_ADD_VIEW_MAP.ADD_KANBAN: { prepareAddView(VIEW_TYPE.KANBAN); return; } case KEY_ADD_VIEW_MAP.ADD_MAP: { prepareAddView(VIEW_TYPE.MAP); return; } case TextTranslation.RENAME.key: { setRenaming(true); return; } case TextTranslation.DELETE.key: { deleteFolder(folderId); return; } default: { return; } } }, [prepareAddView, folderId, deleteFolder]); const onDragStart = useCallback((event) => { if (!canDrop) return false; const dragData = JSON.stringify({ type: METADATA_VIEWS_KEY, folder_id: folderId, mode: VIEWS_TYPE_FOLDER }); event.dataTransfer.effectAllowed = 'move'; event.dataTransfer.setData(METADATA_VIEWS_DRAG_DATA_KEY, dragData); setDragMode(VIEWS_TYPE_FOLDER); }, [canDrop, folderId, setDragMode]); const onDragEnter = useCallback((event) => { if (!canDrop) { // not allowed drag folder into folder return false; } if (!canDrop) { return false; } setDropShow(true); }, [canDrop]); const onDragLeave = useCallback(() => { if (!canDrop) return false; setDropShow(false); }, [canDrop]); const onDragMove = useCallback((event) => { if (!canDrop) return false; event.preventDefault(); event.dataTransfer.dropEffect = 'move'; }, [canDrop]); const onDrop = useCallback((event) => { if (!canDrop) return false; event.stopPropagation(); setDropShow(false); let dragData = event.dataTransfer.getData(METADATA_VIEWS_DRAG_DATA_KEY); if (!dragData) return; dragData = JSON.parse(dragData); if (dragData.type !== METADATA_VIEWS_KEY) return false; const dragMode = getDragMode(); const { view_id: sourceViewId, folder_id: sourceFolderId } = dragData; if ((dragMode === VIEWS_TYPE_VIEW && !sourceViewId)) { return; } moveView({ sourceViewId, sourceFolderId, targetFolderId: folderId }); }, [canDrop, folderId, getDragMode, moveView]); const onConfirmRename = useCallback((name) => { const foldersNames = getFoldersNames(); const otherFoldersNames = foldersNames.filter((currFolderName) => currFolderName !== folderName); const { isValid, message } = validateName(name, otherFoldersNames); if (!isValid) { toaster.danger(message); return; } if (message === folderName) { setRenaming(false); return; } modifyFolder(folderId, { name: message }); setRenaming(false); }, [folderId, folderName, getFoldersNames, modifyFolder]); const closeNewView = useCallback(() => { setNewView(null); }, []); const addViewIntoFolder = useCallback((viewName, viewType) => { addView({ folderId, name: viewName, type: viewType }); }, [folderId, addView]); const deleteViewFromFolder = useCallback((viewId, isSelected) => { deleteView({ folderId, viewId, isSelected }); }, [folderId, deleteView]); const duplicateViewFromFolder = useCallback((viewId) => { duplicateView({ folderId, viewId }); }, [folderId, duplicateView]); const renderViews = () => { if (!Array.isArray(children) || children.length === 0) { return null; } return children.map((children) => { const { _id: viewId, type: childType } = children || {}; if (!viewId || childType !== VIEWS_TYPE_VIEW) { return null; } const view = idViewMap[viewId]; if (!view) return null; const viewPath = '/' + PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES + '/' + viewId; const isSelected = currentPath === viewPath; return ( ); }); }; return (
{isRenaming ? ( ) : folderName}
{(highlight && folderMoreOperationMenus.length > 0) && ( folderMoreOperationMenus} onMenuItemClick={clickMenu} menuStyle={isMobile ? { zIndex: 1050 } : {}} /> )}
{expanded && renderViews()} {newView && }
); }; ViewsFolder.propTypes = { leftIndent: PropTypes.number, folder: PropTypes.object, currentPath: PropTypes.string, userPerm: PropTypes.string, canDeleteView: PropTypes.bool, getFoldersNames: PropTypes.func, getMoveableFolders: PropTypes.func, generateNewViewDefaultName: PropTypes.func, setDragMode: PropTypes.func, getDragMode: PropTypes.func, selectView: PropTypes.func, modifyView: PropTypes.func, }; export default ViewsFolder;