feat(communities/portal): add tags filtering

This commit is contained in:
Patryk Osmaczko 2022-10-17 12:03:08 +02:00 committed by osmaczko
parent 534a0d0f45
commit 27a9133882
6 changed files with 91 additions and 22 deletions

View File

@ -68,7 +68,7 @@ Item {
StatusCommunityTags { StatusCommunityTags {
model: tagsModel model: tagsModel
showOnlySelected: true mode: StatusCommunityTags.ShowSelectedOnly
onClicked: { onClicked: {
cntSelectedTags--; cntSelectedTags--;
item.selected = false; item.selected = false;

View File

@ -3,14 +3,22 @@ import QtQuick 2.14
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2
Item { Item {
id: root id: root
property string filterString property string filterString
property bool showOnlySelected: false
property bool active: true property bool active: true
property alias model: repeater.model enum Mode {
ShowUnselectedOnly,
ShowSelectedOnly,
Highlight
}
property int mode: StatusCommunityTags.ShowUnselectedOnly
property var model
property alias contentWidth: flow.width property alias contentWidth: flow.width
readonly property int itemsWidth: { readonly property int itemsWidth: {
@ -35,14 +43,39 @@ Item {
Repeater { Repeater {
id: repeater id: repeater
model: SortFilterProxyModel {
id: filterModel
sourceModel: root.model
function selectionPredicate(selected) {
return root.mode === StatusCommunityTags.ShowSelectedOnly ? selected : !selected
}
filters: [
ExpressionFilter {
enabled: root.filterString !== ""
expression: {
root.filterString
return model.name.toUpperCase().indexOf(root.filterString.toUpperCase()) !== -1
}
},
ExpressionFilter {
enabled: root.mode !== StatusCommunityTags.Highlight
expression: {
root.mode
return filterModel.selectionPredicate(model.selected)
}
}
]
}
delegate: StatusCommunityTag { delegate: StatusCommunityTag {
emoji: model.emoji emoji: model.emoji
name: model.name name: model.name
visible: (root.showOnlySelected ? model.selected : !model.selected) && removable: root.mode === StatusCommunityTags.ShowSelectedOnly && root.active
(filterString == 0 || name.toUpperCase().indexOf(filterString.toUpperCase()) !== -1) highlighted: root.mode === StatusCommunityTags.Highlight && model.selected
width: visible ? implicitWidth : -flow.spacing
height: visible ? implicitHeight : 0
removable: root.showOnlySelected && root.active
onClicked: root.clicked(model) onClicked: root.clicked(model)
} }
} }

View File

@ -10,6 +10,7 @@ Rectangle {
property string emoji property string emoji
property string name property string name
property bool removable: false property bool removable: false
property bool highlighted: false
signal clicked() signal clicked()
@ -18,7 +19,7 @@ Rectangle {
radius: height / 2 radius: height / 2
border.color: Theme.palette.baseColor2 border.color: Theme.palette.baseColor2
border.width: 1 border.width: 1
color: mouseArea.containsMouse ? Theme.palette.primaryColor2 : "transparent" color: root.highlighted || mouseArea.containsMouse ? Theme.palette.primaryColor2 : "transparent"
MouseArea { MouseArea {
id: mouseArea id: mouseArea

View File

@ -59,18 +59,33 @@ StatusSectionLayout {
} }
SortFilterProxyModel { SortFilterProxyModel {
id: searchModel id: filteredCommunitiesModel
function selectedTagsPredicate(selectedTagsNames, tagsJSON) {
const tags = JSON.parse(tagsJSON)
for (const i in tags) {
selectedTagsNames = selectedTagsNames.filter(name => name !== tags[i].name)
}
return selectedTagsNames.length === 0
}
sourceModel: root.communitiesStore.curatedCommunitiesModel sourceModel: root.communitiesStore.curatedCommunitiesModel
filters: ExpressionFilter { filters: [
ExpressionFilter {
enabled: d.searchMode enabled: d.searchMode
expression: { expression: {
searcher.text searcher.text
return name.toLowerCase().includes(searcher.text.toLowerCase()) return name.toLowerCase().includes(searcher.text.toLowerCase())
} }
},
ExpressionFilter {
expression: {
return filteredCommunitiesModel.selectedTagsPredicate(communityTags.selectedTagsNames, model.tags)
} }
} }
]
}
centerPanel: Item { centerPanel: Item {
anchors.top: parent.top anchors.top: parent.top
@ -137,8 +152,10 @@ StatusSectionLayout {
} }
CommunityTagsRow { CommunityTagsRow {
tags: root.communitiesStore.communityTags id: communityTags
Layout.fillWidth: true Layout.fillWidth: true
tags: root.communitiesStore.communityTags
} }
Item { Item {
@ -158,7 +175,7 @@ StatusSectionLayout {
bottomPadding: d.layoutBottomMargin bottomPadding: d.layoutBottomMargin
locale: communitiesStore.locale locale: communitiesStore.locale
model: searchModel model: filteredCommunitiesModel
searchLayout: d.searchMode searchLayout: d.searchMode
onCardClicked: d.navigateToCommunity(communityId) onCardClicked: d.navigateToCommunity(communityId)
@ -168,7 +185,7 @@ StatusSectionLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
anchors.topMargin: parent.height / 3.1 anchors.topMargin: parent.height / 3.1
visible: d.searchMode && searchModel.count === 0 visible: d.searchMode && filteredCommunitiesModel.count === 0
text: qsTr("No communities found") text: qsTr("No communities found")
color: Theme.palette.baseColor1 color: Theme.palette.baseColor1
font.pixelSize: 15 font.pixelSize: 15

View File

@ -11,6 +11,7 @@ StatusRollArea {
id: root id: root
property string tags property string tags
property var selectedTagsNames: []
onTagsChanged: { onTagsChanged: {
var obj = JSON.parse(tags); var obj = JSON.parse(tags);
@ -19,16 +20,33 @@ StatusRollArea {
for (const key of Object.keys(obj)) { for (const key of Object.keys(obj)) {
d.tagsModel.append({ name: key, emoji: obj[key], selected: false }); d.tagsModel.append({ name: key, emoji: obj[key], selected: false });
} }
d.evaluateSelectedTags()
} }
QtObject { QtObject {
id: d id: d
property ListModel tagsModel: ListModel {} property ListModel tagsModel: ListModel {}
function evaluateSelectedTags() {
let selectedTagsNames = []
for(let i = 0; i < tagsModel.count; i++) {
let tag = tagsModel.get(i)
if (tag.selected) selectedTagsNames.push(tag.name)
}
root.selectedTagsNames = selectedTagsNames
}
} }
content: StatusCommunityTags { content: StatusCommunityTags {
id: tagsFlow id: tagsFlow
model: d.tagsModel model: d.tagsModel
mode: StatusCommunityTags.Highlight
onClicked: {
item.selected = !item.selected
d.evaluateSelectedTags()
}
} }
} }

View File

@ -126,7 +126,7 @@ StatusScrollView {
StatusCommunityTags { StatusCommunityTags {
model: d.tagsModel model: d.tagsModel
showOnlySelected: true mode: StatusCommunityTags.ShowSelectedOnly
onClicked: { onClicked: {
d.cntSelectedTags--; d.cntSelectedTags--;
item.selected = false; item.selected = false;