From d27ea6be9f2660d9357e9c64707dad68947cb948 Mon Sep 17 00:00:00 2001 From: zhouwenxuan Date: Thu, 20 Mar 2025 16:29:39 +0800 Subject: [PATCH 1/3] sort tag files --- .../src/components/cur-dir-path/dir-tool.js | 101 +++++++++--------- .../src/metadata/constants/event-bus-type.js | 1 + frontend/src/tag/constants/sort.js | 13 ++- frontend/src/tag/hooks/tag-view.js | 32 +++++- frontend/src/tag/utils/file.js | 47 ++++++++ .../src/tag/views/tag-files/sort-setter.js | 31 ++++++ 6 files changed, 171 insertions(+), 54 deletions(-) create mode 100644 frontend/src/tag/views/tag-files/sort-setter.js diff --git a/frontend/src/components/cur-dir-path/dir-tool.js b/frontend/src/components/cur-dir-path/dir-tool.js index 7b0333d08c..0d5b5296c0 100644 --- a/frontend/src/components/cur-dir-path/dir-tool.js +++ b/frontend/src/components/cur-dir-path/dir-tool.js @@ -12,7 +12,8 @@ import MetadataViewToolBar from '../../metadata/components/view-toolbar'; import TagsTableSearcher from '../../tag/views/all-tags/tags-table/tags-searcher'; import { PRIVATE_FILE_TYPE } from '../../constants'; import { ALL_TAGS_ID } from '../../tag/constants'; -import SortSetter from '../../tag/views/all-tags/tags-table/sort-setter'; +import AllTagsSortSetter from '../../tag/views/all-tags/tags-table/sort-setter'; +import TagFilesSortSetter from '../../tag/views/tag-files/sort-setter'; const propTypes = { repoID: PropTypes.string.isRequired, @@ -120,8 +121,8 @@ class DirTool extends React.Component { if (isTagView) { return (
- - {isAllTagsView && } + {isAllTagsView && } + {isAllTagsView ? : }
); } @@ -131,57 +132,57 @@ class DirTool extends React.Component {
- {(!isCustomPermission) && + {(!isCustomPermission) && (
- } - {menuItems.length > 0 && - - - - - {menuItems.map((menuItem, index) => { - if (menuItem === 'Divider') { - return ; - } else { - return ( - {menuItem.value} - - ); - } - })} - - - } + )} + {menuItems.length > 0 && ( + + + + + {menuItems.map((menuItem, index) => { + if (menuItem === 'Divider') { + return ; + } else { + return ( + {menuItem.value} + + ); + } + })} + + + )}
- {this.state.isRepoTagDialogOpen && - - - - } + {this.state.isRepoTagDialogOpen && ( + + + + )} ); } diff --git a/frontend/src/metadata/constants/event-bus-type.js b/frontend/src/metadata/constants/event-bus-type.js index 8dda5ca3d1..2d977a37bb 100644 --- a/frontend/src/metadata/constants/event-bus-type.js +++ b/frontend/src/metadata/constants/event-bus-type.js @@ -98,6 +98,7 @@ export const EVENT_BUS_TYPE = { DELETE_TAG_FILES: 'delete_tag_files', SELECT_TAG_FILES: 'select_tag_files', UNSELECT_TAG_FILES: 'unselect_tag_files', + MODIFY_TAG_FILES_SORT: 'modify_tag_files_sort', // tags SELECT_TAGS: 'select_tags', diff --git a/frontend/src/tag/constants/sort.js b/frontend/src/tag/constants/sort.js index 64eb8ff106..e83a418225 100644 --- a/frontend/src/tag/constants/sort.js +++ b/frontend/src/tag/constants/sort.js @@ -1,12 +1,21 @@ export const ALL_TAGS_SORT = 'all_tags_sort'; - export const TAGS_DEFAULT_SORT = { sort_by: 'name', order: 'asc' }; - export const ALL_TAGS_SORT_KEY = { NAME: 'name', CHILD_TAGS_COUNT: 'child_tags_count', TAG_FILE_COUNT: 'tag_file_count' }; + +export const TAG_FILES_SORT = 'tag_files_sort'; +export const TAG_FILES_DEFAULT_SORT = { + sort_by: 'name', + order: 'asc' +}; +export const TAG_FILES_SORT_KEY = { + NAME: 'name', + SIZE: 'size', + TIME: 'time' +}; diff --git a/frontend/src/tag/hooks/tag-view.js b/frontend/src/tag/hooks/tag-view.js index e7edfaa22c..580569a3aa 100644 --- a/frontend/src/tag/hooks/tag-view.js +++ b/frontend/src/tag/hooks/tag-view.js @@ -9,12 +9,13 @@ import { getAllChildTagsIdsFromNode } from '../utils/tree'; import { seafileAPI } from '../../utils/seafile-api'; import { TAG_FILE_KEY } from '../constants/file'; import { EVENT_BUS_TYPE } from '../../metadata/constants'; -import { getFileById } from '../utils/file'; +import { getFileById, sortTagFiles } from '../utils/file'; import { getRowById } from '../../components/sf-table/utils/table'; import { getTagFilesLinks } from '../utils/cell'; import { PRIVATE_COLUMN_KEY } from '../constants'; import URLDecorator from '../../utils/url-decorator'; import { fileServerRoot, useGoFileserver } from '../../utils/constants'; +import { TAG_FILES_DEFAULT_SORT, TAG_FILES_SORT } from '../constants/sort'; // This hook provides content related to seahub interaction, such as whether to enable extended attributes, views data, etc. const TagViewContext = React.createContext(null); @@ -156,6 +157,14 @@ export const TagViewProvider = ({ }); }, [repoID, convertFileCallback]); + const sortFiles = useCallback((sort) => { + const sorted = sortTagFiles(tagFiles, sort); + setTagFiles({ + ...tagFiles, + rows: sorted, + }); + }, [tagFiles]); + useEffect(() => { setLoading(true); const childTagsIds = getChildTagsIds(tagID, nodeKey); @@ -165,7 +174,10 @@ export const TagViewProvider = ({ } tagsAPI.getTagsFiles(repoID, tagsIds).then(res => { const rows = res.data?.results || []; - setTagFiles({ columns: res.data?.metadata || [], rows }); + const savedSort = window.sfTagsDataContext?.localStorage?.getItem(TAG_FILES_SORT); + const sort = savedSort ? JSON.parse(savedSort) : TAG_FILES_DEFAULT_SORT; + const sorted = sortTagFiles(rows, sort); + setTagFiles({ columns: res.data?.metadata || [], rows: sorted }); setLoading(false); }).catch(error => { const errorMessage = Utils.getErrorMsg(error); @@ -175,6 +187,21 @@ export const TagViewProvider = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [repoID, tagID, nodeKey]); + useEffect(() => { + const unsubscribeModifyTagFilesSort = window.sfTagsDataContext?.eventBus?.subscribe(EVENT_BUS_TYPE.MODIFY_TAG_FILES_SORT, (sort) => { + const files = tagFiles?.rows || []; + const sorted = sortTagFiles(files, sort); + setTagFiles({ + ...tagFiles, + rows: sorted, + }); + }); + + return () => { + unsubscribeModifyTagFilesSort && unsubscribeModifyTagFilesSort(); + }; + }, [tagFiles]); + return ( {children} diff --git a/frontend/src/tag/utils/file.js b/frontend/src/tag/utils/file.js index 64c1591e0e..796de04ee1 100644 --- a/frontend/src/tag/utils/file.js +++ b/frontend/src/tag/utils/file.js @@ -1,7 +1,11 @@ +import { getFileMTimeFromRecord, getFileSizedFromRecord } from '../../metadata/utils/cell'; +import { compareString } from '../../metadata/utils/sort'; import { enableSeadoc, fileAuditEnabled, isPro } from '../../utils/constants'; import TextTranslation from '../../utils/text-translation'; import { Utils } from '../../utils/utils'; import { TAG_FILE_KEY } from '../constants/file'; +import { TAG_FILES_SORT_KEY } from '../constants/sort'; +import { getSortBy, getSortOrder } from './sort'; export const getFileById = (tagFiles, fileId) => { return fileId ? tagFiles.rows.find(file => file._id === fileId) : ''; @@ -15,6 +19,14 @@ export const getFileParentDir = (file) => { return file ? file[TAG_FILE_KEY.PARENT_DIR] : ''; }; +export const getFileMTime = (file) => { + return file ? file[TAG_FILE_KEY.FILE_MTIME] : ''; +}; + +export const getFileSize = (file) => { + return file ? file[TAG_FILE_KEY.SIZE] : ''; +}; + export const getTagFileOperationList = (fileName, repo, canModify) => { const { SHARE, DOWNLOAD, DELETE, RENAME, MOVE, COPY, HISTORY, ACCESS_LOG, OPEN_VIA_CLIENT, CONVERT_AND_EXPORT, CONVERT_TO_MARKDOWN, CONVERT_TO_DOCX, EXPORT_DOCX, CONVERT_TO_SDOC, EXPORT_SDOC @@ -60,3 +72,38 @@ export const getTagFileOperationList = (fileName, repo, canModify) => { } return menuList; }; + +export const sortTagFiles = (files, sort) => { + const sortBy = getSortBy(sort); + const order = getSortOrder(sort); + + const compare = (a, b) => { + let valueA = ''; + let valueB = ''; + switch (sortBy) { + case TAG_FILES_SORT_KEY.NAME: + valueA = getFileName(a); + valueB = getFileName(b); + break; + case TAG_FILES_SORT_KEY.SIZE: + valueA = getFileSize(a); + valueB = getFileSize(b); + break; + case TAG_FILES_SORT_KEY.TIME: + valueA = getFileMTime(a); + valueB = getFileMTime(b); + break; + default: + break; + } + + const result = + sortBy === TAG_FILES_SORT_KEY.SIZE + ? valueA - valueB + : compareString(valueA, valueB); + + return order === 'asc' ? result : -result; + }; + + return files.sort(compare); +}; diff --git a/frontend/src/tag/views/tag-files/sort-setter.js b/frontend/src/tag/views/tag-files/sort-setter.js new file mode 100644 index 0000000000..e8881f5bd1 --- /dev/null +++ b/frontend/src/tag/views/tag-files/sort-setter.js @@ -0,0 +1,31 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import SortMenu from '../../../components/sort-menu'; +import { EVENT_BUS_TYPE } from '../../../metadata/constants'; +import { TAG_FILES_SORT, TAG_FILES_DEFAULT_SORT } from '../../constants/sort'; +import { getSortBy, getSortOrder } from '../../utils/sort'; + +const SortSetter = () => { + const [sort, setSort] = useState(TAG_FILES_DEFAULT_SORT); + + const eventBus = useMemo(() => window.sfTagsDataContext?.eventBus, []); + const localStorage = useMemo(() => window.sfTagsDataContext?.localStorage, []); + + const onSelectSortOption = useCallback((item) => { + const [sortBy, order] = item.value.split('-'); + const newSort = { sort_by: sortBy, order }; + setSort(newSort); + eventBus && eventBus.dispatch(EVENT_BUS_TYPE.MODIFY_TAG_FILES_SORT, newSort); + }, [eventBus]); + + useEffect(() => { + const storedSort = localStorage && localStorage.getItem(TAG_FILES_SORT); + const sort = storedSort ? JSON.parse(storedSort) : TAG_FILES_DEFAULT_SORT; + setSort(sort); + }, [localStorage]); + + return ( + + ); +}; + +export default SortSetter; From 41a12fa90e5e04d08103e6f3dcc81a90e662e9d1 Mon Sep 17 00:00:00 2001 From: zhouwenxuan Date: Thu, 20 Mar 2025 16:32:33 +0800 Subject: [PATCH 2/3] optimize --- frontend/src/components/cur-dir-path/dir-tool.js | 12 ++++++------ frontend/src/tag/constants/sort.js | 4 ++++ frontend/src/tag/utils/file.js | 1 - 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/cur-dir-path/dir-tool.js b/frontend/src/components/cur-dir-path/dir-tool.js index 0d5b5296c0..a2dbf928db 100644 --- a/frontend/src/components/cur-dir-path/dir-tool.js +++ b/frontend/src/components/cur-dir-path/dir-tool.js @@ -132,12 +132,12 @@ class DirTool extends React.Component {
- {(!isCustomPermission) && ( + {(!isCustomPermission) &&
- )} - {menuItems.length > 0 && ( + } + {menuItems.length > 0 && - )} + }
- {this.state.isRepoTagDialogOpen && ( + {this.state.isRepoTagDialogOpen && - )} + } ); } diff --git a/frontend/src/tag/constants/sort.js b/frontend/src/tag/constants/sort.js index e83a418225..43d4ecabb4 100644 --- a/frontend/src/tag/constants/sort.js +++ b/frontend/src/tag/constants/sort.js @@ -1,8 +1,10 @@ export const ALL_TAGS_SORT = 'all_tags_sort'; + export const TAGS_DEFAULT_SORT = { sort_by: 'name', order: 'asc' }; + export const ALL_TAGS_SORT_KEY = { NAME: 'name', CHILD_TAGS_COUNT: 'child_tags_count', @@ -10,10 +12,12 @@ export const ALL_TAGS_SORT_KEY = { }; export const TAG_FILES_SORT = 'tag_files_sort'; + export const TAG_FILES_DEFAULT_SORT = { sort_by: 'name', order: 'asc' }; + export const TAG_FILES_SORT_KEY = { NAME: 'name', SIZE: 'size', diff --git a/frontend/src/tag/utils/file.js b/frontend/src/tag/utils/file.js index 796de04ee1..aa48b9fd6d 100644 --- a/frontend/src/tag/utils/file.js +++ b/frontend/src/tag/utils/file.js @@ -1,4 +1,3 @@ -import { getFileMTimeFromRecord, getFileSizedFromRecord } from '../../metadata/utils/cell'; import { compareString } from '../../metadata/utils/sort'; import { enableSeadoc, fileAuditEnabled, isPro } from '../../utils/constants'; import TextTranslation from '../../utils/text-translation'; From b93e47b6064fdb67754438106512587639f95ca0 Mon Sep 17 00:00:00 2001 From: Michael An <1822852997@qq.com> Date: Sun, 23 Mar 2025 09:40:39 +0800 Subject: [PATCH 3/3] fix span key --- .../src/metadata/components/cell-formatter/file-tags/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/src/metadata/components/cell-formatter/file-tags/index.js b/frontend/src/metadata/components/cell-formatter/file-tags/index.js index bff1e99bed..2f064c375b 100644 --- a/frontend/src/metadata/components/cell-formatter/file-tags/index.js +++ b/frontend/src/metadata/components/cell-formatter/file-tags/index.js @@ -20,7 +20,9 @@ const FileTagsFormatter = ({ tagsData, value: oldValue, className, children: emp const tag = getRowById(tagsData, item); const tagColor = getTagColor(tag); const tagName = getTagName(tag); - if (!showName) return ; + if (!showName) return ( + + ); return (