status-desktop/ui/app/AppLayouts/Communities/panels/SharedAddressesPermissionsP...

438 lines
18 KiB
QML

import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
import AppLayouts.Communities.controls 1.0
import AppLayouts.Communities.views 1.0
import AppLayouts.Communities.helpers 1.0
import utils 1.0
Rectangle {
id: root
property var permissionsModel
property var assetsModel
property var collectiblesModel
property string communityName
property string communityIcon
implicitHeight: permissionsScrollView.contentHeight - permissionsScrollView.anchors.topMargin
color: Theme.palette.baseColor2
QtObject {
id: d
// UI
readonly property int absLeftMargin: 12
readonly property color tableBorderColor: Theme.palette.directColor7
// internal logic
readonly property var uniquePermissionChannels:
root.permissionsModel && root.permissionsModel.count ?
PermissionsHelpers.getUniquePermissionChannels(root.permissionsModel, [PermissionTypes.Type.Read, PermissionTypes.Type.ViewAndPost])
: []
// models
readonly property var adminPermissionsModel: SortFilterProxyModel {
id: adminPermissionsModel
sourceModel: root.permissionsModel
function filterPredicate(modelData) {
return (modelData.permissionType === Constants.permissionType.admin) &&
(modelData.tokenCriteriaMet && !modelData.isPrivate) // admin privs are hidden if criteria not met
}
filters: ExpressionFilter {
expression: adminPermissionsModel.filterPredicate(model)
}
}
readonly property var joinPermissionsModel: SortFilterProxyModel {
id: joinPermissionsModel
sourceModel: root.permissionsModel
function filterPredicate(modelData) {
return (modelData.permissionType === Constants.permissionType.member) &&
(modelData.tokenCriteriaMet || !modelData.isPrivate)
}
filters: ExpressionFilter {
expression: joinPermissionsModel.filterPredicate(model)
}
}
}
StatusScrollView {
id: permissionsScrollView
anchors.fill: parent
anchors.topMargin: -Style.current.padding
contentWidth: availableWidth
ColumnLayout {
width: parent.width
spacing: Style.current.halfPadding
// header
RowLayout {
Layout.fillWidth: true
Layout.bottomMargin: 4
spacing: Style.current.padding
StatusRoundedImage {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.leftMargin: d.absLeftMargin
image.source: root.communityIcon
}
StatusBaseText {
font.weight: Font.Medium
text: qsTr("Permissions")
}
}
// permission types
PermissionPanel {
permissionType: PermissionTypes.Type.Member
permissionsModel: d.joinPermissionsModel
}
PermissionPanel {
permissionType: PermissionTypes.Type.Admin
permissionsModel: d.adminPermissionsModel
}
Repeater { // channel repeater
model: d.uniquePermissionChannels
delegate: ChannelPermissionPanel {}
}
}
}
component PanelBg: Rectangle {
color: Theme.palette.statusListItem.backgroundColor
border.width: 1
border.color: Theme.palette.baseColor2
radius: Style.current.radius
}
component PanelIcon: StatusRoundIcon {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignTop
asset.name: {
switch (permissionType) {
case PermissionTypes.Type.Admin:
return "admin"
case PermissionTypes.Type.Member:
return "communities"
default:
return "channel"
}
}
radius: height/2
}
component PanelHeading: StatusBaseText {
Layout.fillWidth: true
elide: Text.ElideRight
font.weight: Font.Medium
text: {
switch (permissionType) {
case PermissionTypes.Type.Admin:
return qsTr("Become an admin")
case PermissionTypes.Type.Member:
return qsTr("Join %1").arg(root.communityName)
default:
return d.uniquePermissionChannels[index][1]
}
}
}
component SinglePermissionFlow: Flow {
width: parent.width
spacing: Style.current.halfPadding
Repeater {
model: HoldingsSelectionModel {
sourceModel: model.holdingsListModel
assetsModel: root.assetsModel
collectiblesModel: root.collectiblesModel
}
delegate: Row {
spacing: 4
StatusRoundedImage {
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
image.source: model.imageSource
}
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Theme.tertiaryTextFontSize
text: model.text
color: model.available ? Theme.palette.successColor1 : Theme.palette.directColor1
}
}
}
}
component PermissionPanel: Control {
id: permissionPanel
property int permissionType: PermissionTypes.Type.None
property var permissionsModel
readonly property bool tokenCriteriaMet: overallPermissionRow.tokenCriteriaMet
visible: permissionsModel.count
Layout.fillWidth: true
padding: d.absLeftMargin
background: PanelBg {}
contentItem: RowLayout {
spacing: Style.current.padding
PanelIcon {}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
PanelHeading {}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: grid.implicitHeight + grid.anchors.margins*2
border.width: 1
border.color: d.tableBorderColor
radius: Style.current.radius
color: "transparent"
GridLayout {
id: grid
anchors.fill: parent
anchors.margins: Style.current.halfPadding
rowSpacing: Style.current.halfPadding
columnSpacing: Style.current.halfPadding
columns: 2
Repeater {
id: permissionsRepeater
property int revision
model: permissionPanel.permissionsModel
delegate: Column {
Layout.column: 0
Layout.row: index
Layout.fillWidth: true
spacing: Style.current.halfPadding
readonly property bool tokenCriteriaMet: model.tokenCriteriaMet ?? false
onTokenCriteriaMetChanged: permissionsRepeater.revision++
SinglePermissionFlow {}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width + grid.anchors.margins*2
height: 1
color: d.tableBorderColor
visible: index < permissionsRepeater.count - 1
}
}
}
RowLayout {
id: overallPermissionRow
Layout.column: 1
Layout.rowSpan: permissionsRepeater.count || 1
Layout.preferredWidth: 110
Layout.fillHeight: true
readonly property bool tokenCriteriaMet: {
permissionsRepeater.revision // NB no let/const here b/c of https://bugreports.qt.io/browse/QTBUG-91917
for (var i = 0; i < permissionsRepeater.count; i++) {
var permissionItem = permissionsRepeater.itemAt(i);
if (permissionItem.tokenCriteriaMet)
return true
}
return false
}
Rectangle {
Layout.preferredWidth: 1
Layout.fillHeight: true
Layout.topMargin: -Style.current.halfPadding
Layout.bottomMargin: -Style.current.halfPadding
color: d.tableBorderColor
}
Row {
Layout.alignment: Qt.AlignCenter
StatusIcon {
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
icon: overallPermissionRow.tokenCriteriaMet ? "tiny/checkmark" : "tiny/secure"
color: overallPermissionRow.tokenCriteriaMet ? Theme.palette.successColor1 : Theme.palette.baseColor1
}
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Theme.tertiaryTextFontSize
text: {
switch (permissionPanel.permissionType) {
case PermissionTypes.Type.Admin:
return qsTr("Admin")
case PermissionTypes.Type.Member:
return qsTr("Join")
case PermissionTypes.Type.Read:
return qsTr("View only")
case PermissionTypes.Type.ViewAndPost:
return qsTr("View & post")
default:
return "???"
}
}
color: overallPermissionRow.tokenCriteriaMet ? Theme.palette.directColor1 : Theme.palette.baseColor1
}
}
}
}
}
}
}
}
component ChannelPermissionPanel: Control {
id: channelPermsPanel
Layout.fillWidth: true
spacing: 10
padding: d.absLeftMargin
background: PanelBg {}
readonly property string channelKey: d.uniquePermissionChannels[index][0]
contentItem: RowLayout {
spacing: Style.current.padding
PanelIcon {}
ColumnLayout {
Layout.fillWidth: true
Layout.fillHeight: true
spacing: Style.current.smallPadding
PanelHeading {}
Repeater { // permissions repeater
model: [PermissionTypes.Type.Read, PermissionTypes.Type.ViewAndPost]
delegate: Rectangle {
id: channelPermsSubPanel
readonly property int permissionType: modelData
Layout.fillWidth: true
Layout.preferredHeight: grid2.implicitHeight + grid2.anchors.margins*2
border.width: 1
border.color: d.tableBorderColor
radius: Style.current.radius
color: "transparent"
GridLayout {
id: grid2
anchors.fill: parent
anchors.margins: Style.current.halfPadding
rowSpacing: Style.current.halfPadding
columnSpacing: Style.current.halfPadding
columns: 2
Repeater {
id: permissionsRepeater2
property int revision
model: SortFilterProxyModel {
id: channelPermissionsModel
sourceModel: root.permissionsModel
function filterPredicate(modelData) {
return modelData.permissionType === channelPermsSubPanel.permissionType &&
!modelData.isPrivate &&
ModelUtils.contains(modelData.channelsListModel, "key", channelPermsPanel.channelKey) // filter and group by channel "key"
}
filters: ExpressionFilter {
expression: channelPermissionsModel.filterPredicate(model)
}
}
delegate: Column {
Layout.column: 0
Layout.row: index
Layout.fillWidth: true
spacing: Style.current.halfPadding
readonly property bool tokenCriteriaMet: model.tokenCriteriaMet ?? false
onTokenCriteriaMetChanged: permissionsRepeater2.revision++
SinglePermissionFlow {}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
width: parent.width + grid2.anchors.margins*2
height: 1
color: d.tableBorderColor
visible: index < permissionsRepeater2.count - 1
}
}
}
RowLayout {
id: overallPermissionRow2
Layout.column: 1
Layout.rowSpan: channelPermissionsModel.count || 1
Layout.preferredWidth: 110
Layout.fillHeight: true
readonly property bool tokenCriteriaMet: {
permissionsRepeater2.revision
for (let i = 0; i < permissionsRepeater2.count; i++) {
const permissionItem = permissionsRepeater2.itemAt(i);
if (permissionItem.tokenCriteriaMet)
return true
}
return false
}
Rectangle {
Layout.preferredWidth: 1
Layout.fillHeight: true
Layout.topMargin: -Style.current.halfPadding
Layout.bottomMargin: -Style.current.halfPadding
color: d.tableBorderColor
}
Row {
Layout.alignment: Qt.AlignCenter
StatusIcon {
anchors.verticalCenter: parent.verticalCenter
width: 16
height: 16
icon: overallPermissionRow2.tokenCriteriaMet ? "tiny/checkmark" : "tiny/secure"
color: overallPermissionRow2.tokenCriteriaMet ? Theme.palette.successColor1 : Theme.palette.baseColor1
}
StatusBaseText {
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: Theme.tertiaryTextFontSize
text: {
switch (channelPermsSubPanel.permissionType) {
case PermissionTypes.Type.Read:
return qsTr("View only")
case PermissionTypes.Type.ViewAndPost:
return qsTr("View & post")
case PermissionTypes.Type.Moderator:
return qsTr("Moderate")
default:
return "???"
}
}
color: overallPermissionRow2.tokenCriteriaMet ? Theme.palette.directColor1 : Theme.palette.baseColor1
}
}
}
}
}
}
}
}
}
}