feat: Implement Community Overview footer with mocked data

1. Adding OverviewSettingsFooter.qml according to design
2. Adding the footer to storybook
3. Add the footer in the overview page
4. Remove the squish tests for the old footer
This commit is contained in:
Alex Jbanca 2023-07-06 11:02:41 +03:00 committed by Alex Jbanca
parent ce06fc3a99
commit 3b57915155
15 changed files with 246 additions and 105 deletions

View File

@ -181,6 +181,10 @@ ListModel {
title: "EditSettingsPanel"
section: "Panels"
}
ListElement {
title: "OverviewSettingsFooter"
section: "Panels"
}
ListElement {
title: "BurnTokensPopup"
section: "Popups"

View File

@ -227,5 +227,8 @@
],
"EditSettingsPanel": [
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?node-id=3132%3A383870&mode=dev"
],
"OverviewSettingsFooter": [
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba⎜Desktop?type=design&node-id=31171-629792&mode=design&t=IAlt2Frp5gx0yPAn-0"
]
}

View File

@ -0,0 +1,58 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import AppLayouts.Communities.panels 1.0
import utils 1.0
SplitView {
id: root
Item {
id: wrapper
SplitView.fillWidth: true
SplitView.fillHeight: true
OverviewSettingsFooter {
id: footer
width: parent.width
anchors.centerIn: parent
isControlNode: controlNodeSwitch.checked
communityName: "Socks"
}
}
Pane {
SplitView.preferredWidth: 300
SplitView.fillHeight: true
ColumnLayout {
Switch {
id: controlNodeSwitch
text: "Control node on/off"
checked: true
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: "Login type::"
}
RadioButton {
checked: true
text: qsTr("Password")
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Password
}
RadioButton {
text: qsTr("Biometrics")
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Biometrics
}
RadioButton {
text: qsTr("Keycard")
onCheckedChanged: if(checked) footer.loginType = Constants.LoginType.Keycard
}
}
}
}
}

View File

@ -111,14 +111,7 @@ class CreateOrEditCommunityCategoryPopup(Enum):
COMMUNITY_CATEGORY_LIST: str = "createOrEditCommunityCategoryChannelList_ListView"
COMMUNITY_CATEGORY_LIST_ITEM_PLACEHOLDER: str = "createOrEditCommunityCategoryChannelList_ListItem_Placeholder"
COMMUNITY_CATEGORY_BUTTON: str = "createOrEditCommunityCategoryBtn_StatusButton"
MODAL_CLOSE_BUTTON = "modal_Close_Button"
class CommunityOverviewScreenComponents(Enum):
# Constants definitions:
COMMUNITY_PRIVATE_KEY_LENGHT_UI = 35 # length of community PK on the Transfer Ownership popup
# Components:
COMMUNITY_OVERVIEW_BACK_UP_BUTTON ="communityOverview_Back_up_StatusButton"
COMMUNITY_OVERVIEW_AIRDROP_TOKENS_BUTTON="communityOverview_Airdrop_Tokens_StatusButton"
MODAL_CLOSE_BUTTON = "modal_Close_Button"
class StatusCommunityScreen:
@ -575,18 +568,4 @@ class StatusCommunityScreen:
assert BaseElement(str(CommunityWelcomeScreenComponents.ADD_NEW_ITEM_BUTTON.value)).is_enabled
button_title = get_obj(CommunityWelcomeScreenComponents.ADD_NEW_ITEM_BUTTON.value).text
verify_equals(option, str(button_title))
def verify_community_private_key(self):
Button(CommunityOverviewScreenComponents.COMMUNITY_OVERVIEW_BACK_UP_BUTTON.value).click()
transferOwnershipPopup = BackUpCommunityPrivateKeyPopup().wait_until_appears()
transferOwnershipPopup.copy_community_private_key()
community_private_key = transferOwnershipPopup.private_key
assert len(community_private_key) == (CommunityOverviewScreenComponents.COMMUNITY_PRIVATE_KEY_LENGHT_UI.value), f"Current key length: {len(community_private_key)}"
assert community_private_key.startswith("0x"), f"Current private key does not start with 0x: {community_private_key}"
def open_airdrops_from_overview(self):
Button(CommunityOverviewScreenComponents.COMMUNITY_OVERVIEW_AIRDROP_TOKENS_BUTTON.value).click()
welcome_screen_title = get_obj(CommunityWelcomeScreenComponents.WELCOME_SCREEN_TITLE.value).text
ref_value = CommunityWelcomeScreenComponents.WELCOME_SCREEN_TITLE_OPTION_AIRDROPS.value
assert welcome_screen_title == ref_value, f"Current screen title: {welcome_screen_title}, expected: {ref_value}"

