refactor(Communities): use `StatusModal` in `CreateCommunityPopup`

This replaces the modal popup with `StatusModal` in the `CreateCommunityPopup`
and also ensures that it adheres to the design.

There are still things to be refactored in here, primarily form control components.
Those will be tackled in future commits once they have been built in StatusQ

Closes #2882
This commit is contained in:
Pascal Precht 2021-07-16 12:11:03 +02:00 committed by Iuri Matias
parent 9795890544
commit 9eb752885d
3 changed files with 301 additions and 298 deletions

View File

@ -4,9 +4,14 @@ import QtGraphicalEffects 1.13
import QtQuick.Dialogs 1.3 import QtQuick.Dialogs 1.3
import "../../../../imports" import "../../../../imports"
import "../../../../shared" import "../../../../shared"
import "../../../../shared/status"
ModalPopup { import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Popups 0.1
StatusModal {
property QtObject community: chatsModel.communities.activeCommunity property QtObject community: chatsModel.communities.activeCommunity
property bool isEdit: false property bool isEdit: false
@ -23,72 +28,81 @@ ModalPopup {
| Utils.Validate.TextHexColor | Utils.Validate.TextHexColor
id: popup id: popup
height: 600
onOpened: { onOpened: {
if (isEdit) { if (isEdit) {
nameInput.text = community.name; contentComponent.communityName.text = community.name;
descriptionTextArea.text = community.description; contentComponent.communityDescription.text = community.description;
colorPicker.defaultColor = community.communityColor; contentComponent.communityColor.color = community.communityColor;
contentComponent.communityColor.colorSelected = true
if (community.largeImage) { if (community.largeImage) {
addImageButton.selectedImage = community.largeImage contentComponent.communityImage.selectedImage = community.largeImage
} }
membershipRequirementSettingPopup.checkedMembership = community.access membershipRequirementSettingPopup.checkedMembership = community.access
} }
nameInput.forceActiveFocus(Qt.MouseFocusReason) contentComponent.communityName.forceActiveFocus(Qt.MouseFocusReason)
} }
onClosed: destroy() onClosed: destroy()
function isFormValid() { function isFormValid() {
return Utils.validateAndReturnError(nameInput.text, return Utils.validateAndReturnError(contentComponent.communityName.text,
communityNameValidator, communityNameValidator,
//% "community name" //% "community name"
qsTrId("community-name"), qsTrId("community-name"),
maxCommunityNameLength) === "" maxCommunityNameLength) === ""
&& Utils.validateAndReturnError(descriptionTextArea.text, && Utils.validateAndReturnError(contentComponent.communityDescription.text,
communityDescValidator, communityDescValidator,
//% "community decription" //% "community decription"
qsTrId("community-decription"), qsTrId("community-decription"),
maxCommunityDescLength) === "" maxCommunityDescLength) === ""
&& Utils.validateAndReturnError(colorPicker.text, && Utils.validateAndReturnError(contentComponent.communityColor.color.toString().toUpperCase(),
communityColorValidator) === "" communityColorValidator) === ""
} }
title: isEdit ? header.title: isEdit ?
//% "Edit community" //% "Edit community"
qsTrId("edit-community") : qsTrId("edit-community") :
//% "New community" //% "New community"
qsTrId("new-community") qsTrId("new-community")
ScrollView { content: ScrollView {
property ScrollBar vScrollBar: ScrollBar.vertical
id: scrollView id: scrollView
anchors.fill: parent
rightPadding: Style.current.padding property ScrollBar vScrollBar: ScrollBar.vertical
anchors.rightMargin: -Style.current.padding
anchors.topMargin: -Style.current.padding property alias communityName: nameInput
leftPadding: Style.current.padding property alias communityDescription: descriptionTextArea
topPadding: Style.current.padding property alias communityColor: colorDialog
anchors.leftMargin: -Style.current.padding property alias communityImage: addImageButton
property alias imageCropperModal: imageCropperModal
contentHeight: content.height contentHeight: content.height
bottomPadding: 8
height: Math.min(content.height, 432)
width: popup.width
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
clip: true clip: true
function scrollBackUp() { function scrollBackUp() {
vScrollBar.setPosition(0) vScrollBar.setPosition(0)
} }
Item { Column {
id: content id: content
height: childrenRect.height + 100 // Bottom padding width: popup.width
width: parent.width
Item {
width: parent.width
height: 76
Input { Input {
id: nameInput id: nameInput
//% "Name your community"
label: qsTrId("name-your-community") width: parent.width - 32
anchors.centerIn: parent
//% "A catchy name" //% "A catchy name"
placeholderText: qsTrId("name-your-community-placeholder") placeholderText: qsTrId("name-your-community-placeholder")
maxLength: maxCommunityNameLength maxLength: maxCommunityNameLength
@ -96,21 +110,26 @@ ModalPopup {
onTextEdited: { onTextEdited: {
validationError = Utils.validateAndReturnError(text, validationError = Utils.validateAndReturnError(text,
communityNameValidator, communityNameValidator,
//% "community name" qsTr("community name"),
qsTrId("community-name"),
maxCommunityNameLength) maxCommunityNameLength)
} }
} }
}
Item {
height: descriptionTextArea.height + 26
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 16
anchors.rightMargin: 16
StyledTextArea { StyledTextArea {
id: descriptionTextArea id: descriptionTextArea
//% "Give it a short description" label: qsTr("Description")
label: qsTrId("give-a-short-description-community")
//% "What your community is about" //% "What your community is about"
placeholderText: qsTrId("what-your-community-is-about") placeholderText: qsTrId("what-your-community-is-about")
anchors.top: nameInput.bottom
anchors.topMargin: Style.current.bigPadding
customHeight: 88 customHeight: 88
textField.wrapMode: TextEdit.Wrap textField.wrapMode: TextEdit.Wrap
@ -123,8 +142,7 @@ ModalPopup {
validationError = Utils.validateAndReturnError(text, validationError = Utils.validateAndReturnError(text,
communityDescValidator, communityDescValidator,
//% "community decription" qsTr("community decription"),
qsTrId("community-decription"),
maxCommunityDescLength) maxCommunityDescLength)
} }
} }
@ -132,24 +150,25 @@ ModalPopup {
StyledText { StyledText {
id: charLimit id: charLimit
text: `${descriptionTextArea.text.length}/${maxCommunityDescLength}` text: `${descriptionTextArea.text.length}/${maxCommunityDescLength}`
anchors.top: descriptionTextArea.bottom
anchors.topMargin: !descriptionTextArea.validationError ? 5 : - Style.current.smallPadding
anchors.right: descriptionTextArea.right anchors.right: descriptionTextArea.right
font.pixelSize: 12 font.pixelSize: 12
color: !descriptionTextArea.validationError ? Style.current.textColor : Style.current.danger color: !descriptionTextArea.validationError ? Style.current.textColor : Style.current.danger
} }
}
StyledText { StatusBaseText {
id: thumbnailText id: thumbnailText
//% "Thumbnail image" //% "Thumbnail image"
text: qsTrId("thumbnail-image") text: qsTrId("thumbnail-image")
anchors.top: charLimit.bottom
anchors.topMargin: Style.current.smallPadding
font.pixelSize: 13 font.pixelSize: 13
color: Style.current.textColor color: Theme.palette.directColor1
font.weight: Font.Medium anchors.left: parent.left
anchors.leftMargin: 16
} }
Item {
width: parent.width
height: addImageButton.height + 32
Rectangle { Rectangle {
id: addImageButton id: addImageButton
@ -157,12 +176,9 @@ ModalPopup {
width: 128 width: 128
height: width height: width
radius: width / 2 radius: width / 2
anchors.horizontalCenter: parent.horizontalCenter anchors.centerIn: parent
anchors.top: thumbnailText.bottom
anchors.topMargin: Style.current.padding
property string selectedImage: "" property string selectedImage: ""
FileDialog { FileDialog {
id: imageDialog id: imageDialog
//% "Please choose an image" //% "Please choose an image"
@ -210,8 +226,7 @@ ModalPopup {
visible: !imagePreview.visible visible: !imagePreview.visible
width: uploadText.width width: uploadText.width
height: childrenRect.height height: childrenRect.height
anchors.horizontalCenter: parent.horizontalCenter anchors.centerIn: parent
anchors.verticalCenter: parent.verticalCenter
SVGImage { SVGImage {
id: imageImg id: imageImg
@ -232,25 +247,18 @@ ModalPopup {
} }
} }
Rectangle { StatusRoundButton {
color: Style.current.primary type: StatusRoundButton.Type.Secondary
width: 40 icon.name: "add"
height: width
radius: width / 2
anchors.top: parent.top anchors.top: parent.top
anchors.right: parent.right anchors.right: parent.right
anchors.rightMargin: Style.current.halfPadding anchors.rightMargin: Style.current.halfPadding
highlighted: sensor.containsMouse
SVGImage {
source: "../../../img/plusSign.svg"
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
width: 13
height: 13
}
} }
MouseArea { MouseArea {
id: sensor
hoverEnabled: true
anchors.fill: parent anchors.fill: parent
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: imageDialog.open() onClicked: imageDialog.open()
@ -261,82 +269,72 @@ ModalPopup {
selectedImage: addImageButton.selectedImage selectedImage: addImageButton.selectedImage
ratio: "1:1" ratio: "1:1"
} }
} }
StyledText { }
id: imageValidation
visible: text && text !== "" StatusBaseText {
anchors.top: addImageButton.bottom text: qsTr("Community colour")
anchors.topMargin: Style.current.smallPadding font.pixelSize: 13
color: Theme.palette.directColor1
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.leftMargin: 16
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
color: Style.current.danger
} }
Input { Item {
property string defaultColor: Style.current.blue anchors.horizontalCenter: parent.horizontalCenter
height: colorSelectorButton.height + 16
width: parent.width - 32
id: colorPicker StatusPickerButton {
//% "Community color" id: colorSelectorButton
label: qsTrId("community-color") anchors.top: parent.top
//% "Pick a color" anchors.topMargin: 10
placeholderText: qsTrId("pick-a-color")
anchors.top: imageValidation.bottom
anchors.topMargin: Style.current.smallPadding
textField.text: defaultColor
textField.onReleased: colorDialog.open()
property string validationError: ""
bgColor: colorDialog.colorSelected ?
colorDialog.color : Theme.palette.baseColor2
contentColor: colorDialog.colorSelected ? Theme.palette.indirectColor1 : Theme.palette.baseColor1
text: colorDialog.colorSelected ?
colorDialog.color.toString().toUpperCase() :
qsTr("Pick a color")
onClicked: colorDialog.open();
onTextChanged: { onTextChanged: {
if (colorDialog.colorSelected) {
validationError = Utils.validateAndReturnError(text, communityColorValidator) validationError = Utils.validateAndReturnError(text, communityColorValidator)
} }
StatusIconButton {
icon.name: "caret"
iconRotation: -90
iconColor: Style.current.textColor
icon.width: 13
icon.height: 7
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
anchors.top: parent.top
anchors.topMargin: colorPicker.textField.height / 2 - height / 2 + Style.current.bigPadding
onClicked: colorDialog.open()
} }
ColorDialog { ColorDialog {
id: colorDialog id: colorDialog
//% "Please choose a color" property bool colorSelected: false
title: qsTrId("please-choose-a-color") color: Theme.palette.primaryColor1
color: colorPicker.defaultColor onAccepted: colorSelected = true
onAccepted: {
colorPicker.text = colorDialog.color
}
} }
} }
Separator { StatusBaseText {
id: separator1 text: colorSelectorButton.validationError
anchors.top: colorPicker.bottom visible: !!text
anchors.topMargin: isEdit ? 0 : Style.current.bigPadding color: Theme.palette.dangerColor1
anchors.left: parent.left anchors.top: colorSelectorButton.bottom
anchors.leftMargin: -Style.current.padding anchors.topMargin: 4
anchors.right: parent.right anchors.right: colorSelectorButton.right
anchors.rightMargin: -Style.current.padding }
}
StatusModalDivider {
topPadding: 8
bottomPadding: 8
visible: !isEdit visible: !isEdit
} }
StatusSettingsLineButton { StatusListItem {
id: membershipRequirementSetting anchors.horizontalCenter: parent.horizontalCenter
// TODO: remove 'isEnabled: false' when we no longer need to force visible: !isEdit
// "request access" membership title: qsTr("Membership requirement")
isEnabled: false label: {
anchors.top: separator1.bottom
anchors.topMargin: Style.current.halfPadding
//% "Membership requirement"
text: qsTrId("membership-title")
currentValue: {
switch (membershipRequirementSettingPopup.checkedMembership) { switch (membershipRequirementSettingPopup.checkedMembership) {
//% "Require invite from another member" //% "Require invite from another member"
case Constants.communityChatInvitationOnlyAccess: return qsTrId("membership-invite") case Constants.communityChatInvitationOnlyAccess: return qsTrId("membership-invite")
@ -346,23 +344,26 @@ ModalPopup {
default: return qsTrId("membership-free") default: return qsTrId("membership-free")
} }
} }
onClicked: { sensor.onClicked: membershipRequirementSettingPopup.open()
membershipRequirementSettingPopup.open() components: [
StatusIcon {
icon: "chevron-down"
rotation: 270
color: Theme.palette.baseColor1
} }
]
} }
StyledText { StatusBaseText {
visible: !isEdit visible: !isEdit
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
id: privateExplanation
anchors.top: membershipRequirementSetting.bottom
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
anchors.topMargin: isEdit ? 0 : Style.current.halfPadding
font.pixelSize: 13 font.pixelSize: 13
color: Style.current.secondaryText color: Theme.palette.baseColor1
width: parent.width * 0.78 width: parent.width * 0.78
//% "You can require new members to meet certain criteria before they can join. This can be changed at any time" text: qsTr("You can require new members to meet certain criteria before they can join. This can be changed at any time")
text: qsTrId("membership-none-placeholder") anchors.left: parent.left
anchors.leftMargin: 16
} }
// Feature commented temporarily // Feature commented temporarily
@ -410,23 +411,11 @@ ModalPopup {
*/ */
} }
MembershipRequirementPopup {
id: membershipRequirementSettingPopup
// TODO: remove the 'checkedMemership' setting when we no longer need
// to force "require approval" membership
checkedMembership: Constants.communityChatOnRequestAccess
}
} }
footer: Item { leftButtons: [
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: btnCreateEdit.height
StatusRoundButton { StatusRoundButton {
id: btnBack id: btnBack
anchors.left: parent.left
visible: isEdit visible: isEdit
icon.name: "arrow-right" icon.name: "arrow-right"
icon.width: 20 icon.width: 20
@ -434,6 +423,9 @@ ModalPopup {
rotation: 180 rotation: 180
onClicked: popup.destroy() onClicked: popup.destroy()
} }
]
rightButtons: [
StatusButton { StatusButton {
id: btnCreateEdit id: btnCreateEdit
enabled: isFormValid() enabled: isFormValid()
@ -442,38 +434,42 @@ ModalPopup {
qsTrId("Save") : qsTrId("Save") :
//% "Create" //% "Create"
qsTrId("create") qsTrId("create")
anchors.right: parent.right
onClicked: { onClicked: {
if (!isFormValid()) { if (!isFormValid()) {
scrollView.scrollBackUp() popup.contentComponent.scrollBackUp()
return return
} }
let error = false; let error = false;
if(isEdit) { if(isEdit) {
error = chatsModel.communities.editCommunity(community.id, error = chatsModel.communities.editCommunity(
Utils.filterXSS(nameInput.text), community.id,
Utils.filterXSS(descriptionTextArea.text), Utils.filterXSS(popup.contentComponent.communityName.text),
Utils.filterXSS(popup.contentComponent.communityDescription.text),
membershipRequirementSettingPopup.checkedMembership, membershipRequirementSettingPopup.checkedMembership,
false, false,
colorPicker.text, popup.contentComponent.communityColor.color.toString().toUpperCase(),
// to retain the existing image, pass "" for the image path // to retain the existing image, pass "" for the image path
addImageButton.selectedImage === community.largeImage ? "" : addImageButton.selectedImage, popup.contentComponent.communityImage.selectedImage === community.largeImage ? "" :
imageCropperModal.aX, popup.contentComponent.communityImage.selectedImage,
imageCropperModal.aY, popup.contentComponent.imageCropperModal.aX,
imageCropperModal.bX, popup.contentComponent.imageCropperModal.aY,
imageCropperModal.bY) popup.contentComponent.imageCropperModal.bX,
popup.contentComponent.imageCropperModal.bY
)
} else { } else {
error = chatsModel.communities.createCommunity(Utils.filterXSS(nameInput.text), error = chatsModel.communities.createCommunity(
Utils.filterXSS(descriptionTextArea.text), Utils.filterXSS(popup.contentComponent.communityName.text),
Utils.filterXSS(popup.contentComponent.communityDescription.text),
membershipRequirementSettingPopup.checkedMembership, membershipRequirementSettingPopup.checkedMembership,
false, // ensOnlySwitch.switchChecked, // TODO: false, // ensOnlySwitch.switchChecked, // TODO:
colorPicker.text, popup.contentComponent.communityColor.color.toString().toUpperCase(),
addImageButton.selectedImage, popup.contentComponent.communityImage.selectedImage,
imageCropperModal.aX, popup.contentComponent.imageCropperModal.aX,
imageCropperModal.aY, popup.contentComponent.imageCropperModal.aY,
imageCropperModal.bX, popup.contentComponent.imageCropperModal.bX,
imageCropperModal.bY) popup.contentComponent.imageCropperModal.bY
)
} }
if (error) { if (error) {
@ -483,6 +479,8 @@ ModalPopup {
popup.close() popup.close()
} }
}
]
MessageDialog { MessageDialog {
id: creatingError id: creatingError
@ -491,7 +489,12 @@ ModalPopup {
icon: StandardIcon.Critical icon: StandardIcon.Critical
standardButtons: StandardButton.Ok standardButtons: StandardButton.Ok
} }
}
MembershipRequirementPopup {
id: membershipRequirementSettingPopup
// TODO: remove the 'checkedMemership' setting when we no longer need
// to force "require approval" membership
checkedMembership: Constants.communityChatOnRequestAccess
} }
} }

View File

@ -210,6 +210,7 @@ Item {
Component { Component {
id: createCommunitiesPopupComponent id: createCommunitiesPopupComponent
CreateCommunityPopup { CreateCommunityPopup {
anchors.centerIn: parent
onClosed: { onClosed: {
destroy() destroy()
} }

View File

@ -174,9 +174,8 @@ StatusAppLayout {
} }
StatusMenuItem { StatusMenuItem {
enabled: false//chatsModel.communities.observedCommunity.admin enabled: chatsModel.communities.observedCommunity.admin
//% "Edit Community" text: qsTr("Edit Community")
text: qsTrId("edit-community")
icon.name: "edit" icon.name: "edit"
onTriggered: openPopup(editCommunityPopup, {community: chatsModel.communities.observedCommunity}) onTriggered: openPopup(editCommunityPopup, {community: chatsModel.communities.observedCommunity})
} }