feat(CommunityMintTokens): Using sortable list of tokens holders

New list contains also dropdown menu with some actions, basic
integration is done for holder types and actions supported currently
by the backend.

Closes: #10621
This commit is contained in:
Michał Cieślak 2023-06-05 15:49:36 +02:00 committed by Michał
parent 99ad85047d
commit 8102600c5b
5 changed files with 83 additions and 20 deletions

View File

@ -33,6 +33,10 @@ SettingsPageLayout {
d.selectCollectible(key, amount)
}
function addAddresses(addresses) {
d.addAddresses(addresses)
}
QtObject {
id: d
@ -43,6 +47,7 @@ SettingsPageLayout {
readonly property string newAirdropViewPageTitle: qsTr("New airdrop")
signal selectCollectible(string key, int amount)
signal addAddresses(var addresses)
}
content: StackView {
@ -110,7 +115,10 @@ SettingsPageLayout {
}
onNavigateToMintTokenSettings: root.navigateToMintTokenSettings()
Component.onCompleted: d.selectCollectible.connect(view.selectCollectible)
Component.onCompleted: {
d.selectCollectible.connect(view.selectCollectible)
d.addAddresses.connect(view.addAddresses)
}
}
}
}

View File

@ -78,7 +78,7 @@ SettingsPageLayout {
signal burnCollectibles(string tokenKey,
int amount)
signal airdropCollectible(string tokenKey)
signal airdropCollectible(string tokenKey, var addresses)
signal deleteToken(string tokenKey)
@ -127,6 +127,7 @@ SettingsPageLayout {
onInitialItemChanged: updateInitialStackView()
signal airdropClicked()
signal remoteDestructAddressClicked(string address)
signal retryMintClicked()
@ -430,6 +431,7 @@ SettingsPageLayout {
collectibleName: root.title
model: d.tokenOwnersModel
destroyOnClose: false
onRemotelyDestructClicked: {
d.selfDestructTokensList = selfDestructTokensList
@ -443,6 +445,8 @@ SettingsPageLayout {
property int tokenCount
destroyOnClose: false
title: qsTr("Remotely destruct %n token(s)", "", tokenCount)
acceptBtnText: qsTr("Remotely destruct")
alertText: qsTr("Continuing will destroy tokens held by members and revoke any permissions they are given. To undo you will have to issue them new tokens.")
@ -501,6 +505,15 @@ SettingsPageLayout {
signTransactionPopup.open()
}
}
Connections {
target: d
function onRemoteDestructAddressClicked(address) {
remotelyDestructPopup.open()
// TODO: set the address selected in the popup's list
}
}
}
}
@ -649,11 +662,24 @@ SettingsPageLayout {
}
}
onGeneralAirdropRequested: {
root.airdropCollectible(view.symbol, [])
}
onAirdropRequested: {
root.airdropCollectible(view.symbol, [address])
}
onRemoteDestructRequested: {
d.remoteDestructAddressClicked(address)
}
Connections {
target: d
// handle airdrop request from the footer
function onAirdropClicked() {
root.airdropCollectible(view.symbol) // TODO: Backend. It should just be the key (hash(chainId + contractAddress)
root.airdropCollectible(view.symbol, []) // TODO: Backend. It should just be the key (hash(chainId + contractAddress)
}
}
}

View File

@ -342,7 +342,9 @@ StatusSectionLayout {
}
onSignBurnTransactionOpened: communityTokensStore.computeBurnFee(chainId)
onBurnCollectibles: communityTokensStore.burnCollectibles(tokenKey, amount)
onAirdropCollectible: root.goTo(Constants.CommunitySettingsSections.Airdrops)
onAirdropCollectible: {
root.goTo(Constants.CommunitySettingsSections.Airdrops)
}
onDeleteToken: communityTokensStore.deleteToken(root.community.id, tokenKey)
onRetryMintToken: communityTokensStore.retryMintToken(root.community.id, tokenKey)
@ -478,12 +480,15 @@ StatusSectionLayout {
Connections {
target: mintPanel
function onAirdropCollectible(key) {
function onAirdropCollectible(key, addresses) {
// Here it is forced a navigation to the new airdrop form, like if it was clicked the header button
airdropPanel.primaryHeaderButtonClicked()
// Force a token selection to be airdroped with default amount 1
airdropPanel.selectCollectible(key, 1)
// Set given addresses as recipients
airdropPanel.addAddresses(addresses)
}
}
}
@ -505,12 +510,15 @@ StatusSectionLayout {
function goTo(section: int, subSection: int) {
//find and enable section
const matchingIndex = listView.model.findIndex((modelItem, index) => modelItem.id === section && modelItem.enabled)
if(matchingIndex !== -1) {
d.currentIndex = matchingIndex
//find and enable subsection if subSection navigation is available
if(d.currentItem && d.currentItem.goTo) {
d.currentItem.goTo(subSection)
}
if(matchingIndex === -1)
return
d.currentIndex = matchingIndex
//find and enable subsection if subSection navigation is available
if(d.currentItem && d.currentItem.goTo) {
d.currentItem.goTo(subSection)
}
}
}

View File

@ -46,6 +46,10 @@ StatusScrollView {
selectedHoldingsModel.append(entry)
}
function addAddresses(_addresses) {
addresses.addAddresses(_addresses)
}
QtObject {
id: d
@ -265,21 +269,27 @@ StatusScrollView {
ListModel {
id: addresses
function addAddressesFromString(addresses) {
const words = addresses.trim().split(/[\s+,]/)
function addAddresses(_addresses) {
const existing = new Set()
for (let i = 0; i < count; i++)
existing.add(get(i).address)
words.forEach(word => {
if (word === "" || existing.has(word))
_addresses.forEach(address => {
if (existing.has(address))
return
const valid = Utils.isValidAddress(word)
append({ valid, address: word })
const valid = Utils.isValidAddress(address)
append({ valid, address })
})
}
function addAddressesFromString(addressesString) {
const words = addressesString.trim().split(/[\s+,]/)
const wordsNonEmpty = words.filter(word => !!word)
addAddresses(wordsNonEmpty)
}
}
function openPopup(popup) {

View File

@ -69,6 +69,11 @@ StatusScrollView {
int chainId,
string accountName)
signal airdropRequested(string address)
signal generalAirdropRequested
signal remoteDestructRequested(string address)
QtObject {
id: d
@ -373,13 +378,19 @@ StatusScrollView {
}
}
TokenHoldersPanel {
SortableTokenHoldersPanel {
visible: !root.preview
tokenName: root.name
model: root.tokenOwnersModel
tokenName: root.name
showRemotelyDestructMenuItem: !root.isAssetView && root.selfDestruct
Layout.topMargin: Style.current.padding
Layout.fillWidth: true
Layout.fillHeight: true
onAirdropRequested: root.airdropRequested(address)
onGeneralAirdropRequested: root.generalAirdropRequested()
onRemoteDestructRequested: root.remoteDestructRequested(address)
}
}
}