diff --git a/storybook/pages/MembersTabPanelPage.qml b/storybook/pages/MembersTabPanelPage.qml index fff2a076c2..3015bb4f72 100644 --- a/storybook/pages/MembersTabPanelPage.qml +++ b/storybook/pages/MembersTabPanelPage.qml @@ -1,34 +1,76 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import Qt.labs.settings 1.0 import AppLayouts.Communities.panels 1.0 +import utils 1.0 + import Models 1.0 import SortFilterProxyModel 0.2 +import Storybook 1.0 SplitView { id: root + orientation: Qt.Vertical + Logs { id: logs } + MembersTabPanel { id: membersTabPanelPage + SplitView.fillWidth: true + SplitView.fillHeight: true placeholderText: "Placeholder text" model: usersModelWithMembershipState - panelType: MembersTabPanel.TabType.PendingRequests + panelType: viewStateSelector.currentValue + + onKickUserClicked: { + logs.logEvent("MembersTabPanel::onKickUserClicked") + } + + onBanUserClicked: { + logs.logEvent("MembersTabPanel::onBanUserClicked") + } + + onUnbanUserClicked: { + logs.logEvent("MembersTabPanel::onUnbanUserClicked") + } + + onAcceptRequestToJoin: { + logs.logEvent("MembersTabPanel::onAcceptRequestToJoin") + } + + onDeclineRequestToJoin: { + logs.logEvent("MembersTabPanel::onDeclineRequestToJoin") + } } UsersModel { id: usersModel } + SortFilterProxyModel { id: usersModelWithMembershipState - readonly property var acceptedStates: [0, 3, 4] + readonly property var membershipStatePerView: [ + [Constants.CommunityMembershipRequestState.Accepted , Constants.CommunityMembershipRequestState.BannedPending, Constants.CommunityMembershipRequestState.KickedPending], + [Constants.CommunityMembershipRequestState.Banned], + [Constants.CommunityMembershipRequestState.Pending, Constants.CommunityMembershipRequestState.AcceptedPending, Constants.CommunityMembershipRequestState.RejectedPending], + [Constants.CommunityMembershipRequestState.Rejected] + ] + sourceModel: usersModel + sortRole: membersTabPanelPage.panelType proxyRoles: [ ExpressionRole { name: "membershipRequestState" - expression: usersModelWithMembershipState.acceptedStates[model.index % (usersModelWithMembershipState.acceptedStates.length)] + expression: { + var memberStates = usersModelWithMembershipState.membershipStatePerView[membersTabPanelPage.panelType] + return memberStates[model.index % (memberStates.length)] + } }, ExpressionRole { name: "requestToJoinLoading" @@ -36,4 +78,38 @@ SplitView { } ] } + + LogsAndControlsPanel { + SplitView.minimumHeight: 100 + SplitView.preferredHeight: 320 + + logsView.logText: logs.logText + + ColumnLayout { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + Label { + text: "View state" + } + + ComboBox { + id: viewStateSelector + textRole: "text" + valueRole: "value" + model: ListModel { + id: model + ListElement { text: "All members"; value: MembersTabPanel.TabType.AllMembers } + ListElement { text: "Banned Members"; value: MembersTabPanel.TabType.BannedMembers } + ListElement { text: "Pending Members"; value: MembersTabPanel.TabType.PendingRequests } + ListElement { text: "Declined Members"; value: MembersTabPanel.TabType.DeclinedRequests } + } + } + } + + } + + Settings { + property alias membersTabPanelSelection: viewStateSelector.currentIndex + } } diff --git a/test/ui-test/testSuites/suite_communities/shared/scripts/community_names.py b/test/ui-test/testSuites/suite_communities/shared/scripts/community_names.py index f77ead3c3e..c789d6b348 100644 --- a/test/ui-test/testSuites/suite_communities/shared/scripts/community_names.py +++ b/test/ui-test/testSuites/suite_communities/shared/scripts/community_names.py @@ -31,7 +31,7 @@ communitySettingsView_NavigationListItem_Mint_Tokens = {"container": statusDeskt communitySettings_Permissions_NavigationListItem = {"container": statusDesktop_mainWindow, "objectName": "CommunitySettingsView_NavigationListItem_Permissions", "type": "StatusNavigationListItem", "visible": True} communitySettingsView_NavigationListItem_Overview = {"container": statusDesktop_mainWindow, "objectName": "CommunitySettingsView_NavigationListItem_Overview", "type": "StatusNavigationListItem", "visible": True} communitySettings_MembersTab_Members_ListView = {"container": statusDesktop_mainWindow, "objectName": "CommunityMembersTabPanel_MembersListViews", "type": "ListView", "visible": True} -communitySettings_MembersTab_Member_Kick_Button = {"container": communitySettings_MembersTab_Members_ListView, "objectName": "MemberListIten_KickButton", "type": "StatusButton", "visible": True} +communitySettings_MembersTab_Member_Kick_Button = {"container": communitySettings_MembersTab_Members_ListView, "objectName": "MemberListItem_KickButton", "type": "StatusButton", "visible": True} communitySettings_KickModal_Kick_Button = {"container": statusDesktop_mainWindow_overlay, "objectName": "CommunityMembers_KickModal_KickButton", "type": "StatusButton", "visible": True} # Chat components diff --git a/ui/app/AppLayouts/Communities/panels/MembersTabPanel.qml b/ui/app/AppLayouts/Communities/panels/MembersTabPanel.qml index 479aca3160..bda857ab0f 100644 --- a/ui/app/AppLayouts/Communities/panels/MembersTabPanel.qml +++ b/ui/app/AppLayouts/Communities/panels/MembersTabPanel.qml @@ -72,6 +72,15 @@ Item { readonly property bool itsMe: model.pubKey.toLowerCase() === userProfile.pubKey.toLowerCase() readonly property bool isHovered: memberItem.sensor.containsMouse readonly property bool canBeBanned: !memberItem.itsMe && (model.memberRole !== Constants.memberRole.owner && model.memberRole !== Constants.memberRole.admin) + readonly property bool canEnableKickBanButtons: canBeBanned && root.panelType === MembersTabPanel.TabType.AllMembers + readonly property bool kickEnabled: canEnableKickBanButtons && model.membershipRequestState !== Constants.CommunityMembershipRequestState.KickedPending + readonly property bool banEnabled: canEnableKickBanButtons && model.membershipRequestState !== Constants.CommunityMembershipRequestState.BannedPending + readonly property bool kickVisible: (isHovered || !kickEnabled) && banEnabled + readonly property bool banVisible: (isHovered || !banEnabled) && kickEnabled + readonly property bool unBanVisible: (root.panelType === MembersTabPanel.TabType.BannedMembers) && isHovered && canBeBanned + + readonly property bool isRejectedPending: model.membershipRequestState === Constants.CommunityMembershipRequestState.RejectedPending + readonly property bool isAcceptedPending: model.membershipRequestState === Constants.CommunityMembershipRequestState.AcceptedPending statusListItemComponentsSlot.spacing: 16 statusListItemTitleArea.anchors.rightMargin: 0 @@ -80,25 +89,38 @@ Item { leftPadding: 12 components: [ - StatusButton { - objectName: "MemberListIten_KickButton" - visible: (root.panelType === MembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned - text: qsTr("Kick") - type: StatusBaseButton.Type.Danger - size: StatusBaseButton.Size.Small - onClicked: root.kickUserClicked(model.pubKey, model.displayName) + DisabledTooltipButton { + id: kickButton + visible: kickVisible + interactive: kickEnabled + tooltipText: qsTr("Waiting for owner node to come online") + buttonComponent: StatusButton { + objectName: "MemberListItem_KickButton" + text: model.membershipRequestState === Constants.CommunityMembershipRequestState.KickedPending ? qsTr("Kick pending") : qsTr("Kick") + type: StatusBaseButton.Type.Danger + size: StatusBaseButton.Size.Small + onClicked: root.kickUserClicked(model.pubKey, model.displayName) + enabled: kickButton.interactive + } + }, + + DisabledTooltipButton { + id: banButton + //using opacity instead of visible to avoid the acceptButton jumping around + opacity: banVisible + interactive: banEnabled + tooltipText: qsTr("Waiting for owner node to come online") + buttonComponent: StatusButton { + text: model.membershipRequestState === Constants.CommunityMembershipRequestState.BannedPending || !banVisible ? qsTr("Ban pending") : qsTr("Ban") + type: StatusBaseButton.Type.Danger + size: StatusBaseButton.Size.Small + onClicked: root.banUserClicked(model.pubKey, model.displayName) + enabled: banButton.interactive + } }, StatusButton { - visible: (root.panelType === MembersTabPanel.TabType.AllMembers) && isHovered && canBeBanned - text: qsTr("Ban") - type: StatusBaseButton.Type.Danger - size: StatusBaseButton.Size.Small - onClicked: root.banUserClicked(model.pubKey, model.displayName) - }, - - StatusButton { - visible: (root.panelType === MembersTabPanel.TabType.BannedMembers) && isHovered && canBeBanned + visible: unBanVisible text: qsTr("Unban") onClicked: root.unbanUserClicked(model.pubKey) }, @@ -107,13 +129,13 @@ Item { id: acceptButton visible: ((root.panelType === MembersTabPanel.TabType.PendingRequests || root.panelType === MembersTabPanel.TabType.DeclinedRequests) && isHovered) || - model.membershipRequestState === Constants.CommunityMembershipRequestState.AcceptedPending + isAcceptedPending //TODO: Only the current user can reject a pending request, so we should check that here tooltipText: qsTr("Waiting for owner node to come online") - interactive: model.membershipRequestState !== Constants.CommunityMembershipRequestState.AcceptedPending + interactive: !isAcceptedPending buttonComponent: StatusButton { - text: model.membershipRequestState == Constants.CommunityMembershipRequestState.AcceptedPending ? qsTr("Accept pending") : qsTr("Accept") + text: isAcceptedPending ? qsTr("Accept Pending") : qsTr("Accept") icon.name: "checkmark-circle" icon.color: enabled ? Theme.palette.successColor1 : disabledTextColor normalColor: Theme.palette.successColor2 @@ -128,14 +150,13 @@ Item { DisabledTooltipButton { id: rejectButton //using opacity instead of visible to avoid the acceptButton jumping around - opacity: ((root.panelType === MembersTabPanel.TabType.PendingRequests) && isHovered) || - model.membershipRequestState === Constants.CommunityMembershipRequestState.RejectedPending + opacity: ((root.panelType === MembersTabPanel.TabType.PendingRequests) && isHovered) || isRejectedPending //TODO: Only the current user can reject a pending request, so we should check that here tooltipText: qsTr("Waiting for owner node to come online") - interactive: model.membershipRequestState !== Constants.CommunityMembershipRequestState.RejectedPending + interactive: !isRejectedPending buttonComponent: StatusButton { - text: model.membershipRequestState == Constants.CommunityMembershipRequestState.RejectedPending ? qsTr("Reject pending") : qsTr("Reject") + text: isRejectedPending ? qsTr("Reject pending") : qsTr("Reject") type: StatusBaseButton.Type.Danger icon.name: "close-circle" icon.color: enabled ? Style.current.danger : disabledTextColor