From f6336ad3c3df7e26ebf6ca758a6aacfd8b1d0602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 20 Jan 2023 12:04:12 +0100 Subject: [PATCH 1/4] chore(CommunityPermissions): Disable granting admin permission for non-owners --- .../pages/CommunityPermissionsSettingsPanelPage.qml | 8 ++++++++ .../Chat/controls/community/PermissionListItem.qml | 9 +++++++++ .../Chat/controls/community/PermissionsDropdown.qml | 4 ++++ ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml | 2 ++ .../views/communities/CommunityNewPermissionView.qml | 1 + 5 files changed, 24 insertions(+) diff --git a/storybook/pages/CommunityPermissionsSettingsPanelPage.qml b/storybook/pages/CommunityPermissionsSettingsPanelPage.qml index 41377132d40..de60e9b3a32 100644 --- a/storybook/pages/CommunityPermissionsSettingsPanelPage.qml +++ b/storybook/pages/CommunityPermissionsSettingsPanelPage.qml @@ -25,6 +25,8 @@ SplitView { topMargin: 50 } store: CommunitiesStore { + readonly property bool isOwner: isOwnerCheckBox.checked + assetsModel: AssetsModel {} collectiblesModel: CollectiblesModel {} channelsModel: ListModel { @@ -80,6 +82,12 @@ SplitView { SplitView.preferredHeight: 150 logsView.logText: logs.logText + + CheckBox { + id: isOwnerCheckBox + + text: "Is owner" + } } } } diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml index 523bc3e29a1..b3e4344d8be 100644 --- a/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml +++ b/ui/app/AppLayouts/Chat/controls/community/PermissionListItem.qml @@ -5,6 +5,8 @@ import StatusQ.Controls 0.1 import QtQuick 2.14 import QtQuick.Controls 2.14 +import utils 1.0 + StatusListItem { id: root @@ -22,10 +24,17 @@ StatusListItem { asset.bgWidth: 32 asset.bgHeight: 32 + Binding on asset.color { + when: !root.enabled + value: Style.current.darkGrey + } + components: [ StatusRadioButton { id: radioButton + visible: root.enabled + // reference to root for better integration with ButtonGroup // by accessing main component via ButtonGroup::checkedButton.item readonly property alias item: root diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml index 79ff813f105..016d07002fa 100644 --- a/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml +++ b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml @@ -15,6 +15,8 @@ StatusDropdown { property int mode: PermissionsDropdown.Mode.Add property int initialPermissionType: PermissionTypes.Type.None + property bool disableAdminPermission: false + enum Mode { Add, Update } @@ -93,6 +95,8 @@ StatusDropdown { checked: d.initialPermissionType === permissionType buttonGroup: group + enabled: !root.disableAdminPermission + Layout.fillWidth: true } diff --git a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml index 6195365400c..ea405d9e827 100644 --- a/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml +++ b/ui/app/AppLayouts/Chat/stores/CommunitiesStore.qml @@ -3,6 +3,8 @@ import QtQuick 2.0 QtObject { id: root + readonly property bool isOwner: false + property var permissionsModel: ListModel {} // Backend permissions list object model assignment. Please check the current expected data in qml defined in `createPermissions` method property var permissionConflict: QtObject { // Backend conflicts object model assignment. Now mocked data. property bool exists: false diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml index 28e335b47b9..ba4bcd9e955 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml @@ -414,6 +414,7 @@ StatusScrollView { id: permissionsDropdown initialPermissionType: d.permissionType + disableAdminPermission: !root.store.isOwner onDone: { d.permissionType = permissionType From 9437315f85113d0230e099a76ae94446b4f3566f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 20 Jan 2023 12:08:20 +0100 Subject: [PATCH 2/4] chore(CommunityPermissions): Simplify InDropdown popup (selecting only channels, no add channel button) --- storybook/pages/InDropdownPage.qml | 17 +++++++++++++++++ .../Chat/controls/community/InDropdown.qml | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/storybook/pages/InDropdownPage.qml b/storybook/pages/InDropdownPage.qml index 4aa0dcb8440..9520457ea28 100644 --- a/storybook/pages/InDropdownPage.qml +++ b/storybook/pages/InDropdownPage.qml @@ -1,5 +1,6 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 import AppLayouts.Chat.controls.community 1.0 @@ -23,6 +24,9 @@ SplitView { parent: pane anchors.centerIn: parent + allowChoosingEntireCommunity: allowChoosingEntireCommunityCheckBox.checked + showAddChannelButton: showAddChannelButtonCheckBox.checked + communityName: "Socks" communityImage: ModelsData.icons.socks communityColor: "red" @@ -53,5 +57,18 @@ SplitView { SplitView.preferredHeight: 200 logsView.logText: logs.logText + + ColumnLayout { + CheckBox { + id: allowChoosingEntireCommunityCheckBox + + text: "Allow choosing entire community" + } + CheckBox { + id: showAddChannelButtonCheckBox + + text: "Show \"Add channel\" button" + } + } } } diff --git a/ui/app/AppLayouts/Chat/controls/community/InDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/InDropdown.qml index 17c49bf00a1..8cefc92ccd7 100644 --- a/ui/app/AppLayouts/Chat/controls/community/InDropdown.qml +++ b/ui/app/AppLayouts/Chat/controls/community/InDropdown.qml @@ -14,6 +14,9 @@ import SortFilterProxyModel 0.2 StatusDropdown { id: root + property bool allowChoosingEntireCommunity: false + property bool showAddChannelButton: false + property string communityName property string communityImage property color communityColor @@ -100,6 +103,7 @@ StatusDropdown { Layout.topMargin: 9 Layout.preferredHeight: 44 + visible: root.allowChoosingEntireCommunity title: root.communityName subTitle: qsTr("Community") @@ -147,6 +151,8 @@ StatusDropdown { Layout.fillWidth: true Layout.topMargin: 4 - implicitHeight / 2 Layout.bottomMargin: 4 - implicitHeight / 2 + + visible: root.allowChoosingEntireCommunity } StatusScrollView { @@ -154,6 +160,8 @@ StatusDropdown { Layout.fillWidth: true Layout.bottomMargin: 9 + Layout.topMargin: + !root.allowChoosingEntireCommunity && !root.allowChoosingEntireCommunity ? 9 : 0 padding: 0 @@ -166,6 +174,8 @@ StatusDropdown { StatusIconTextButton { Layout.preferredHeight: 36 + visible: root.showAddChannelButton + leftPadding: 8 spacing: 8 statusIcon: "add" From 8ad1bb46893426ebac38797bd5e8cc5cbdb6ee37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 20 Jan 2023 12:15:05 +0100 Subject: [PATCH 3/4] chore(CommunityPermissions): Setting icon/default values for 'In' section depending on chosen permission --- .../StatusQ/Components/StatusItemSelector.qml | 10 +++- .../CommunityNewPermissionView.qml | 59 ++++++++++++++----- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml b/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml index 638ddc1c280..bf682821435 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusItemSelector.qml @@ -117,6 +117,13 @@ Rectangle { */ property bool useLetterIdenticons: false + /*! + \qmlproperty bool StatusItemSelector::itemsClickable + This property determines if items in the selector are clickable (cursor + is changed on hover and itemClicked emitted when clicked) + */ + property bool itemsClickable: true + /*! \qmlsignal StatusItemSelector::itemClicked This signal is emitted when the item is clicked. @@ -217,7 +224,8 @@ Rectangle { MouseArea { anchors.fill: parent - cursorShape: Qt.PointingHandCursor + enabled: root.itemsClickable + cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: root.itemClicked(parent, model.index, mouse) } diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml index ba4bcd9e955..8cf52f7bfa9 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml @@ -76,6 +76,23 @@ StatusScrollView { readonly property int dropdownVerticalOffset: 1 property int permissionType: PermissionTypes.Type.None + + readonly property bool isCommunityPermission: + permissionType === PermissionTypes.Type.Admin || + permissionType === PermissionTypes.Type.Member + + onIsCommunityPermissionChanged: { + if (isCommunityPermission) { + inModelChannels.clear() + inSelector.wholeCommunitySelected = true + inSelector.itemsModel = inModelCommunity + } else { + inSelector.itemsModel = 0 + inSelector.wholeCommunitySelected = false + inSelector.itemsModel = inModelChannels + } + } + property bool triggerDirtyTool: false // Trick: Used to force the reevaluation of dirty when an item of the list is updated property QtObject dirtyValues: QtObject { @@ -417,6 +434,11 @@ StatusScrollView { disableAdminPermission: !root.store.isOwner onDone: { + if (d.permissionType === permissionType) { + permissionsDropdown.close() + return + } + d.permissionType = permissionType d.dirtyValues.permissionObject.key = permissionType d.dirtyValues.permissionObject.text = title @@ -454,8 +476,13 @@ StatusScrollView { StatusItemSelector { id: inSelector + readonly property bool editable: !d.isCommunityPermission + + addButton.visible: editable + itemsClickable: editable + Layout.fillWidth: true - icon: Style.svg("create-category") + icon: d.isCommunityPermission ? Style.svg("communities") : Style.svg("create-category") iconSize: 24 title: qsTr("In") defaultItemText: qsTr("Example: `#general` channel") @@ -464,6 +491,21 @@ StatusScrollView { property bool wholeCommunitySelected: false + function openInDropdown(parent, x, y) { + inDropdown.parent = parent + inDropdown.x = x + inDropdown.y = y + + const selectedChannels = [] + + if (!inSelector.wholeCommunitySelected) + for (let i = 0; i < inModelChannels.count; i++) + selectedChannels.push(inModelChannels.get(i).itemId) + + inDropdown.setSelectedChannels(selectedChannels) + inDropdown.open() + } + ListModel { id: inModelCommunity @@ -522,21 +564,6 @@ StatusScrollView { } } - function openInDropdown(parent, x, y) { - inDropdown.parent = parent - inDropdown.x = x - inDropdown.y = y - - const selectedChannels = [] - - if (!inSelector.wholeCommunitySelected) - for (let i = 0; i < inModelChannels.count; i++) - selectedChannels.push(inModelChannels.get(i).itemId) - - inDropdown.setSelectedChannels(selectedChannels) - inDropdown.open() - } - addButton.onClicked: { inDropdown.acceptMode = InDropdown.AcceptMode.Add openInDropdown(inSelector.addButton, From ea7510ba5b2e3c6b682d1a5f5609bdefed5e0d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Cie=C5=9Blak?= Date: Fri, 20 Jan 2023 12:22:04 +0100 Subject: [PATCH 4/4] chore(CommunityPermissions): Adjust behavior of 'Hide permission' switch depending on selected permission Closes: #9050 --- .../pages/CommunityNewPermissionViewPage.qml | 87 ++++++++----- .../CommunityPermissionsSettingsPanelPage.qml | 119 +++++++++--------- .../community/PermissionsDropdown.qml | 6 +- .../CommunityNewPermissionView.qml | 19 ++- 4 files changed, 134 insertions(+), 97 deletions(-) diff --git a/storybook/pages/CommunityNewPermissionViewPage.qml b/storybook/pages/CommunityNewPermissionViewPage.qml index 621ef73cb04..9f6dda00543 100644 --- a/storybook/pages/CommunityNewPermissionViewPage.qml +++ b/storybook/pages/CommunityNewPermissionViewPage.qml @@ -4,51 +4,76 @@ import QtQuick.Controls 2.14 import AppLayouts.Chat.views.communities 1.0 import AppLayouts.Chat.stores 1.0 +import Storybook 1.0 import Models 1.0 -Pane { - id: root +SplitView { + orientation: Qt.Vertical + SplitView.fillWidth: true - CommunityNewPermissionView { + Logs { id: logs } - store: CommunitiesStore { - readonly property var assetsModel: AssetsModel {} - readonly property var collectiblesModel: CollectiblesModel {} - readonly property var channelsModel: ChannelsModel {} - readonly property var permissionConflict: QtObject { - property bool exists: true - property string holdings: "1 ETH" - property string permissions: "View and Post" - property string channels: "#general" + Pane { + id: root - } + CommunityNewPermissionView { - function editPermission(index, holdings, permissions, channels, isPrivate) { - logs.logEvent("CommunitiesStore::editPermission - index: " + index) - } + store: CommunitiesStore { + readonly property var assetsModel: AssetsModel {} + readonly property var collectiblesModel: CollectiblesModel {} + readonly property var channelsModel: ChannelsModel {} + readonly property var permissionConflict: QtObject { + property bool exists: true + property string holdings: "1 ETH" + property string permissions: "View and Post" + property string channels: "#general" - function duplicatePermission(index) { - logs.logEvent("CommunitiesStore::duplicatePermission - index: " + index) - } + } - function removePermission(index) { - logs.logEvent("CommunitiesStore::removePermission - index: " + index) - } - } + readonly property bool isOwner: isOwnerCheckBox.checked + + function editPermission(index, holdings, permissions, channels, isPrivate) { + logs.logEvent("CommunitiesStore::editPermission - index: " + index) + } + + function duplicatePermission(index) { + logs.logEvent("CommunitiesStore::duplicatePermission - index: " + index) + } - rootStore: QtObject { - readonly property QtObject chatCommunitySectionModule: QtObject { - readonly property var model: ChannelsModel {} + function removePermission(index) { + logs.logEvent("CommunitiesStore::removePermission - index: " + index) + } } - readonly property QtObject mainModuleInst: QtObject { + rootStore: QtObject { + readonly property QtObject chatCommunitySectionModule: QtObject { + readonly property var model: ChannelsModel {} + } + + readonly property QtObject mainModuleInst: QtObject { - readonly property QtObject activeSection: QtObject { - readonly property string name: "Socks" - readonly property string image: ModelsData.icons.socks - readonly property color color: "red" + readonly property QtObject activeSection: QtObject { + readonly property string name: "Socks" + readonly property string image: ModelsData.icons.socks + readonly property color color: "red" + } } } } } + + LogsAndControlsPanel { + id: logsAndControlsPanel + + SplitView.minimumHeight: 100 + SplitView.preferredHeight: 150 + + logsView.logText: logs.logText + + CheckBox { + id: isOwnerCheckBox + + text: "Is owner" + } + } } diff --git a/storybook/pages/CommunityPermissionsSettingsPanelPage.qml b/storybook/pages/CommunityPermissionsSettingsPanelPage.qml index de60e9b3a32..894c4cbf018 100644 --- a/storybook/pages/CommunityPermissionsSettingsPanelPage.qml +++ b/storybook/pages/CommunityPermissionsSettingsPanelPage.qml @@ -8,86 +8,85 @@ import StatusQ.Core.Theme 0.1 import Storybook 1.0 import Models 1.0 + SplitView { + orientation: Qt.Vertical + SplitView.fillWidth: true + Logs { id: logs } - SplitView { - orientation: Qt.Vertical + Rectangle { SplitView.fillWidth: true - - Rectangle { - SplitView.fillWidth: true - SplitView.fillHeight: true - color: Theme.palette.statusAppLayout.rightPanelBackgroundColor - CommunityPermissionsSettingsPanel { - anchors { - fill: parent - topMargin: 50 - } - store: CommunitiesStore { - readonly property bool isOwner: isOwnerCheckBox.checked - - assetsModel: AssetsModel {} - collectiblesModel: CollectiblesModel {} - channelsModel: ListModel { - Component.onCompleted: { - append([ - { - key: "welcome", - iconSource: ModelsData.assets.inch, - name: "#welcome" - }, - { - key: "general", - iconSource: ModelsData.assets.inch, - name: "#general" - } - ]) - } + SplitView.fillHeight: true + color: Theme.palette.statusAppLayout.rightPanelBackgroundColor + CommunityPermissionsSettingsPanel { + anchors { + fill: parent + topMargin: 50 + } + store: CommunitiesStore { + readonly property bool isOwner: isOwnerCheckBox.checked + + assetsModel: AssetsModel {} + collectiblesModel: CollectiblesModel {} + channelsModel: ListModel { + Component.onCompleted: { + append([ + { + key: "welcome", + iconSource: ModelsData.assets.inch, + name: "#welcome" + }, + { + key: "general", + iconSource: ModelsData.assets.inch, + name: "#general" + } + ]) } + } - function editPermission(index, holdings, permissions, channels, isPrivate) { - logs.logEvent("CommunitiesStore::editPermission - index: " + index) - } + function editPermission(index, holdings, permissions, channels, isPrivate) { + logs.logEvent("CommunitiesStore::editPermission - index: " + index) + } - function duplicatePermission(index) { - logs.logEvent("CommunitiesStore::duplicatePermission - index: " + index) - } + function duplicatePermission(index) { + logs.logEvent("CommunitiesStore::duplicatePermission - index: " + index) + } - function removePermission(index) { - logs.logEvent("CommunitiesStore::removePermission - index: " + index) - } + function removePermission(index) { + logs.logEvent("CommunitiesStore::removePermission - index: " + index) } + } - rootStore: QtObject { - readonly property QtObject chatCommunitySectionModule: QtObject { - readonly property var model: ChannelsModel {} - } + rootStore: QtObject { + readonly property QtObject chatCommunitySectionModule: QtObject { + readonly property var model: ChannelsModel {} + } - readonly property QtObject mainModuleInst: QtObject { - readonly property QtObject activeSection: QtObject { - readonly property string name: "Socks" - readonly property string image: ModelsData.icons.socks - readonly property color color: "red" - } + readonly property QtObject mainModuleInst: QtObject { + readonly property QtObject activeSection: QtObject { + readonly property string name: "Socks" + readonly property string image: ModelsData.icons.socks + readonly property color color: "red" } } } } + } - LogsAndControlsPanel { - id: logsAndControlsPanel + LogsAndControlsPanel { + id: logsAndControlsPanel - SplitView.minimumHeight: 100 - SplitView.preferredHeight: 150 + SplitView.minimumHeight: 100 + SplitView.preferredHeight: 150 - logsView.logText: logs.logText + logsView.logText: logs.logText - CheckBox { - id: isOwnerCheckBox + CheckBox { + id: isOwnerCheckBox - text: "Is owner" - } + text: "Is owner" } } } diff --git a/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml index 016d07002fa..742442c3248 100644 --- a/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml +++ b/ui/app/AppLayouts/Chat/controls/community/PermissionsDropdown.qml @@ -15,7 +15,7 @@ StatusDropdown { property int mode: PermissionsDropdown.Mode.Add property int initialPermissionType: PermissionTypes.Type.None - property bool disableAdminPermission: false + property bool enableAdminPermission: true enum Mode { Add, Update @@ -95,7 +95,7 @@ StatusDropdown { checked: d.initialPermissionType === permissionType buttonGroup: group - enabled: !root.disableAdminPermission + enabled: root.enableAdminPermission Layout.fillWidth: true } @@ -160,7 +160,7 @@ StatusDropdown { readonly property string description: qsTr("Members who meet the requirements will be allowed to read the selected channels") - title: qsTr("Read") + title: qsTr("View only") asset.name: "show" checked: d.initialPermissionType === permissionType buttonGroup: group diff --git a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml index 8cf52f7bfa9..e54425f5a5d 100644 --- a/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml +++ b/ui/app/AppLayouts/Chat/views/communities/CommunityNewPermissionView.qml @@ -81,6 +81,18 @@ StatusScrollView { permissionType === PermissionTypes.Type.Admin || permissionType === PermissionTypes.Type.Member + onPermissionTypeChanged: { + if (permissionType === PermissionTypes.Type.Admin) { + d.dirtyValues.isPrivateDirty = (root.isPrivate === false) + } else { + if (permissionType === PermissionTypes.Type.Moderator) { + d.dirtyValues.isPrivateDirty = (root.isPrivate === false) + } else { + d.dirtyValues.isPrivateDirty = (root.isPrivate === true) + } + } + } + onIsCommunityPermissionChanged: { if (isCommunityPermission) { inModelChannels.clear() @@ -431,7 +443,7 @@ StatusScrollView { id: permissionsDropdown initialPermissionType: d.permissionType - disableAdminPermission: !root.store.isOwner + enableAdminPermission: root.store.isOwner onDone: { if (d.permissionType === permissionType) { @@ -594,14 +606,14 @@ StatusScrollView { ColumnLayout { Layout.fillWidth: true StatusBaseText { - text: qsTr("Private") + text: qsTr("Hide permission") color: Theme.palette.directColor1 font.pixelSize: 15 } StatusBaseText { Layout.fillWidth: true Layout.fillHeight: true - text: qsTr("Make this permission private to hide it from members who don’t meet it’s requirements") + text: qsTr("Make this permission hidden from members who don’t meet it’s requirements") color: Theme.palette.baseColor1 font.pixelSize: 15 lineHeight: 1.2 @@ -611,6 +623,7 @@ StatusScrollView { } } StatusSwitch { + enabled: d.permissionType !== PermissionTypes.Type.Admin checked: d.dirtyValues.isPrivateDirty ? !root.isPrivate : root.isPrivate onToggled: d.dirtyValues.isPrivateDirty = (root.isPrivate !== checked) }