Add room permissions
Signed-off-by: Ajay Bura <ajbura@gmail.com>
This commit is contained in:
parent
af61f4f1db
commit
769d24d196
5 changed files with 238 additions and 16 deletions
208
src/app/molecules/room-permissions/RoomPermissions.jsx
Normal file
208
src/app/molecules/room-permissions/RoomPermissions.jsx
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import './RoomPermissions.scss';
|
||||||
|
|
||||||
|
import initMatrix from '../../../client/initMatrix';
|
||||||
|
import { getPowerLabel } from '../../../util/matrixUtil';
|
||||||
|
|
||||||
|
import Text from '../../atoms/text/Text';
|
||||||
|
import Button from '../../atoms/button/Button';
|
||||||
|
import { MenuHeader } from '../../atoms/context-menu/ContextMenu';
|
||||||
|
import SettingTile from '../setting-tile/SettingTile';
|
||||||
|
|
||||||
|
import ChevronBottomIC from '../../../../public/res/ic/outlined/chevron-bottom.svg';
|
||||||
|
|
||||||
|
const permissionsInfo = {
|
||||||
|
users_default: {
|
||||||
|
name: 'Default role',
|
||||||
|
description: 'Set default role for all members.',
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
events_default: {
|
||||||
|
name: 'Send messages',
|
||||||
|
description: 'Set minimum power level to send messages in room.',
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
redact: {
|
||||||
|
name: 'Delete messages sent by others',
|
||||||
|
description: 'Set minimum power level to delete messages in room.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
notifications: {
|
||||||
|
name: 'Ping room',
|
||||||
|
description: 'Set minimum power level to ping room.',
|
||||||
|
default: {
|
||||||
|
room: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'm.space.child': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Manage rooms in space',
|
||||||
|
description: 'Set minimum power level to manage rooms in space.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
invite: {
|
||||||
|
name: 'Invite',
|
||||||
|
description: 'Set minimum power level to invite members.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
kick: {
|
||||||
|
name: 'Kick',
|
||||||
|
description: 'Set minimum power level to kick members.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
ban: {
|
||||||
|
name: 'Ban',
|
||||||
|
description: 'Set minimum power level to ban members.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.avatar': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change avatar',
|
||||||
|
description: 'Set minimum power level to change room/space avatar.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.name': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change name',
|
||||||
|
description: 'Set minimum power level to change room/space name.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.topic': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change topic',
|
||||||
|
description: 'Set minimum power level to change room/space topic.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
state_default: {
|
||||||
|
name: 'Change settings',
|
||||||
|
description: 'Set minimum power level to change settings.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.canonical_alias': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change published address',
|
||||||
|
description: 'Set minimum power level to publish and set main address.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.power_levels': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change permissions',
|
||||||
|
description: 'Set minimum power level to change permissions.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.encryption': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Enable room encryption',
|
||||||
|
description: 'Set minimum power level to enable room encryption.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.history_visibility': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change history visibility',
|
||||||
|
description: 'Set minimum power level to change room messages history visibility.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.tombstone': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Upgrade room',
|
||||||
|
description: 'Set minimum power level to upgrade room.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.pinned_events': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Pin messages',
|
||||||
|
description: 'Set minimum power level to pin messages in room.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'm.room.server_acl': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Change server ACLs',
|
||||||
|
description: 'Set minimum power level to change server ACLs.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
'im.vector.modular.widgets': {
|
||||||
|
parent: 'events',
|
||||||
|
name: 'Modify widgets',
|
||||||
|
description: 'Set minimum power level to modify room widgets.',
|
||||||
|
default: 50,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const roomPermsGroups = {
|
||||||
|
'General Permissions': ['users_default', 'events_default', 'redact', 'notifications'],
|
||||||
|
'Manage members permissions': ['invite', 'kick', 'ban'],
|
||||||
|
'Room profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'],
|
||||||
|
'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels', 'm.room.encryption', 'm.room.history_visibility'],
|
||||||
|
'Other permissions': ['m.room.tombstone', 'm.room.pinned_events', 'm.room.server_acl', 'im.vector.modular.widgets'],
|
||||||
|
};
|
||||||
|
|
||||||
|
const spacePermsGroups = {
|
||||||
|
'General Permissions': ['users_default', 'm.space.child'],
|
||||||
|
'Manage members permissions': ['invite', 'kick', 'ban'],
|
||||||
|
'Space profile permissions': ['m.room.avatar', 'm.room.name', 'm.room.topic'],
|
||||||
|
'Settings permissions': ['state_default', 'm.room.canonical_alias', 'm.room.power_levels'],
|
||||||
|
};
|
||||||
|
|
||||||
|
function RoomPermissions({ roomId }) {
|
||||||
|
const mx = initMatrix.matrixClient;
|
||||||
|
const room = mx.getRoom(roomId);
|
||||||
|
const pLEvent = room.currentState.getStateEvents('m.room.power_levels')[0];
|
||||||
|
const permissions = pLEvent.getContent();
|
||||||
|
const canChangePermission = room.currentState.maySendStateEvent('m.room.power_levels', mx.getUserId());
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="room-permissions">
|
||||||
|
{
|
||||||
|
Object.keys(roomPermsGroups).map((groupKey) => {
|
||||||
|
const groupedPermKeys = roomPermsGroups[groupKey];
|
||||||
|
return (
|
||||||
|
<div className="room-permissions__card" key={groupKey}>
|
||||||
|
<MenuHeader>{groupKey}</MenuHeader>
|
||||||
|
{
|
||||||
|
groupedPermKeys.map((permKey) => {
|
||||||
|
const permInfo = permissionsInfo[permKey];
|
||||||
|
|
||||||
|
let powerLevel = 0;
|
||||||
|
let permValue = permInfo.parent
|
||||||
|
? permissions[permInfo.parent][permKey]
|
||||||
|
: permissions[permKey];
|
||||||
|
|
||||||
|
if (!permValue) permValue = permInfo.default;
|
||||||
|
|
||||||
|
if (typeof permValue === 'number') {
|
||||||
|
powerLevel = permValue;
|
||||||
|
} else if (permKey === 'notifications') {
|
||||||
|
powerLevel = permValue.room || 50;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SettingTile
|
||||||
|
key={permKey}
|
||||||
|
title={permInfo.name}
|
||||||
|
content={<Text variant="b3">{permInfo.description}</Text>}
|
||||||
|
options={(
|
||||||
|
<Button
|
||||||
|
iconSrc={canChangePermission ? ChevronBottomIC : null}
|
||||||
|
>
|
||||||
|
<Text variant="b2">
|
||||||
|
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoomPermissions.propTypes = {
|
||||||
|
roomId: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoomPermissions;
|
11
src/app/molecules/room-permissions/RoomPermissions.scss
Normal file
11
src/app/molecules/room-permissions/RoomPermissions.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.room-permissions {
|
||||||
|
& .setting-tile {
|
||||||
|
margin: 0 var(--sp-normal);
|
||||||
|
margin-top: var(--sp-tight);
|
||||||
|
padding-bottom: var(--sp-tight);
|
||||||
|
border-bottom: 1px solid var(--bg-surface-border);
|
||||||
|
&:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -261,6 +261,7 @@ function ProfileViewer() {
|
||||||
function renderProfile() {
|
function renderProfile() {
|
||||||
const member = room.getMember(userId) || mx.getUser(userId) || {};
|
const member = room.getMember(userId) || mx.getUser(userId) || {};
|
||||||
const avatarMxc = member.getMxcAvatarUrl?.() || member.avatarUrl;
|
const avatarMxc = member.getMxcAvatarUrl?.() || member.avatarUrl;
|
||||||
|
const powerLevel = member.powerLevel || 0;
|
||||||
const canChangeRole = room.currentState.maySendEvent('m.room.power_levels', mx.getUserId());
|
const canChangeRole = room.currentState.maySendEvent('m.room.power_levels', mx.getUserId());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -278,7 +279,9 @@ function ProfileViewer() {
|
||||||
</div>
|
</div>
|
||||||
<div className="profile-viewer__user__role">
|
<div className="profile-viewer__user__role">
|
||||||
<Text variant="b3">Role</Text>
|
<Text variant="b3">Role</Text>
|
||||||
<Button iconSrc={canChangeRole ? ChevronBottomIC : null}>{getPowerLabel(member.powerLevel) || 'Member'}</Button>
|
<Button iconSrc={canChangeRole ? ChevronBottomIC : null}>
|
||||||
|
{`${getPowerLabel(powerLevel) || 'Member'} - ${powerLevel}`}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<SessionInfo userId={userId} />
|
<SessionInfo userId={userId} />
|
||||||
|
|
|
@ -19,12 +19,12 @@ import RoomVisibility from '../../molecules/room-visibility/RoomVisibility';
|
||||||
import RoomAliases from '../../molecules/room-aliases/RoomAliases';
|
import RoomAliases from '../../molecules/room-aliases/RoomAliases';
|
||||||
import RoomHistoryVisibility from '../../molecules/room-history-visibility/RoomHistoryVisibility';
|
import RoomHistoryVisibility from '../../molecules/room-history-visibility/RoomHistoryVisibility';
|
||||||
import RoomEncryption from '../../molecules/room-encryption/RoomEncryption';
|
import RoomEncryption from '../../molecules/room-encryption/RoomEncryption';
|
||||||
|
import RoomPermissions from '../../molecules/room-permissions/RoomPermissions';
|
||||||
|
|
||||||
import SettingsIC from '../../../../public/res/ic/outlined/settings.svg';
|
import SettingsIC from '../../../../public/res/ic/outlined/settings.svg';
|
||||||
import SearchIC from '../../../../public/res/ic/outlined/search.svg';
|
import SearchIC from '../../../../public/res/ic/outlined/search.svg';
|
||||||
import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg';
|
import ShieldUserIC from '../../../../public/res/ic/outlined/shield-user.svg';
|
||||||
import LockIC from '../../../../public/res/ic/outlined/lock.svg';
|
import LockIC from '../../../../public/res/ic/outlined/lock.svg';
|
||||||
import InfoIC from '../../../../public/res/ic/outlined/info.svg';
|
|
||||||
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
|
import AddUserIC from '../../../../public/res/ic/outlined/add-user.svg';
|
||||||
import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
|
import LeaveArrowIC from '../../../../public/res/ic/outlined/leave-arrow.svg';
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ const tabText = {
|
||||||
SEARCH: 'Search',
|
SEARCH: 'Search',
|
||||||
PERMISSIONS: 'Permissions',
|
PERMISSIONS: 'Permissions',
|
||||||
SECURITY: 'Security',
|
SECURITY: 'Security',
|
||||||
ADVANCED: 'Advanced',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const tabItems = [{
|
const tabItems = [{
|
||||||
|
@ -54,10 +53,6 @@ const tabItems = [{
|
||||||
iconSrc: LockIC,
|
iconSrc: LockIC,
|
||||||
text: tabText.SECURITY,
|
text: tabText.SECURITY,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
}, {
|
|
||||||
iconSrc: InfoIC,
|
|
||||||
text: tabText.ADVANCED,
|
|
||||||
disabled: false,
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
function GeneralSettings({ roomId }) {
|
function GeneralSettings({ roomId }) {
|
||||||
|
@ -156,6 +151,7 @@ function RoomSettings({ roomId }) {
|
||||||
/>
|
/>
|
||||||
<div className="room-settings__cards-wrapper">
|
<div className="room-settings__cards-wrapper">
|
||||||
{selectedTab.text === tabText.GENERAL && <GeneralSettings roomId={roomId} />}
|
{selectedTab.text === tabText.GENERAL && <GeneralSettings roomId={roomId} />}
|
||||||
|
{selectedTab.text === tabText.PERMISSIONS && <RoomPermissions roomId={roomId} />}
|
||||||
{selectedTab.text === tabText.SECURITY && <SecuritySettings roomId={roomId} />}
|
{selectedTab.text === tabText.SECURITY && <SecuritySettings roomId={roomId} />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -32,16 +32,20 @@
|
||||||
padding: 0 var(--sp-normal);
|
padding: 0 var(--sp-normal);
|
||||||
@include dir.side(padding, var(--sp-normal), var(--sp-extra-tight));
|
@include dir.side(padding, var(--sp-normal), var(--sp-extra-tight));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__card {
|
.room-settings__card {
|
||||||
margin: var(--sp-normal) 0;
|
margin: var(--sp-normal) 0;
|
||||||
background-color: var(--bg-surface);
|
background-color: var(--bg-surface);
|
||||||
border-radius: var(--bo-radius);
|
border-radius: var(--bo-radius);
|
||||||
box-shadow: var(--bs-surface-border);
|
box-shadow: var(--bs-surface-border);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
& > .context-menu__header:first-child {
|
& > .context-menu__header:first-child {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-settings .room-permissions__card {
|
||||||
|
@extend .room-settings__card;
|
||||||
}
|
}
|
Loading…
Reference in a new issue