chore: Adding new component ChannelPermissionsModelEditor
The purpose of this component is to hold the dirty permissions edited my the user. This is a functional component used to create/edit/delete permissions. The edited permissions are detached from the backend.
This commit is contained in:
parent
fc81568fe9
commit
35c1475403
|
@ -0,0 +1,343 @@
|
||||||
|
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 duplicating a permission. The new permission will be have a different id and key
|
||||||
|
function duplicatePermission(index) {
|
||||||
|
const permission = channelPermissionsModel.get(index)
|
||||||
|
|
||||||
|
if (!permission)
|
||||||
|
return
|
||||||
|
|
||||||
|
permission.id = Utils.uuid()
|
||||||
|
permission.key = Utils.uuid()
|
||||||
|
permission.holdingsListModel = d.newHoldingsModel(StatusQUtils.ModelUtils.modelToArray(permission.holdingsListModel))
|
||||||
|
permission.channelsListModel = d.newChannelsModel(StatusQUtils.ModelUtils.modelToArray(permission.channelsListModel))
|
||||||
|
channelPermissionsModel.append(permission)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function removing a permission by index
|
||||||
|
function removePermission(index) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
ChannelPermissionsModelEditor 1.0 ChannelPermissionsModelEditor.qml
|
Loading…
Reference in New Issue