1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-18 08:16:07 +00:00
Files
seahub/frontend/src/pages/wiki2/view-structure/views/view-item.js
2024-05-22 10:26:08 +08:00

329 lines
10 KiB
JavaScript

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import { DragSource, DropTarget } from 'react-dnd';
import ViewEditPopover from './view-edit-popover';
import PageDropdownMenu from './page-dropdownmenu';
import DeleteDialog from './delete-dialog';
import { DRAGGED_FOLDER_MODE, DRAGGED_VIEW_MODE } from '../constant';
import Icon from '../../../../components/icon';
const dragSource = {
beginDrag: props => {
return {
idx: props.viewIndex,
data: { ...props.view, index: props.viewIndex },
folderId: props.folderId,
mode: DRAGGED_VIEW_MODE,
};
},
endDrag(props, monitor) {
const viewSource = monitor.getItem();
const didDrop = monitor.didDrop();
let viewTarget = {};
if (!didDrop) {
return { viewSource, viewTarget };
}
},
isDragging(props) {
const { draggedRow, infolder, viewIndex: targetIndex } = props;
if (infolder) {
return false;
}
const { idx } = draggedRow;
return idx > targetIndex;
}
};
const dropTarget = {
drop(props, monitor) {
const sourceRow = monitor.getItem();
// 1 drag page
if (sourceRow.mode === DRAGGED_VIEW_MODE) {
const { infolder, viewIndex: targetIndex, view: targetView, folderId: targetFolderId } = props;
const sourceFolderId = sourceRow.folderId;
const draggedViewId = sourceRow.data.id;
const targetViewId = targetView.id;
if (draggedViewId !== targetViewId) {
const sourceIndex = sourceRow.idx;
let move_position;
if (infolder) {
move_position = 'move_below';
} else {
move_position = sourceIndex > targetIndex ? 'move_above' : 'move_below';
}
props.onMoveView({
moved_view_id: draggedViewId,
target_view_id: targetViewId,
source_view_folder_id: sourceFolderId,
target_view_folder_id: targetFolderId,
move_position,
});
}
return;
}
// 1 drag folder
if (sourceRow.mode === DRAGGED_FOLDER_MODE) {
const { viewIndex: targetIndex, view: targetView } = props;
const draggedFolderId = sourceRow.data.id;
const targetViewId = targetView.id;
const sourceIndex = sourceRow.idx;
// Drag the parent folder to the child page, return
if (props.foldersStr.split('-').includes(draggedFolderId)) return;
props.onMoveFolder(
draggedFolderId,
targetViewId,
sourceIndex > targetIndex ? 'move_above' : 'move_below',
);
return;
}
}
};
const dragCollect = (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
});
const dropCollect = (connect, monitor) => ({
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver(),
canDrop: monitor.canDrop(),
draggedRow: monitor.getItem()
});
class ViewItem extends Component {
constructor(props) {
super(props);
this.state = {
isShowViewEditor: false,
isShowViewOperationDropdown: false,
isShowDeleteDialog: false,
viewName: props.view.name || '',
viewIcon: props.view.icon,
isSelected: props.currentPageId === props.view.id,
};
this.viewItemRef = React.createRef();
}
onMouseEnter = () => {
if (this.state.isSelected) return;
};
onMouseLeave = () => {
if (this.state.isSelected) return;
};
onCurrentPageChanged = (currentPageId) => {
const { isSelected } = this.state;
if (currentPageId === this.props.view.id && isSelected === false) {
this.setState({ isSelected: true });
} else if (currentPageId !== this.props.view.id && isSelected === true) {
this.setState({ isSelected: false });
}
};
toggleViewEditor = (e) => {
if (e) e.stopPropagation();
this.setState({ isShowViewEditor: !this.state.isShowViewEditor }, () => {
if (!this.state.isShowViewEditor) {
this.saveViewProperties();
}
});
};
saveViewProperties = () => {
const { name, icon, id } = this.props.view;
const { viewIcon } = this.state;
let viewName = this.state.viewName.trim();
if (viewIcon !== icon || viewName !== name) {
let newView = {};
if (viewName !== name) {
newView.name = viewName;
}
if (viewIcon !== icon) {
newView.icon = viewIcon;
}
this.props.onUpdatePage(id, newView);
}
};
onChangeName = (newViewName) => {
this.setState({ viewName: newViewName });
};
onChangeIcon = (newViewIcon) => {
this.setState({ viewIcon: newViewIcon });
};
openDeleteDialog = () => {
this.setState({ isShowDeleteDialog: true });
};
closeDeleteDialog = () => {
this.setState({ isShowDeleteDialog: false });
};
onViewOperationDropdownToggle = () => {
const isShowViewOperationDropdown = !this.state.isShowViewOperationDropdown;
this.setState({ isShowViewOperationDropdown });
this.changeItemFreeze(isShowViewOperationDropdown);
};
changeItemFreeze = (isFreeze) => {
if (isFreeze) {
this.viewItemRef.classList.add('view-freezed');
} else {
this.viewItemRef.classList.remove('view-freezed');
}
};
renderIcon = (icon) => {
if (!icon) {
return null;
}
if (icon.includes('dtable-icon')) {
return <span className={`mr-2 dtable-font ${icon}`}></span>;
} else {
return <Icon className="mr-2" symbol={icon}/>;
}
};
setDocUuid = (docUuid) => {
window.seafile['docUuid'] = docUuid;
};
render() {
const {
connectDragSource, connectDragPreview, connectDropTarget, isOver, canDrop, isDragging,
infolder, view, tableGridsLength, isEditMode, folderId, isOnlyOneView, foldersStr,
} = this.props;
const { isShowViewEditor, viewName, viewIcon, isSelected } = this.state;
const isOverView = isOver && canDrop;
if (isSelected) this.setDocUuid(view.docUuid);
const isSpecialInstance = false;
let viewCanDropTop;
let viewCanDrop;
if (infolder) {
viewCanDropTop = false;
viewCanDrop = isOverView;
} else {
viewCanDropTop = isOverView && isDragging;
viewCanDrop = isOverView && !isDragging;
}
let viewEditorId = `view-editor-${view.id}`;
return connectDropTarget(
connectDragPreview(
<div
className={classnames('view-item', 'view',
{ 'selected-view': isSelected },
{ 'view-can-drop-top': viewCanDropTop },
{ 'view-can-drop': viewCanDrop },
{ 'readonly': !isEditMode },
)}
ref={ref => this.viewItemRef = ref}
onMouseEnter={this.onMouseEnter}
onMouseLeave={this.onMouseLeave}
id={viewEditorId}
>
<div className="view-item-main" onClick={isShowViewEditor ? () => {} : this.props.onSelectView}>
{(isEditMode && !isSpecialInstance) ?
connectDragSource(
<div className="rdg-drag-handle">
<Icon symbol={'drag'}/>
</div>
)
:
<div className="rdg-drag-handle"></div>
}
<div className='view-content' style={foldersStr ? { marginLeft: `${(foldersStr.split('-').length) * 24}px` } : {}}>
{this.renderIcon(view.icon)}
<span className="view-title text-truncate" title={view.name}>{view.name}</span>
{isShowViewEditor && (
<ViewEditPopover
viewName={viewName}
viewIcon={viewIcon}
viewEditorId={viewEditorId}
onChangeName={this.onChangeName}
onChangeIcon={this.onChangeIcon}
toggleViewEditor={this.toggleViewEditor}
/>
)}
</div>
</div>
<div className="d-flex">
{isEditMode &&
<div className="more-view-operation" onClick={this.onViewOperationDropdownToggle}>
<Icon symbol={'more-level'}/>
{this.state.isShowViewOperationDropdown &&
<PageDropdownMenu
view={view}
views={this.props.views}
tableGridsLength={tableGridsLength}
isOnlyOneView={isOnlyOneView}
folderId={folderId}
canDelete={!isSpecialInstance}
canDuplicate={!isSpecialInstance}
toggle={this.onViewOperationDropdownToggle}
renderFolderMenuItems={this.props.renderFolderMenuItems}
toggleViewEditor={this.toggleViewEditor}
duplicatePage={this.props.duplicatePage}
onSetFolderId={this.props.onSetFolderId}
onDeleteView={this.openDeleteDialog}
onMoveViewToFolder={this.props.onMoveViewToFolder}
/>
}
</div>
}
</div>
{this.state.isShowDeleteDialog &&
<DeleteDialog
closeDeleteDialog={this.closeDeleteDialog}
handleSubmit={this.props.onDeleteView}
/>
}
</div>
)
);
}
}
ViewItem.propTypes = {
isOver: PropTypes.bool,
canDrop: PropTypes.bool,
isDragging: PropTypes.bool,
draggedRow: PropTypes.object,
isEditMode: PropTypes.bool,
infolder: PropTypes.bool,
view: PropTypes.object,
views: PropTypes.array,
viewIndex: PropTypes.number,
folderId: PropTypes.string,
tableGridsLength: PropTypes.number,
connectDragSource: PropTypes.func,
connectDragPreview: PropTypes.func,
connectDropTarget: PropTypes.func,
renderFolderMenuItems: PropTypes.func,
duplicatePage: PropTypes.func,
onSetFolderId: PropTypes.func,
onSelectView: PropTypes.func,
onUpdatePage: PropTypes.func,
onDeleteView: PropTypes.func,
onMoveViewToFolder: PropTypes.func,
onMoveView: PropTypes.func,
isOnlyOneView: PropTypes.bool,
onMoveFolder: PropTypes.func,
foldersStr: PropTypes.string,
currentPageId: PropTypes.string,
};
export default DropTarget('ViewStructure', dropTarget, dropCollect)(
DragSource('ViewStructure', dragSource, dragCollect)(ViewItem)
);