mirror of
https://github.com/haiwen/seahub.git
synced 2025-08-01 23:38:37 +00:00
optimize
This commit is contained in:
parent
befb6de6aa
commit
dfab8a0fe4
57
frontend/src/components/search/search-tags/index.css
Normal file
57
frontend/src/components/search/search-tags/index.css
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
.search-tags-container {
|
||||||
|
width: 100%;
|
||||||
|
height: fit-content;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
font-size: 0.8125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .tags-title {
|
||||||
|
width: 100%;
|
||||||
|
height: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0 16px;
|
||||||
|
margin: 10px 0 4px;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .tags-content {
|
||||||
|
width: 100%;
|
||||||
|
height: fit-content;
|
||||||
|
max-height: 180px;
|
||||||
|
overflow: auto;
|
||||||
|
scrollbar-color: #C1C1C1 rgba(0, 0, 0, 0);
|
||||||
|
padding: 0 16px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .tags-content .tag-item {
|
||||||
|
width: 100%;
|
||||||
|
height: 40px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .tags-content .tag-item:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .tags-content .tag-item .tag-color {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tags-container .search-tags-divider {
|
||||||
|
height: 0;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
margin: 0 16px;
|
||||||
|
}
|
70
frontend/src/components/search/search-tags/index.js
Normal file
70
frontend/src/components/search/search-tags/index.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { gettext } from '../../../utils/constants';
|
||||||
|
import { getTagColor, getTagId, getTagName } from '../../../tag/utils/cell';
|
||||||
|
import { PRIVATE_FILE_TYPE } from '../../../constants';
|
||||||
|
import { EVENT_BUS_TYPE } from '../../../metadata/constants';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
const SearchTags = ({ repoID, data, keyword, onSelectTag }) => {
|
||||||
|
const [displayTags, setDisplayTags] = useState([]);
|
||||||
|
|
||||||
|
const handleClick = useCallback((e, tagId) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
children: [],
|
||||||
|
path: '/' + PRIVATE_FILE_TYPE.TAGS_PROPERTIES + '/' + tagId,
|
||||||
|
isExpanded: false,
|
||||||
|
isLoaded: true,
|
||||||
|
isPreload: true,
|
||||||
|
object: {
|
||||||
|
file_tags: [],
|
||||||
|
id: tagId,
|
||||||
|
type: PRIVATE_FILE_TYPE.TAGS_PROPERTIES,
|
||||||
|
isDir: () => false,
|
||||||
|
},
|
||||||
|
parentNode: {},
|
||||||
|
key: repoID,
|
||||||
|
tag_id: tagId,
|
||||||
|
};
|
||||||
|
onSelectTag(node);
|
||||||
|
window.sfTagsDataContext?.eventBus?.dispatch(EVENT_BUS_TYPE.UPDATE_SELECTED_TAG, tagId);
|
||||||
|
}, [repoID, onSelectTag]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data || !keyword) return;
|
||||||
|
const tags = data?.filter((tag) => getTagName(tag).toLowerCase().includes(keyword.toLowerCase()));
|
||||||
|
setDisplayTags(tags);
|
||||||
|
}, [data, keyword]);
|
||||||
|
|
||||||
|
if (!data || !keyword || displayTags.length === 0) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="search-tags-container">
|
||||||
|
<div className="tags-title">{gettext('Tags')}</div>
|
||||||
|
<div className="tags-content">
|
||||||
|
{displayTags.map((tag) => {
|
||||||
|
const tagId = getTagId(tag);
|
||||||
|
const tagName = getTagName(tag);
|
||||||
|
const tagColor = getTagColor(tag);
|
||||||
|
return (
|
||||||
|
<div className="tag-item" key={tagId} onClick={(e) => handleClick(e, tagId)}>
|
||||||
|
<div className="tag-color" style={{ backgroundColor: tagColor }} />
|
||||||
|
<div className="tag-name">{tagName}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<div className="search-tags-divider" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
SearchTags.propTypes = {
|
||||||
|
data: PropTypes.object.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SearchTags;
|
@ -14,7 +14,7 @@ import Loading from '../loading';
|
|||||||
import { SEARCH_MASK, SEARCH_CONTAINER } from '../../constants/zIndexes';
|
import { SEARCH_MASK, SEARCH_CONTAINER } from '../../constants/zIndexes';
|
||||||
import { PRIVATE_FILE_TYPE } from '../../constants';
|
import { PRIVATE_FILE_TYPE } from '../../constants';
|
||||||
import SearchFilters from './search-filters';
|
import SearchFilters from './search-filters';
|
||||||
import Tags from './tags';
|
import SearchTags from './search-tags';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
repoID: PropTypes.string,
|
repoID: PropTypes.string,
|
||||||
@ -807,7 +807,7 @@ class Search extends Component {
|
|||||||
<SearchFilters onChange={this.handleFiltersChange} />
|
<SearchFilters onChange={this.handleFiltersChange} />
|
||||||
}
|
}
|
||||||
{isTagsShow &&
|
{isTagsShow &&
|
||||||
<Tags repoID={repoID} data={tagsData} keyword={this.state.value} onSelectTag={this.handleSelectTag} />
|
<SearchTags repoID={repoID} data={tagsData} keyword={this.state.value} onSelectTag={this.handleSelectTag} />
|
||||||
}
|
}
|
||||||
<div
|
<div
|
||||||
className="search-result-container dropdown-search-result-container"
|
className="search-result-container dropdown-search-result-container"
|
||||||
|
@ -42,7 +42,7 @@ class CommonToolbar extends React.Component {
|
|||||||
if (this.props.eventBus) {
|
if (this.props.eventBus) {
|
||||||
this.unsubscribeLibChange = this.props.eventBus.subscribe(EVENT_BUS_TYPE.CURRENT_LIBRARY_CHANGED, this.onRepoChange);
|
this.unsubscribeLibChange = this.props.eventBus.subscribe(EVENT_BUS_TYPE.CURRENT_LIBRARY_CHANGED, this.onRepoChange);
|
||||||
this.unsubscribeTagStatus = this.props.eventBus.subscribe(EVENT_BUS_TYPE.TAG_STATUS, (status) => this.onTagStatus(status));
|
this.unsubscribeTagStatus = this.props.eventBus.subscribe(EVENT_BUS_TYPE.TAG_STATUS, (status) => this.onTagStatus(status));
|
||||||
this.unsubscribeTagsChanged = this.props.eventBus.subscribe(EVENT_BUS_TYPE.TAGS_CHANGED, this.onTagsChanged);
|
this.unsubscribeTagsChanged = this.props.eventBus.subscribe(EVENT_BUS_TYPE.TAGS_CHANGED, (tags) => this.setState({ tagsData: tags }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,13 +62,6 @@ class CommonToolbar extends React.Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onTagsChanged = () => {
|
|
||||||
tagsAPI.getTags(this.state.repoID).then((res) => {
|
|
||||||
const tags = res?.data?.results || null;
|
|
||||||
this.setState({ tagsData: tags });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onSelectTag = (tag) => {
|
onSelectTag = (tag) => {
|
||||||
this.props.eventBus.dispatch(EVENT_BUS_TYPE.SELECT_TAG, tag);
|
this.props.eventBus.dispatch(EVENT_BUS_TYPE.SELECT_TAG, tag);
|
||||||
};
|
};
|
||||||
|
@ -2273,8 +2273,8 @@ class LibContentView extends React.Component {
|
|||||||
this.clearRepoTags();
|
this.clearRepoTags();
|
||||||
};
|
};
|
||||||
|
|
||||||
tagsChangedCallback = () => {
|
tagsChangedCallback = (tags) => {
|
||||||
this.props.eventBus.dispatch(EVENT_BUS_TYPE.TAGS_CHANGED);
|
this.props.eventBus.dispatch(EVENT_BUS_TYPE.TAGS_CHANGED, tags);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -31,7 +31,7 @@ export const TagsProvider = ({ repoID, currentPath, selectTagsView, tagsChangedC
|
|||||||
|
|
||||||
const tagsChanged = useCallback(() => {
|
const tagsChanged = useCallback(() => {
|
||||||
setTagsData(storeRef.current.data);
|
setTagsData(storeRef.current.data);
|
||||||
tagsChangedCallback && tagsChangedCallback();
|
tagsChangedCallback && tagsChangedCallback(storeRef.current.data.rows);
|
||||||
}, [tagsChangedCallback]);
|
}, [tagsChangedCallback]);
|
||||||
|
|
||||||
const handleTableError = useCallback((error) => {
|
const handleTableError = useCallback((error) => {
|
||||||
|
@ -105,7 +105,7 @@ const TagsTreeView = ({ currentPath }) => {
|
|||||||
}, [getKeyTreeNodeExpandedMap]);
|
}, [getKeyTreeNodeExpandedMap]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.sfTagsDataContext?.eventBus?.subscribe(EVENT_BUS_TYPE.UPDATE_SELECTED_TAG, (tagId) => {
|
const unsubscribeUpdateSelectedTag = window.sfTagsDataContext?.eventBus?.subscribe(EVENT_BUS_TYPE.UPDATE_SELECTED_TAG, (tagId) => {
|
||||||
if (tagId) {
|
if (tagId) {
|
||||||
const node = recordsTree.find((node) => getTreeNodeId(node) === tagId);
|
const node = recordsTree.find((node) => getTreeNodeId(node) === tagId);
|
||||||
const nodeKey = getTreeNodeKey(node);
|
const nodeKey = getTreeNodeKey(node);
|
||||||
@ -115,7 +115,7 @@ const TagsTreeView = ({ currentPath }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.sfTagsDataContext?.eventBus?.unsubscribe(EVENT_BUS_TYPE.UPDATE_SELECTED_TAG);
|
unsubscribeUpdateSelectedTag && unsubscribeUpdateSelectedTag();
|
||||||
};
|
};
|
||||||
}, [recordsTree]);
|
}, [recordsTree]);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user