chore(CommunitySettingsView): Sections cross referencing simplified

Additionally:
- stack components directly define content of the left list
- fixed navigation from Permissions section to minting
- various code style fixes

Closes: #11179
This commit is contained in:
Michał Cieślak 2023-07-04 16:35:00 +02:00 committed by Michał
parent 6247110293
commit a4b1b5500a
1 changed files with 257 additions and 268 deletions

View File

@ -1,31 +1,25 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import QtQuick.Dialogs 1.3
import QtGraphicalEffects 1.15
import SortFilterProxyModel 0.2
import utils 1.0
import shared.panels 1.0
import shared.popups 1.0
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as StatusQUtils
import StatusQ.Layout 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Controls.Validators 0.1
import AppLayouts.Communities.controls 1.0
import shared.panels 1.0
import shared.popups 1.0
import shared.stores 1.0
import shared.views.chat 1.0
import utils 1.0
import AppLayouts.Communities.controls 1.0
import AppLayouts.Communities.panels 1.0
import AppLayouts.Communities.popups 1.0
import AppLayouts.Communities.layouts 1.0
StatusSectionLayout {
id: root
@ -34,32 +28,6 @@ StatusSectionLayout {
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
onNotificationButtonClicked: Global.openActivityCenterPopup()
readonly property var settingsMenuModel: [
{
id: Constants.CommunitySettingsSections.Overview,
name: qsTr("Overview"), icon: "show", enabled: true
},
{
id: Constants.CommunitySettingsSections.Members,
name: qsTr("Members"), icon: "group-chat", enabled: true
},
{
id: Constants.CommunitySettingsSections.Permissions,
name: qsTr("Permissions"), icon: "objects", enabled: true
},
{
id: Constants.CommunitySettingsSections.MintTokens,
name: qsTr("Mint Tokens"), icon: "token", enabled: root.isOwner
},
{
id: Constants.CommunitySettingsSections.Airdrops,
name: qsTr("Airdrops"), icon: "airdrop", enabled: root.isOwner
}
]
// TODO: Next community settings options:
// {name: qsTr("Token sales"), icon: "token-sale"},
// {name: qsTr("Subscriptions"), icon: "subscription"},
property var rootStore
property var chatCommunitySectionModule
property var community
@ -78,7 +46,8 @@ StatusSectionLayout {
if (!!json)
tagsArray = json.map(tag => tag.name)
} catch (e) {
console.warn("Error parsing community tags: ", community.tags, " error: ", e.message)
console.warn("Error parsing community tags: ", community.tags,
" error: ", e.message)
}
}
return JSON.stringify(tagsArray)
@ -86,14 +55,14 @@ StatusSectionLayout {
signal backToCommunityClicked
backButtonName: stackLayout.children[d.currentIndex].previousPageName || ""
//navigate to a specific section and subsection
function goTo(section: int, subSection: int) {
d.goTo(section, subSection)
}
onBackButtonClicked: {
stackLayout.children[d.currentIndex].navigateBack()
}
onBackButtonClicked: stackLayout.children[d.currentIndex].navigateBack()
leftPanel: Item {
anchors.fill: parent
@ -132,20 +101,20 @@ StatusSectionLayout {
Layout.fillHeight: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
model: root.settingsMenuModel
model: stackLayout.children
spacing: 8
delegate: StatusNavigationListItem {
objectName: "CommunitySettingsView_NavigationListItem_" + modelData.name
width: listView.width
title: modelData.name
asset.name: modelData.icon
objectName: "CommunitySettingsView_NavigationListItem_" + model.sectionName
width: ListView.view.width
title: model.sectionName
asset.name: model.sectionIcon
asset.height: 24
asset.width: 24
selected: d.currentIndex === index
onClicked: d.currentIndex = index
visible: modelData.enabled
height: modelData.enabled ? implicitHeight : 0
visible: model.sectionEnabled
height: visible ? implicitHeight : 0
}
}
}
@ -180,6 +149,11 @@ StatusSectionLayout {
currentIndex: d.currentIndex
OverviewSettingsPanel {
readonly property int sectionKey: Constants.CommunitySettingsSections.Overview
readonly property string sectionName: qsTr("Overview")
readonly property string sectionIcon: "show"
readonly property bool sectionEnabled: true
communityId: root.community.id
name: root.community.name
description: root.community.description
@ -202,7 +176,8 @@ StatusSectionLayout {
StatusQUtils.Utils.filterXSS(item.description),
StatusQUtils.Utils.filterXSS(item.introMessage),
StatusQUtils.Utils.filterXSS(item.outroMessage),
item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess : Constants.communityChatPublicAccess,
item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess
: Constants.communityChatPublicAccess,
item.color.toString().toUpperCase(),
item.selectedTags,
Utils.getImageAndCropInfoJson(item.logoImagePath, item.logoCropRect),
@ -228,10 +203,14 @@ StatusSectionLayout {
privateKey: root.chatCommunitySectionModule.exportCommunity(root.community.id),
})
}
onPreviousPageNameChanged: root.backButtonName = previousPageName
}
MembersSettingsPanel {
readonly property int sectionKey: Constants.CommunitySettingsSections.Members
readonly property string sectionName: qsTr("Members")
readonly property string sectionIcon: "group-chat"
readonly property bool sectionEnabled: true
rootStore: root.rootStore
membersModel: root.community.members
bannedMembersModel: root.community.bannedMembers
@ -248,6 +227,11 @@ StatusSectionLayout {
}
PermissionsSettingsPanel {
readonly property int sectionKey: Constants.CommunitySettingsSections.Permissions
readonly property string sectionName: qsTr("Permissions")
readonly property string sectionIcon: "objects"
readonly property bool sectionEnabled: true
readonly property PermissionsStore permissionsStore:
rootStore.permissionsStore
@ -275,27 +259,36 @@ StatusSectionLayout {
onRemovePermissionRequested:
permissionsStore.removePermission(key)
onPreviousPageNameChanged: root.backButtonName = previousPageName
onNavigateToMintTokenSettings: {
root.goTo(Constants.CommunitySettingsSections.MintTokens)
root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanel.openNewTokenForm(false)
}
}
MintTokensSettingsPanel {
id: mintPanel
readonly property int sectionKey: Constants.CommunitySettingsSections.MintTokens
readonly property string sectionName: qsTr("Mint Tokens")
readonly property string sectionIcon: "token"
readonly property bool sectionEnabled: root.isOwner
readonly property CommunityTokensStore communityTokensStore:
rootStore.communityTokensStore
function setFeesInfo(ethCurrency, fiatCurrency, errorCode) {
if (errorCode === Constants.ComputeFeeErrorCode.Success || errorCode === Constants.ComputeFeeErrorCode.Balance) {
let valueStr = LocaleUtils.currencyAmountToLocaleString(ethCurrency) + "(" + LocaleUtils.currencyAmountToLocaleString(fiatCurrency) + ")"
if (errorCode === Constants.ComputeFeeErrorCode.Success
|| errorCode === Constants.ComputeFeeErrorCode.Balance) {
const valueStr = LocaleUtils.currencyAmountToLocaleString(ethCurrency)
+ "(" + LocaleUtils.currencyAmountToLocaleString(fiatCurrency) + ")"
mintPanel.feeText = valueStr
if (errorCode === Constants.ComputeFeeErrorCode.Balance) {
if (errorCode === Constants.ComputeFeeErrorCode.Balance)
mintPanel.errorText = qsTr("Not enough funds to make transaction")
}
mintPanel.isFeeLoading = false
return
} else if (errorCode === Constants.ComputeFeeErrorCode.Infura) {
mintPanel.errorText = qsTr("Infura error")
@ -316,180 +309,53 @@ StatusSectionLayout {
allNetworks: communityTokensStore.allNetworks
accounts: root.rootStore.accounts
onPreviousPageNameChanged: root.backButtonName = previousPageName
onSignMintTransactionOpened: communityTokensStore.computeDeployFee(chainId, accountAddress, tokenType)
onMintCollectible: communityTokensStore.deployCollectible(root.community.id, collectibleItem)
onMintAsset: communityTokensStore.deployAsset(root.community.id, assetItem)
onSignRemoteDestructTransactionOpened: communityTokensStore.computeSelfDestructFee(remotelyDestructTokensList, tokenKey)
onRemotelyDestructCollectibles: {
communityTokensStore.remoteSelfDestructCollectibles(root.community.id,
remotelyDestructTokensList,
tokenKey)
}
onSignBurnTransactionOpened: communityTokensStore.computeBurnFee(tokenKey, amount)
onBurnToken: communityTokensStore.burnToken(root.community.id, tokenKey, amount)
onDeleteToken: communityTokensStore.deleteToken(root.community.id, tokenKey)
onSignMintTransactionOpened:
communityTokensStore.computeDeployFee(
chainId, accountAddress, tokenType)
onMintCollectible:
communityTokensStore.deployCollectible(
root.community.id, collectibleItem)
onMintAsset:
communityTokensStore.deployAsset(root.community.id, assetItem)
onSignRemoteDestructTransactionOpened:
communityTokensStore.computeSelfDestructFee(
remotelyDestructTokensList, tokenKey)
onRemotelyDestructCollectibles:
communityTokensStore.remoteSelfDestructCollectibles(
root.community.id, remotelyDestructTokensList, tokenKey)
onSignBurnTransactionOpened:
communityTokensStore.computeBurnFee(tokenKey, amount)
onBurnToken:
communityTokensStore.burnToken(root.community.id, tokenKey, amount)
onDeleteToken:
communityTokensStore.deleteToken(root.community.id, tokenKey)
onAirdropToken: {
root.goTo(Constants.CommunitySettingsSections.Airdrops)
}
// Force a token selection to be airdroped with default amount 1
airdropPanel.selectToken(tokenKey, 1, type)
Connections {
target: rootStore.communityTokensStore
function onDeployFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onSelfDestructFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onBurnFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onRemoteDestructStateChanged(communityId, tokenName, status, url) {
if (root.community.id !== communityId) {
return
}
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Remotely destroying tokens...")
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("%1 tokens destroyed").arg(tokenName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("%1 tokens destruction failed").arg(tokenName)
break
default:
console.warn("Unknown destruction state: "+status)
return
}
Global.displayToastMessage(title,
qsTr("View on etherscan"),
"",
loading,
type,
url)
}
function onAirdropStateChanged(communityId, tokenName, chainName, status, url) {
if (root.community.id !== communityId) {
return
}
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Airdrop on %1 in progress...").arg(chainName)
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("Airdrop on %1 in complete").arg(chainName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("Airdrop on %1 failed").arg(chainName)
break
default:
console.warn("Unknown airdrop state: "+status)
return
}
Global.displayToastMessage(title,
qsTr("View on etherscan"),
"",
loading,
type,
url)
}
function onBurnStateChanged(communityId, tokenName, status, url) {
if (root.community.id !== communityId) {
return
}
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("%1 being burned...").arg(tokenName)
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("%1 burning is complete").arg(tokenName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("%1 burning is failed").arg(tokenName)
break
default:
console.warn("Unknown burning state: "+status)
return
}
Global.displayToastMessage(title,
qsTr("View on etherscan"),
"",
loading,
type,
url)
}
function onDeploymentStateChanged(communityId, status, url) {
if (root.community.id !== communityId) {
return
}
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Token is being minted...")
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("Token minting finished")
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("Token minting failed")
break
default:
console.warn("Unknown deploy state: "+status)
return
}
Global.displayToastMessage(title,
qsTr("View on etherscan"),
"",
loading,
type,
url)
}
}
Connections {
target: airdropPanel
function onNavigateToMintTokenSettings(isAssetType) {
mintPanel.openNewTokenForm(isAssetType)
}
// Set given addresses as recipients
airdropPanel.addAddresses(addresses)
}
}
AirdropsSettingsPanel {
id: airdropPanel
readonly property int sectionKey: Constants.CommunitySettingsSections.Airdrops
readonly property string sectionName: qsTr("Airdrops")
readonly property string sectionIcon: "airdrop"
readonly property bool sectionEnabled: root.isOwner
communityDetails: d.communityDetails
readonly property CommunityTokensStore communityTokensStore:
rootStore.communityTokensStore
@ -569,48 +435,24 @@ StatusSectionLayout {
return chatContentModule.usersModule.model
}
onPreviousPageNameChanged: root.backButtonName = previousPageName
onAirdropClicked: communityTokensStore.airdrop(root.community.id, airdropTokens, addresses)
onNavigateToMintTokenSettings: root.goTo(Constants.CommunitySettingsSections.MintTokens)
onAirdropClicked: communityTokensStore.airdrop(root.community.id,
airdropTokens, addresses)
onNavigateToMintTokenSettings: {
root.goTo(Constants.CommunitySettingsSections.MintTokens)
mintPanel.openNewTokenForm(isAssetType)
}
onAirdropFeesRequested:
communityTokensStore.computeAirdropFee(
root.community.id, contractKeysAndAmounts, addresses)
Connections {
target: mintPanel
function onAirdropToken(tokenKey, type, addresses) {
// Force a token selection to be airdroped with default amount 1
airdropPanel.selectToken(tokenKey, 1, type)
// Set given addresses as recipients
airdropPanel.addAddresses(addresses)
}
}
Connections {
target: rootStore.communityTokensStore
function onAirdropFeeUpdated(airdropFees) {
airdropPanel.airdropFees = airdropFees
}
}
}
onCurrentIndexChanged:
root.backButtonName = stackLayout.children[d.currentIndex].previousPageName || ""
}
onSettingsMenuModelChanged: d.currentIndex = 0
QtObject {
id: d
property int currentIndex: 0
readonly property var currentItem: stackLayout && stackLayout.children[d.currentIndex]
? stackLayout.children[d.currentIndex]
: null
readonly property QtObject communityDetails: QtObject {
readonly property string id: root.community.id
@ -622,23 +464,26 @@ StatusSectionLayout {
}
function goTo(section: int, subSection: int) {
//find and enable section
const matchingIndex = listView.model.findIndex((modelItem, index) => modelItem.id === section && modelItem.enabled)
const stackContent = stackLayout.children
if(matchingIndex === -1)
return
for (let i = 0; stackContent.length; i++) {
const item = stackContent[i]
d.currentIndex = matchingIndex
if (item.sectionKey === section) {
d.currentIndex = i
//find and enable subsection if subSection navigation is available
if(d.currentItem && d.currentItem.goTo) {
d.currentItem.goTo(subSection)
if(item.goTo)
item.goTo(subSection)
break
}
}
}
}
MessageDialog {
id: errorDialog
title: qsTr("Error editing the community")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
@ -646,6 +491,7 @@ StatusSectionLayout {
Component {
id: transferOwnershipPopup
TransferOwnershipPopup {
anchors.centerIn: parent
store: root.rootStore
@ -655,6 +501,7 @@ StatusSectionLayout {
Component {
id: noPermissionsPopupCmp
NoPermissionsToJoinPopup {
onRejectButtonClicked: {
root.rootStore.declineRequestToJoinCommunity(requestId, communityId)
@ -664,16 +511,158 @@ StatusSectionLayout {
}
}
Connections {
target: root.chatCommunitySectionModule
function onOpenNoPermissionsToJoinPopup(communityName: string, userName: string, communityId: string, requestId: string) {
Global.openPopup(noPermissionsPopupCmp, {
communityName: communityName,
userName: userName,
communityId: communityId,
requestId: requestId
})
target: rootStore.communityTokensStore
function onDeployFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onSelfDestructFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onBurnFeeUpdated(ethCurrency, fiatCurrency, errorCode) {
mintPanel.setFeesInfo(ethCurrency, fiatCurrency, errorCode)
}
function onAirdropFeeUpdated(airdropFees) {
airdropPanel.airdropFees = airdropFees
}
function onRemoteDestructStateChanged(communityId, tokenName, status, url) {
if (root.community.id !== communityId)
return
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Remotely destroying tokens...")
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("%1 tokens destroyed").arg(tokenName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("%1 tokens destruction failed").arg(tokenName)
break
default:
console.warn("Unknown destruction state: "+status)
return
}
Global.displayToastMessage(title, qsTr("View on etherscan"), "",
loading, type, url)
}
function onAirdropStateChanged(communityId, tokenName, chainName,
status, url) {
if (root.community.id !== communityId)
return
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Airdrop on %1 in progress...").arg(chainName)
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("Airdrop on %1 in complete").arg(chainName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("Airdrop on %1 failed").arg(chainName)
break
default:
console.warn("Unknown airdrop state: "+status)
return
}
Global.displayToastMessage(title, qsTr("View on etherscan"), "",
loading, type, url)
}
function onBurnStateChanged(communityId, tokenName, status, url) {
if (root.community.id !== communityId)
return
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("%1 being burned...").arg(tokenName)
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("%1 burning is complete").arg(tokenName)
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("%1 burning is failed").arg(tokenName)
break
default:
console.warn("Unknown burning state: "+status)
return
}
Global.displayToastMessage(title, qsTr("View on etherscan"), "",
loading, type, url)
}
function onDeploymentStateChanged(communityId, status, url) {
if (root.community.id !== communityId)
return
let title = ""
let loading = false
let type = Constants.ephemeralNotificationType.normal
switch (status) {
case Constants.ContractTransactionStatus.InProgress:
title = qsTr("Token is being minted...")
loading = true
break
case Constants.ContractTransactionStatus.Completed:
title = qsTr("Token minting finished")
type = Constants.ephemeralNotificationType.success
break
case Constants.ContractTransactionStatus.Failed:
title = qsTr("Token minting failed")
break
default:
console.warn("Unknown deploy state: "+status)
return
}
Global.displayToastMessage(title, qsTr("View on etherscan"), "",
loading, type, url)
}
}
Connections {
target: root.chatCommunitySectionModule
function onOpenNoPermissionsToJoinPopup(communityName: string,
userName: string, communityId:
string, requestId: string) {
const properties = {
communityName: communityName,
userName: userName,
communityId: communityId,
requestId: requestId
}
Global.openPopup(noPermissionsPopupCmp, properties)
}
}
}