feat(CommunityPermissions): Created `CommunityPermissionsView` layout

- Created `CommunityPermissionsView` and integrated into the flow.
- Created `PermissionItem` component.
- Added `holdingsListModel`, `permissionsObjectModel` and `channelsListModel` flows with mocked data.
- Added `isPrivate` permission property.
- Added button header in `SettingsPageLayout`
- Added signals/methods for edit/duplicate/remove permissions
- Created new file `OperatorsUtils.qml` specific for `Operators`
This commit is contained in:
Noelia 2022-11-25 18:35:30 +01:00 committed by Noelia
parent 5aeef81bad
commit 1cbb3e2ad3
19 changed files with 531 additions and 115 deletions

View File

@ -13,8 +13,6 @@ ColumnLayout {
iconSize: 24
title: "Item Selector Title"
defaultItemText: "Example: Empty items"
andOperatorText: "and"
orOperatorText: "or"
itemsModel: ListModel {
id: model
@ -39,7 +37,7 @@ ColumnLayout {
model.append({
text: input.text,
imageSource: "qrc:/images/SNT.png",
operator: model.count > 0 ? Utils.Operators.Or : Utils.Operators.None
operator: model.count > 0 ? OperatorsUtils.Operators.Or : OperatorsUtils.Operators.None
})
dropdown.close()

View File

@ -100,38 +100,12 @@ Rectangle {
an image or an icon.
*/
property bool useIcons: false
/*!
\qmlproperty string StatusItemSelector::andOperatorText
This property holds the string text representation for an `AND` logical operator.
*/
property string andOperatorText: qsTr("and")
/*!
\qmlproperty string StatusItemSelector::orOperatorText
This property holds the string text representation for an `OR` logical operator.
*/
property string orOperatorText: qsTr("or")
/*!
\qmlsignal StatusItemSelector::itemClicked
This signal is emitted when the item is clicked.
*/
signal itemClicked(var item, int index, var mouse)
QtObject {
id: d
function operatorTextFormat(operator) {
switch(operator) {
case Utils.Operators.And:
return root.andOperatorText
case Utils.Operators.Or:
return root.orOperatorText
case Utils.Operators.None:
return ""
}
}
}
color: Theme.palette.baseColor4
implicitHeight: columnLayout.implicitHeight + columnLayout.anchors.topMargin + columnLayout.anchors.bottomMargin
implicitWidth: 560
@ -190,9 +164,9 @@ Rectangle {
spacing: flow.spacing
StatusBaseText {
visible: model.operator !== Utils.Operators.None
visible: model.operator !== OperatorsUtils.Operators.None
Layout.alignment: Qt.AlignVCenter
text: d.operatorTextFormat(model.operator)
text: OperatorsUtils.setOperatorTextFormat(model.operator)
color: Theme.palette.primaryColor1
font.pixelSize: 17
MouseArea {
@ -200,10 +174,10 @@ Rectangle {
cursorShape: Qt.PointingHandCursor
onClicked: {
// Switch operator
if(model.operator === Utils.Operators.And)
model.operator = Utils.Operators.Or
if(model.operator === OperatorsUtils.Operators.And)
model.operator = OperatorsUtils.Operators.Or
else
model.operator = Utils.Operators.And
model.operator = OperatorsUtils.Operators.And
}
}
}

View File

@ -0,0 +1,36 @@
pragma Singleton
import QtQuick 2.13
QtObject {
id: root
/*!
\qmlproperty string OperatorsUtils::andOperatorText
This property holds the string text representation for an `AND` logical operator.
*/
readonly property string andOperatorText: qsTr("and")
/*!
\qmlproperty string OperatorsUtils::orOperatorText
This property holds the string text representation for an `OR` logical operator.
*/
readonly property string orOperatorText: qsTr("or")
// Logical operators
enum Operators {
None,
And,
Or
}
function setOperatorTextFormat(operator) {
switch(operator) {
case OperatorsUtils.Operators.And:
return root.andOperatorText
case OperatorsUtils.Operators.Or:
return root.orOperatorText
case OperatorsUtils.Operators.None:
return ""
}
}
}

View File

@ -5,13 +5,7 @@ import StatusQ.Core.Theme 0.1
import "./xss.js" as XSS
QtObject {
// Logical operators
enum Operators {
None,
And,
Or
}
id: root
function getAbsolutePosition(node) {
var returnPos = {};

View File

@ -5,3 +5,4 @@ XSS 1.0 xss.js
singleton Utils 0.1 Utils.qml
singleton Emoji 0.1 Emoji.qml
JSONListModel 0.1 JSONListModel.qml
singleton OperatorsUtils 0.1 OperatorsUtils.qml

View File

@ -193,5 +193,6 @@
<file>StatusQ/Core/StatusRollArea.qml</file>
<file>StatusQ/Popups/Dialog/StatusDialogBackground.qml</file>
<file>StatusQ/Popups/StatusMenuInstantiator.qml</file>
<file>StatusQ/Core/Utils/OperatorsUtils.qml</file>
</qresource>
</RCC>

View File

@ -5,7 +5,7 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Utils 0.1 as SQ
import StatusQ.Core.Utils 0.1
StatusDropdown {
@ -35,7 +35,7 @@ StatusDropdown {
function reset() {
d.currentHoldingType = HoldingTypes.Type.Token
d.operator = SQ.Utils.Operators.None
d.operator = OperatorsUtils.Operators.None
d.tokenAmountText = ""
d.collectibleAmountText = ""
@ -106,7 +106,7 @@ StatusDropdown {
property int currentHoldingType: HoldingTypes.Type.Token
property int operator: SQ.Utils.Operators.None
property int operator: OperatorsUtils.Operators.None
property bool ensDomainNameValid: false
signal addClicked
@ -304,7 +304,7 @@ StatusDropdown {
const modelItem = store.getTokenByKey(tokenKey)
if (modelItem) {
tokensPanel.tokenName = modelItem.name
tokensPanel.tokenName = modelItem.shortName
tokensPanel.tokenImage = modelItem.iconSource
} else {
tokensPanel.tokenName = d.defaultTokenNameText

View File

@ -3,7 +3,7 @@ import QtQuick 2.14
import StatusQ.Controls 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1 as SQ
import StatusQ.Core.Utils 0.1
import utils 1.0
@ -19,12 +19,12 @@ ColumnLayout {
{
icon: "add",
text: qsTr("And..."),
operator: SQ.Utils.Operators.And
operator: OperatorsUtils.Operators.And
},
{
icon: "condition-Or",
text: qsTr("Or..."),
operator: SQ.Utils.Operators.Or
operator: OperatorsUtils.Operators.Or
}
]

View File

@ -0,0 +1,245 @@
import QtQuick 2.3
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.14
import StatusQ.Core.Theme 0.1
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Utils 0.1
Control{
id: root
property var holdingsListModel
property string permissionName
property var permissionImageSource
property var channelsListModel
property bool isPrivate: false
signal editClicked
signal duplicateClicked
signal removeClicked
QtObject {
id: d
readonly property int flowRowHeight: 32
readonly property int commonMargin: 16
readonly property int designRadius: 16
readonly property int itemTextPixelSize: 17
readonly property int tagTextPixelSize: 15
readonly property int buttonTextPixelSize: 12
readonly property int buttonDiameter: 36
readonly property int buttonTextSpacing: 6
}
background: Rectangle {
color: "transparent"
border.color: Theme.palette.baseColor2
border.width: 1
radius: d.designRadius
}
contentItem: ColumnLayout {
spacing: 0
Rectangle {
id: header
color: Theme.palette.baseColor2
Layout.fillWidth: true
Layout.preferredHeight: 34
radius: d.designRadius
RowLayout {
anchors.fill: parent
spacing: 8
StatusIcon {
Layout.leftMargin: 19
icon: "checkmark"
Layout.preferredWidth: 11
Layout.preferredHeight: 8
color: Theme.palette.directColor1
}
StatusBaseText {
Layout.fillWidth: true
text: qsTr("Active")
font.pixelSize: d.tagTextPixelSize
}
StatusIcon {
Layout.rightMargin: 10
visible: root.isPrivate
icon: "hide"
color: Theme.palette.baseColor1
}
}
}
Flow {
id: content
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: 8
Layout.rightMargin: d.commonMargin
Layout.leftMargin: d.commonMargin
Layout.bottomMargin: 20
spacing: 6
StatusBaseText {
font.pixelSize: d.itemTextPixelSize
height: d.flowRowHeight
text: qsTr("Anyone who holds")
verticalAlignment: Text.AlignVCenter
}
Repeater {
model: root.holdingsListModel
RowLayout {
spacing: content.spacing
StatusBaseText {
Layout.preferredHeight: d.flowRowHeight
visible: model.operator !== OperatorsUtils.Operators.None
Layout.alignment: Qt.AlignVCenter
text: OperatorsUtils.setOperatorTextFormat(model.operator)
font.pixelSize: d.itemTextPixelSize
verticalAlignment: Text.AlignVCenter
}
StatusListItemTag {
Layout.preferredHeight: d.flowRowHeight
title: model.text
asset.name: model.imageSource
asset.isImage: true
asset.bgColor: "transparent"
asset.height: 28
asset.width: asset.height
color: Theme.palette.primaryColor3
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: d.tagTextPixelSize
}
}
}
StatusBaseText {
height: d.flowRowHeight
font.pixelSize: d.itemTextPixelSize
text: qsTr("is allowed to")
verticalAlignment: Text.AlignVCenter
}
StatusListItemTag {
height: d.flowRowHeight
title: root.permissionName
asset.name: root.permissionImageSource
asset.isImage: false
asset.bgColor: "transparent"
color: Theme.palette.primaryColor3
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: d.tagTextPixelSize
}
StatusBaseText {
height: d.flowRowHeight
font.pixelSize: d.itemTextPixelSize
text: qsTr("in")
verticalAlignment: Text.AlignVCenter
}
Repeater {
model: root.channelsListModel
RowLayout {
spacing: content.spacing
StatusBaseText {
Layout.preferredHeight: d.flowRowHeight
visible: model.index !== 0
Layout.alignment: Qt.AlignVCenter
text: qsTr("and")
font.pixelSize: d.itemTextPixelSize
verticalAlignment: Text.AlignVCenter
}
StatusListItemTag {
Layout.preferredHeight: d.flowRowHeight
title: model.text
asset.name: model.imageSource
asset.isImage: true
asset.bgColor: "transparent"
color: Theme.palette.primaryColor3
closeButtonVisible: false
titleText.color: Theme.palette.primaryColor1
titleText.font.pixelSize: d.tagTextPixelSize
}
}
}
}
RowLayout {
id: footer
spacing: 85
Layout.fillWidth: true
Layout.bottomMargin: d.commonMargin
Layout.alignment: Qt.AlignHCenter
ColumnLayout {
spacing: d.buttonTextSpacing
StatusRoundButton {
Layout.alignment: Qt.AlignHCenter
icon.name: "edit_pencil"
Layout.preferredHeight: d.buttonDiameter
Layout.preferredWidth: Layout.preferredHeight
type: StatusRoundButton.Type.Primary
onClicked: root.editClicked()
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Edit")
color: Theme.palette.primaryColor1
font.pixelSize: d.buttonTextPixelSize
}
}
ColumnLayout {
spacing: d.buttonTextSpacing
StatusRoundButton {
Layout.alignment: Qt.AlignHCenter
icon.name: "copy"
Layout.preferredHeight: d.buttonDiameter
Layout.preferredWidth: Layout.preferredHeight
type: StatusRoundButton.Type.Primary
onClicked: root.duplicateClicked()
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Duplicate")
color: Theme.palette.primaryColor1
font.pixelSize: d.buttonTextPixelSize
}
}
ColumnLayout {
spacing: d.buttonTextSpacing
StatusRoundButton {
Layout.alignment: Qt.AlignHCenter
icon.name: "delete"
Layout.preferredHeight: d.buttonDiameter
Layout.preferredWidth: Layout.preferredHeight
type: StatusRoundButton.Type.Quaternary
onClicked: root.removeClicked()
}
StatusBaseText {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Remove")
color: Theme.palette.dangerColor1
font.pixelSize: d.buttonTextPixelSize
}
}
}
}
}

View File

@ -0,0 +1,2 @@
HoldingTypes 1.0 HoldingTypes.qml
PermissionItem 1.0 PermissionItem.qml

View File

@ -19,6 +19,9 @@ Item {
// optional
property bool dirty: false
property bool editable: false
property bool headerButtonVisible: false
property string headerButtonText: ""
property int headerWidth: 0
readonly property Item contentItem: contentLoader.item
readonly property size settingsDirtyToastMessageImplicitSize:
@ -27,6 +30,7 @@ Item {
signal saveChangesClicked
signal resetChangesClicked
signal headerButtonClicked
function reloadContent() {
contentLoader.active = false
@ -46,17 +50,28 @@ Item {
anchors.fill: parent
spacing: 16
Item {
width: parent.width
RowLayout {
Layout.maximumWidth: root.headerWidth === 0 ? parent.width : (root.headerWidth + itemHeader.Layout.leftMargin)
Layout.preferredHeight: 56
Layout.leftMargin: 36
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
id: itemHeader
Layout.leftMargin: 64
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
text: root.title
color: Theme.palette.directColor1
font.pixelSize: 26
font.bold: true
}
StatusButton {
visible: root.headerButtonVisible
text: root.headerButtonText
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter
onClicked: root.headerButtonClicked()
}
}
Loader {
@ -64,7 +79,7 @@ Item {
Layout.fillWidth: true
Layout.fillHeight: true
Layout.topMargin: 16
Layout.leftMargin: 24
Layout.leftMargin: 64
Layout.rightMargin: 24
sourceComponent: root.content

View File

@ -0,0 +1 @@
SettingsPageLayout 1.0 SettingsPageLayout.qml

View File

@ -1,11 +1,15 @@
import QtQuick 2.14
import "../../layouts"
import "../../views/communities"
import AppLayouts.Chat.layouts 1.0
import AppLayouts.Chat.views.communities 1.0
import AppLayouts.Chat.stores 1.0
SettingsPageLayout {
id: root
property var store: CommunitiesStore {}
property int viewWidth: 560 // by design
property string previousPageName
function updateState() {
if (root.state === d.newPermissionViewState) {
@ -18,34 +22,69 @@ SettingsPageLayout {
readonly property string welcomeViewState: "WELCOME"
readonly property string newPermissionViewState: "NEWPERMISSION"
readonly property string permissionsViewState: "PERMISSIONS"
}
state: d.welcomeViewState // Initial state
state: root.store.permissionsModel.count > 0 ? d.permissionsViewState : d.welcomeViewState
states: [
State {
name: d.welcomeViewState
PropertyChanges {target: root; title: qsTr("Permissions")}
PropertyChanges {target: root; previousPageName: ""}
PropertyChanges {target: root; content: welcomeView}
PropertyChanges {target: root; headerButtonVisible: true}
PropertyChanges {target: root; headerButtonText: qsTr("Add new permission")}
PropertyChanges {target: root; headerWidth: root.viewWidth}
},
State {
name: d.newPermissionViewState
PropertyChanges {target: root; title: qsTr("New permission")}
PropertyChanges {target: root; previousPageName: qsTr("Permissions")}
PropertyChanges {target: root; content: newPermissionView}
PropertyChanges {target: root; headerButtonVisible: false}
PropertyChanges {target: root; headerWidth: 0}
},
State {
name: d.permissionsViewState
PropertyChanges {target: root; title: qsTr("Permissions")}
PropertyChanges {target: root; previousPageName: ""}
PropertyChanges {target: root; content: permissionsView}
PropertyChanges {target: root; headerButtonVisible: true}
PropertyChanges {target: root; headerButtonText: qsTr("Add new permission")}
PropertyChanges {target: root; headerWidth: root.viewWidth}
}
]
onHeaderButtonClicked: {
if(root.state === d.welcomeViewState)
root.state = d.newPermissionViewState
else if (root.state === d.permissionsViewState)
root.state = d.newPermissionViewState
}
// Community Permissions possible view contents:
Component {
id: welcomeView
CommunityWelcomePermissionsView {
onAddPermission: root.state = d.newPermissionViewState
viewWidth: root.viewWidth
}
}
Component {
id: newPermissionView
CommunityNewPermissionView {}
CommunityNewPermissionView {
viewWidth: root.viewWidth
store: root.store
onPermissionCreated: root.state = d.permissionsViewState
}
}
Component {
id: permissionsView
CommunityPermissionsView {
viewWidth: root.viewWidth
store: root.store
}
}
}

View File

@ -1,6 +1,13 @@
import QtQuick 2.0
import AppLayouts.Chat.controls.community 1.0
import StatusQ.Core.Utils 0.1 as SQ
import utils 1.0
QtObject {
id: root
property var permissionsModel: ListModel {} // Backend permissions list object model asignement. Please check the current expected data in qml defined in `createPermissions` method
// TODO: Replace to real data, now dummy model
property var tokensModel: ListModel {
@ -71,6 +78,12 @@ QtObject {
}
}
// TODO: Replace to real data, now dummy model
property var channelsModel: ListModel {
ListElement { key: "wellcome"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#welcome"}
ListElement { key: "general"; iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png"; name: "#general"}
}
readonly property QtObject _d: QtObject {
id: d
@ -105,7 +118,73 @@ QtObject {
return null
}
function createPermissions(permissions) {
console.log("TODO: Create permissions - backend call")
function createPermissions(holdings, permissions, isPrivate) {
console.log("TODO: Create permissions - backend call - Now dummy data shown")
// TO BE REMOVED: It shold just be a call to the backend sharing `holdings`, `permissions`, `channels` and `isPrivate` properties.
var permission = {
isPrivate: true,
holdingsListModel: [],
permissionsObjectModel: {
key: "",
text: "",
imageSource: ""
},
channelsListModel: []
};
// Setting HOLDINGS:
for (var i = 0; i < holdings.count; i++ ) {
var entry = holdings.get(i);
// roles: type, key, name, amount, imageSource, operator
permission.holdingsListModel.push({
operator: entry.operator,
type: entry.type,
key: entry.key,
name: entry.name,
amount: entry.amount,
imageSource: entry.imageSource
});
}
// Setting PERMISSIONS:
permission.permissionsObjectModel.key = permissions.key
permission.permissionsObjectModel.text = permissions.text
permission.permissionsObjectModel.imageSource = permissions.imageSource
// Setting PRIVATE permission property:
permission.isPrivate = isPrivate
// TODO: Set channels list. Now mocked data.
permission.channelsListModel = root.channelsModel
// Add into permission model:
root.permissionsModel.append(permission)
}
function setHoldingsTextFormat(type, name, amount) {
switch (type) {
case HoldingTypes.Type.Token:
case HoldingTypes.Type.Collectible:
return `${LocaleUtils.numberToLocaleString(amount)} ${name}`
case HoldingTypes.Type.Ens:
if (name)
return qsTr("ENS username on '%1' domain").arg(name)
else
return qsTr("Any ENS username")
default:
return ""
}
}
function editPermission(index) {
console.log("TODO: Edit permissions - backend call")
}
function duplicatePermission(index) {
console.log("TODO: Duplicate permissions - backend call")
}
function removePermission(index) {
console.log("TODO: Remove permissions - backend call")
}
}

View File

@ -158,11 +158,7 @@ StatusSectionLayout {
centerPanel: Loader {
id: centerPanelContentLoader
anchors.fill: parent
//anchors.margins: 32
anchors {
leftMargin: 28
bottomMargin: 16
}
anchors.bottomMargin: 16
active: root.community
sourceComponent: StackLayout {
currentIndex: d.currentIndex

View File

@ -5,7 +5,7 @@ import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import StatusQ.Core.Utils 0.1 as SQ
import StatusQ.Core.Utils 0.1
import utils 1.0
import shared.panels 1.0
@ -13,25 +13,18 @@ import shared.panels 1.0
import SortFilterProxyModel 0.2
import "../../../Chat/controls/community"
import "../../stores"
Flickable {
id: root
property var store: CommunitiesStore {}
property var store
property int viewWidth: 560 // by design
signal createPermission()
// TODO: Call this when permissions are stored in backend to start a new permissions flow
function clearPermissions() {
d.permissions.clear()
}
signal permissionCreated()
QtObject {
id: d
property bool isPrivate: false
property ListModel permissions: ListModel{}
property int permissionType: PermissionTypes.Type.None
}
@ -42,7 +35,7 @@ Flickable {
ColumnLayout {
id: mainLayout
width: 560 // by design
width: root.viewWidth
spacing: 0
CurveSeparatorWithText {
Layout.alignment: Qt.AlignLeft
@ -55,8 +48,6 @@ Flickable {
icon: Style.svg("contact_verified")
title: qsTr("Who holds")
defaultItemText: qsTr("Example: 10 SNT")
andOperatorText: qsTr("and")
orOperatorText: qsTr("or")
// roles: type, key, name, amount, imageSource, operator
ListModel {
@ -64,28 +55,12 @@ Flickable {
}
property int editedIndex
function getText(type, name, amount) {
switch (type) {
case HoldingTypes.Type.Token:
case HoldingTypes.Type.Collectible:
return `${LocaleUtils.numberToLocaleString(amount)} ${name}`
case HoldingTypes.Type.Ens:
if (name)
return qsTr("ENS username on '%1' domain").arg(name)
else
return qsTr("Any ENS username")
default:
return ""
}
}
itemsModel: SortFilterProxyModel {
sourceModel: holdingsModel
proxyRoles: ExpressionRole {
name: "text"
expression: tokensSelector.getText(model.type, model.name, model.amount)
expression: root.store.setHoldingsTextFormat(model.type, model.name, model.amount)
}
}
@ -95,11 +70,10 @@ Flickable {
function addItem(type, item, amount, operator) {
const key = item.key
const name = item.name
const name = item.shortName ? item.shortName : item.name
const imageSource = item.iconSource.toString()
holdingsModel.append({ type, key, name, amount, imageSource, operator })
d.permissions.append([{ key }, { operator }])
}
onAddToken: {
@ -120,13 +94,12 @@ Flickable {
const icon = Style.svg("ensUsernames")
holdingsModel.append({type: HoldingTypes.Type.Ens, key, name, amount: 1, imageSource: icon, operator })
d.permissions.append([{ key }, { operator }])
dropdown.close()
}
onUpdateToken: {
const modelItem = store.getTokenByKey(key)
const name = modelItem.name
const name = modelItem.shortName ? modelItem.shortName : modelItem.name
const imageSource = modelItem.iconSource.toString()
holdingsModel.set(tokensSelector.editedIndex, { type: HoldingTypes.Type.Token, key, name, amount, imageSource })
@ -155,7 +128,7 @@ Flickable {
holdingsModel.remove(tokensSelector.editedIndex)
if (holdingsModel.count) {
holdingsModel.set(0, { operator: SQ.Utils.Operators.None})
holdingsModel.set(0, { operator: OperatorsUtils.Operators.None})
}
dropdown.close()
@ -229,7 +202,8 @@ Flickable {
value: QtObject {
id: permissionsListObjectModel
readonly property int operator: SQ.Utils.Operators.None
readonly property int operator: OperatorsUtils.Operators.None
property var key
property string text: ""
property string imageSource: ""
}
@ -244,6 +218,7 @@ Flickable {
onDone: {
d.permissionType = permissionType
permissionsListObjectModel.key = permissionType
permissionsListObjectModel.text = title
permissionsListObjectModel.imageSource = asset
permissionsDropdown.close()
@ -321,13 +296,13 @@ Flickable {
StatusButton {
Layout.topMargin: 24
text: qsTr("Create permission")
enabled: d.permissions.count > 0
enabled: holdingsModel.count > 0 && permissionsListObjectModel.key !== undefined
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
onClicked: {
root.store.createPermissions(d.permissions)
root.clearPermissions()
root.store.createPermissions(holdingsModel, permissionsListObjectModel, d.isPrivate)
root.permissionCreated()
}
}
}

View File

@ -0,0 +1,65 @@
import QtQuick 2.14
import QtQuick.Layouts 1.14
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Controls 0.1
import SortFilterProxyModel 0.2
import utils 1.0
import AppLayouts.Chat.controls.community 1.0
Flickable {
id: root
property var store
property int viewWidth: 560 // by design
contentWidth: mainLayout.width
contentHeight: mainLayout.height + mainLayout.anchors.topMargin
clip: true
flickableDirection: Flickable.AutoFlickIfNeeded
ColumnLayout {
id: mainLayout
width: root.viewWidth
spacing: 24
Repeater {
model: root.store.permissionsModel
delegate: PermissionItem {
Layout.preferredWidth: root.viewWidth
holdingsListModel: SortFilterProxyModel {
sourceModel: model.holdingsListModel
proxyRoles: ExpressionRole {
name: "text"
expression: root.store.setHoldingsTextFormat(model.type, model.name, model.amount)
}
}
permissionName: model.permissionsObjectModel.text
permissionImageSource: model.permissionsObjectModel.imageSource
channelsListModel: SortFilterProxyModel {
sourceModel: model.channelsListModel
proxyRoles: [
ExpressionRole {
name: "text"
expression: model.name
},
ExpressionRole {
name: "imageSource"
expression: model.iconSource
}
]
}
isPrivate: model.isPrivate
onEditClicked: store.editPermission(model.index)
onDuplicateClicked: store.duplicatePermission(model.index)
onRemoveClicked: store.removePermission(model.index)
}
}
}
}

View File

@ -10,7 +10,7 @@ import utils 1.0
Flickable {
id: root
signal addPermission()
property int viewWidth: 560 // by design
contentWidth: mainLayout.width
contentHeight: mainLayout.height + mainLayout.anchors.topMargin
@ -19,7 +19,7 @@ Flickable {
ColumnLayout {
id: mainLayout
width: 560 // by design
width: root.viewWidth
spacing: 24
Rectangle {
@ -127,13 +127,5 @@ Flickable {
}
}
}
StatusButton {
text: qsTr("Add permission")
height: 44
Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true
onClicked: root.addPermission()
}
}
}

View File

@ -0,0 +1,3 @@
CommunityWelcomePermissionsView 1.0 CommunityWelcomePermissionsView.qml
CommunityNewPermissionView 1.0 CommunityNewPermissionView.qml
CommunityPermissionsView 1.0 CommunityPermissionsView.qml