chore(CommunityPermissions): refactor access to stores in CP components

So far CP components (views, panels) were accessing stores directly.
Now `CommunitySettingsView` is a single place where stores are accessed.
Other components no longer depend on stores.

Moreover:
- dedicated store `PermissionsStore` created for handling permissions
  in a single, separated place
- storybook pages fixed

Closes: #9784
This commit is contained in:
Michał Cieślak 2023-03-07 09:47:04 +01:00 committed by Michał
parent 6f03a89685
commit d813cc12b8
12 changed files with 339 additions and 352 deletions

View File

@ -3,7 +3,6 @@ import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14 import QtQuick.Layouts 1.14
import AppLayouts.Chat.views.communities 1.0 import AppLayouts.Chat.views.communities 1.0
import AppLayouts.Chat.stores 1.0
import Storybook 1.0 import Storybook 1.0
import Models 1.0 import Models 1.0
@ -15,8 +14,6 @@ SplitView {
Logs { id: logs } Logs { id: logs }
Pane { Pane {
id: root
SplitView.fillWidth: true SplitView.fillWidth: true
SplitView.fillHeight: true SplitView.fillHeight: true
@ -27,48 +24,21 @@ SplitView {
isEditState: isEditStateCheckBox.checked isEditState: isEditStateCheckBox.checked
isPrivate: isPrivateCheckBox.checked isPrivate: isPrivateCheckBox.checked
isOwner: isOwnerCheckBox.checked
duplicationWarningVisible: isDuplicationWarningVisibleCheckBox.checked duplicationWarningVisible: isDuplicationWarningVisibleCheckBox.checked
store: CommunitiesStore { assetsModel: AssetsModel {}
readonly property var assetsModel: AssetsModel {} collectiblesModel: CollectiblesModel {}
readonly property var collectiblesModel: CollectiblesModel {} channelsModel: ChannelsModel {}
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"
} communityDetails: QtObject {
readonly property bool isOwner: isOwnerCheckBox.checked
function createPermission(holdings, permissions, isPrivate, channels) {
logs.logEvent("CommunitiesStore::creatPermission")
}
function editPermission(key, holdings, permissions, channels, isPrivate) {
logs.logEvent("CommunitiesStore::editPermission - key: " + key)
}
function removePermission(key) {
logs.logEvent("CommunitiesStore::removePermission - key: " + key)
}
}
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 name: "Socks"
readonly property string image: ModelsData.icons.socks readonly property string image: ModelsData.icons.socks
readonly property string color: "red" readonly property string color: "red"
} }
}
onCreatePermissionClicked: {
logs.logEvent("CommunityNewPermissionView::onCreatePermissionClicked")
} }
} }
} }
@ -81,9 +51,7 @@ SplitView {
logsView.logText: logs.logText logsView.logText: logs.logText
ColumnLayout { ColumnLayout {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@ -3,7 +3,6 @@ import QtQuick.Controls 2.14
import QtQuick.Layouts 1.14 import QtQuick.Layouts 1.14
import AppLayouts.Chat.panels.communities 1.0 import AppLayouts.Chat.panels.communities 1.0
import AppLayouts.Chat.stores 1.0
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 import StatusQ.Core.Utils 0.1
@ -17,55 +16,18 @@ SplitView {
Logs { id: logs } Logs { id: logs }
Rectangle { QtObject {
SplitView.fillWidth: true id: permissionsStoreMock
SplitView.fillHeight: true
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
CommunityPermissionsSettingsPanel { readonly property ListModel permissionsModel: ListModel {}
id: communityPermissionsSettingsPanel
anchors {
fill: parent
topMargin: 50
}
store: CommunitiesStore {
readonly property bool isOwner: isOwnerCheckBox.checked
property var permissionConflict: QtObject { // Backend conflicts object model assignment. Now mocked data.
property bool exists: false
property string holdings: qsTr("1 ETH")
property string permissions: qsTr("View and Post")
property string channels: qsTr("#general")
}
readonly property var permissionsModel: ListModel {}
readonly property var assetsModel: AssetsModel {}
readonly property var collectiblesModel: CollectiblesModel {}
readonly property var channelsModel: ListModel {
Component.onCompleted: {
append([
{
key: "welcome",
iconSource: ModelsData.assets.inch,
name: "#welcome"
},
{
key: "general",
iconSource: ModelsData.assets.inch,
name: "#general"
}
])
}
}
readonly property QtObject _d: QtObject { readonly property QtObject _d: QtObject {
id: d id: d
property int keyCounter: 0 property int keyCounter: 0
function createPermissionEntry(holdings, permissionType, isPrivate, channels) { function createPermissionEntry(holdings, permissionType, isPrivate,
channels) {
const permission = { const permission = {
holdingsListModel: holdings, holdingsListModel: holdings,
channelsListModel: channels, channelsListModel: channels,
@ -77,7 +39,7 @@ SplitView {
} }
} }
function createPermission(holdings, permissionType, isPrivate, channels, index = null) { function createPermission(holdings, permissionType, isPrivate, channels) {
const permissionEntry = d.createPermissionEntry( const permissionEntry = d.createPermissionEntry(
holdings, permissionType, isPrivate, channels) holdings, permissionType, isPrivate, channels)
@ -99,21 +61,43 @@ SplitView {
} }
} }
rootStore: QtObject { Rectangle {
readonly property QtObject chatCommunitySectionModule: QtObject { SplitView.fillWidth: true
readonly property var model: ChannelsModel {} SplitView.fillHeight: true
color: Theme.palette.statusAppLayout.rightPanelBackgroundColor
CommunityPermissionsSettingsPanel {
id: communityPermissionsSettingsPanel
anchors.fill: parent
anchors.topMargin: 50
permissionsModel: permissionsStoreMock.permissionsModel
assetsModel: AssetsModel {}
collectiblesModel: CollectiblesModel {}
channelsModel: ChannelsModel {}
isOwner: isOwnerCheckBox.checked
onCreatePermissionRequested: {
permissionsStoreMock.createPermission(holdings, permissionType,
isPrivate, channels)
} }
readonly property QtObject mainModuleInst: QtObject { onUpdatePermissionRequested:
readonly property QtObject activeSection: QtObject { permissionsStoreMock.editPermission(key, holdings, permissionType,
channels, isPrivate)
onRemovePermissionRequested:
permissionsStoreMock.removePermission(key)
communityDetails: QtObject {
readonly property string name: "Socks" readonly property string name: "Socks"
readonly property string image: ModelsData.icons.socks readonly property string image: ModelsData.icons.socks
readonly property string color: "red" readonly property string color: "red"
} }
} }
} }
}
}
LogsAndControlsPanel { LogsAndControlsPanel {
id: logsAndControlsPanel id: logsAndControlsPanel

View File

@ -1,14 +1,14 @@
import QtQuick 2.14 import QtQuick 2.15
import QtQuick.Controls 2.14 import QtQuick.Controls 2.15
import AppLayouts.Chat.views.communities 1.0
import AppLayouts.Chat.stores 1.0
import Storybook 1.0
import Models 1.0
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 import StatusQ.Core.Utils 0.1
import AppLayouts.Chat.views.communities 1.0
import Models 1.0
import Storybook 1.0
SplitView { SplitView {
Logs { id: logs } Logs { id: logs }
@ -28,44 +28,37 @@ SplitView {
margins: 50 margins: 50
} }
store: CommunitiesStore { permissionsModel: ListModel {
id: mockedCommunity id: permissionsModel
readonly property ListModel permissionsModel: ListModel {
Component.onCompleted: append(PermissionsModel.permissionsModelData) Component.onCompleted: append(PermissionsModel.permissionsModelData)
} }
readonly property AssetsModel assetsModel: AssetsModel { assetsModel: AssetsModel {
id: assetsModel id: assetsModel
} }
readonly property CollectiblesModel collectiblesModel: CollectiblesModel { collectiblesModel: CollectiblesModel {
id: collectiblesModel id: collectiblesModel
} }
}
rootStore: QtObject { channelsModel: ChannelsModel {
readonly property QtObject chatCommunitySectionModule: QtObject {
readonly property var model: ChannelsModel {
id: channelsModel id: channelsModel
} }
}
readonly property QtObject mainModuleInst: QtObject { communityDetails: QtObject {
readonly property QtObject activeSection: QtObject {
readonly property string name: "Socks" readonly property string name: "Socks"
readonly property string image: ModelsData.icons.socks readonly property string image: ModelsData.icons.socks
readonly property string color: "red" readonly property string color: "red"
} }
}
function log(method, index) {
logs.logEvent(`CommunityPermissionsView::${method} - index: ${index}`)
} }
onEditPermissionRequested: onEditPermissionRequested: log("editPermissionRequested", index)
logs.logEvent("CommunityPermissionsView::editPermissionRequested - index: " + index) onRemovePermissionRequested: log("removePermissionRequested", index)
onRemovePermissionRequested: onDuplicatePermissionRequested: log("duplicatePermissionRequested", index)
logs.logEvent("CommunityPermissionsView::removePermissionRequested - index: " + index)
onDuplicatePermissionRequested:
logs.logEvent("CommunityPermissionsView::duplicatePermissionRequested - index: " + index)
} }
} }
@ -85,7 +78,7 @@ SplitView {
CommunityPermissionsSettingsPanelEditor { CommunityPermissionsSettingsPanelEditor {
anchors.fill: parent anchors.fill: parent
model: mockedCommunity.permissionsModel model: permissionsModel
assetKeys: assetsModel.data.map(asset => asset.key) assetKeys: assetsModel.data.map(asset => asset.key)
collectibleKeys: collectiblesModel.data.map(collectible => collectible.key) collectibleKeys: collectiblesModel.data.map(collectible => collectible.key)

View File

@ -18,7 +18,7 @@ StatusDropdown {
property string communityName property string communityName
property string communityImage property string communityImage
property color communityColor property string communityColor
property var model property var model

View File

@ -11,10 +11,26 @@ import utils 1.0
SettingsPageLayout { SettingsPageLayout {
id: root id: root
property var rootStore required property var permissionsModel
required property CommunitiesStore store required property var assetsModel
required property var collectiblesModel
required property var channelsModel
// name, image, color properties expected
required property var communityDetails
property bool isOwner: false
property int viewWidth: 560 // by design property int viewWidth: 560 // by design
signal createPermissionRequested(
int permissionType, var holdings, var channels, bool isPrivate)
signal updatePermissionRequested(
string key, int permissionType, var holdings, var channels, bool isPrivate)
signal removePermissionRequested(string key)
function navigateBack() { function navigateBack() {
if (root.state === d.newPermissionViewState) { if (root.state === d.newPermissionViewState) {
root.state = d.initialState root.state = d.initialState
@ -55,7 +71,7 @@ SettingsPageLayout {
} }
} }
readonly property string initialState: root.rootStore.permissionsModel.count > 0 readonly property string initialState: root.permissionsModel.count > 0
? d.permissionsViewState : d.welcomeViewState ? d.permissionsViewState : d.welcomeViewState
function initializeData() { function initializeData() {
@ -152,13 +168,16 @@ SettingsPageLayout {
viewWidth: root.viewWidth viewWidth: root.viewWidth
rootStore: root.rootStore assetsModel: root.assetsModel
store: root.store collectiblesModel: root.collectiblesModel
channelsModel: root.channelsModel
communityDetails: root.communityDetails
isOwner: root.isOwner
isEditState: root.state === d.editPermissionViewState isEditState: root.state === d.editPermissionViewState
holdingsModel: d.holdingsToEditModel selectedHoldingsModel: d.holdingsToEditModel
channelsModel: d.channelsToEditModel selectedChannelsModel: d.channelsToEditModel
permissionType: d.permissionTypeToEdit permissionType: d.permissionTypeToEdit
isPrivate: d.isPrivateToEditValue isPrivate: d.isPrivateToEditValue
@ -169,7 +188,7 @@ SettingsPageLayout {
channelsTracker.revision channelsTracker.revision
communityNewPermissionView.dirtyValues.permissionType communityNewPermissionView.dirtyValues.permissionType
communityNewPermissionView.dirtyValues.isPrivate communityNewPermissionView.dirtyValues.isPrivate
const model = root.rootStore.permissionsModel const model = root.permissionsModel
const count = model.rowCount() const count = model.rowCount()
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
@ -185,8 +204,8 @@ SettingsPageLayout {
const same = (a, b) => ModelUtils.checkEqualitySet(a, b, ["key"]) const same = (a, b) => ModelUtils.checkEqualitySet(a, b, ["key"])
if (same(dirtyValues.holdingsModel, holdings) if (same(dirtyValues.selectedHoldingsModel, holdings)
&& same(dirtyValues.channelsModel, channels) && same(dirtyValues.selectedChannelsModel, channels)
&& dirtyValues.permissionType === permissionType) && dirtyValues.permissionType === permissionType)
return true return true
} }
@ -196,16 +215,15 @@ SettingsPageLayout {
onCreatePermissionClicked: { onCreatePermissionClicked: {
const holdings = ModelUtils.modelToArray( const holdings = ModelUtils.modelToArray(
dirtyValues.holdingsModel, dirtyValues.selectedHoldingsModel,
["key", "type", "amount"]) ["key", "type", "amount"])
const channels = ModelUtils.modelToArray( const channels = ModelUtils.modelToArray(
dirtyValues.channelsModel, ["key"]) dirtyValues.selectedChannelsModel, ["key"])
root.store.createPermission(holdings, root.createPermissionRequested(
dirtyValues.permissionType, dirtyValues.permissionType, holdings, channels,
dirtyValues.isPrivate, dirtyValues.isPrivate)
channels)
root.state = d.permissionsViewState root.state = d.permissionsViewState
} }
@ -215,18 +233,15 @@ SettingsPageLayout {
function onSaveChanges() { function onSaveChanges() {
const holdings = ModelUtils.modelToArray( const holdings = ModelUtils.modelToArray(
dirtyValues.holdingsModel, dirtyValues.selectedHoldingsModel,
["key", "type", "amount"]) ["key", "type", "amount"])
const channels = ModelUtils.modelToArray( const channels = ModelUtils.modelToArray(
dirtyValues.channelsModel, ["key"]) dirtyValues.selectedChannelsModel, ["key"])
root.store.editPermission( root.updatePermissionRequested(
d.permissionKeyToEdit, d.permissionKeyToEdit, dirtyValues.permissionType,
holdings, holdings, channels, dirtyValues.isPrivate)
dirtyValues.permissionType,
channels,
dirtyValues.isPrivate)
} }
function onResetChanges() { function onResetChanges() {
@ -243,13 +258,13 @@ SettingsPageLayout {
ModelChangeTracker { ModelChangeTracker {
id: holdingsTracker id: holdingsTracker
model: communityNewPermissionView.dirtyValues.holdingsModel model: communityNewPermissionView.dirtyValues.selectedHoldingsModel
} }
ModelChangeTracker { ModelChangeTracker {
id: channelsTracker id: channelsTracker
model: communityNewPermissionView.dirtyValues.channelsModel model: communityNewPermissionView.dirtyValues.selectedChannelsModel
} }
Binding { Binding {
@ -265,13 +280,17 @@ SettingsPageLayout {
id: permissionsView id: permissionsView
CommunityPermissionsView { CommunityPermissionsView {
permissionsModel: root.permissionsModel
assetsModel: root.assetsModel
collectiblesModel: root.collectiblesModel
channelsModel: root.channelsModel
communityDetails: root.communityDetails
viewWidth: root.viewWidth viewWidth: root.viewWidth
height: root.height height: root.height
rootStore: root.rootStore
store: root.store
function setInitialValuesFromIndex(index) { function setInitialValuesFromIndex(index) {
const item = ModelUtils.get(root.rootStore.permissionsModel, index) const item = ModelUtils.get(root.permissionsModel, index)
d.holdingsToEditModel = item.holdingsListModel d.holdingsToEditModel = item.holdingsListModel
d.channelsToEditModel = item.channelsListModel d.channelsToEditModel = item.channelsListModel
@ -282,7 +301,7 @@ SettingsPageLayout {
onEditPermissionRequested: { onEditPermissionRequested: {
setInitialValuesFromIndex(index) setInitialValuesFromIndex(index)
d.permissionKeyToEdit = ModelUtils.get( d.permissionKeyToEdit = ModelUtils.get(
root.rootStore.permissionsModel, index, "key") root.permissionsModel, index, "key")
root.state = d.editPermissionViewState root.state = d.editPermissionViewState
} }
@ -292,8 +311,8 @@ SettingsPageLayout {
} }
onRemovePermissionRequested: { onRemovePermissionRequested: {
const key = ModelUtils.get(root.rootStore.permissionsModel, index, "key") const key = ModelUtils.get(root.permissionsModel, index, "key")
root.store.removePermission(key) root.removePermissionRequested(key)
} }
} }
} }

View File

@ -1,68 +1,11 @@
import QtQuick 2.15 import QtQuick 2.15
import AppLayouts.Chat.controls.community 1.0
import StatusQ.Core.Utils 0.1
QtObject { QtObject {
id: root id: root
property var mainModuleInst: mainModule
property var communitiesModuleInst: communitiesModule
readonly property bool isOwner: false
property var mintingModuleInst: mintingModule ?? null property var mintingModuleInst: mintingModule ?? null
property var permissionConflict: QtObject { // Backend conflicts object model assignment. Now mocked data.
property bool exists: false
property string holdings: qsTr("1 ETH")
property string permissions: qsTr("View and Post")
property string channels: qsTr("#general")
}
property var assetsModel: chatCommunitySectionModule.tokenList
property var collectiblesModel: chatCommunitySectionModule.collectiblesModel
// TODO: Replace to real data, now dummy model
property var channelsModel: ListModel {
ListElement { key: "welcome"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#welcome"}
ListElement { key: "general"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#general"}
}
readonly property QtObject _d: QtObject {
id: d
property int keyCounter: 0
function createPermissionEntry(holdings, permissionType, isPrivate, channels) {
const permission = {
holdingsListModel: holdings,
channelsListModel: channels,
permissionType,
isPrivate
}
return permission
}
}
function createPermission(holdings, permissionType, isPrivate, channels, index = null) {
const permissionEntry = d.createPermissionEntry(
holdings, permissionType, isPrivate, channels)
chatCommunitySectionModule.createOrEditCommunityTokenPermission(root.mainModuleInst.activeSection.id, "", permissionEntry.permissionType, JSON.stringify(permissionEntry.holdingsListModel), permissionEntry.isPrivate)
}
function editPermission(key, holdings, permissionType, channels, isPrivate) {
const permissionEntry = d.createPermissionEntry(
holdings, permissionType, isPrivate, channels)
chatCommunitySectionModule.createOrEditCommunityTokenPermission(root.mainModuleInst.activeSection.id, key, permissionEntry.permissionType, JSON.stringify(permissionEntry.holdingsListModel), permissionEntry.isPrivate)
}
function removePermission(key) {
chatCommunitySectionModule.deleteCommunityTokenPermission(root.mainModuleInst.activeSection.id, key)
}
// Minting tokens: // Minting tokens:
function mintCollectible(communityId, address, name, symbol, description, supply, function mintCollectible(communityId, address, name, symbol, description, supply,
infiniteSupply, transferable, selfDestruct, chainId, artworkSource) infiniteSupply, transferable, selfDestruct, chainId, artworkSource)

View File

@ -0,0 +1,50 @@
import QtQml 2.15
QtObject {
id: root
required property string activeSectionId
required property var chatCommunitySectionModuleInst
readonly property var permissionsModel:
chatCommunitySectionModuleInst.permissionsModel
readonly property bool isOwner: false
readonly property QtObject _d: QtObject {
id: d
function createPermissionEntry(holdings, permissionType, isPrivate,
channels) {
return {
holdingsListModel: holdings,
channelsListModel: channels,
permissionType,
isPrivate
}
}
function createOrEdit(key, holdings, permissionType, isPrivate,
channels) {
root.chatCommunitySectionModuleInst.createOrEditCommunityTokenPermission(
root.activeSectionId, key,
permissionType,
JSON.stringify(holdings),
isPrivate)
}
}
function createPermission(holdings, permissionType, isPrivate, channels) {
d.createOrEdit("", holdings, permissionType, isPrivate, channels)
}
function editPermission(key, holdings, permissionType, channels, isPrivate) {
d.createOrEdit(key, holdings, permissionType, isPrivate, channels)
}
function removePermission(key) {
root.chatCommunitySectionModuleInst.deleteCommunityTokenPermission(
root.activeSectionId, key)
}
}

View File

@ -9,6 +9,11 @@ QtObject {
property var contactsStore property var contactsStore
readonly property PermissionsStore permissionsStore: PermissionsStore {
activeSectionId: mainModuleInst.activeSection.id
chatCommunitySectionModuleInst: chatCommunitySectionModule
}
property bool openCreateChat: false property bool openCreateChat: false
property string createChatInitMessage: "" property string createChatInitMessage: ""
property var createChatFileUrls: [] property var createChatFileUrls: []
@ -165,7 +170,6 @@ QtObject {
stickersModule: stickersModuleInst stickersModule: stickersModuleInst
} }
property var permissionsModel: chatCommunitySectionModule.permissionsModel
property var assetsModel: chatCommunitySectionModule.tokenList property var assetsModel: chatCommunitySectionModule.tokenList
property var collectiblesModel: chatCommunitySectionModule.collectiblesModel property var collectiblesModel: chatCommunitySectionModule.collectiblesModel

View File

@ -1,5 +1,6 @@
CommunitiesStore 1.0 CommunitiesStore.qml
PermissionsStore 1.0 PermissionsStore.qml
RootStore 1.0 RootStore.qml
StickerData 1.0 StickerData.qml StickerData 1.0 StickerData.qml
StickerPackData 1.0 StickerPackData.qml StickerPackData 1.0 StickerPackData.qml
StickersStore 1.0 StickersStore.qml StickersStore 1.0 StickersStore.qml
CommunitiesStore 1.0 CommunitiesStore.qml
RootStore 1.0 RootStore.qml

View File

@ -246,8 +246,33 @@ StatusSectionLayout {
} }
CommunityPermissionsSettingsPanel { CommunityPermissionsSettingsPanel {
rootStore: root.rootStore readonly property PermissionsStore permissionsStore:
store: root.communityStore rootStore.permissionsStore
permissionsModel: permissionsStore.permissionsModel
assetsModel: rootStore.assetsModel
collectiblesModel: rootStore.collectiblesModel
channelsModel: rootStore.chatCommunitySectionModule.model
communityDetails: QtObject {
readonly property var _activeSection:
rootStore.mainModuleInst.activeSection
readonly property string name: _activeSection.name
readonly property string image: _activeSection.image
readonly property string color: _activeSection.color
}
onCreatePermissionRequested:
permissionsStore.createPermission(holdings, permissionType,
isPrivate, channels)
onUpdatePermissionRequested:
permissionsStore.editPermission(
key, holdings, permissionType, channels, isPrivate)
onRemovePermissionRequested:
permissionsStore.removePermission(key)
onPreviousPageNameChanged: root.backButtonName = previousPageName onPreviousPageNameChanged: root.backButtonName = previousPageName
} }

View File

@ -13,15 +13,20 @@ import shared.panels 1.0
import AppLayouts.Chat.helpers 1.0 import AppLayouts.Chat.helpers 1.0
import AppLayouts.Chat.panels.communities 1.0 import AppLayouts.Chat.panels.communities 1.0
import AppLayouts.Chat.stores 1.0
import "../../../Chat/controls/community" import "../../../Chat/controls/community"
StatusScrollView { StatusScrollView {
id: root id: root
property var rootStore required property var assetsModel
required property CommunitiesStore store required property var collectiblesModel
required property var channelsModel
// name, image, color properties expected
required property var communityDetails
property bool isOwner: false
property int viewWidth: 560 // by design property int viewWidth: 560 // by design
property bool isEditState: false property bool isEditState: false
@ -35,18 +40,18 @@ StatusScrollView {
readonly property alias dirtyValues: d.dirtyValues readonly property alias dirtyValues: d.dirtyValues
readonly property bool isFullyFilled: readonly property bool isFullyFilled:
dirtyValues.holdingsModel.count > 0 && dirtyValues.selectedHoldingsModel.count > 0 &&
dirtyValues.permissionType !== PermissionTypes.Type.None && dirtyValues.permissionType !== PermissionTypes.Type.None &&
(d.isCommunityPermission || dirtyValues.channelsModel.count > 0) (d.isCommunityPermission || dirtyValues.selectedChannelsModel.count > 0)
property int permissionType: PermissionTypes.Type.None property int permissionType: PermissionTypes.Type.None
property bool isPrivate: false property bool isPrivate: false
// roles: type, key, name, amount, imageSource // roles: type, key, name, amount, imageSource
property var holdingsModel: ListModel {} property var selectedHoldingsModel: ListModel {}
// roles: itemId, text, icon, emoji, color, colorId // roles: itemId, text, icon, emoji, color, colorId
property var channelsModel: ListModel {} property var selectedChannelsModel: ListModel {}
property alias duplicationWarningVisible: duplicationPanel.visible property alias duplicationWarningVisible: duplicationPanel.visible
@ -59,8 +64,8 @@ StatusScrollView {
ModelsComparator { ModelsComparator {
id: holdingsModelComparator id: holdingsModelComparator
modelA: root.dirtyValues.holdingsModel modelA: root.dirtyValues.selectedHoldingsModel
modelB: root.holdingsModel modelB: root.selectedHoldingsModel
roles: ["key", "amount"] roles: ["key", "amount"]
mode: ModelsComparator.CompareMode.Set mode: ModelsComparator.CompareMode.Set
@ -69,8 +74,8 @@ StatusScrollView {
ModelsComparator { ModelsComparator {
id: channelsModelComparator id: channelsModelComparator
modelA: root.dirtyValues.channelsModel modelA: root.dirtyValues.selectedChannelsModel
modelB: root.channelsModel modelB: root.selectedChannelsModel
roles: ["itemId"] roles: ["itemId"]
mode: ModelsComparator.CompareMode.Set mode: ModelsComparator.CompareMode.Set
@ -89,7 +94,7 @@ StatusScrollView {
onIsCommunityPermissionChanged: { onIsCommunityPermissionChanged: {
if (isCommunityPermission) { if (isCommunityPermission) {
d.dirtyValues.channelsModel.clear() d.dirtyValues.selectedChannelsModel.clear()
inSelector.wholeCommunitySelected = true inSelector.wholeCommunitySelected = true
inSelector.itemsModel = inModelCommunity inSelector.itemsModel = inModelCommunity
} else { } else {
@ -100,8 +105,8 @@ StatusScrollView {
} }
readonly property QtObject dirtyValues: QtObject { readonly property QtObject dirtyValues: QtObject {
readonly property ListModel holdingsModel: ListModel {} readonly property ListModel selectedHoldingsModel: ListModel {}
readonly property ListModel channelsModel: ListModel {} readonly property ListModel selectedChannelsModel: ListModel {}
property int permissionType: PermissionTypes.Type.None property int permissionType: PermissionTypes.Type.None
property bool isPrivate: false property bool isPrivate: false
@ -112,17 +117,17 @@ StatusScrollView {
} }
function getHoldingIndex(key) { function getHoldingIndex(key) {
return ModelUtils.indexOf(holdingsModel, "key", key) return ModelUtils.indexOf(selectedHoldingsModel, "key", key)
} }
function getTokenKeysAndAmounts() { function getTokenKeysAndAmounts() {
return ModelUtils.modelToArray(holdingsModel, ["type", "key", "amount"]) return ModelUtils.modelToArray(selectedHoldingsModel, ["type", "key", "amount"])
.filter(item => item.type !== HoldingTypes.Type.Ens) .filter(item => item.type !== HoldingTypes.Type.Ens)
.map(item => ({ key: item.key, amount: item.amount })) .map(item => ({ key: item.key, amount: item.amount }))
} }
function getEnsNames() { function getEnsNames() {
return ModelUtils.modelToArray(holdingsModel, ["type", "name"]) return ModelUtils.modelToArray(selectedHoldingsModel, ["type", "name"])
.filter(item => item.type === HoldingTypes.Type.Ens) .filter(item => item.type === HoldingTypes.Type.Ens)
.map(item => item.name) .map(item => item.name)
} }
@ -130,20 +135,22 @@ StatusScrollView {
function loadInitValues() { function loadInitValues() {
// Holdings: // Holdings:
d.dirtyValues.holdingsModel.clear() d.dirtyValues.selectedHoldingsModel.clear()
d.dirtyValues.holdingsModel.append( d.dirtyValues.selectedHoldingsModel.append(
ModelUtils.modelToArray(root.holdingsModel, ["type", "key", "amount"])) ModelUtils.modelToArray(root.selectedHoldingsModel,
["type", "key", "amount"]))
// Permissions: // Permissions:
d.dirtyValues.permissionType = root.permissionType d.dirtyValues.permissionType = root.permissionType
// Channels // Channels
d.dirtyValues.channelsModel.clear() d.dirtyValues.selectedChannelsModel.clear()
d.dirtyValues.selectedChannelsModel.append(
ModelUtils.modelToArray(root.selectedChannelsModel, ["key"]))
d.dirtyValues.channelsModel.append( if (root.selectedChannelsModel &&
ModelUtils.modelToArray(root.channelsModel, ["key"])) (root.selectedChannelsModel.rowCount()
|| d.dirtyValues.permissionType === PermissionTypes.Type.None)) {
if (root.channelsModel && (root.channelsModel.count || d.dirtyValues.permissionType === PermissionTypes.Type.None)) {
inSelector.wholeCommunitySelected = false inSelector.wholeCommunitySelected = false
inSelector.itemsModel = channelsSelectionModel inSelector.itemsModel = channelsSelectionModel
} else { } else {
@ -187,22 +194,23 @@ StatusScrollView {
addButton.visible: itemsModel.count < d.maxHoldingsItems addButton.visible: itemsModel.count < d.maxHoldingsItems
itemsModel: HoldingsSelectionModel { itemsModel: HoldingsSelectionModel {
sourceModel: d.dirtyValues.holdingsModel sourceModel: d.dirtyValues.selectedHoldingsModel
assetsModel: root.store.assetsModel assetsModel: root.assetsModel
collectiblesModel: root.store.collectiblesModel collectiblesModel: root.collectiblesModel
} }
HoldingsDropdown { HoldingsDropdown {
id: dropdown id: dropdown
assetsModel: store.assetsModel assetsModel: root.assetsModel
collectiblesModel: store.collectiblesModel collectiblesModel: root.collectiblesModel
function addItem(type, item, amount) { function addItem(type, item, amount) {
const key = item.key const key = item.key
d.dirtyValues.holdingsModel.append({ type, key, amount }) d.dirtyValues.selectedHoldingsModel.append(
{ type, key, amount })
} }
function prepareUpdateIndex(key) { function prepareUpdateIndex(key) {
@ -210,8 +218,8 @@ StatusScrollView {
const existingIndex = d.dirtyValues.getHoldingIndex(key) const existingIndex = d.dirtyValues.getHoldingIndex(key)
if (itemIndex !== -1 && existingIndex !== -1 && itemIndex !== existingIndex) { if (itemIndex !== -1 && existingIndex !== -1 && itemIndex !== existingIndex) {
const previousKey = d.dirtyValues.holdingsModel.get(itemIndex).key const previousKey = d.dirtyValues.selectedHoldingsModel.get(itemIndex).key
d.dirtyValues.holdingsModel.remove(existingIndex) d.dirtyValues.selectedHoldingsModel.remove(existingIndex)
return d.dirtyValues.getHoldingIndex(previousKey) return d.dirtyValues.getHoldingIndex(previousKey)
} }
@ -228,49 +236,54 @@ StatusScrollView {
} }
onAddAsset: { onAddAsset: {
const modelItem = CommunityPermissionsHelpers.getTokenByKey(store.assetsModel, key) const modelItem = CommunityPermissionsHelpers.getTokenByKey(
root.assetsModel, key)
addItem(HoldingTypes.Type.Asset, modelItem, amount) addItem(HoldingTypes.Type.Asset, modelItem, amount)
dropdown.close() dropdown.close()
} }
onAddCollectible: { onAddCollectible: {
const modelItem = CommunityPermissionsHelpers.getTokenByKey(store.collectiblesModel, key) const modelItem = CommunityPermissionsHelpers.getTokenByKey(
root.collectiblesModel, key)
addItem(HoldingTypes.Type.Collectible, modelItem, amount) addItem(HoldingTypes.Type.Collectible, modelItem, amount)
dropdown.close() dropdown.close()
} }
onAddEns: { onAddEns: {
d.dirtyValues.holdingsModel.append( d.dirtyValues.selectedHoldingsModel.append(
{ type: HoldingTypes.Type.Ens, key: domain, amount: 1 }) { type: HoldingTypes.Type.Ens, key: domain, amount: 1 })
dropdown.close() dropdown.close()
} }
onUpdateAsset: { onUpdateAsset: {
const itemIndex = prepareUpdateIndex(key) const itemIndex = prepareUpdateIndex(key)
const modelItem = CommunityPermissionsHelpers.getTokenByKey(store.assetsModel, key) const modelItem = CommunityPermissionsHelpers.getTokenByKey(root.assetsModel, key)
d.dirtyValues.holdingsModel.set(itemIndex, d.dirtyValues.selectedHoldingsModel.set(
{ type: HoldingTypes.Type.Asset, key, amount }) itemIndex, { type: HoldingTypes.Type.Asset, key, amount })
dropdown.close() dropdown.close()
} }
onUpdateCollectible: { onUpdateCollectible: {
const itemIndex = prepareUpdateIndex(key) const itemIndex = prepareUpdateIndex(key)
const modelItem = CommunityPermissionsHelpers.getTokenByKey(store.collectiblesModel, key) const modelItem = CommunityPermissionsHelpers.getTokenByKey(
root.collectiblesModel, key)
d.dirtyValues.holdingsModel.set(itemIndex, d.dirtyValues.selectedHoldingsModel.set(
itemIndex,
{ type: HoldingTypes.Type.Collectible, key, amount }) { type: HoldingTypes.Type.Collectible, key, amount })
dropdown.close() dropdown.close()
} }
onUpdateEns: { onUpdateEns: {
d.dirtyValues.holdingsModel.set(tokensSelector.editedIndex, d.dirtyValues.selectedHoldingsModel.set(
tokensSelector.editedIndex,
{ type: HoldingTypes.Type.Ens, key: domain, amount: 1 }) { type: HoldingTypes.Type.Ens, key: domain, amount: 1 })
dropdown.close() dropdown.close()
} }
onRemoveClicked: { onRemoveClicked: {
d.dirtyValues.holdingsModel.remove(tokensSelector.editedIndex) d.dirtyValues.selectedHoldingsModel.remove(tokensSelector.editedIndex)
dropdown.close() dropdown.close()
} }
} }
@ -349,7 +362,7 @@ StatusScrollView {
id: permissionsDropdown id: permissionsDropdown
initialPermissionType: d.dirtyValues.permissionType initialPermissionType: d.dirtyValues.permissionType
enableAdminPermission: root.store.isOwner enableAdminPermission: root.isOwner
onDone: { onDone: {
if (d.dirtyValues.permissionType === permissionType) { if (d.dirtyValues.permissionType === permissionType) {
@ -417,9 +430,13 @@ StatusScrollView {
const selectedChannels = [] const selectedChannels = []
if (!inSelector.wholeCommunitySelected) if (!inSelector.wholeCommunitySelected) {
for (let i = 0; i < d.dirtyValues.channelsModel.count; i++) const model = d.dirtyValues.selectedChannelsModel
selectedChannels.push(d.dirtyValues.channelsModel.get(i).key) const count = model.count
for (let i = 0; i < count; i++)
selectedChannels.push(model.get(i).key)
}
inDropdown.setSelectedChannels(selectedChannels) inDropdown.setSelectedChannels(selectedChannels)
inDropdown.open() inDropdown.open()
@ -430,10 +447,10 @@ StatusScrollView {
Component.onCompleted: { Component.onCompleted: {
append({ append({
imageSource: inDropdown.communityData.image, imageSource: inDropdown.communityImage,
text: inDropdown.communityData.name, text: inDropdown.communityName,
operator: OperatorsUtils.Operators.None, operator: OperatorsUtils.Operators.None,
color: inDropdown.communityData.color color: inDropdown.communityColor
}) })
} }
} }
@ -441,36 +458,34 @@ StatusScrollView {
ChannelsSelectionModel { ChannelsSelectionModel {
id: channelsSelectionModel id: channelsSelectionModel
sourceModel: d.dirtyValues.channelsModel sourceModel: d.dirtyValues.selectedChannelsModel
channelsModel: root.rootStore.chatCommunitySectionModule.model channelsModel: root.channelsModel
} }
InDropdown { InDropdown {
id: inDropdown id: inDropdown
model: root.rootStore.chatCommunitySectionModule.model model: root.channelsModel
readonly property var communityData: rootStore.mainModuleInst.activeSection communityName: root.communityDetails.name
communityImage: root.communityDetails.image
communityName: communityData.name communityColor: root.communityDetails.color
communityImage: communityData.image
communityColor: communityData.color
onChannelsSelected: { onChannelsSelected: {
d.dirtyValues.channelsModel.clear() d.dirtyValues.selectedChannelsModel.clear()
inSelector.itemsModel = 0 inSelector.itemsModel = 0
inSelector.wholeCommunitySelected = false inSelector.wholeCommunitySelected = false
const modelData = channels.map(key => ({ key })) const modelData = channels.map(key => ({ key }))
d.dirtyValues.channelsModel.append(modelData) d.dirtyValues.selectedChannelsModel.append(modelData)
inSelector.itemsModel = channelsSelectionModel inSelector.itemsModel = channelsSelectionModel
close() close()
} }
onCommunitySelected: { onCommunitySelected: {
d.dirtyValues.channelsModel.clear() d.dirtyValues.selectedChannelsModel.clear()
inSelector.wholeCommunitySelected = true inSelector.wholeCommunitySelected = true
inSelector.itemsModel = inModelCommunity inSelector.itemsModel = inModelCommunity
close() close()
@ -507,18 +522,6 @@ StatusScrollView {
onToggled: d.dirtyValues.isPrivate = checked onToggled: d.dirtyValues.isPrivate = checked
} }
PermissionConflictWarningPanel {
id: conflictPanel
Layout.fillWidth: true
Layout.topMargin: 50 // by desing
visible: store.permissionConflict.exists
holdings: store.permissionConflict.holdings
permissions: store.permissionConflict.permissions
channels: store.permissionConflict.channels
}
PermissionDuplicationWarningPanel { PermissionDuplicationWarningPanel {
id: duplicationPanel id: duplicationPanel
@ -532,9 +535,7 @@ StatusScrollView {
Layout.preferredHeight: 44 Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true Layout.fillWidth: true
Layout.topMargin: conflictPanel.visible Layout.topMargin: Style.current.bigPadding
? conflictPanel.Layout.topMargin
: Style.current.bigPadding
visible: !root.isEditState visible: !root.isEditState
text: qsTr("Create permission") text: qsTr("Create permission")

View File

@ -2,21 +2,22 @@ import QtQuick 2.14
import QtQuick.Layouts 1.14 import QtQuick.Layouts 1.14
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2 import SortFilterProxyModel 0.2
import shared.popups 1.0 import shared.popups 1.0
import AppLayouts.Chat.controls.community 1.0 import AppLayouts.Chat.controls.community 1.0
import AppLayouts.Chat.helpers 1.0
import AppLayouts.Chat.stores 1.0
StatusScrollView { StatusScrollView {
id: root id: root
property var rootStore required property var permissionsModel
required property CommunitiesStore store required property var assetsModel
required property var collectiblesModel
required property var channelsModel
// name, image, color properties expected
required property var communityDetails
property int viewWidth: 560 // by design property int viewWidth: 560 // by design
@ -41,27 +42,25 @@ StatusScrollView {
ListModel { ListModel {
id: communityItemModel id: communityItemModel
readonly property var communityData: rootStore.mainModuleInst.activeSection
Component.onCompleted: { Component.onCompleted: {
append({ append({
text: communityData.name, text: root.communityDetails.name,
imageSource: communityData.image, imageSource: root.communityDetails.image,
color: communityData.color color: root.communityDetails.color
}) })
} }
} }
Repeater { Repeater {
model: root.rootStore.permissionsModel model: root.permissionsModel
delegate: PermissionItem { delegate: PermissionItem {
Layout.preferredWidth: root.viewWidth Layout.preferredWidth: root.viewWidth
holdingsListModel: HoldingsSelectionModel { holdingsListModel: HoldingsSelectionModel {
sourceModel: model.holdingsListModel sourceModel: model.holdingsListModel
assetsModel: store.assetsModel assetsModel: root.assetsModel
collectiblesModel: store.collectiblesModel collectiblesModel: root.collectiblesModel
} }
permissionType: model.permissionType permissionType: model.permissionType
@ -70,7 +69,7 @@ StatusScrollView {
id: channelsSelectionModel id: channelsSelectionModel
sourceModel: model.channelsListModel sourceModel: model.channelsListModel
channelsModel: rootStore.chatCommunitySectionModule.model channelsModel: root.channelsModel
} }
channelsListModel: channelsSelectionModel.count channelsListModel: channelsSelectionModel.count