[NEW] Create Team (#3082)
Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
8f571fd029
commit
1f0ff830a3
|
@ -0,0 +1,5 @@
|
||||||
|
// https://github.com/RocketChat/Rocket.Chat/blob/develop/definition/ITeam.ts
|
||||||
|
export const TEAM_TYPE = {
|
||||||
|
PUBLIC: 0,
|
||||||
|
PRIVATE: 1
|
||||||
|
};
|
|
@ -709,5 +709,12 @@
|
||||||
"This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}",
|
"This_room_encryption_has_been_disabled_by__username_": "This room's encryption has been disabled by {{username}}",
|
||||||
"Teams": "Teams",
|
"Teams": "Teams",
|
||||||
"No_team_channels_found": "No channels found",
|
"No_team_channels_found": "No channels found",
|
||||||
"Team_not_found": "Team not found"
|
"Team_not_found": "Team not found",
|
||||||
|
"Create_Team": "Create Team",
|
||||||
|
"Team_Name": "Team Name",
|
||||||
|
"Private_Team": "Private Team",
|
||||||
|
"Read_Only_Team": "Read Only Team",
|
||||||
|
"Broadcast_Team": "Broadcast Team",
|
||||||
|
"creating_team" : "creating team",
|
||||||
|
"team-name-already-exists": "A team with that name already exists"
|
||||||
}
|
}
|
|
@ -60,6 +60,7 @@ import UserPreferences from './userPreferences';
|
||||||
import { Encryption } from './encryption';
|
import { Encryption } from './encryption';
|
||||||
import EventEmitter from '../utils/events';
|
import EventEmitter from '../utils/events';
|
||||||
import { sanitizeLikeString } from './database/utils';
|
import { sanitizeLikeString } from './database/utils';
|
||||||
|
import { TEAM_TYPE } from '../definition/ITeam';
|
||||||
|
|
||||||
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
const TOKEN_KEY = 'reactnativemeteor_usertoken';
|
||||||
const CURRENT_SERVER = 'currentServer';
|
const CURRENT_SERVER = 'currentServer';
|
||||||
|
@ -732,7 +733,24 @@ const RocketChat = {
|
||||||
prid, pmid, t_name, reply, users, encrypted
|
prid, pmid, t_name, reply, users, encrypted
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
createTeam({
|
||||||
|
name, users, type, readOnly, broadcast, encrypted
|
||||||
|
}) {
|
||||||
|
const params = {
|
||||||
|
name,
|
||||||
|
users,
|
||||||
|
type: type ? TEAM_TYPE.PRIVATE : TEAM_TYPE.PUBLIC,
|
||||||
|
room: {
|
||||||
|
readOnly,
|
||||||
|
extraData: {
|
||||||
|
broadcast,
|
||||||
|
encrypted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// RC 3.13.0
|
||||||
|
return this.post('teams.create', params);
|
||||||
|
},
|
||||||
joinRoom(roomId, joinCode, type) {
|
joinRoom(roomId, joinCode, type) {
|
||||||
// TODO: join code
|
// TODO: join code
|
||||||
// RC 0.48.0
|
// RC 0.48.0
|
||||||
|
|
|
@ -21,6 +21,10 @@ const createGroupChat = function createGroupChat() {
|
||||||
return RocketChat.createGroupChat();
|
return RocketChat.createGroupChat();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createTeam = function createTeam(data) {
|
||||||
|
return RocketChat.createTeam(data);
|
||||||
|
};
|
||||||
|
|
||||||
const handleRequest = function* handleRequest({ data }) {
|
const handleRequest = function* handleRequest({ data }) {
|
||||||
try {
|
try {
|
||||||
const auth = yield select(state => state.login.isAuthenticated);
|
const auth = yield select(state => state.login.isAuthenticated);
|
||||||
|
@ -29,7 +33,21 @@ const handleRequest = function* handleRequest({ data }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let sub;
|
let sub;
|
||||||
if (data.group) {
|
if (data.isTeam) {
|
||||||
|
const {
|
||||||
|
type,
|
||||||
|
readOnly,
|
||||||
|
broadcast,
|
||||||
|
encrypted
|
||||||
|
} = data;
|
||||||
|
logEvent(events.CR_CREATE, {
|
||||||
|
type,
|
||||||
|
readOnly,
|
||||||
|
broadcast,
|
||||||
|
encrypted
|
||||||
|
});
|
||||||
|
sub = yield call(createTeam, data);
|
||||||
|
} else if (data.group) {
|
||||||
logEvent(events.SELECTED_USERS_CREATE_GROUP);
|
logEvent(events.SELECTED_USERS_CREATE_GROUP);
|
||||||
const result = yield call(createGroupChat);
|
const result = yield call(createGroupChat);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
@ -56,7 +74,7 @@ const handleRequest = function* handleRequest({ data }) {
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
yield db.action(async() => {
|
yield db.action(async() => {
|
||||||
await subCollection.create((s) => {
|
await subCollection.create((s) => {
|
||||||
s._raw = sanitizedRaw({ id: sub.rid }, subCollection.schema);
|
s._raw = sanitizedRaw({ id: sub.team ? sub.team.roomId : sub.rid }, subCollection.schema);
|
||||||
Object.assign(s, sub);
|
Object.assign(s, sub);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -64,7 +82,17 @@ const handleRequest = function* handleRequest({ data }) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
yield put(createChannelSuccess(sub));
|
let successParams = {};
|
||||||
|
if (data.isTeam) {
|
||||||
|
successParams = {
|
||||||
|
...sub.team,
|
||||||
|
rid: sub.team.roomId,
|
||||||
|
t: sub.team.type ? 'p' : 'c'
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
successParams = data;
|
||||||
|
}
|
||||||
|
yield put(createChannelSuccess(successParams));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CR_CREATE_F']);
|
logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CR_CREATE_F']);
|
||||||
yield put(createChannelFailure(err));
|
yield put(createChannelFailure(err));
|
||||||
|
@ -81,7 +109,7 @@ const handleSuccess = function* handleSuccess({ data }) {
|
||||||
|
|
||||||
const handleFailure = function handleFailure({ err }) {
|
const handleFailure = function handleFailure({ err }) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const msg = err.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
const msg = err.data ? I18n.t(err.data.error) : err.reason || I18n.t('There_was_an_error_while_action', { action: I18n.t('creating_channel') });
|
||||||
showErrorAlert(msg);
|
showErrorAlert(msg);
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,6 +88,7 @@ export default {
|
||||||
|
|
||||||
// NEW MESSAGE VIEW
|
// NEW MESSAGE VIEW
|
||||||
NEW_MSG_CREATE_CHANNEL: 'new_msg_create_channel',
|
NEW_MSG_CREATE_CHANNEL: 'new_msg_create_channel',
|
||||||
|
NEW_MSG_CREATE_TEAM: 'new_msg_create_team',
|
||||||
NEW_MSG_CREATE_GROUP_CHAT: 'new_msg_create_group_chat',
|
NEW_MSG_CREATE_GROUP_CHAT: 'new_msg_create_group_chat',
|
||||||
NEW_MSG_CREATE_DISCUSSION: 'new_msg_create_discussion',
|
NEW_MSG_CREATE_DISCUSSION: 'new_msg_create_discussion',
|
||||||
NEW_MSG_CHAT_WITH_USER: 'new_msg_chat_with_user',
|
NEW_MSG_CHAT_WITH_USER: 'new_msg_chat_with_user',
|
||||||
|
|
|
@ -45,3 +45,5 @@ export const getBadgeColor = ({ subscription, messageId, theme }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeThreadName = messageRecord => messageRecord.msg || messageRecord?.attachments[0]?.title;
|
export const makeThreadName = messageRecord => messageRecord.msg || messageRecord?.attachments[0]?.title;
|
||||||
|
|
||||||
|
export const isTeamRoom = ({ teamId, joined }) => teamId && joined;
|
||||||
|
|
|
@ -68,12 +68,9 @@ const styles = StyleSheet.create({
|
||||||
});
|
});
|
||||||
|
|
||||||
class CreateChannelView extends React.Component {
|
class CreateChannelView extends React.Component {
|
||||||
static navigationOptions = () => ({
|
|
||||||
title: I18n.t('Create_Channel')
|
|
||||||
});
|
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
navigation: PropTypes.object,
|
navigation: PropTypes.object,
|
||||||
|
route: PropTypes.object,
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
create: PropTypes.func.isRequired,
|
create: PropTypes.func.isRequired,
|
||||||
removeUser: PropTypes.func.isRequired,
|
removeUser: PropTypes.func.isRequired,
|
||||||
|
@ -89,12 +86,19 @@ class CreateChannelView extends React.Component {
|
||||||
theme: PropTypes.string
|
theme: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
const { route } = this.props;
|
||||||
|
const isTeam = route?.params?.isTeam || false;
|
||||||
|
this.state = {
|
||||||
channelName: '',
|
channelName: '',
|
||||||
type: true,
|
type: true,
|
||||||
readOnly: false,
|
readOnly: false,
|
||||||
encrypted: false,
|
encrypted: false,
|
||||||
broadcast: false
|
broadcast: false,
|
||||||
|
isTeam
|
||||||
|
};
|
||||||
|
this.setHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
|
@ -134,6 +138,15 @@ class CreateChannelView extends React.Component {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setHeader = () => {
|
||||||
|
const { navigation } = this.props;
|
||||||
|
const { isTeam } = this.state;
|
||||||
|
|
||||||
|
navigation.setOptions({
|
||||||
|
title: isTeam ? I18n.t('Create_Team') : I18n.t('Create_Channel')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toggleRightButton = (channelName) => {
|
toggleRightButton = (channelName) => {
|
||||||
const { navigation } = this.props;
|
const { navigation } = this.props;
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
|
@ -152,9 +165,11 @@ class CreateChannelView extends React.Component {
|
||||||
|
|
||||||
submit = () => {
|
submit = () => {
|
||||||
const {
|
const {
|
||||||
channelName, type, readOnly, broadcast, encrypted
|
channelName, type, readOnly, broadcast, encrypted, isTeam
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { users: usersProps, isFetching, create } = this.props;
|
const {
|
||||||
|
users: usersProps, isFetching, create
|
||||||
|
} = this.props;
|
||||||
|
|
||||||
if (!channelName.trim() || isFetching) {
|
if (!channelName.trim() || isFetching) {
|
||||||
return;
|
return;
|
||||||
|
@ -163,9 +178,9 @@ class CreateChannelView extends React.Component {
|
||||||
// transform users object into array of usernames
|
// transform users object into array of usernames
|
||||||
const users = usersProps.map(user => user.name);
|
const users = usersProps.map(user => user.name);
|
||||||
|
|
||||||
// create channel
|
// create channel or team
|
||||||
create({
|
create({
|
||||||
name: channelName, users, type, readOnly, broadcast, encrypted
|
name: channelName, users, type, readOnly, broadcast, encrypted, isTeam
|
||||||
});
|
});
|
||||||
|
|
||||||
Review.pushPositiveEvent();
|
Review.pushPositiveEvent();
|
||||||
|
@ -196,11 +211,12 @@ class CreateChannelView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderType() {
|
renderType() {
|
||||||
const { type } = this.state;
|
const { type, isTeam } = this.state;
|
||||||
|
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'type',
|
id: 'type',
|
||||||
value: type,
|
value: type,
|
||||||
label: 'Private_Channel',
|
label: isTeam ? 'Private_Team' : 'Private_Channel',
|
||||||
onValueChange: (value) => {
|
onValueChange: (value) => {
|
||||||
logEvent(events.CR_TOGGLE_TYPE);
|
logEvent(events.CR_TOGGLE_TYPE);
|
||||||
// If we set the channel as public, encrypted status should be false
|
// If we set the channel as public, encrypted status should be false
|
||||||
|
@ -210,11 +226,12 @@ class CreateChannelView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderReadOnly() {
|
renderReadOnly() {
|
||||||
const { readOnly, broadcast } = this.state;
|
const { readOnly, broadcast, isTeam } = this.state;
|
||||||
|
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'readonly',
|
id: 'readonly',
|
||||||
value: readOnly,
|
value: readOnly,
|
||||||
label: 'Read_Only_Channel',
|
label: isTeam ? 'Read_Only_Team' : 'Read_Only_Channel',
|
||||||
onValueChange: (value) => {
|
onValueChange: (value) => {
|
||||||
logEvent(events.CR_TOGGLE_READ_ONLY);
|
logEvent(events.CR_TOGGLE_READ_ONLY);
|
||||||
this.setState({ readOnly: value });
|
this.setState({ readOnly: value });
|
||||||
|
@ -244,11 +261,12 @@ class CreateChannelView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBroadcast() {
|
renderBroadcast() {
|
||||||
const { broadcast, readOnly } = this.state;
|
const { broadcast, readOnly, isTeam } = this.state;
|
||||||
|
|
||||||
return this.renderSwitch({
|
return this.renderSwitch({
|
||||||
id: 'broadcast',
|
id: 'broadcast',
|
||||||
value: broadcast,
|
value: broadcast,
|
||||||
label: 'Broadcast_Channel',
|
label: isTeam ? 'Broadcast_Team' : 'Broadcast_Channel',
|
||||||
onValueChange: (value) => {
|
onValueChange: (value) => {
|
||||||
logEvent(events.CR_TOGGLE_BROADCAST);
|
logEvent(events.CR_TOGGLE_BROADCAST);
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -301,8 +319,10 @@ class CreateChannelView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { channelName } = this.state;
|
const { channelName, isTeam } = this.state;
|
||||||
const { users, isFetching, theme } = this.props;
|
const {
|
||||||
|
users, isFetching, theme
|
||||||
|
} = this.props;
|
||||||
const userCount = users.length;
|
const userCount = users.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -312,18 +332,18 @@ class CreateChannelView extends React.Component {
|
||||||
keyboardVerticalOffset={128}
|
keyboardVerticalOffset={128}
|
||||||
>
|
>
|
||||||
<StatusBar />
|
<StatusBar />
|
||||||
<SafeAreaView testID='create-channel-view'>
|
<SafeAreaView testID={isTeam ? 'create-team-view' : 'create-channel-view'}>
|
||||||
<ScrollView {...scrollPersistTaps}>
|
<ScrollView {...scrollPersistTaps}>
|
||||||
<View style={[sharedStyles.separatorVertical, { borderColor: themes[theme].separatorColor }]}>
|
<View style={[sharedStyles.separatorVertical, { borderColor: themes[theme].separatorColor }]}>
|
||||||
<TextInput
|
<TextInput
|
||||||
autoFocus
|
autoFocus
|
||||||
style={[styles.input, { backgroundColor: themes[theme].backgroundColor }]}
|
style={[styles.input, { backgroundColor: themes[theme].backgroundColor }]}
|
||||||
label={I18n.t('Channel_Name')}
|
label={isTeam ? I18n.t('Team_Name') : I18n.t('Channel_Name')}
|
||||||
value={channelName}
|
value={channelName}
|
||||||
onChangeText={this.onChangeText}
|
onChangeText={this.onChangeText}
|
||||||
placeholder={I18n.t('Channel_Name')}
|
placeholder={isTeam ? I18n.t('Team_Name') : I18n.t('Channel_Name')}
|
||||||
returnKeyType='done'
|
returnKeyType='done'
|
||||||
testID='create-channel-name'
|
testID={isTeam ? 'create-team-name' : 'create-channel-name'}
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
autoCapitalize='none'
|
autoCapitalize='none'
|
||||||
theme={theme}
|
theme={theme}
|
||||||
|
|
|
@ -116,6 +116,12 @@ class NewMessageView extends React.Component {
|
||||||
navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView') });
|
navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView') });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createTeam = () => {
|
||||||
|
logEvent(events.NEW_MSG_CREATE_TEAM);
|
||||||
|
const { navigation } = this.props;
|
||||||
|
navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView', { isTeam: true }) });
|
||||||
|
}
|
||||||
|
|
||||||
createGroupChat = () => {
|
createGroupChat = () => {
|
||||||
logEvent(events.NEW_MSG_CREATE_GROUP_CHAT);
|
logEvent(events.NEW_MSG_CREATE_GROUP_CHAT);
|
||||||
const { createChannel, maxUsers, navigation } = this.props;
|
const { createChannel, maxUsers, navigation } = this.props;
|
||||||
|
@ -172,6 +178,12 @@ class NewMessageView extends React.Component {
|
||||||
testID: 'new-message-view-create-channel',
|
testID: 'new-message-view-create-channel',
|
||||||
first: true
|
first: true
|
||||||
})}
|
})}
|
||||||
|
{this.renderButton({
|
||||||
|
onPress: this.createTeam,
|
||||||
|
title: I18n.t('Create_Team'),
|
||||||
|
icon: 'teams',
|
||||||
|
testID: 'new-message-view-create-team'
|
||||||
|
})}
|
||||||
{maxUsers > 2 ? this.renderButton({
|
{maxUsers > 2 ? this.renderButton({
|
||||||
onPress: this.createGroupChat,
|
onPress: this.createGroupChat,
|
||||||
title: I18n.t('Create_Direct_Messages'),
|
title: I18n.t('Create_Direct_Messages'),
|
||||||
|
@ -253,7 +265,7 @@ const mapStateToProps = state => ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
createChannel: params => dispatch(createChannelRequest(params))
|
create: params => dispatch(createChannelRequest(params))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
export default connect(mapStateToProps, mapDispatchToProps)(withTheme(NewMessageView));
|
||||||
|
|
|
@ -7,6 +7,7 @@ import * as HeaderButton from '../../containers/HeaderButton';
|
||||||
import database from '../../lib/database';
|
import database from '../../lib/database';
|
||||||
import { getUserSelector } from '../../selectors/login';
|
import { getUserSelector } from '../../selectors/login';
|
||||||
import { logEvent, events } from '../../utils/log';
|
import { logEvent, events } from '../../utils/log';
|
||||||
|
import { isTeamRoom } from '../../utils/room';
|
||||||
|
|
||||||
class RightButtonsContainer extends Component {
|
class RightButtonsContainer extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -15,10 +16,11 @@ class RightButtonsContainer extends Component {
|
||||||
rid: PropTypes.string,
|
rid: PropTypes.string,
|
||||||
t: PropTypes.string,
|
t: PropTypes.string,
|
||||||
tmid: PropTypes.string,
|
tmid: PropTypes.string,
|
||||||
teamId: PropTypes.bool,
|
teamId: PropTypes.string,
|
||||||
navigation: PropTypes.object,
|
navigation: PropTypes.object,
|
||||||
isMasterDetail: PropTypes.bool,
|
isMasterDetail: PropTypes.bool,
|
||||||
toggleFollowThread: PropTypes.func
|
toggleFollowThread: PropTypes.func,
|
||||||
|
joined: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -163,7 +165,7 @@ class RightButtonsContainer extends Component {
|
||||||
isFollowingThread, tunread, tunreadUser, tunreadGroup
|
isFollowingThread, tunread, tunreadUser, tunreadGroup
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const {
|
const {
|
||||||
t, tmid, threadsEnabled, teamId
|
t, tmid, threadsEnabled, teamId, joined
|
||||||
} = this.props;
|
} = this.props;
|
||||||
if (t === 'l') {
|
if (t === 'l') {
|
||||||
return null;
|
return null;
|
||||||
|
@ -181,7 +183,7 @@ class RightButtonsContainer extends Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<HeaderButton.Container>
|
<HeaderButton.Container>
|
||||||
{teamId ? (
|
{isTeamRoom({ teamId, joined }) ? (
|
||||||
<HeaderButton.Item
|
<HeaderButton.Item
|
||||||
iconName='channel-public'
|
iconName='channel-public'
|
||||||
onPress={this.goTeamChannels}
|
onPress={this.goTeamChannels}
|
||||||
|
|
|
@ -38,7 +38,9 @@ import { themes } from '../../constants/colors';
|
||||||
import debounce from '../../utils/debounce';
|
import debounce from '../../utils/debounce';
|
||||||
import ReactionsModal from '../../containers/ReactionsModal';
|
import ReactionsModal from '../../containers/ReactionsModal';
|
||||||
import { LISTENER } from '../../containers/Toast';
|
import { LISTENER } from '../../containers/Toast';
|
||||||
import { getBadgeColor, isBlocked, makeThreadName } from '../../utils/room';
|
import {
|
||||||
|
getBadgeColor, isBlocked, makeThreadName, isTeamRoom
|
||||||
|
} from '../../utils/room';
|
||||||
import { isReadOnly } from '../../utils/isReadOnly';
|
import { isReadOnly } from '../../utils/isReadOnly';
|
||||||
import { isIOS, isTablet } from '../../utils/deviceInfo';
|
import { isIOS, isTablet } from '../../utils/deviceInfo';
|
||||||
import { showErrorAlert } from '../../utils/info';
|
import { showErrorAlert } from '../../utils/info';
|
||||||
|
@ -301,7 +303,7 @@ class RoomView extends React.Component {
|
||||||
|
|
||||||
setHeader = () => {
|
setHeader = () => {
|
||||||
const {
|
const {
|
||||||
room, unreadsCount, roomUserId
|
room, unreadsCount, roomUserId, joined
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const {
|
const {
|
||||||
navigation, isMasterDetail, theme, baseUrl, user, insets, route
|
navigation, isMasterDetail, theme, baseUrl, user, insets, route
|
||||||
|
@ -331,7 +333,7 @@ class RoomView extends React.Component {
|
||||||
let numIconsRight = 2;
|
let numIconsRight = 2;
|
||||||
if (tmid) {
|
if (tmid) {
|
||||||
numIconsRight = 1;
|
numIconsRight = 1;
|
||||||
} else if (teamId) {
|
} else if (isTeamRoom({ teamId, joined })) {
|
||||||
numIconsRight = 3;
|
numIconsRight = 3;
|
||||||
}
|
}
|
||||||
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight });
|
const headerTitlePosition = getHeaderTitlePosition({ insets, numIconsRight });
|
||||||
|
@ -380,6 +382,8 @@ class RoomView extends React.Component {
|
||||||
rid={rid}
|
rid={rid}
|
||||||
tmid={tmid}
|
tmid={tmid}
|
||||||
teamId={teamId}
|
teamId={teamId}
|
||||||
|
teamMain={teamMain}
|
||||||
|
joined={joined}
|
||||||
t={t}
|
t={t}
|
||||||
navigation={navigation}
|
navigation={navigation}
|
||||||
toggleFollowThread={this.toggleFollowThread}
|
toggleFollowThread={this.toggleFollowThread}
|
||||||
|
|
|
@ -17,7 +17,6 @@ import sharedStyles from './Styles';
|
||||||
import * as HeaderButton from '../containers/HeaderButton';
|
import * as HeaderButton from '../containers/HeaderButton';
|
||||||
import StatusBar from '../containers/StatusBar';
|
import StatusBar from '../containers/StatusBar';
|
||||||
import { themes } from '../constants/colors';
|
import { themes } from '../constants/colors';
|
||||||
import { animateNextTransition } from '../utils/layoutAnimation';
|
|
||||||
import { withTheme } from '../theme';
|
import { withTheme } from '../theme';
|
||||||
import { getUserSelector } from '../selectors/login';
|
import { getUserSelector } from '../selectors/login';
|
||||||
import {
|
import {
|
||||||
|
@ -28,6 +27,9 @@ import {
|
||||||
import { showErrorAlert } from '../utils/info';
|
import { showErrorAlert } from '../utils/info';
|
||||||
import SafeAreaView from '../containers/SafeAreaView';
|
import SafeAreaView from '../containers/SafeAreaView';
|
||||||
|
|
||||||
|
const ITEM_WIDTH = 250;
|
||||||
|
const getItemLayout = (_, index) => ({ length: ITEM_WIDTH, offset: ITEM_WIDTH * index, index });
|
||||||
|
|
||||||
class SelectedUsersView extends React.Component {
|
class SelectedUsersView extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
baseUrl: PropTypes.string,
|
baseUrl: PropTypes.string,
|
||||||
|
@ -50,7 +52,7 @@ class SelectedUsersView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.init();
|
this.init();
|
||||||
|
this.flatlist = React.createRef();
|
||||||
const maxUsers = props.route.params?.maxUsers;
|
const maxUsers = props.route.params?.maxUsers;
|
||||||
this.state = {
|
this.state = {
|
||||||
maxUsers,
|
maxUsers,
|
||||||
|
@ -151,7 +153,6 @@ class SelectedUsersView extends React.Component {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
animateNextTransition();
|
|
||||||
if (!this.isChecked(user.name)) {
|
if (!this.isChecked(user.name)) {
|
||||||
if (this.isGroupChat() && users.length === maxUsers) {
|
if (this.isGroupChat() && users.length === maxUsers) {
|
||||||
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
|
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
|
||||||
|
@ -184,15 +185,23 @@ class SelectedUsersView extends React.Component {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFlatListRef = ref => this.flatlist = ref;
|
||||||
|
|
||||||
|
onContentSizeChange = () => this.flatlist.scrollToEnd({ animated: true });
|
||||||
|
|
||||||
renderSelected = () => {
|
renderSelected = () => {
|
||||||
const { users, theme } = this.props;
|
const { users, theme } = this.props;
|
||||||
|
|
||||||
if (users.length === 0) {
|
if (users.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FlatList
|
<FlatList
|
||||||
data={users}
|
data={users}
|
||||||
|
ref={this.setFlatListRef}
|
||||||
|
onContentSizeChange={this.onContentSizeChange}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
keyExtractor={item => item._id}
|
keyExtractor={item => item._id}
|
||||||
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
|
style={[sharedStyles.separatorTop, { borderColor: themes[theme].separatorColor }]}
|
||||||
contentContainerStyle={{ marginVertical: 5 }}
|
contentContainerStyle={{ marginVertical: 5 }}
|
||||||
|
|
|
@ -42,6 +42,11 @@ const data = {
|
||||||
name: `detox-private-${ value }`
|
name: `detox-private-${ value }`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
teams: {
|
||||||
|
private: {
|
||||||
|
name: `detox-team-${ value }`
|
||||||
|
}
|
||||||
|
},
|
||||||
registeringUser: {
|
registeringUser: {
|
||||||
username: `newuser${ value }`,
|
username: `newuser${ value }`,
|
||||||
password: `password${ value }`,
|
password: `password${ value }`,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
const axios = require('axios').default;
|
const axios = require('axios').default;
|
||||||
const data = require('../data');
|
const data = require('../data');
|
||||||
|
const { TEAM_TYPE } = require('../../app/definition/ITeam');
|
||||||
|
|
||||||
let server = data.server
|
let server = data.server
|
||||||
|
|
||||||
|
@ -57,6 +58,24 @@ const createChannelIfNotExists = async (channelname) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createTeamIfNotExists = async (teamname) => {
|
||||||
|
console.log(`Creating private team ${teamname}`)
|
||||||
|
try {
|
||||||
|
await rocketchat.post('teams.create', {
|
||||||
|
"name": teamname,
|
||||||
|
"type": TEAM_TYPE.PRIVATE
|
||||||
|
})
|
||||||
|
} catch (createError) {
|
||||||
|
try { //Maybe it exists already?
|
||||||
|
await rocketchat.get(`teams.info?teamName=${teamname}`)
|
||||||
|
} catch (infoError) {
|
||||||
|
console.log(JSON.stringify(createError))
|
||||||
|
console.log(JSON.stringify(infoError))
|
||||||
|
throw "Failed to find or create private team"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const createGroupIfNotExists = async (groupname) => {
|
const createGroupIfNotExists = async (groupname) => {
|
||||||
console.log(`Creating private group ${groupname}`)
|
console.log(`Creating private group ${groupname}`)
|
||||||
try {
|
try {
|
||||||
|
@ -133,6 +152,13 @@ const setup = async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var teamKey in data.teams) {
|
||||||
|
if (data.teams.hasOwnProperty(teamKey)) {
|
||||||
|
const team = data.teams[teamKey]
|
||||||
|
await createTeamIfNotExists(team.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
const {
|
||||||
|
device, expect, element, by, waitFor
|
||||||
|
} = require('detox');
|
||||||
|
const data = require('../../data');
|
||||||
|
const { tapBack, sleep, navigateToLogin, login, tryTapping } = require('../../helpers/app');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
describe('Create team screen', () => {
|
||||||
|
before(async() => {
|
||||||
|
await device.launchApp({ permissions: { notifications: 'YES' }, delete: true });
|
||||||
|
await navigateToLogin();
|
||||||
|
await login(data.users.regular.username, data.users.regular.password);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('New Message', async() => {
|
||||||
|
before(async() => {
|
||||||
|
await element(by.id('rooms-list-view-create-channel')).tap();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Render', async() => {
|
||||||
|
it('should have team button', async() => {
|
||||||
|
await waitFor(element(by.id('new-message-view-create-channel'))).toBeVisible().withTimeout(2000);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Usage', async() => {
|
||||||
|
it('should navigate to select users', async() => {
|
||||||
|
await element(by.id('new-message-view-create-channel')).tap();
|
||||||
|
await waitFor(element(by.id('select-users-view'))).toExist().withTimeout(5000);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Select Users', async() => {
|
||||||
|
it('should search users', async() => {
|
||||||
|
await element(by.id('select-users-view-search')).replaceText('rocket.cat');
|
||||||
|
await waitFor(element(by.id(`select-users-view-item-rocket.cat`))).toBeVisible().withTimeout(10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should select/unselect user', async() => {
|
||||||
|
// Spotlight issues
|
||||||
|
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||||
|
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000);
|
||||||
|
await element(by.id('selected-user-rocket.cat')).tap();
|
||||||
|
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeNotVisible().withTimeout(10000);
|
||||||
|
// Spotlight issues
|
||||||
|
await element(by.id('select-users-view-item-rocket.cat')).tap();
|
||||||
|
await waitFor(element(by.id('selected-user-rocket.cat'))).toBeVisible().withTimeout(10000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create team', async() => {
|
||||||
|
await element(by.id('selected-users-view-submit')).tap();
|
||||||
|
await waitFor(element(by.id('create-channel-view'))).toExist().withTimeout(10000);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Create Team', async() => {
|
||||||
|
describe('Usage', async() => {
|
||||||
|
it('should get invalid team name', async() => {
|
||||||
|
await element(by.id('create-channel-name')).typeText(`${data.teams.private.name}`);
|
||||||
|
await element(by.id('create-channel-submit')).tap();
|
||||||
|
await element(by.text('OK')).tap();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create private team', async() => {
|
||||||
|
const room = `private${ data.random }`;
|
||||||
|
await element(by.id('create-channel-name')).replaceText('');
|
||||||
|
await element(by.id('create-channel-name')).typeText(room);
|
||||||
|
await element(by.id('create-channel-submit')).tap();
|
||||||
|
await waitFor(element(by.id('room-view'))).toExist().withTimeout(20000);
|
||||||
|
await expect(element(by.id('room-view'))).toExist();
|
||||||
|
await waitFor(element(by.id(`room-view-title-${ room }`))).toExist().withTimeout(6000);
|
||||||
|
await expect(element(by.id(`room-view-title-${ room }`))).toExist();
|
||||||
|
await tapBack();
|
||||||
|
await waitFor(element(by.id('rooms-list-view'))).toExist().withTimeout(10000);
|
||||||
|
await waitFor(element(by.id(`rooms-list-view-item-${ room }`))).toExist().withTimeout(6000);
|
||||||
|
await expect(element(by.id(`rooms-list-view-item-${ room }`))).toExist();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue