feat(OwnerToken): Create `EditTokenView.qml` for mint owner token flow
- It creates a generic `TokenInfoPanel` that will be reused in different mint token views. - It creates new `EditOwnerTokenView` and storybook page support. - It adds new `EditOwnerTokenView` into the minting flow, linking sign transaction flow and adding needed method to the store to do the deployment. Closes #11296
This commit is contained in:
parent
32952e4e01
commit
c8cb2d6c7c
|
@ -85,6 +85,10 @@ ListModel {
|
|||
title: "EditNetworkView"
|
||||
section: "Views"
|
||||
}
|
||||
ListElement {
|
||||
title: "EditOwnerTokenView"
|
||||
section: "Views"
|
||||
}
|
||||
ListElement {
|
||||
title: "StatusCommunityCard"
|
||||
section: "Panels"
|
||||
|
|
|
@ -239,5 +239,9 @@
|
|||
],
|
||||
"OverviewSettingsChart": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31281-635619&mode=design&t=RYpVRgwqCjp8fUEX-0"
|
||||
],
|
||||
"EditOwnerTokenView": [
|
||||
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?type=design&node-id=34794-590207&mode=design&t=ZnwK9yenS5oSgwws-0"
|
||||
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import AppLayouts.Communities.views 1.0
|
||||
|
||||
import Storybook 1.0
|
||||
import Models 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
SplitView {
|
||||
|
||||
Logs { id: logs }
|
||||
|
||||
SplitView {
|
||||
orientation: Qt.Vertical
|
||||
SplitView.fillWidth: true
|
||||
|
||||
Item {
|
||||
SplitView.fillWidth: true
|
||||
SplitView.fillHeight: true
|
||||
|
||||
EditOwnerTokenView {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 50
|
||||
|
||||
communityName: communityName.text
|
||||
communityLogo: doodles.checked ? ModelsData.collectibles.doodles : ModelsData.collectibles.mana
|
||||
communityColor: color1.checked ? "#FFC4E9" : "#f44336"
|
||||
|
||||
layer1Networks: NetworksModel.layer1Networks
|
||||
layer2Networks: NetworksModel.layer2Networks
|
||||
testNetworks: NetworksModel.testNetworks
|
||||
enabledNetworks: NetworksModel.enabledNetworks
|
||||
allNetworks: enabledNetworks
|
||||
accounts: WalletAccountsModel {}
|
||||
|
||||
onMintClicked: logs.logEvent("EditOwnerTokenView::onMintClicked")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LogsAndControlsPanel {
|
||||
id: logsAndControlsPanel
|
||||
|
||||
SplitView.minimumHeight: 100
|
||||
SplitView.preferredHeight: 150
|
||||
|
||||
logsView.logText: logs.logText
|
||||
|
||||
ColumnLayout {
|
||||
|
||||
RowLayout {
|
||||
Label {
|
||||
text: "Community name:"
|
||||
}
|
||||
|
||||
TextInput {
|
||||
id: communityName
|
||||
text: "Doodles"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
RadioButton {
|
||||
id: color1
|
||||
|
||||
text: "Light pink"
|
||||
checked: true
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
text: "Orange"
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
RadioButton {
|
||||
id: doodles
|
||||
text: "Doodles"
|
||||
checked: true
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
text: "Mana"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -82,4 +82,14 @@ QtObject {
|
|||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// It generates a symbol from a given community name.
|
||||
// It will be used to autogenerate the Owner and Token Master token symbols.
|
||||
function autogenerateSymbol(isOwner, communityName) {
|
||||
const shortName = communityName.substring(0, 3)
|
||||
if(isOwner)
|
||||
return "OWN" + shortName.toUpperCase()
|
||||
else
|
||||
return "TM" + shortName.toUpperCase()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,11 @@ import utils 1.0
|
|||
QtObject {
|
||||
property int type: Constants.TokenType.ERC20
|
||||
|
||||
// Special token (Owner and TMaster tokens):
|
||||
property bool isPrivilegedToken: false
|
||||
property bool isOwner: false
|
||||
property color color
|
||||
|
||||
// Unique identifier:
|
||||
property string key
|
||||
|
||||
|
@ -19,7 +24,7 @@ QtObject {
|
|||
property string description
|
||||
property bool infiniteSupply: true
|
||||
property int supply: 1
|
||||
property int remainingTokens
|
||||
property int remainingTokens: supply
|
||||
|
||||
// Artwork related properties:
|
||||
property url artworkSource
|
||||
|
|
|
@ -50,6 +50,7 @@ StackView {
|
|||
|
||||
signal mintCollectible(var collectibleItem)
|
||||
signal mintAsset(var assetItem)
|
||||
signal mintOwnerToken(var ownerToken, var tMasterToken)
|
||||
|
||||
signal signMintTransactionOpened(int chainId, string accountAddress, int tokenType)
|
||||
|
||||
|
@ -138,11 +139,66 @@ StackView {
|
|||
title: qsTr("Mint Owner token")
|
||||
|
||||
contentItem: OwnerTokenWelcomeView {
|
||||
viewWidth: root.viewWidth
|
||||
communityLogo: root.communityLogo
|
||||
communityColor: root.communityColor
|
||||
communityName: root.communityName
|
||||
|
||||
onNextClicked: root.push(newTokenViewComponent, StackView.Immediate) // TEMP: It will navigate to new token owner flow. Now, to current minting flow.
|
||||
onNextClicked: root.push(ownerTokenEditViewComponent, StackView.Immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: ownerTokenEditViewComponent
|
||||
|
||||
SettingsPage {
|
||||
id: ownerTokenPage
|
||||
|
||||
title: qsTr("Mint Owner token")
|
||||
|
||||
contentItem: EditOwnerTokenView {
|
||||
id: editOwnerTokenView
|
||||
|
||||
function signMintTransaction() {
|
||||
root.mintOwnerToken(ownerToken, tMasterToken)
|
||||
root.resetNavigation()
|
||||
}
|
||||
|
||||
viewWidth: root.viewWidth
|
||||
communityLogo: root.communityLogo
|
||||
communityColor: root.communityColor
|
||||
communityName: root.communityName
|
||||
layer1Networks: root.layer1Networks
|
||||
layer2Networks: root.layer2Networks
|
||||
testNetworks: root.testNetworks
|
||||
enabledNetworks: root.testNetworks
|
||||
allNetworks: root.allNetworks
|
||||
accounts: root.accounts
|
||||
|
||||
onMintClicked: signMintPopup.open()
|
||||
|
||||
SignTokenTransactionsPopup {
|
||||
id: signMintPopup
|
||||
|
||||
anchors.centerIn: Overlay.overlay
|
||||
title: qsTr("Sign transaction - Mint %1 tokens").arg(signMintPopup.tokenName)
|
||||
tokenName: editOwnerTokenView.communityName
|
||||
accountName: editOwnerTokenView.ownerToken.accountName
|
||||
networkName: editOwnerTokenView.ownerToken.chainName
|
||||
feeText: root.feeText
|
||||
errorText: root.errorText
|
||||
isFeeLoading: root.isFeeLoading
|
||||
|
||||
onOpened: {
|
||||
root.setFeeLoading()
|
||||
root.signMintTransactionOpened(editOwnerTokenView.ownerToken.chainId,
|
||||
editOwnerTokenView.ownerToken.accountAddress,
|
||||
Constants.TokenType.ERC721)
|
||||
}
|
||||
onCancelClicked: close()
|
||||
onSignTransactionClicked: editOwnerTokenView.signMintTransaction()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import utils 1.0
|
|||
Control {
|
||||
id: root
|
||||
|
||||
required property bool isOwner
|
||||
// https://bugreports.qt.io/browse/QTBUG-84269
|
||||
/*required*/ property bool isOwner
|
||||
|
||||
property bool showTag: false
|
||||
property int size: PrivilegedTokenArtworkPanel.Size.Small
|
||||
|
|
|
@ -0,0 +1,272 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Layouts 1.15
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
||||
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
import utils 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
Control {
|
||||
id: root
|
||||
|
||||
// Panel properties:
|
||||
property bool preview: false
|
||||
|
||||
// Token object properties:
|
||||
/* required */ property TokenObject token // https://bugreports.qt.io/browse/QTBUG-84269
|
||||
readonly property bool isAssetPanel: token.type === Constants.TokenType.ERC20
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int imageSelectorRectSize: root.isAssetPanel ? 104 : 280
|
||||
readonly property string infiniteSymbol: "∞"
|
||||
readonly property int burnState: token.burnState
|
||||
|
||||
function startAnimation(isBurn) {
|
||||
totalbox.highlighted = true
|
||||
|
||||
if(isBurn)
|
||||
remainingBox.highlighted = true
|
||||
}
|
||||
|
||||
onBurnStateChanged: if(burnState === Constants.ContractTransactionStatus.Completed) d.startAnimation(true)
|
||||
}
|
||||
|
||||
implicitWidth: 560 // by design
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
id: mainLayout
|
||||
|
||||
spacing: Style.current.padding
|
||||
|
||||
// General artwork representation:
|
||||
Rectangle {
|
||||
visible: !token.isPrivilegedToken
|
||||
Layout.preferredHeight: d.imageSelectorRectSize
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
|
||||
radius: root.isAssetPanel ? Layout.preferredWidth / 2 : 8
|
||||
color:Theme.palette.baseColor2
|
||||
|
||||
Image {
|
||||
id: image
|
||||
|
||||
readonly property rect imageCropRect: token.artworkCropRect
|
||||
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectFit
|
||||
visible: false
|
||||
source: token.artworkSource
|
||||
sourceClipRect: imageCropRect ? imageCropRect : undefined
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
anchors.fill: image
|
||||
source: image
|
||||
maskSource: parent
|
||||
}
|
||||
}
|
||||
|
||||
// Special artwork representation for `Owner and Master Token` tokens:
|
||||
PrivilegedTokenArtworkPanel {
|
||||
visible: token.isPrivilegedToken
|
||||
size: PrivilegedTokenArtworkPanel.Size.Large
|
||||
artwork: token.artworkSource
|
||||
color: token.color
|
||||
isOwner: token.isOwner
|
||||
}
|
||||
|
||||
Flow {
|
||||
spacing: Style.current.halfPadding
|
||||
Layout.fillWidth: true
|
||||
|
||||
component CustomPreviewBox: Rectangle {
|
||||
id: previewBox
|
||||
|
||||
property string label
|
||||
property string value
|
||||
property bool isLoading: false
|
||||
property bool highlighted: false
|
||||
|
||||
radius: 8
|
||||
border.color: Theme.palette.baseColor2
|
||||
implicitWidth: Math.min(boxContent.implicitWidth + Style.current.padding, mainLayout.width)
|
||||
implicitHeight: boxContent.implicitHeight + Style.current.padding
|
||||
states: [
|
||||
State {
|
||||
when: !previewBox.highlighted
|
||||
PropertyChanges { target: previewBox; color: "transparent" }
|
||||
},
|
||||
State {
|
||||
when: previewBox.highlighted
|
||||
PropertyChanges { target: previewBox; color: Theme.palette.primaryColor3 }
|
||||
}
|
||||
]
|
||||
|
||||
onHighlightedChanged: if(highlighted) animation.start()
|
||||
|
||||
ColumnLayout {
|
||||
id: boxContent
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
text: previewBox.label
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: Style.current.additionalTextSize
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 3
|
||||
|
||||
StatusBaseText {
|
||||
text: StatusQUtils.Emoji.fromCodePoint("1f525") // :fire: emoji
|
||||
font.pixelSize: Style.current.tertiaryTextFontSize
|
||||
visible: previewBox.isLoading
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: mainLayout.width - Style.current.padding
|
||||
text: previewBox.value
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusLoadingIndicator {
|
||||
Layout.preferredHeight: Theme.primaryTextFontSize
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.leftMargin: 6
|
||||
Layout.rightMargin: 3
|
||||
visible: previewBox.isLoading
|
||||
color: Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: animation
|
||||
|
||||
interval: 1500
|
||||
onRunningChanged: if(!running) previewBox.highlighted = false
|
||||
}
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: symbolBox
|
||||
|
||||
label: qsTr("Symbol")
|
||||
value: token.symbol
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: totalbox
|
||||
|
||||
label: qsTr("Total")
|
||||
value: token.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(token.supply)
|
||||
isLoading: !token.infiniteSupply &&
|
||||
((!root.isAssetPanel && token.remotelyDestructState === Constants.ContractTransactionStatus.InProgress) ||
|
||||
(d.burnState === Constants.ContractTransactionStatus.InProgress))
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: remainingBox
|
||||
|
||||
readonly property int remainingTokens: root.preview ? token.supply : token.remainingTokens
|
||||
|
||||
label: qsTr("Remaining")
|
||||
value: token.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(remainingTokens)
|
||||
isLoading: !token.infiniteSupply && (d.burnState === Constants.ContractTransactionStatus.InProgress)
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: root.isAssetPanel
|
||||
label: qsTr("DP")
|
||||
value: token.decimals
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: !root.isAssetPanel
|
||||
label: qsTr("Transferable")
|
||||
value: token.transferable ? qsTr("Yes") : qsTr("No")
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: !root.isAssetPanel
|
||||
|
||||
label: qsTr("Destructible")
|
||||
value: token.remotelyDestruct ? qsTr("Yes") : qsTr("No")
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: !token.isPrivilegedToken
|
||||
|
||||
label: qsTr("Account")
|
||||
value: token.accountName
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: !token.isPrivilegedToken
|
||||
height: symbolBox.height
|
||||
width: rowChain.implicitWidth + 2 * Style.current.padding
|
||||
border.width: 1
|
||||
radius: 8
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
|
||||
RowLayout {
|
||||
id: rowChain
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.current.padding
|
||||
|
||||
SVGImage {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
height: 24
|
||||
width: height
|
||||
source: token.chainIcon ? Style.svg(token.chainIcon) : undefined
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
text: token.chainName
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: token.description
|
||||
wrapMode: TextEdit.WordWrap
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
lineHeight: 1.2
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: token
|
||||
|
||||
function onRemotelyDestructStateChanged() {
|
||||
if(token.remotelyDestructState === Constants.ContractTransactionStatus.Completed) d.startAnimation(false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ SortableTokenHoldersPanel 1.0 SortableTokenHoldersPanel.qml
|
|||
TagsPanel 1.0 TagsPanel.qml
|
||||
TokenHoldersPanel 1.0 TokenHoldersPanel.qml
|
||||
TokenHoldersProxyModel 1.0 TokenHoldersProxyModel.qml
|
||||
TokenInfoPanel 1.0 TokenInfoPanel.qml
|
||||
WarningPanel 1.0 WarningPanel.qml
|
||||
WelcomeBannerPanel 1.0 WelcomeBannerPanel.qml
|
||||
EditSettingsPanel 1.0 EditSettingsPanel.qml
|
||||
|
|
|
@ -326,6 +326,10 @@ StatusSectionLayout {
|
|||
onMintAsset:
|
||||
communityTokensStore.deployAsset(root.community.id, assetItem)
|
||||
|
||||
onMintOwnerToken:
|
||||
communityTokensStore.deployOwnerToken(
|
||||
root.community.id, ownerToken, tMasterToken)
|
||||
|
||||
onSignRemoteDestructTransactionOpened:
|
||||
communityTokensStore.computeSelfDestructFee(
|
||||
remotelyDestructTokensList, tokenKey)
|
||||
|
|
|
@ -60,19 +60,7 @@ StatusScrollView {
|
|||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int imageSelectorRectSize: root.isAssetView ? 104 : 280
|
||||
readonly property int iconSize: 20
|
||||
readonly property string infiniteSymbol: "∞"
|
||||
readonly property int burnState: root.token.burnState
|
||||
|
||||
function startAnimation(isBurn) {
|
||||
totalbox.highlighted = true
|
||||
|
||||
if(isBurn)
|
||||
remainingBox.highlighted = true
|
||||
}
|
||||
|
||||
onBurnStateChanged: if(burnState === Constants.ContractTransactionStatus.Completed) d.startAnimation(true)
|
||||
}
|
||||
|
||||
padding: 0
|
||||
|
@ -109,202 +97,10 @@ StatusScrollView {
|
|||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.preferredHeight: d.imageSelectorRectSize
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
|
||||
radius: root.isAssetView ? Layout.preferredWidth / 2 : 8
|
||||
color:Theme.palette.baseColor2
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
id: image
|
||||
|
||||
readonly property rect imageCropRect: root.artworkCropRect
|
||||
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectFit
|
||||
visible: false
|
||||
source: root.artworkSource
|
||||
sourceClipRect: imageCropRect ? imageCropRect : undefined
|
||||
}
|
||||
|
||||
OpacityMask {
|
||||
anchors.fill: image
|
||||
source: image
|
||||
maskSource: parent
|
||||
}
|
||||
}
|
||||
|
||||
Flow {
|
||||
spacing: Style.current.halfPadding
|
||||
TokenInfoPanel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
component CustomPreviewBox: Rectangle {
|
||||
id: previewBox
|
||||
|
||||
property string label
|
||||
property string value
|
||||
property bool isLoading: false
|
||||
property bool highlighted: false
|
||||
|
||||
radius: 8
|
||||
border.color: Theme.palette.baseColor2
|
||||
implicitWidth: Math.min(boxContent.implicitWidth + Style.current.padding, mainLayout.width)
|
||||
implicitHeight: boxContent.implicitHeight + Style.current.padding
|
||||
states: [
|
||||
State {
|
||||
when: !previewBox.highlighted
|
||||
PropertyChanges { target: previewBox; color: "transparent" }
|
||||
},
|
||||
State {
|
||||
when: previewBox.highlighted
|
||||
PropertyChanges { target: previewBox; color: Theme.palette.primaryColor3 }
|
||||
}
|
||||
]
|
||||
|
||||
onHighlightedChanged: if(highlighted) animation.start()
|
||||
|
||||
ColumnLayout {
|
||||
id: boxContent
|
||||
anchors.centerIn: parent
|
||||
spacing: 2
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
text: previewBox.label
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
spacing: 3
|
||||
|
||||
StatusBaseText {
|
||||
text: StatusQUtils.Emoji.fromCodePoint("1f525") // :fire: emoji
|
||||
font.pixelSize: Theme.tertiaryTextFontSize
|
||||
visible: previewBox.isLoading
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: mainLayout.width - Style.current.padding
|
||||
text: previewBox.value
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusLoadingIndicator {
|
||||
Layout.preferredHeight: Theme.primaryTextFontSize
|
||||
Layout.preferredWidth: Layout.preferredHeight
|
||||
Layout.leftMargin: 6
|
||||
Layout.rightMargin: 3
|
||||
visible: previewBox.isLoading
|
||||
color: Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: animation
|
||||
|
||||
interval: 1500
|
||||
onRunningChanged: if(!running) previewBox.highlighted = false
|
||||
}
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: symbolBox
|
||||
|
||||
label: qsTr("Symbol")
|
||||
value: root.symbol
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: totalbox
|
||||
|
||||
label: qsTr("Total")
|
||||
value: root.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(root.supply)
|
||||
isLoading: !root.infiniteSupply &&
|
||||
((!root.isAssetView && root.remotelyDestructState === Constants.ContractTransactionStatus.InProgress) ||
|
||||
(d.burnState === Constants.ContractTransactionStatus.InProgress))
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
id: remainingBox
|
||||
|
||||
label: qsTr("Remaining")
|
||||
value: root.infiniteSupply ? d.infiniteSymbol : LocaleUtils.numberToLocaleString(root.remainingTokens)
|
||||
isLoading: !root.infiniteSupply && (d.burnState === Constants.ContractTransactionStatus.InProgress)
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: root.isAssetView
|
||||
label: qsTr("DP")
|
||||
value: root.decimals
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: !root.isAssetView
|
||||
label: qsTr("Transferable")
|
||||
value: root.transferable ? qsTr("Yes") : qsTr("No")
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
visible: !root.isAssetView
|
||||
|
||||
label: qsTr("Destructible")
|
||||
value: root.remotelyDestruct ? qsTr("Yes") : qsTr("No")
|
||||
}
|
||||
|
||||
CustomPreviewBox {
|
||||
label: qsTr("Account")
|
||||
value: root.accountName
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: symbolBox.height
|
||||
width: rowChain.implicitWidth + 2 * Style.current.padding
|
||||
border.width: 1
|
||||
radius: 8
|
||||
border.color: Theme.palette.baseColor2
|
||||
color: "transparent"
|
||||
|
||||
RowLayout {
|
||||
id: rowChain
|
||||
|
||||
anchors.centerIn: parent
|
||||
spacing: Style.current.padding
|
||||
|
||||
SVGImage {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
height: 24
|
||||
width: height
|
||||
source: Style.svg(root.chainIcon)
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
|
||||
text: root.chainName
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: root.description
|
||||
wrapMode: TextEdit.WordWrap
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
lineHeight: 1.2
|
||||
token: root.token
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
|
@ -324,7 +120,7 @@ StatusScrollView {
|
|||
wrapMode: Text.Wrap
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
color: Theme.palette.baseColor1
|
||||
text: qsTr("Make sure you’re happy with your token before minting it as it can’t be edited later")
|
||||
text: qsTr("Review token details before minting it as they can’t be edited later")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,12 +150,4 @@ StatusScrollView {
|
|||
onRemoteDestructRequested: root.remoteDestructRequested(address)
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: root.token
|
||||
|
||||
function onRemotelyDestructStateChanged() {
|
||||
if(root.remotelyDestructState === Constants.ContractTransactionStatus.Completed) d.startAnimation(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
import QtQuick 2.15
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Utils 0.1 as SQUtils
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import AppLayouts.Communities.panels 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
import AppLayouts.Wallet.controls 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
StatusScrollView {
|
||||
id: root
|
||||
|
||||
property int viewWidth: 560 // by design
|
||||
|
||||
// Community info:
|
||||
property string communityName
|
||||
property url communityLogo
|
||||
property color communityColor
|
||||
|
||||
// Network related properties:
|
||||
property var layer1Networks
|
||||
property var layer2Networks
|
||||
property var testNetworks
|
||||
property var enabledNetworks
|
||||
property var allNetworks
|
||||
|
||||
// Wallet account expected roles: address, name, color, emoji, walletType
|
||||
property var accounts
|
||||
|
||||
// Privileged tokens:
|
||||
readonly property TokenObject ownerToken: TokenObject {
|
||||
type: Constants.TokenType.ERC721
|
||||
isPrivilegedToken: true
|
||||
isOwner: true
|
||||
artworkSource: root.communityLogo
|
||||
color: root.communityColor
|
||||
symbol: PermissionsHelpers.autogenerateSymbol(isOwner, root.communityName)
|
||||
transferable: true
|
||||
remotelyDestruct: false
|
||||
supply: 1
|
||||
infiniteSupply: false
|
||||
description: qsTr("This is the %1 Owner token. The hodler of this collectible has ultimate control over %1 Community token administration.").arg(root.communityName)
|
||||
}
|
||||
readonly property TokenObject tMasterToken: TokenObject {
|
||||
type: Constants.TokenType.ERC721
|
||||
isPrivilegedToken: true
|
||||
artworkSource: root.communityLogo
|
||||
color: root.communityColor
|
||||
symbol: PermissionsHelpers.autogenerateSymbol(isOwner, root.communityName)
|
||||
remotelyDestruct: true
|
||||
description: qsTr("This is the %1 TokenMaster token. The hodler of this collectible has full admin rights for the %1 Community in Status and can mint and airdrop %1 Community tokens.").arg(root.communityName)
|
||||
}
|
||||
|
||||
signal mintClicked
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property int titleSize: 17
|
||||
readonly property int iconSize: 20
|
||||
}
|
||||
|
||||
padding: 0
|
||||
contentWidth: mainLayout.width
|
||||
contentHeight: mainLayout.height
|
||||
|
||||
Component.onCompleted: networkSelector.setChain(ownerToken.chainId)
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
|
||||
width: root.viewWidth
|
||||
spacing: Style.current.padding
|
||||
|
||||
// Owner token defintion:
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: root.viewWidth
|
||||
|
||||
elide: Text.ElideMiddle
|
||||
font.pixelSize: d.titleSize
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("Owner-%1").arg(root.communityName)
|
||||
}
|
||||
|
||||
TokenInfoPanel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
token: root.ownerToken
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
Layout.fillWidth: true
|
||||
|
||||
topPadding: Style.current.padding
|
||||
bottomPadding: Style.current.padding
|
||||
}
|
||||
|
||||
// TMaster token definition:
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: root.viewWidth
|
||||
|
||||
elide: Text.ElideMiddle
|
||||
font.pixelSize: d.titleSize
|
||||
font.bold: true
|
||||
|
||||
text: qsTr("TMaster-%1").arg(root.communityName)
|
||||
}
|
||||
|
||||
TokenInfoPanel {
|
||||
Layout.fillWidth: true
|
||||
|
||||
token: root.tMasterToken
|
||||
}
|
||||
|
||||
StatusModalDivider {
|
||||
Layout.fillWidth: true
|
||||
|
||||
topPadding: Style.current.padding
|
||||
bottomPadding: Style.current.padding
|
||||
}
|
||||
|
||||
// TO BE REMOVED: It will be removed with the new fees panel
|
||||
CustomLabelDescriptionComponent {
|
||||
|
||||
label: qsTr("Select account")
|
||||
description: qsTr("This account will be where you receive your Owner token and will also be the account that pays the token minting gas fees.")
|
||||
}
|
||||
|
||||
// TO BE REMOVED: It will be removed with the new fees panel
|
||||
StatusEmojiAndColorComboBox {
|
||||
id: accountBox
|
||||
|
||||
readonly property string address: SQUtils.ModelUtils.get(root.accounts, currentIndex, "address")
|
||||
readonly property string initAccountName: ownerToken.accountName
|
||||
readonly property int initIndex: SQUtils.ModelUtils.indexOf(root.accounts, "name", initAccountName)
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: -Style.current.halfPadding
|
||||
|
||||
currentIndex: (initIndex !== -1) ? initIndex : 0
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: root.accounts
|
||||
proxyRoles: [
|
||||
ExpressionRole {
|
||||
name: "color"
|
||||
|
||||
function getColor(colorId) {
|
||||
return Utils.getColorForId(colorId)
|
||||
}
|
||||
|
||||
// Direct call for singleton function is not handled properly by
|
||||
// SortFilterProxyModel that's why helper function is used instead.
|
||||
expression: { return getColor(model.colorId) }
|
||||
}
|
||||
]
|
||||
filters: ValueFilter {
|
||||
roleName: "walletType"
|
||||
value: Constants.watchWalletType
|
||||
inverted: true
|
||||
}
|
||||
}
|
||||
type: StatusComboBox.Type.Secondary
|
||||
size: StatusComboBox.Size.Small
|
||||
implicitHeight: 44
|
||||
defaultAssetName: "filled-account"
|
||||
|
||||
onAddressChanged: {
|
||||
ownerToken.accountAddress = address
|
||||
tMasterToken.accountAddress = address
|
||||
}
|
||||
control.onDisplayTextChanged: {
|
||||
ownerToken.accountName = control.displayText
|
||||
tMasterToken.accountName = control.displayText
|
||||
}
|
||||
}
|
||||
|
||||
CustomNetworkFilterRowComponent {
|
||||
id: networkSelector
|
||||
|
||||
label: qsTr("Select network")
|
||||
description: qsTr("The network on which these tokens will be minted.")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.halfPadding
|
||||
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: d.iconSize
|
||||
Layout.preferredHeight: d.iconSize
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
||||
color: Theme.palette.baseColor1
|
||||
icon: "info"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
color: Theme.palette.baseColor1
|
||||
lineHeight: 1.2
|
||||
text: qsTr("Make sure you’re happy with the blockchain network selected before minting these tokens as they can’t be moved to a different network later.")
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.preferredHeight: 44
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
Layout.bottomMargin: Style.current.padding
|
||||
text: qsTr("Mint")
|
||||
|
||||
onClicked: root.mintClicked()
|
||||
}
|
||||
}
|
||||
|
||||
component CustomLabelDescriptionComponent: ColumnLayout {
|
||||
id: labelDescComponent
|
||||
|
||||
property string label
|
||||
property string description
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
StatusBaseText {
|
||||
text: labelDescComponent.label
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
text: labelDescComponent.description
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: Theme.primaryTextFontSize
|
||||
lineHeight: 1.2
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
component CustomNetworkFilterRowComponent: ColumnLayout {
|
||||
id: networkComponent
|
||||
|
||||
property string label
|
||||
property string description
|
||||
|
||||
function setChain(chainId) { netFilter.setChain(chainId) }
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: Style.current.padding
|
||||
spacing: 8
|
||||
|
||||
CustomLabelDescriptionComponent {
|
||||
label: networkComponent.label
|
||||
description: networkComponent.description
|
||||
}
|
||||
|
||||
NetworkFilter {
|
||||
id: netFilter
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
allNetworks: root.allNetworks
|
||||
layer1Networks: root.layer1Networks
|
||||
layer2Networks: root.layer2Networks
|
||||
testNetworks: root.testNetworks
|
||||
enabledNetworks: root.enabledNetworks
|
||||
|
||||
multiSelection: false
|
||||
|
||||
onToggleNetwork: (network) =>
|
||||
{
|
||||
// Set Owner Token network properties:
|
||||
ownerToken.chainId = network.chainId
|
||||
ownerToken.chainName = network.chainName
|
||||
ownerToken.chainIcon = network.iconUrl
|
||||
|
||||
// Set TMaster Token network properties:
|
||||
tMasterToken.chainId = network.chainId
|
||||
tMasterToken.chainName = network.chainName
|
||||
tMasterToken.chainIcon = network.iconUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import StatusQ.Controls 0.1
|
|||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import AppLayouts.Communities.panels 1.0
|
||||
import AppLayouts.Communities.helpers 1.0
|
||||
|
||||
import utils 1.0
|
||||
|
||||
|
@ -24,19 +25,6 @@ StatusScrollView {
|
|||
contentWidth: mainLayout.width
|
||||
contentHeight: mainLayout.height
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
function generateSymbol(isOwner) {
|
||||
// TODO: Add a kind of verification for not repeating symbols
|
||||
const shortName = root.communityName.substring(0, 3)
|
||||
if(isOwner)
|
||||
return "OWN" + shortName.toUpperCase()
|
||||
else
|
||||
return "TM" + shortName.toUpperCase()
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
|
||||
|
@ -146,7 +134,7 @@ StatusScrollView {
|
|||
|
||||
Layout.alignment: Qt.AlignBottom
|
||||
|
||||
text: d.generateSymbol(panel.isOwner)
|
||||
text: PermissionsHelpers.autogenerateSymbol(panel.isOwner, root.communityName)
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ CommunityTokenView 1.0 CommunityTokenView.qml
|
|||
EditAirdropView 1.0 EditAirdropView.qml
|
||||
EditPermissionView 1.0 EditPermissionView.qml
|
||||
EditCommunityTokenView 1.0 EditCommunityTokenView.qml
|
||||
EditOwnerTokenView 1.0 EditOwnerTokenView.qml
|
||||
HoldingsSelectionModel 1.0 HoldingsSelectionModel.qml
|
||||
JoinCommunityView 1.0 JoinCommunityView.qml
|
||||
MintedTokensView 1.0 MintedTokensView.qml
|
||||
|
|
|
@ -45,6 +45,13 @@ QtObject {
|
|||
assetItem.infiniteSupply, assetItem.decimals, assetItem.chainId, jsonArtworkFile)
|
||||
}
|
||||
|
||||
function deployOwnerToken(communityId, ownerToken, tMasterToken)
|
||||
{
|
||||
// NOTE for backend team: `ownerToken` and `tMasterToken` can be used to do an assertion before the deployment process starts, since
|
||||
// the objects have been created to display the token details to the user and must be the same than backend builds.
|
||||
console.log("TODO: Backend Owner and Token Master token deployment!")
|
||||
}
|
||||
|
||||
function deleteToken(communityId, contractUniqueKey) {
|
||||
console.log("TODO: Delete token bakend!")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue