330 lines
12 KiB
QML
330 lines
12 KiB
QML
import QtQuick 2.15
|
|
|
|
import StatusQ 0.1
|
|
|
|
import AppLayouts.Communities.controls 1.0
|
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
import StatusQ.Core.Utils 0.1 as StatusQUtils
|
|
|
|
import utils 1.0
|
|
|
|
|
|
/// Helper component for editing channel permissions
|
|
/// This component will create the necessary temporary models to be used until the changes are saved
|
|
|
|
QtObject {
|
|
id: root
|
|
|
|
// Input properties
|
|
|
|
// Model containing all channels
|
|
required property var channelsModel
|
|
// Model containing all permissions for the current community
|
|
required property var permissionsModel
|
|
|
|
// Channel ID
|
|
required property string channelId
|
|
// Channel name
|
|
required property string name
|
|
// Channel color
|
|
required property string color
|
|
// Channel emoji
|
|
required property string emoji
|
|
// Specify whether the channel is being edited or created
|
|
required property bool newChannelMode
|
|
|
|
|
|
// Output properties
|
|
|
|
// The edited channel permissions model
|
|
readonly property alias channelPermissionsModel: d.channelPermissionsModel
|
|
// Live model of channels contaning the temporarely edited channel
|
|
readonly property alias liveChannelsModel: d.liveChannelsModel
|
|
|
|
readonly property alias dirtyPermissions: d.channelPermissionsModel.dirty
|
|
|
|
|
|
// Input functions
|
|
|
|
// Function creating a new permission based on the given arguments
|
|
function appendPermission(holdings, channels, permissionType, isPrivate) {
|
|
d.appendPermission(holdings, channels, permissionType, isPrivate)
|
|
}
|
|
|
|
// Function editing a permission based on the given arguments
|
|
function editPermission(key, permissionType, holdings, channels, isPrivate) {
|
|
d.editPermission(key, permissionType, holdings, channels, isPrivate)
|
|
}
|
|
|
|
// Function removing a permission by index
|
|
function removePermission(index) {
|
|
return channelPermissionsModel.remove(index, 1);
|
|
}
|
|
|
|
|
|
// Output functions
|
|
|
|
// Function returning the list of added permissions
|
|
// The returned list contains the permissions that were added since the last reset
|
|
// Each item contains a map of role names and data value pairs as defined in the model
|
|
function getAddedPermissions() {
|
|
return d.flattenPermissions(channelPermissionsModel.getInsertedItems())
|
|
}
|
|
|
|
// Function returning the list of removed permissions
|
|
// The returned list contains the permissions that were removed since the last reset
|
|
// This list contains the permissions that are no longer available in the root.channelPermissionsModel, but are still available in the root.permissionsModel
|
|
// Each item contains a map of role names and data value pairs as defined in the model
|
|
function getRemovedPermissions() {
|
|
return d.flattenPermissions(channelPermissionsModel.getRemovedItems())
|
|
}
|
|
|
|
// Function returning the list of edited permissions
|
|
// The returned list contains the permissions that were edited since the last reset
|
|
// Each item contains a map of role names and data value pairs as defined in the model
|
|
function getEditedPermissions() {
|
|
return d.flattenPermissions(channelPermissionsModel.getEditedItems())
|
|
}
|
|
|
|
// This function resets the temporary models
|
|
// The dirtyPermissions property will be set to false
|
|
function reset() {
|
|
d.reset()
|
|
}
|
|
|
|
//internals
|
|
readonly property QtObject d: QtObject {
|
|
id: d
|
|
|
|
signal resetDone()
|
|
|
|
function reset() {
|
|
channelPermissionsModel.revert();
|
|
liveChannelsModel.revert();
|
|
d.resetDone();
|
|
}
|
|
|
|
function appendPermission(holdings, channels, permissionType, isPrivate) {
|
|
var permissionsModelData = {
|
|
id: Utils.uuid(),
|
|
key: Utils.uuid(),
|
|
holdingsListModel: d.newHoldingsModel(holdings),
|
|
channelsListModel: d.newChannelsModel(channels),
|
|
"permissionType": permissionType,
|
|
"isPrivate": isPrivate
|
|
};
|
|
|
|
d.channelPermissionsModel.append(permissionsModelData)
|
|
}
|
|
|
|
function editPermission(key, permissionType, holdings, channels, isPrivate) {
|
|
const index = StatusQUtils.ModelUtils.indexOf(d.channelPermissionsModel, "key", key)
|
|
if (index === -1)
|
|
return
|
|
|
|
const permissionItem = d.channelPermissionsModel.get(index)
|
|
|
|
d.channelPermissionsModel.set(index, {
|
|
"permissionType": permissionType,
|
|
"channelsListModel": d.newEditedChannelsModel(channels, permissionItem.channelsListModel),
|
|
"holdingsListModel": d.newEditedHoldingsModel(holdings, permissionItem.holdingsListModel),
|
|
"isPrivate": isPrivate
|
|
})
|
|
}
|
|
|
|
// Creates a new channel model to be used in the permissions model
|
|
// Expected roles: "key"
|
|
function newChannelsModel(channelsArray) {
|
|
var channelsModel = selfDestroyingModel.createObject(d.channelPermissionsModel);
|
|
|
|
for (var i = 0; i < channelsArray.length; i++) {
|
|
channelsModel.append({ key: channelsArray[i].key })
|
|
}
|
|
|
|
return channelsModel;
|
|
}
|
|
|
|
// Creates a new writable channel model on top of base model to be used in the permissions model
|
|
function newEditedChannelsModel(channelsArray, baseModel) {
|
|
var channelsModel = selfDestroyingWritableModel.createObject(d.channelPermissionsModel, {sourceModel: baseModel});
|
|
|
|
const count = channelsModel.rowCount()
|
|
for (var i = 0; i < count; i++) {
|
|
const ok = channelsModel.remove(0)
|
|
|
|
console.assert(ok
|
|
, "Failed to remove channel")
|
|
}
|
|
|
|
for (var i = 0; i < channelsArray.length; i++) {
|
|
const ok = channelsModel.append({
|
|
key: channelsArray[i].key,
|
|
})
|
|
|
|
console.assert(ok, "Failed to append channel");
|
|
}
|
|
|
|
return channelsModel;
|
|
}
|
|
|
|
// Creates a new holdings model to be used in the permissions model
|
|
function newHoldingsModel(holdingsArray, sourceModel) {
|
|
var holdingsModel = selfDestroyingModel.createObject(d.channelPermissionsModel);
|
|
for (var i = 0; i < holdingsArray.length; i++) {
|
|
holdingsModel.append(holdingsArray[i]);
|
|
}
|
|
|
|
return holdingsModel;
|
|
}
|
|
|
|
function newEditedHoldingsModel(holdingsArray, baseModel) {
|
|
var holdingsModel = selfDestroyingWritableModel.createObject(d.channelPermissionsModel, {sourceModel: baseModel});
|
|
|
|
const count = holdingsModel.rowCount()
|
|
for (var i = 0; i < count; i++) {
|
|
const ok = holdingsModel.remove(0)
|
|
console.assert(ok, "Failed to remove holding")
|
|
}
|
|
|
|
for (var i = 0; i < holdingsArray.length; i++) {
|
|
const ok = holdingsModel.append(holdingsArray[i])
|
|
console.assert(ok, "Failed to append holding");
|
|
}
|
|
|
|
return holdingsModel;
|
|
}
|
|
|
|
function flattenPermissions(permissionsItems) {
|
|
for (var i = 0; i < permissionsItems.length; i++) {
|
|
permissionsItems[i].holdingsListModel = StatusQUtils.ModelUtils.modelToArray(permissionsItems[i].holdingsListModel)
|
|
permissionsItems[i].channelsListModel = StatusQUtils.ModelUtils.modelToArray(permissionsItems[i].channelsListModel)
|
|
}
|
|
|
|
return permissionsItems
|
|
}
|
|
|
|
|
|
property Connections chatIdConnections: Connections {
|
|
target: root
|
|
enabled: root.newChannelMode
|
|
|
|
property string previousChannelId: ""
|
|
|
|
Component.onCompleted: previousChannelId = root.channelId
|
|
|
|
/// go through all the channels and replace the old channel id with the new one
|
|
function onChannelIdChanged() {
|
|
if (previousChannelId === root.channelId)
|
|
return;
|
|
|
|
if (previousChannelId == "") {
|
|
previousChannelId = root.channelId;
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < liveChannelsModel.rowCount(); i++) {
|
|
if (liveChannelsModel.get(i).itemId === previousChannelId) {
|
|
liveChannelsModel.set(i, { itemId: root.channelId })
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < channelPermissionsModel.rowCount(); i++) {
|
|
const currentItem = channelPermissionsModel.get(i)
|
|
const channelsListModel = currentItem.channelsListModel
|
|
|
|
for (var j = 0; j < channelsListModel.rowCount(); j++) {
|
|
if (channelsListModel.get(j).key === previousChannelId) {
|
|
channelsListModel.set(j, { key: root.channelId })
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
previousChannelId = root.channelId;
|
|
}
|
|
}
|
|
|
|
|
|
// Channel permissions model containing the temporarely edited permissions
|
|
property WritableProxyModel channelPermissionsModel: WritableProxyModel {
|
|
sourceModel: SortFilterProxyModel {
|
|
id: filteredPermissionsModel
|
|
|
|
sourceModel: root.permissionsModel
|
|
|
|
filters: [
|
|
FastExpressionFilter {
|
|
function filterPredicate(id, permissionType) {
|
|
return !PermissionTypes.isCommunityPermission(permissionType) && root.permissionsModel.belongsToChat(id, root.channelId)
|
|
}
|
|
expression: {
|
|
return filterPredicate(model.id, model.permissionType)
|
|
}
|
|
expectedRoles: [ "id", "permissionType" ]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
// Channels model containing the temporarely edited channel
|
|
property WritableProxyModel liveChannelsModel: WritableProxyModel {
|
|
id: newChannelModel
|
|
|
|
function updateCurrentChannelProperty(nameAndValue) {
|
|
const index = StatusQUtils.ModelUtils.indexOf(newChannelModel, "itemId", root.channelId)
|
|
if (index !== -1) {
|
|
newChannelModel.set(index, nameAndValue)
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
if (!root.newChannelMode)
|
|
return;
|
|
|
|
console.assert(newChannelModel.append({
|
|
itemId: root.channelId,
|
|
name: root.name,
|
|
emoji: root.emoji,
|
|
color: root.color
|
|
}), "Failed to add channel to channelsModel")
|
|
}
|
|
|
|
property Connections channelConnections: Connections {
|
|
target: root
|
|
function onColorChanged() {
|
|
newChannelModel.updateCurrentChannelProperty({"color": root.color})
|
|
}
|
|
function onNameChanged() {
|
|
newChannelModel.updateCurrentChannelProperty({"name": root.name})
|
|
}
|
|
function onEmojiChanged() {
|
|
newChannelModel.updateCurrentChannelProperty({"emoji": root.emoji})
|
|
}
|
|
}
|
|
|
|
sourceModel: root.channelsModel
|
|
}
|
|
|
|
// Used for dynamic model creation using Component.createObject
|
|
property Component selfDestroyingModel: Component {
|
|
ListModel {
|
|
id: model
|
|
|
|
Component.onCompleted: d.resetDone.connect(model.destroy)
|
|
Component.onDestruction: d.resetDone.disconnect(model.destroy)
|
|
}
|
|
}
|
|
|
|
property Component selfDestroyingWritableModel: Component {
|
|
WritableProxyModel {
|
|
id: model
|
|
|
|
Component.onCompleted: d.resetDone.connect(model.destroy)
|
|
Component.onDestruction: d.resetDone.disconnect(model.destroy)
|
|
}
|
|
}
|
|
}
|
|
}
|