View File

@ -85,13 +85,6 @@ communitySettings_EditCommunity_ColorPicker_Button = {"container": communitySett
communitySettings_ColorPanel_HexColor_Input = {"container": statusDesktop_mainWindow_overlay, "objectName": "communityColorPanelHexInput", "type": "TextEdit", "visible": True}
communitySettings_SaveColor_Button = {"container": statusDesktop_mainWindow_overlay, "objectName": "communityColorPanelSelectColorButton", "type": "StatusButton", "visible": True}
# Community Overview
communityOverview_Back_up_Banner = {"container": statusDesktop_mainWindow, "objectName": "backUpBanner", "type": "BannerPanel", "visible": True}
communityOverview_Back_up_StatusButton = {"container": communityOverview_Back_up_Banner, "objectName": "communityBannerButton", "type": "StatusButton", "visible": True}
communityOverview_Airdrop_Tokens_Banner = {"container": statusDesktop_mainWindow, "objectName": "airdropBanner", "type": "BannerPanel", "visible": True}
communityOverview_Airdrop_Tokens_StatusButton = {"container": communityOverview_Airdrop_Tokens_Banner, "objectName": "communityBannerButton", "type": "StatusButton", "visible": True}
transferOwnerShipTextEdit = {"container": statusDesktop_mainWindow_overlay, "id": "edit", "type": "TextEdit", "unnamed": 1, "visible": True}
# Community transfer ownership
copyCommunityPrivateKeyButton = {"container": statusDesktop_mainWindow, "objectName": "copyCommunityPrivateKeyButton", "type": "StatusButton", "visible": True}

View File

@ -267,14 +267,6 @@ def step(context, option:str, list):
@Then("\"|any|\" button is present")
def step (context, action_button_name):
_statusCommunityScreen.verify_action_button_enabled(action_button_name)
@Then("the user is able to open Back up modal and copy private key")
def step(context):
_statusCommunityScreen.verify_community_private_key()
@Then("the user is able to click Airdrop Tokens button and navigate to Airdrops screen")
def step(context):
_statusCommunityScreen.open_airdrops_from_overview()
###########################################################################
### COMMON methods used in different steps given/when/then region:

View File

@ -4,33 +4,22 @@
Feature: Community -> Manage Community -> Overview page
Background:
Given A first time user lands on the status desktop and generates new key
And the user signs up with username "tester123" and password "TesTEr16843/!@00"
And the user lands on the signed in app
And the user opens the community portal section
And the user lands on the community portal section
And the user creates a community named "Test-Community", with description "My community description", intro "Community Intro" and outro "Community Outro"
And the user lands on the community named "Test-Community"
Background:
Given A first time user lands on the status desktop and generates new key
And the user signs up with username "tester123" and password "TesTEr16843/!@00"
And the user lands on the signed in app
And the user opens the community portal section
And the user lands on the community portal section
And the user creates a community named "Test-Community", with description "My community description", intro "Community Intro" and outro "Community Outro"
And the user lands on the community named "Test-Community"
Scenario: Community admin is able to back up community key from community overview page
When "Manage Community" is clicked in the community sidebar
And "Overview" section is selected
Then the user is able to open Back up modal and copy private key
Scenario: Community admin is able to navigate to Airdrops page from Overview screen
When "Manage Community" is clicked in the community sidebar
And "Overview" section is selected
Then the user is able to click Airdrop Tokens button and navigate to Airdrops screen
Scenario Outline: Manage community -> Overview: community admin edits the community name, description and color
When the admin renames the community to "<new_community_name>" and description to "<new_community_description>" and color to "<new_community_color>"
Then the community overview name is "<new_community_name>"
And the community overview description is "<new_community_description>"
And the community overview color is "<new_community_color>"
When the admin goes back to the community
Then the user lands on the community named "<new_community_name>"
Examples:
| new_community_name | new_community_description | new_community_color |
| myCommunityNamedChanged | Cool new description 123 | #ff0000 |
Scenario Outline: Manage community -> Overview: community admin edits the community name, description and color
When the admin renames the community to "<new_community_name>" and description to "<new_community_description>" and color to "<new_community_color>"
Then the community overview name is "<new_community_name>"
And the community overview description is "<new_community_description>"
And the community overview color is "<new_community_color>"
When the admin goes back to the community
Then the user lands on the community named "<new_community_name>"
Examples:
| new_community_name | new_community_description | new_community_color |
| myCommunityNamedChanged | Cool new description 123 | #ff0000 |

View File

@ -185,6 +185,7 @@
<file>assets/img/icons/ETH.png</file>
<file>assets/img/icons/exchange.svg</file>
<file>assets/img/icons/external.svg</file>
<file>assets/img/icons/external-link.svg</file>
<file>assets/img/icons/face-id.svg</file>
<file>assets/img/icons/face-sad.svg</file>
<file>assets/img/icons/favourite.svg</file>

View File

@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Action / External Link">
<path id="Icon" fill-rule="evenodd" clip-rule="evenodd" d="M12 5.75C12 6.16421 12.3358 6.5 12.75 6.5L15.0459 6.5C15.4914 6.5 15.7145 7.03857 15.3995 7.35355L10.2197 12.5334C9.92678 12.8263 9.92678 13.3011 10.2197 13.594C10.5126 13.8869 10.9874 13.8869 11.2803 13.594L16.4602 8.41421C16.7751 8.09923 17.3137 8.32231 17.3137 8.76777L17.3137 11.344C17.3137 11.7583 17.6495 12.094 18.0637 12.094C18.4779 12.094 18.8137 11.7583 18.8137 11.344L18.8137 5.75C18.8137 5.33579 18.4779 5 18.0637 5H12.75C12.3358 5 12 5.33579 12 5.75ZM10 6.75C10 7.16421 9.66421 7.5 9.25 7.5H9C7.61929 7.5 6.5 8.61929 6.5 10V15C6.5 16.3807 7.61929 17.5 9 17.5H14C15.3807 17.5 16.5 16.3807 16.5 15V14.75C16.5 14.3358 16.8358 14 17.25 14C17.6642 14 18 14.3358 18 14.75V15C18 17.2091 16.2091 19 14 19H9C6.79086 19 5 17.2091 5 15V10C5 7.79086 6.79086 6 9 6H9.25C9.66421 6 10 6.33579 10 6.75Z" fill="#4360DF"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1017 B

View File

@ -61,11 +61,6 @@ Control {
return root.joinCommunity ? (root.requiresRequest ? d.communityRevealAddressWithRequestText : d.communityRevealAddressText) : d.channelRevealAddressText
}
function getRevealAddressIcon() {
if(root.loginType == Constants.LoginType.Password) return "password"
return root.loginType == Constants.LoginType.Biometrics ? "touch-id" : "keycard"
}
function filterPermissions(model) {
return !!model && (model.tokenCriteriaMet || !model.isPrivate)
}
@ -153,7 +148,7 @@ Control {
Layout.alignment: Qt.AlignHCenter
visible: !root.showOnlyPanels && !root.isJoinRequestRejected && root.requiresRequest
text: root.isInvitationPending ? d.getInvitationPendingText() : d.getRevealAddressText()
icon.name: root.isInvitationPending ? "" : d.getRevealAddressIcon()
icon.name: root.isInvitationPending ? "" : Constants.authenticationIconByType[root.loginType]
font.pixelSize: 13
enabled: root.requirementsMet || d.communityPermissionsModel.count == 0
onClicked: root.isInvitationPending ? root.invitationPendingClicked() : root.revealAddressClicked()

View File

@ -0,0 +1,133 @@
import QtQuick 2.15
import QtQml 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0
Control {
id: root
property bool isControlNode: true
property int loginType: Constants.LoginType.Password
property string communityName: ""
signal primaryButtonClicked
signal secondaryButtonClicked
QtObject {
id: d
readonly property real verticalBreakPoint: 950
readonly property bool twoRowsLayout: contentItem.width <= verticalBreakPoint
property string paragraphTitle
property string paragraphSubtitle
property string primaryButtonText
property string primaryButtonIcon
property string secondaryButtonText
property string secondaryButtonIcon
property string indicatorBgColor
property string indicatorColor
}
contentItem: GridLayout {
id: mainGrid
columnSpacing: 16
rowSpacing: 16
StatusRoundIcon {
id: icon
Layout.row: 0
Layout.column: 0
color: d.indicatorBgColor
asset.color: d.indicatorColor
asset.name: "desktop"
}
ColumnLayout {
id: paragraph
Layout.row: 0
Layout.column: 1
Layout.columnSpan: d.twoRowsLayout ? 2 : 1
Layout.fillWidth: true
spacing: 4
StatusBaseText {
id: title
Layout.fillWidth: true
text: d.paragraphTitle
font.pixelSize: 15
font.bold: true
color: Theme.palette.directColor1
wrapMode: Text.WordWrap
}
StatusBaseText {
id: subtitle
Layout.fillWidth: true
text: d.paragraphSubtitle
font.pixelSize: 15
color: Theme.palette.baseColor1
wrapMode: Text.WordWrap
}
}
Item {
Layout.fillWidth: true
Layout.row: 0
Layout.column: 3
}
RowLayout {
Layout.row: d.twoRowsLayout ? 1 : 0
Layout.column: d.twoRowsLayout ? 1 : 4
Layout.alignment: Qt.AlignLeft
StatusFlatButton {
size: StatusBaseButton.Size.Small
text: d.secondaryButtonText
icon.name: d.secondaryButtonIcon
onClicked: root.secondaryButtonClicked()
}
StatusButton {
size: StatusBaseButton.Size.Small
text: d.primaryButtonText
icon.name: d.primaryButtonIcon
onClicked: root.primaryButtonClicked()
}
}
}
// Behavior
states: [
State {
name: "isControlNode"
when: root.isControlNode
PropertyChanges { target: d; indicatorBgColor: Theme.palette.successColor2 }
PropertyChanges { target: d; indicatorColor: Theme.palette.successColor1 }
PropertyChanges { target: d; paragraphTitle: qsTr("This device is currently the control node for the %1 Community").arg(root.communityName) }
PropertyChanges { target: d; paragraphSubtitle: qsTr("For your Community to function correctly keep this device online with Status running as much as possible.") }
PropertyChanges { target: d; primaryButtonText: qsTr("Move control node") }
PropertyChanges { target: d; primaryButtonIcon: Constants.authenticationIconByType[root.loginType] }
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
},
State {
name: "isNotControlNode"
when: !root.isControlNode
PropertyChanges { target: d; indicatorBgColor: Theme.palette.primaryColor3 }
PropertyChanges { target: d; indicatorColor: Theme.palette.primaryColor1 }
PropertyChanges { target: d; paragraphTitle: qsTr("Make this device the control node for the %1 Community").arg(root.communityName) }
PropertyChanges { target: d; paragraphSubtitle: qsTr("You will need to input the Community private key. Ensure this is a device you can keep online with Status running.") }
PropertyChanges { target: d; primaryButtonText: qsTr("Make this device the control node") }
PropertyChanges { target: d; primaryButtonIcon: "" }
PropertyChanges { target: d; secondaryButtonText: qsTr("Learn more") }
PropertyChanges { target: d; secondaryButtonIcon: "external-link" }
}
]
}

View File

@ -35,6 +35,7 @@ StackLayout {
property bool editable: false
property bool owned: false
property int loginType: Constants.LoginType.Password
function navigateBack() {
if (editSettingsPanelLoader.item.dirty)
@ -138,40 +139,19 @@ StackLayout {
Item {
Layout.fillHeight: true
}
}
RowLayout {
BannerPanel {
objectName: "invitePeopleBanner"
text: qsTr("Welcome to your community!")
buttonText: qsTr("Invite new people")
icon.name: "invite-users"
onButtonClicked: root.inviteNewPeopleClicked()
}
Item {
Layout.fillWidth: true
}
BannerPanel {
objectName: "airdropBanner"
visible: root.owned
text: qsTr("Try an airdrop to reward your community for engagement!")
buttonText: qsTr("Airdrop Tokens")
icon.name: "airdrop"
onButtonClicked: root.airdropTokensClicked()
}
Item {
Layout.fillWidth: true
}
BannerPanel {
objectName: "backUpBanner"
visible: root.owned
text: qsTr("Back up community key")
buttonText: qsTr("Back up")
icon.name: "objects"
onButtonClicked: root.backUpClicked()
}
}
footer: OverviewSettingsFooter {
rightPadding: 64
leftPadding: 64
bottomPadding: 50
loginType: root.loginType
communityName: root.name
//TODO connect to backend
isControlNode: root.owned
onPrimaryButtonClicked: isControlNode = !isControlNode
//TODO update once the domain changes
onSecondaryButtonClicked: Global.openLink(Constants.statusHelpLinkPrefix + "en/status-communities/about-the-control-node-in-status-communities")
}
}

View File

@ -14,6 +14,7 @@ JoinPermissionsOverlayPanel 1.0 JoinPermissionsOverlayPanel.qml
MembersSettingsPanel 1.0 MembersSettingsPanel.qml
MintTokensFooterPanel 1.0 MintTokensFooterPanel.qml
MintTokensSettingsPanel 1.0 MintTokensSettingsPanel.qml
OverviewSettingsFooter 1.0 OverviewSettingsFooter.qml
OverviewSettingsPanel 1.0 OverviewSettingsPanel.qml
PermissionConflictWarningPanel 1.0 PermissionConflictWarningPanel.qml
PermissionQualificationPanel 1.0 PermissionQualificationPanel.qml

View File

@ -169,6 +169,7 @@ StatusSectionLayout {
pinMessagesEnabled: root.community.pinMessageAllMembersEnabled
editable: true
owned: root.community.memberRole === Constants.memberRole.owner
loginType: root.rootStore.loginType
onEdited: {
const error = root.chatCommunitySectionModule.editCommunity(

View File

@ -848,6 +848,7 @@ QtObject {
readonly property string communityLinkPrefix: externalStatusLinkWithHttps + '/c/'
readonly property string userLinkPrefix: externalStatusLinkWithHttps + '/u/'
readonly property string statusLinkPrefix: 'https://status.im/'
readonly property string statusHelpLinkPrefix: `https://help.status.im/`
readonly property int maxUploadFiles: 5
readonly property double maxUploadFilesizeMB: 10
@ -914,6 +915,12 @@ QtObject {
Biometrics,
Keycard
}
// Needs to match the enum above
readonly property var authenticationIconByType: [
"password",
"touch-id",
"keycard",
]
enum ComputeFeeErrorCode {
Success,