mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 00:43:53 +00:00
Optimize/all tags view toolbar (#7593)
* all tags view toolbar * optimize --------- Co-authored-by: zhouwenxuan <aries@Mac.local>
This commit is contained in:
@@ -160,6 +160,7 @@ SFTable.propTypes = {
|
||||
loadAll: PropTypes.func,
|
||||
moveRecords: PropTypes.func,
|
||||
renderCustomDraggedRows: PropTypes.func,
|
||||
updateSelectedRecordIds: PropTypes.func,
|
||||
};
|
||||
|
||||
export default SFTable;
|
||||
|
@@ -411,6 +411,7 @@ class Records extends Component {
|
||||
|
||||
// clear selected records
|
||||
this.onDeselectAllRecords();
|
||||
this.props.updateSelectedRecordIds([]);
|
||||
};
|
||||
|
||||
selectCell = (cellPosition) => {
|
||||
@@ -603,6 +604,7 @@ class Records extends Component {
|
||||
const { treeMetrics } = this.state;
|
||||
let updatedTreeMetrics = { ...treeMetrics };
|
||||
TreeMetrics.selectTreeNodesByKeys(nodesKeys, updatedTreeMetrics);
|
||||
this.props.updateSelectedRecordIds(TreeMetrics.getSelectedIds(updatedTreeMetrics, this.props.treeNodeKeyRecordIdMap));
|
||||
this.setState({ treeMetrics: updatedTreeMetrics });
|
||||
};
|
||||
|
||||
@@ -614,6 +616,7 @@ class Records extends Component {
|
||||
|
||||
let updatedTreeMetrics = { ...treeMetrics };
|
||||
TreeMetrics.selectTreeNode(nodeKey, updatedTreeMetrics);
|
||||
this.props.updateSelectedRecordIds(TreeMetrics.getSelectedIds(updatedTreeMetrics, this.props.treeNodeKeyRecordIdMap));
|
||||
this.setState({ treeMetrics: updatedTreeMetrics });
|
||||
};
|
||||
|
||||
@@ -624,6 +627,7 @@ class Records extends Component {
|
||||
}
|
||||
let updatedTreeMetrics = { ...treeMetrics };
|
||||
TreeMetrics.deselectTreeNode(nodeKey, updatedTreeMetrics);
|
||||
this.props.updateSelectedRecordIds(TreeMetrics.getSelectedIds(updatedTreeMetrics, this.props.treeNodeKeyRecordIdMap));
|
||||
this.setState({ treeMetrics: updatedTreeMetrics });
|
||||
};
|
||||
|
||||
@@ -633,6 +637,7 @@ class Records extends Component {
|
||||
let updatedTreeMetrics = { ...treeMetrics };
|
||||
const allNodesKeys = recordsTree.map((node) => getTreeNodeKey(node)).filter(Boolean);
|
||||
TreeMetrics.selectTreeNodesByKeys(allNodesKeys, updatedTreeMetrics);
|
||||
this.props.updateSelectedRecordIds(TreeMetrics.getSelectedIds(updatedTreeMetrics, this.props.treeNodeKeyRecordIdMap));
|
||||
this.setState({ recordMetrics: updatedTreeMetrics });
|
||||
};
|
||||
|
||||
@@ -1063,6 +1068,7 @@ Records.propTypes = {
|
||||
moveRecord: PropTypes.func,
|
||||
addFolder: PropTypes.func,
|
||||
moveRecords: PropTypes.func,
|
||||
updateSelectedRecordIds: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Records;
|
||||
|
81
frontend/src/components/toolbar/all-tags-toolbar.js
Normal file
81
frontend/src/components/toolbar/all-tags-toolbar.js
Normal file
@@ -0,0 +1,81 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import ItemDropdownMenu from '../dropdown-menu/metadata-item-dropdown-menu';
|
||||
import { EVENT_BUS_TYPE } from '../../metadata/constants';
|
||||
import TextTranslation from '../../utils/text-translation';
|
||||
import EventBus from '../common/event-bus';
|
||||
|
||||
const AllTagsToolbar = () => {
|
||||
const [selectedTagIds, setSelectedTagIds] = useState([]);
|
||||
|
||||
const canDelete = window.sfTagsDataContext && window.sfTagsDataContext.checkCanDeleteTag();
|
||||
const eventBus = EventBus.getInstance();
|
||||
|
||||
const unSelect = useCallback(() => {
|
||||
eventBus && eventBus.dispatch(EVENT_BUS_TYPE.SELECT_NONE);
|
||||
}, [eventBus]);
|
||||
|
||||
const deleteTags = useCallback(() => {
|
||||
eventBus && eventBus.dispatch(EVENT_BUS_TYPE.DELETE_TAGS, selectedTagIds);
|
||||
}, [selectedTagIds, eventBus]);
|
||||
|
||||
const getMenuList = useCallback(() => {
|
||||
const { MERGE_TAGS, NEW_CHILD_TAG } = TextTranslation;
|
||||
const list = [];
|
||||
if (selectedTagIds.length > 1) {
|
||||
list.push(MERGE_TAGS);
|
||||
return list;
|
||||
}
|
||||
list.push(NEW_CHILD_TAG);
|
||||
return list;
|
||||
}, [selectedTagIds]);
|
||||
|
||||
const onMenuItemClick = useCallback((operation, e) => {
|
||||
switch (operation) {
|
||||
case TextTranslation.MERGE_TAGS.key: {
|
||||
eventBus && eventBus.dispatch(EVENT_BUS_TYPE.MERGE_TAGS, selectedTagIds, { left: e.clientX, top: e.clientY });
|
||||
break;
|
||||
}
|
||||
case TextTranslation.NEW_CHILD_TAG.key: {
|
||||
eventBus && eventBus.dispatch(EVENT_BUS_TYPE.NEW_SUB_TAG, selectedTagIds[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, [eventBus, selectedTagIds]);
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribeSelectTags = eventBus && eventBus.subscribe(EVENT_BUS_TYPE.SELECT_TAGS, (ids) => {
|
||||
setSelectedTagIds(ids);
|
||||
});
|
||||
|
||||
return () => {
|
||||
unsubscribeSelectTags && unsubscribeSelectTags();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const length = selectedTagIds.length;
|
||||
return (
|
||||
<div className="selected-dirents-toolbar">
|
||||
<span className="cur-view-path-btn px-2" onClick={unSelect}>
|
||||
<span className="sf3-font-x-01 sf3-font mr-2" aria-label={gettext('Unselect')} title={gettext('Unselect')}></span>
|
||||
<span>{length}{' '}{gettext('selected')}</span>
|
||||
</span>
|
||||
{canDelete &&
|
||||
<span className="cur-view-path-btn" onClick={deleteTags}>
|
||||
<span className="sf3-font-delete1 sf3-font" aria-label={gettext('Delete')} title={gettext('Delete')}></span>
|
||||
</span>
|
||||
}
|
||||
{length > 0 && (
|
||||
<ItemDropdownMenu
|
||||
item={{}}
|
||||
toggleClass={'cur-view-path-btn sf3-font-more-vertical sf3-font'}
|
||||
onMenuItemClick={onMenuItemClick}
|
||||
getMenuList={getMenuList}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AllTagsToolbar;
|
28
frontend/src/components/toolbar/metadata-path-toolbar.js
Normal file
28
frontend/src/components/toolbar/metadata-path-toolbar.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { TAGS_MODE } from '../dir-view-mode/constants';
|
||||
import { ALL_TAGS_ID } from '../../tag/constants';
|
||||
import AllTagsToolbar from './all-tags-toolbar';
|
||||
import TagFilesToolbar from './tag-files-toolbar';
|
||||
import TableFilesToolbar from './table-files-toolbar';
|
||||
|
||||
const MetadataPathToolbar = ({ repoID, repoInfo, mode, path }) => {
|
||||
if (mode === TAGS_MODE) {
|
||||
const isAllTagsView = path.split('/').pop() === ALL_TAGS_ID;
|
||||
if (isAllTagsView) return <AllTagsToolbar />;
|
||||
|
||||
return <TagFilesToolbar currentRepoInfo={repoInfo} />;
|
||||
}
|
||||
return (
|
||||
<TableFilesToolbar repoID={repoID} />
|
||||
);
|
||||
};
|
||||
|
||||
MetadataPathToolbar.propTypes = {
|
||||
repoID: PropTypes.string.isRequired,
|
||||
repoInfo: PropTypes.object.isRequired,
|
||||
mode: PropTypes.string.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default MetadataPathToolbar;
|
@@ -99,6 +99,12 @@ export const EVENT_BUS_TYPE = {
|
||||
SELECT_TAG_FILES: 'select_tag_files',
|
||||
UNSELECT_TAG_FILES: 'unselect_tag_files',
|
||||
|
||||
// tags
|
||||
SELECT_TAGS: 'select_tags',
|
||||
DELETE_TAGS: 'delete_tags',
|
||||
MERGE_TAGS: 'merge_tags',
|
||||
NEW_SUB_TAG: 'new_sub_tag',
|
||||
|
||||
// file
|
||||
FILE_HISTORY: 'file_history',
|
||||
FILE_ACCESS_LOG: 'file_access_log',
|
||||
|
@@ -30,8 +30,7 @@ import DirTool from '../../components/cur-dir-path/dir-tool';
|
||||
import Detail from '../../components/dirent-detail';
|
||||
import DirColumnView from '../../components/dir-view-mode/dir-column-view';
|
||||
import SelectedDirentsToolbar from '../../components/toolbar/selected-dirents-toolbar';
|
||||
import TagFilesToolbar from '../../components/toolbar/tag-files-toolbar';
|
||||
import TableFilesToolbar from '../../components/toolbar/table-files-toolbar';
|
||||
import MetadataPathToolbar from '../../components/toolbar/metadata-path-toolbar';
|
||||
|
||||
import '../../css/lib-content-view.css';
|
||||
|
||||
@@ -2193,7 +2192,7 @@ class LibContentView extends React.Component {
|
||||
render() {
|
||||
const { repoID } = this.props;
|
||||
let { currentRepoInfo, userPerm, isCopyMoveProgressDialogShow, isDeleteFolderDialogOpen, errorMsg,
|
||||
path, usedRepoTags, isDirentSelected } = this.state;
|
||||
path, usedRepoTags, isDirentSelected, currentMode } = this.state;
|
||||
|
||||
if (this.state.libNeedDecrypt) {
|
||||
return (
|
||||
@@ -2278,10 +2277,8 @@ class LibContentView extends React.Component {
|
||||
'animation-children': isDirentSelected
|
||||
})}>
|
||||
{isDirentSelected ? (
|
||||
this.state.currentMode === TAGS_MODE ? (
|
||||
<TagFilesToolbar currentRepoInfo={this.state.currentRepoInfo} />
|
||||
) : this.state.currentMode === METADATA_MODE ? (
|
||||
<TableFilesToolbar repoID={this.props.repoID} />
|
||||
currentMode === TAGS_MODE || currentMode === METADATA_MODE ? (
|
||||
<MetadataPathToolbar repoID={repoID} repoInfo={currentRepoInfo} mode={currentMode} path={path} />
|
||||
) : (
|
||||
<SelectedDirentsToolbar
|
||||
repoID={this.props.repoID}
|
||||
|
@@ -13,7 +13,7 @@ import { ALL_TAGS_ID } from '../../constants';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const AllTags = ({ updateCurrentPath, ...params }) => {
|
||||
const AllTags = ({ updateCurrentPath, toggleShowDirentToolbar, ...params }) => {
|
||||
const [displayTag, setDisplayTag] = useState('');
|
||||
const [isLoadingMore, setLoadingMore] = useState(false);
|
||||
|
||||
@@ -99,6 +99,7 @@ const AllTags = ({ updateCurrentPath, ...params }) => {
|
||||
setDisplayTag={onChangeDisplayTag}
|
||||
isLoadingMoreRecords={isLoadingMore}
|
||||
loadMore={loadMore}
|
||||
toggleShowDirentToolbar={toggleShowDirentToolbar}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@@ -36,6 +36,7 @@ const TagsTable = ({
|
||||
modifyColumnWidth: modifyColumnWidthAPI,
|
||||
setDisplayTag,
|
||||
loadMore,
|
||||
toggleShowDirentToolbar,
|
||||
}) => {
|
||||
const { tagsData, updateTag, deleteTags, addTagLinks, deleteTagLinks, deleteTagsLinks, addChildTag, mergeTags } = useTags();
|
||||
|
||||
@@ -46,6 +47,8 @@ const TagsTable = ({
|
||||
const parentTagIdRef = useRef(null);
|
||||
const mergeTagsSelectorProps = useRef({});
|
||||
|
||||
const eventBus = EventBus.getInstance();
|
||||
|
||||
const table = useMemo(() => {
|
||||
if (!tagsData) {
|
||||
return {
|
||||
@@ -108,10 +111,9 @@ const TagsTable = ({
|
||||
|
||||
const onDeleteTags = useCallback((tagsIds) => {
|
||||
deleteTags(tagsIds);
|
||||
|
||||
const eventBus = EventBus.getInstance();
|
||||
toggleShowDirentToolbar(false);
|
||||
eventBus.dispatch(TABLE_EVENT_BUS_TYPE.SELECT_NONE);
|
||||
}, [deleteTags]);
|
||||
}, [eventBus, deleteTags, toggleShowDirentToolbar]);
|
||||
|
||||
const onNewSubTag = useCallback((parentTagId) => {
|
||||
parentTagIdRef.current = parentTagId;
|
||||
@@ -260,13 +262,25 @@ const TagsTable = ({
|
||||
}
|
||||
}, [table, addTagLinks, deleteTagsLinks]);
|
||||
|
||||
const updateSelectedTagIds = useCallback((ids) => {
|
||||
toggleShowDirentToolbar(ids.length > 0);
|
||||
setTimeout(() => {
|
||||
eventBus && eventBus.dispatch(EVENT_BUS_TYPE.SELECT_TAGS, ids);
|
||||
}, 0);
|
||||
}, [eventBus, toggleShowDirentToolbar]);
|
||||
|
||||
useEffect(() => {
|
||||
const eventBus = EventBus.getInstance();
|
||||
const unsubscribeUpdateSearchResult = eventBus.subscribe(EVENT_BUS_TYPE.UPDATE_SEARCH_RESULT, updateSearchResult);
|
||||
const unsubscribeDeleteTags = eventBus.subscribe(EVENT_BUS_TYPE.DELETE_TAGS, onDeleteTags);
|
||||
const unsubscribeMergeTags = eventBus.subscribe(EVENT_BUS_TYPE.MERGE_TAGS, onMergeTags);
|
||||
const unsubscribeNewSubTag = eventBus.subscribe(EVENT_BUS_TYPE.NEW_SUB_TAG, onNewSubTag);
|
||||
return () => {
|
||||
unsubscribeUpdateSearchResult();
|
||||
unsubscribeDeleteTags();
|
||||
unsubscribeMergeTags();
|
||||
unsubscribeNewSubTag();
|
||||
};
|
||||
}, [updateSearchResult]);
|
||||
}, [eventBus, updateSearchResult, onDeleteTags, onMergeTags, onNewSubTag, updateSelectedTagIds]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -296,6 +310,7 @@ const TagsTable = ({
|
||||
loadMore={loadMore}
|
||||
renderCustomDraggedRows={renderCustomDraggedRows}
|
||||
moveRecords={moveTags}
|
||||
updateSelectedRecordIds={updateSelectedTagIds}
|
||||
/>
|
||||
{isShowNewSubTagDialog && (
|
||||
<EditTagDialog tags={table.rows} title={gettext('New child tag')} onToggle={closeNewSubTagDialog} onSubmit={handelAddChildTag} />
|
||||
@@ -314,6 +329,7 @@ TagsTable.propTypes = {
|
||||
modifyColumnWidth: PropTypes.func,
|
||||
setDisplayTag: PropTypes.func,
|
||||
loadMore: PropTypes.func,
|
||||
toggleShowDirentToolbar: PropTypes.func,
|
||||
};
|
||||
|
||||
export default TagsTable;
|
||||
|
@@ -256,6 +256,16 @@ const TextTranslation = {
|
||||
key: 'OCR',
|
||||
value: gettext('OCR'),
|
||||
},
|
||||
|
||||
// tag view
|
||||
MERGE_TAGS: {
|
||||
key: 'Merge tags',
|
||||
value: gettext('Merge tags'),
|
||||
},
|
||||
NEW_CHILD_TAG: {
|
||||
key: 'New child tag',
|
||||
value: gettext('New child tag'),
|
||||
},
|
||||
};
|
||||
|
||||
export default TextTranslation;
|
||||
|
Reference in New Issue
Block a user