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 (