[IMPROVE] Subscribe to roles (#2992)

* [CHORE] Subscribe to Roles

* subscribe to roles-change

* add subscribe for stream-roles

* fixed subscribe roles

* Add componentDidUpdate to RoomMembersView and propType

* Update componentDidUpdate in RoomMembersView, roles reducer,  getRoles method and actionType

* Minor tweaks

* Remove componentDidUpdate

* Fix add role

* Fix initialState and remove role

* Minor try/catch fix

* Fix lint

* Fix offline first

Co-authored-by: Diego Mello <diegolmello@gmail.com>
Co-authored-by: Gerzon Z <gerzonc@icloud.com>
Co-authored-by: Gerzon Z <gerzonzcanario@gmail.com>
This commit is contained in:
Gung Wah 2021-07-02 00:51:19 +08:00 committed by GitHub
parent 30487c392f
commit 88191b965a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 121 additions and 22 deletions

View File

@ -72,3 +72,4 @@ export const ENTERPRISE_MODULES = createRequestTypes('ENTERPRISE_MODULES', ['CLE
export const ENCRYPTION = createRequestTypes('ENCRYPTION', ['INIT', 'STOP', 'DECODE_KEY', 'SET', 'SET_BANNER']);
export const PERMISSIONS = createRequestTypes('PERMISSIONS', ['SET', 'UPDATE']);
export const ROLES = createRequestTypes('ROLES', ['SET', 'UPDATE', 'REMOVE']);

20
app/actions/roles.js Normal file
View File

@ -0,0 +1,20 @@
import * as types from './actionsTypes';
export function setRoles(roles) {
return {
type: types.ROLES.SET,
roles
};
}
export function updateRoles(id, desc) {
return {
type: types.ROLES.UPDATE,
payload: { id, desc }
};
}
export function removeRoles(id) {
return {
type: types.ROLES.REMOVE,
payload: { id }
};
}

View File

@ -2,9 +2,66 @@ import { sanitizedRaw } from '@nozbe/watermelondb/RawRecord';
import database from '../database';
import log from '../../utils/log';
import reduxStore from '../createStore';
import protectedFunction from './helpers/protectedFunction';
import {
removeRoles, setRoles as setRolesAction, updateRoles
} from '../../actions/roles';
export default function() {
export async function setRoles() {
const db = database.active;
const rolesCollection = db.collections.get('roles');
const allRoles = await rolesCollection.query().fetch();
const parsed = allRoles.reduce((acc, item) => ({ ...acc, [item.id]: item.description || item.id }), {});
reduxStore.dispatch(setRolesAction(parsed));
}
export async function onRolesChanged(ddpMessage) {
const { type, _id, description } = ddpMessage.fields.args[0];
if (/changed/.test(type)) {
const db = database.active;
const rolesCollection = db.get('roles');
try {
const rolesRecord = await rolesCollection.find(_id);
try {
await db.action(async() => {
await rolesRecord.update((u) => {
u.description = description;
});
});
} catch (e) {
log(e);
}
reduxStore.dispatch(updateRoles(_id, description));
} catch (err) {
try {
await db.action(async() => {
await rolesCollection.create((post) => {
post._raw = sanitizedRaw({ id: _id, description }, rolesCollection.schema);
});
});
} catch (e) {
log(e);
}
reduxStore.dispatch(updateRoles(_id, description || _id));
}
}
if (/removed/.test(type)) {
const db = database.active;
const rolesCollection = db.get('roles');
try {
const rolesRecord = await rolesCollection.find(_id);
await db.action(async() => {
await rolesRecord.destroyPermanently();
});
reduxStore.dispatch(removeRoles(_id));
} catch (err) {
console.log(err);
}
}
}
export function getRoles() {
const db = database.active;
return new Promise(async(resolve) => {
try {
@ -50,6 +107,7 @@ export default function() {
} catch (e) {
log(e);
}
setRoles();
return allRecords.length;
});
return resolve();

View File

@ -37,7 +37,7 @@ import {
getEnterpriseModules, setEnterpriseModules, hasLicense, isOmnichannelModuleAvailable
} from './methods/enterpriseModules';
import getSlashCommands from './methods/getSlashCommands';
import getRoles from './methods/getRoles';
import { getRoles, setRoles, onRolesChanged } from './methods/getRoles';
import canOpenRoom from './methods/canOpenRoom';
import triggerBlockAction, { triggerSubmitView, triggerCancel } from './methods/actions';
@ -275,6 +275,8 @@ const RocketChat = {
this.usersListener = this.sdk.onStreamData('users', protectedFunction(ddpMessage => RocketChat._setUser(ddpMessage)));
this.rolesListener = this.sdk.onStreamData('stream-roles', protectedFunction(ddpMessage => onRolesChanged(ddpMessage)));
this.notifyLoggedListener = this.sdk.onStreamData('stream-notify-logged', protectedFunction(async(ddpMessage) => {
const { eventName } = ddpMessage.fields;
if (/user-status/.test(eventName)) {
@ -859,6 +861,7 @@ const RocketChat = {
isOmnichannelModuleAvailable,
getSlashCommands,
getRoles,
setRoles,
parseSettings: settings => settings.reduce((ret, item) => {
ret[item._id] = defaultSettings[item._id] && item[defaultSettings[item._id].type];
if (item._id === 'Hide_System_Messages') {

View File

@ -19,6 +19,7 @@ import createDiscussion from './createDiscussion';
import enterpriseModules from './enterpriseModules';
import encryption from './encryption';
import permissions from './permissions';
import roles from './roles';
import inquiry from '../ee/omnichannel/reducers/inquiry';
@ -43,5 +44,6 @@ export default combineReducers({
inquiry,
enterpriseModules,
encryption,
permissions
permissions,
roles
});

View File

@ -1,8 +1,6 @@
import { PERMISSIONS } from '../actions/actionsTypes';
const initialState = {
permissions: {}
};
const initialState = {};
export default function permissions(state = initialState, action) {
switch (action.type) {

22
app/reducers/roles.js Normal file
View File

@ -0,0 +1,22 @@
import { ROLES } from '../actions/actionsTypes';
const initialState = {};
export default function permissions(state = initialState, action) {
switch (action.type) {
case ROLES.SET:
return action.roles;
case ROLES.UPDATE:
return {
...state,
[action.payload.id]: action.payload.desc || action.payload.id
};
case ROLES.REMOVE: {
const newState = { ...state };
delete newState[action.payload.id];
return newState;
}
default:
return state;
}
}

View File

@ -90,6 +90,7 @@ const fetchCustomEmojis = function* fetchCustomEmojis() {
};
const fetchRoles = function* fetchRoles() {
RocketChat.subscribe('stream-roles', 'roles');
yield RocketChat.getRoles();
};

View File

@ -125,6 +125,7 @@ const handleSelectServer = function* handleSelectServer({ server, version, fetch
RocketChat.setSettings();
RocketChat.setCustomEmojis();
RocketChat.setPermissions();
RocketChat.setRoles();
RocketChat.setEnterpriseModules();
let serverInfo;

View File

@ -6,7 +6,6 @@ import { connect } from 'react-redux';
import UAParser from 'ua-parser-js';
import isEmpty from 'lodash/isEmpty';
import database from '../../lib/database';
import { CustomIcon } from '../../lib/Icons';
import Status from '../../containers/Status';
import Avatar from '../../containers/Avatar';
@ -55,7 +54,8 @@ class RoomInfoView extends React.Component {
theme: PropTypes.string,
isMasterDetail: PropTypes.bool,
jitsiEnabled: PropTypes.bool,
editRoomPermission: PropTypes.array
editRoomPermission: PropTypes.array,
roles: PropTypes.array
}
constructor(props) {
@ -133,18 +133,9 @@ class RoomInfoView extends React.Component {
return room.t === 'l';
}
getRoleDescription = async(id) => {
const db = database.active;
try {
const rolesCollection = db.get('roles');
const role = await rolesCollection.find(id);
if (role) {
return role.description;
}
return null;
} catch (e) {
return null;
}
getRoleDescription = (id) => {
const { roles } = this.props;
return roles[id];
};
loadVisitor = async() => {
@ -378,7 +369,8 @@ const mapStateToProps = state => ({
rooms: state.room.rooms,
isMasterDetail: state.app.isMasterDetail,
jitsiEnabled: state.settings.Jitsi_Enabled || false,
editRoomPermission: state.permissions['edit-room']
editRoomPermission: state.permissions['edit-room'],
roles: state.roles
});
export default connect(mapStateToProps)(withTheme(RoomInfoView));

View File

@ -49,7 +49,8 @@ class RoomMembersView extends React.Component {
room: PropTypes.object,
user: PropTypes.shape({
id: PropTypes.string,
token: PropTypes.string
token: PropTypes.string,
roles: PropTypes.array
}),
showActionSheet: PropTypes.func,
theme: PropTypes.string,