Project tags only search

pull/1297/head
Piero Toffanin 2023-03-13 12:28:18 -04:00
rodzic 8a51317774
commit c852f72b20
4 zmienionych plików z 46 dodań i 7 usunięć

Wyświetl plik

@ -47,7 +47,14 @@ class ProjectFilter(filters.FilterSet):
def filter_search(self, qs, name, value):
value = value.replace(":", "#")
tag_pattern = re.compile("#[^\s]+")
tags = re.findall(tag_pattern, value)
tags = set(re.findall(tag_pattern, value))
project_tags = set([t for t in tags if t.startswith("##")])
deep_tags = tags - project_tags
project_tags = [t.replace("##", "") for t in project_tags]
deep_tags = [t.replace("#", "") for t in deep_tags]
names = re.sub("\s+", " ", re.sub(tag_pattern, "", value)).strip()
if len(names) > 0:
@ -56,13 +63,20 @@ class ProjectFilter(filters.FilterSet):
name_query = SearchQuery(names, search_type="plain")
qs = qs.annotate(n_search=project_name_vec + task_name_vec).filter(n_search=name_query)
if len(tags) > 0:
if len(deep_tags) > 0:
project_tags_vec = SearchVector("tags")
task_tags_vec = SearchVector(StringAgg("task__tags", delimiter=' '))
tags_query = SearchQuery(tags[0])
for t in tags[1:]:
tags_query = SearchQuery(deep_tags[0])
for t in deep_tags[1:]:
tags_query = tags_query & SearchQuery(t)
qs = qs.annotate(t_search=project_tags_vec + task_tags_vec).filter(t_search=tags_query)
qs = qs.annotate(dt_search=project_tags_vec + task_tags_vec).filter(dt_search=tags_query)
if len(project_tags) > 0:
project_tags_vec = SearchVector("tags")
tags_query = SearchQuery(project_tags[0])
for t in project_tags[1:]:
tags_query = tags_query & SearchQuery(t)
qs = qs.annotate(pt_search=project_tags_vec).filter(pt_search=tags_query)
return qs.distinct()

Wyświetl plik

@ -41,9 +41,11 @@ class Paginator extends React.Component {
this.searchButton.addEventListener("click", this.toggleSearch);
this.btnSearch.addEventListener("click", this.search);
document.body.addEventListener("click", this.closeSearch);
document.addEventListener("onProjectListTagClicked", this.addTagAndSearch);
}
componentWillUnmount(){
document.removeEventListener("onProjectListTagClicked", this.addTagAndSearch);
document.body.removeEventListener("click", this.closeSearch);
this.btnSearch.removeEventListener("click", this.search);
this.searchButton.removeEventListener("click", this.toggleSearch);
@ -100,6 +102,20 @@ class Paginator extends React.Component {
});
}
addTagAndSearch = e => {
const tag = e.detail;
if (tag === undefined) return;
let { searchText } = this.state;
if (searchText === "") searchText += "##" + tag;
else searchText += " ##" + tag;
this.setState({searchText});
setTimeout(() => {
this.search();
}, 0);
}
render() {
const { itemsPerPage, totalItems, currentPage } = this.props;
const { searchText } = this.state;
@ -125,7 +141,6 @@ class Paginator extends React.Component {
</li>
</ul>
</li>
<li><a href="javascript:void(0);"><i className="fa fa-filter" title={_("Filter")}></i></a></li>
<li className="btn-group">
<a href="javascript:void(0);" className="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i className="fa fa-sort-alpha-down" title={_("Sort")}></i></a>
<SortPanel selected={this.state.sortKey} items={this.sortItems} onChange={this.sortChanged} />

Wyświetl plik

@ -491,6 +491,13 @@ class ProjectListItem extends React.Component {
}
}
handleTagClick = tag => {
return e => {
const evt = new CustomEvent("onProjectListTagClicked", { detail: tag });
document.dispatchEvent(evt);
}
}
render() {
const { refreshing, data } = this.state;
const numTasks = data.tasks.length;
@ -555,7 +562,7 @@ class ProjectListItem extends React.Component {
<div className="project-name">
{data.name}
{userTags.length > 0 ?
userTags.map((t, i) => <div key={i} className="tag-badge small-badge">{t}</div>)
userTags.map((t, i) => <div key={i} className="tag-badge small-badge" onClick={this.handleTagClick(t)}>{t}</div>)
: ""}
</div>
<div className="project-description">

Wyświetl plik

@ -119,5 +119,8 @@
font-size: 90%;
position: relative;
top: -1px;
&:hover{
cursor: pointer;
}
}
}