[NEW] Log events from RoomsList, SideDrawer and Profile (#2190)

* Create method to track user event to isolate the logic to improve future refactoring

* Track Onboarding view

* Track NewServer view

* Refactor track method due to firebase already send the current screen

* Track default login and all the oAuth options

* Track default sign up in RegisterView

* Change trackUserEvent signature and update all the files

* Track the remaining login services

* track add server, change server and search

* Track SidebarView and refactor to use react-navigation

* Track profile events and handle exceptions

* Track create channel flux

* Track send message to user via NewMessageView

* Track create direct message flux

* Handle failure of create channel and group in the saga

* Track create discussion flux

* Track navigate to directory and its actions

* Track read, favorite and hide a channel, handling its errors

* Track all channels sorting and grouping

* Resolve requests to improve the importing logs and events

* Remove unused events file

* Leave a bugsnag breadcrumb when logging an event

* Move all logEvent to the top of code block and log remaining fail events

* Move all the non-logic-dependent logEvent to the top of code block

* Improve the logging of sidebar events

* Improve events from onboarding and newserver

* Improve events from login and register view, and log enter with apple

* Improve NewMessageView events

* Improve CreateChannel events

* Improve CreateDiscussion and SelectedUsers create group events

* Improve RoomsList events and log trivial events

* Improve ProfileView events

* Remove single line function body for the sidebarNavigate

* Navigate to Status and AdminPanel View using the defined sidebarNavigate method

Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Youssef Muhamad 2020-07-30 10:26:17 -03:00 committed by GitHub
parent 0a6e0f6f78
commit e05aa1eb52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 232 additions and 65 deletions

View File

@ -78,7 +78,7 @@ class LoginServices extends React.PureComponent {
}
onPressFacebook = () => {
logEvent(events.LOGIN_WITH_FACEBOOK);
logEvent(events.ENTER_WITH_FACEBOOK);
const { services, server } = this.props;
const { clientId } = services.facebook;
const endpoint = 'https://m.facebook.com/v2.9/dialog/oauth';
@ -90,7 +90,7 @@ class LoginServices extends React.PureComponent {
}
onPressGithub = () => {
logEvent(events.LOGIN_WITH_GITHUB);
logEvent(events.ENTER_WITH_GITHUB);
const { services, server } = this.props;
const { clientId } = services.github;
const endpoint = `https://github.com/login?client_id=${ clientId }&return_to=${ encodeURIComponent('/login/oauth/authorize') }`;
@ -102,7 +102,7 @@ class LoginServices extends React.PureComponent {
}
onPressGitlab = () => {
logEvent(events.LOGIN_WITH_GITLAB);
logEvent(events.ENTER_WITH_GITLAB);
const { services, server, Gitlab_URL } = this.props;
const { clientId } = services.gitlab;
const baseURL = Gitlab_URL ? Gitlab_URL.trim().replace(/\/*$/, '') : 'https://gitlab.com';
@ -115,7 +115,7 @@ class LoginServices extends React.PureComponent {
}
onPressGoogle = () => {
logEvent(events.LOGIN_WITH_GOOGLE);
logEvent(events.ENTER_WITH_GOOGLE);
const { services, server } = this.props;
const { clientId } = services.google;
const endpoint = 'https://accounts.google.com/o/oauth2/auth';
@ -127,7 +127,7 @@ class LoginServices extends React.PureComponent {
}
onPressLinkedin = () => {
logEvent(events.LOGIN_WITH_LINKEDIN);
logEvent(events.ENTER_WITH_LINKEDIN);
const { services, server } = this.props;
const { clientId } = services.linkedin;
const endpoint = 'https://www.linkedin.com/oauth/v2/authorization';
@ -139,7 +139,7 @@ class LoginServices extends React.PureComponent {
}
onPressMeteor = () => {
logEvent(events.LOGIN_WITH_METEOR);
logEvent(events.ENTER_WITH_METEOR);
const { services, server } = this.props;
const { clientId } = services['meteor-developer'];
const endpoint = 'https://www.meteor.com/oauth2/authorize';
@ -150,7 +150,7 @@ class LoginServices extends React.PureComponent {
}
onPressTwitter = () => {
logEvent(events.LOGIN_WITH_TWITTER);
logEvent(events.ENTER_WITH_TWITTER);
const { server } = this.props;
const state = this.getOAuthState();
const url = `${ server }/_oauth/twitter/?requestTokenAndRedirect=true&state=${ state }`;
@ -158,7 +158,7 @@ class LoginServices extends React.PureComponent {
}
onPressWordpress = () => {
logEvent(events.LOGIN_WITH_WORDPRESS);
logEvent(events.ENTER_WITH_WORDPRESS);
const { services, server } = this.props;
const { clientId, serverURL } = services.wordpress;
const endpoint = `${ serverURL }/oauth/authorize`;
@ -170,7 +170,7 @@ class LoginServices extends React.PureComponent {
}
onPressCustomOAuth = (loginService) => {
logEvent(events.LOGIN_WITH_CUSTOM_OAUTH);
logEvent(events.ENTER_WITH_CUSTOM_OAUTH);
const { server } = this.props;
const {
serverURL, authorizePath, clientId, scope, service
@ -185,7 +185,7 @@ class LoginServices extends React.PureComponent {
}
onPressSaml = (loginService) => {
logEvent(events.LOGIN_WITH_SAML);
logEvent(events.ENTER_WITH_SAML);
const { server } = this.props;
const { clientConfig } = loginService;
const { provider } = clientConfig;
@ -195,7 +195,7 @@ class LoginServices extends React.PureComponent {
}
onPressCas = () => {
logEvent(events.LOGIN_WITH_CAS);
logEvent(events.ENTER_WITH_CAS);
const { server, CAS_login_url } = this.props;
const ssoToken = random(17);
const url = `${ CAS_login_url }?service=${ server }/_cas/${ ssoToken }`;
@ -203,6 +203,7 @@ class LoginServices extends React.PureComponent {
}
onPressAppleLogin = async() => {
logEvent(events.ENTER_WITH_APPLE);
try {
const { fullName, email, identityToken } = await AppleAuthentication.signInAsync({
requestedScopes: [
@ -213,7 +214,7 @@ class LoginServices extends React.PureComponent {
await RocketChat.loginOAuthOrSso({ fullName, email, identityToken });
} catch {
// Do nothing
logEvent(events.ENTER_WITH_APPLE_F);
}
}

View File

@ -10,6 +10,7 @@ import RocketChat from '../lib/rocketchat';
import Navigation from '../lib/Navigation';
import database from '../lib/database';
import I18n from '../i18n';
import { logEvent, events } from '../utils/log';
import { goRoom } from '../utils/goRoom';
const createChannel = function createChannel(data) {
@ -29,11 +30,14 @@ const handleRequest = function* handleRequest({ data }) {
let sub;
if (data.group) {
logEvent(events.SELECTED_USERS_CREATE_GROUP);
const result = yield call(createGroupChat);
if (result.success) {
({ room: sub } = result);
}
} else {
const { type, readOnly, broadcast } = data;
logEvent(events.CREATE_CHANNEL_CREATE, { type: type ? 'private' : 'public', readOnly, broadcast });
sub = yield call(createChannel, data);
}
@ -52,6 +56,7 @@ const handleRequest = function* handleRequest({ data }) {
yield put(createChannelSuccess(sub));
} catch (err) {
logEvent(events[data.group ? 'SELECTED_USERS_CREATE_GROUP_F' : 'CREATE_CHANNEL_CREATE_F']);
yield put(createChannelFailure(err));
}
};

View File

@ -7,12 +7,14 @@ import { CREATE_DISCUSSION, LOGIN } from '../actions/actionsTypes';
import { createDiscussionSuccess, createDiscussionFailure } from '../actions/createDiscussion';
import RocketChat from '../lib/rocketchat';
import database from '../lib/database';
import { logEvent, events } from '../utils/log';
const create = function* create(data) {
return yield RocketChat.createDiscussion(data);
};
const handleRequest = function* handleRequest({ data }) {
logEvent(events.CREATE_DISCUSSION_CREATE);
try {
const auth = yield select(state => state.login.isAuthenticated);
if (!auth) {
@ -35,12 +37,13 @@ const handleRequest = function* handleRequest({ data }) {
} catch {
// do nothing
}
yield put(createDiscussionSuccess(sub));
} else {
logEvent(events.CREATE_DISCUSSION_CREATE_F);
yield put(createDiscussionFailure(result));
}
} catch (err) {
logEvent(events.CREATE_DISCUSSION_CREATE_F);
yield put(createDiscussionFailure(err));
}
};

View File

@ -32,7 +32,7 @@ const loginCall = args => RocketChat.login(args);
const logoutCall = args => RocketChat.logout(args);
const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnError = false }) {
logEvent(events.DEFAULT_LOGIN);
logEvent(events.LOGIN_DEFAULT_LOGIN);
try {
let result;
if (credentials.resume) {
@ -53,7 +53,7 @@ const handleLoginRequest = function* handleLoginRequest({ credentials, logoutOnE
if (logoutOnError && (e.data && e.data.message && /you've been logged out by the server/i.test(e.data.message))) {
yield put(logout(true));
} else {
logEvent(events.DEFAULT_LOGIN_FAIL);
logEvent(events.LOGIN_DEFAULT_LOGIN_F);
yield put(loginFailure(e));
}
}

View File

@ -1,24 +1,108 @@
export default {
JOIN_A_WORKSPACE: 'join_a_workspace',
CREATE_NEW_WORKSPACE: 'create_new_workspace',
CREATE_NEW_WORKSPACE_FAIL: 'create_new_workspace_fail',
CONNECT_TO_WORKSPACE: 'connect_to_workspace',
CONNECT_TO_WORKSPACE_FAIL: 'connect_to_workspace_fail',
JOIN_OPEN_WORKSPACE: 'join_open_workspace',
DEFAULT_LOGIN: 'default_login',
DEFAULT_LOGIN_FAIL: 'default_login_fail',
DEFAULT_SIGN_UP: 'default_sign_up',
DEFAULT_SIGN_UP_FAIL: 'default_sign_up_fail',
FORGOT_PASSWORD: 'forgot_password',
LOGIN_WITH_FACEBOOK: 'login_with_facebook',
LOGIN_WITH_GITHUB: 'login_with_github',
LOGIN_WITH_GITLAB: 'login_with_gitlab',
LOGIN_WITH_LINKEDIN: 'login_with_linkedin',
LOGIN_WITH_GOOGLE: 'login_with_google',
LOGIN_WITH_METEOR: 'login_with_meteor',
LOGIN_WITH_TWITTER: 'login_with_twitter',
LOGIN_WITH_WORDPRESS: 'login_with_wordpress',
LOGIN_WITH_CUSTOM_OAUTH: 'login_with_custom_oauth',
LOGIN_WITH_SAML: 'login_with_saml',
LOGIN_WITH_CAS: 'login_with_cas'
// ONBOARDING VIEW
ONBOARD_JOIN_A_WORKSPACE: 'onboard_join_a_workspace',
ONBOARD_CREATE_NEW_WORKSPACE: 'onboard_create_new_workspace',
ONBOARD_CREATE_NEW_WORKSPACE_F: 'onboard_create_new_workspace_f',
// NEW SERVER VIEW
NEWSERVER_CONNECT_TO_WORKSPACE: 'newserver_connect_to_workspace',
NEWSERVER_CONNECT_TO_WORKSPACE_F: 'newserver_connect_to_workspace_f',
NEWSERVER_JOIN_OPEN_WORKSPACE: 'newserver_join_open_workspace',
// LOGIN VIEW
LOGIN_DEFAULT_LOGIN: 'login_default_login',
LOGIN_DEFAULT_LOGIN_F: 'login_default_login_f',
// FORGOT PASSWORD VIEW
FP_FORGOT_PASSWORD: 'fp_forgot_password',
FP_FORGOT_PASSWORD_F: 'fp_forgot_password_f',
// REGISTER VIEW
REGISTER_DEFAULT_SIGN_UP: 'register_default_sign_up',
REGISTER_DEFAULT_SIGN_UP_F: 'register_default_sign_up_f',
// LOGIN AND REGISTER VIEW
ENTER_WITH_FACEBOOK: 'enter_with_facebook',
ENTER_WITH_GITHUB: 'enter_with_github',
ENTER_WITH_GITLAB: 'enter_with_gitlab',
ENTER_WITH_LINKEDIN: 'enter_with_linkedin',
ENTER_WITH_GOOGLE: 'enter_with_google',
ENTER_WITH_METEOR: 'enter_with_meteor',
ENTER_WITH_TWITTER: 'enter_with_twitter',
ENTER_WITH_WORDPRESS: 'enter_with_wordpress',
ENTER_WITH_CUSTOM_OAUTH: 'enter_with_custom_oauth',
ENTER_WITH_SAML: 'enter_with_saml',
ENTER_WITH_CAS: 'enter_with_cas',
ENTER_WITH_APPLE: 'enter_with_apple',
ENTER_WITH_APPLE_F: 'enter_with_apple_f',
// SIDEBAR VIEW
SIDEBAR_NAVIGATE_TO_STATUS: 'sidebar_navigate_to_status',
SIDEBAR_NAVIGATE_TO_CHATS: 'sidebar_navigate_to_chats',
SIDEBAR_NAVIGATE_TO_PROFILE: 'sidebar_navigate_to_profile',
SIDEBAR_NAVIGATE_TO_SETTINGS: 'sidebar_navigate_to_settings',
SIDEBAR_NAVIGATE_TO_ADMINPANEL: 'sidebar_navigate_to_admin_panel',
// ROOMS LIST VIEW
RL_TOGGLE_SERVER_DROPDOWN: 'rl_toggle_server_dropdown',
RL_ADD_SERVER: 'rl_add_server',
RL_CHANGE_SERVER: 'rl_change_server',
RL_NAVIGATE_TO_NEW_MSG: 'rl_navigate_to_new_msg',
RL_SEARCH: 'rl_search',
RL_NAVIGATE_TO_DIRECTORY: 'rl_navigate_to_directory',
RL_GO_TO_ROOM: 'rl_go_to_room',
RL_FAVORITE_CHANNEL: 'rl_favorite_channel',
RL_UNFAVORITE_CHANNEL: 'rl_unfavorite_channel',
RL_TOGGLE_FAVORITE_F: 'rl_toggle_favorite_f',
RL_READ_CHANNEL: 'rl_read_channel',
RL_UNREAD_CHANNEL: 'rl_unread_channel',
RL_TOGGLE_READ_F: 'rl_toggle_read_f',
RL_HIDE_CHANNEL: 'rl_hide_channel',
RL_HIDE_CHANNEL_F: 'rl_hide_channel_f',
RL_TOGGLE_SORT_DROPDOWN: 'rl_toggle_sort_dropdown',
RL_SORT_CHANNELS_BY_NAME: 'rl_sort_channels_by_name',
RL_SORT_CHANNELS_BY_ACTIVITY: 'rl_sort_channels_by_activity',
RL_SORT_CHANNELS_FAIL: 'rl_sort_channels_fail',
RL_GROUP_CHANNELS_BY_TYPE: 'rl_group_channels_by_type',
RL_GROUP_CHANNELS_BY_FAVORITE: 'rl_group_channels_by_favorite',
RL_GROUP_CHANNELS_BY_UNREAD: 'rl_group_channels_by_unread',
// DIRECTORY VIEW
DIRECTORY_SEARCH_USERS: 'directory_search_users',
DIRECTORY_SEARCH_CHANNELS: 'directory_search_channels',
// NEW MESSAGE VIEW
NEW_MSG_CREATE_CHANNEL: 'new_msg_create_channel',
NEW_MSG_CREATE_GROUP_CHAT: 'new_msg_create_group_chat',
NEW_MSG_CREATE_DISCUSSION: 'new_msg_create_discussion',
NEW_MSG_CHAT_WITH_USER: 'new_msg_chat_with_user',
// SELECTED USERS VIEW
SELECTED_USERS_ADD_USER: 'selected_users_add_user',
SELECTED_USERS_REMOVE_USER: 'selected_users_remove_user',
SELECTED_USERS_CREATE_GROUP: 'selected_users_create_group',
SELECTED_USERS_CREATE_GROUP_F: 'selected_users_create_group_f',
// CREATE CHANNEL VIEW
CREATE_CHANNEL_CREATE: 'create_channel_create',
CREATE_CHANNEL_CREATE_F: 'create_channel_create_f',
CREATE_CHANNEL_TOGGLE_TYPE: 'create_channel_toggle_type',
CREATE_CHANNEL_TOGGLE_READ_ONLY: 'create_channel_toggle_read_only',
CREATE_CHANNEL_TOGGLE_BROADCAST: 'create_channel_toggle_broadcast',
CREATE_CHANNEL_REMOVE_USER: 'create_channel_remove_user',
// CREATE DISCUSSION VIEW
CREATE_DISCUSSION_CREATE: 'create_discussion_create',
CREATE_DISCUSSION_CREATE_F: 'create_discussion_create_f',
CREATE_DISCUSSION_SELECT_CHANNEL: 'create_discussion_select_channel',
CREATE_DISCUSSION_SELECT_USERS: 'create_discussion_select_users',
// PROFILE VIEW
PROFILE_PICK_AVATAR: 'profile_pick_avatar',
PROFILE_PICK_AVATAR_F: 'profile_pick_avatar_f',
PROFILE_PICK_AVATAR_WITH_URL: 'profile_pick_avatar_with_url',
PROFILE_SAVE_AVATAR: 'profile_save_avatar',
PROFILE_SAVE_AVATAR_F: 'profile_save_avatar_f',
PROFILE_SAVE_CHANGES: 'profile_save_changes',
PROFILE_SAVE_CHANGES_F: 'profile_save_changes_f'
};

View File

@ -21,6 +21,7 @@ import { SWITCH_TRACK_COLOR, themes } from '../constants/colors';
import { withTheme } from '../theme';
import { Review } from '../utils/review';
import { getUserSelector } from '../selectors/login';
import { logEvent, events } from '../utils/log';
import SafeAreaView from '../containers/SafeAreaView';
const styles = StyleSheet.create({
@ -166,6 +167,7 @@ class CreateChannelView extends React.Component {
}
removeUser = (user) => {
logEvent(events.CREATE_CHANNEL_REMOVE_USER);
const { removeUser } = this.props;
removeUser(user);
}
@ -194,7 +196,10 @@ class CreateChannelView extends React.Component {
id: 'type',
value: type,
label: 'Private_Channel',
onValueChange: value => this.setState({ type: value })
onValueChange: (value) => {
logEvent(events.CREATE_CHANNEL_TOGGLE_TYPE);
this.setState({ type: value });
}
});
}
@ -204,7 +209,10 @@ class CreateChannelView extends React.Component {
id: 'readonly',
value: readOnly,
label: 'Read_Only_Channel',
onValueChange: value => this.setState({ readOnly: value }),
onValueChange: (value) => {
logEvent(events.CREATE_CHANNEL_TOGGLE_READ_ONLY);
this.setState({ readOnly: value });
},
disabled: broadcast
});
}
@ -216,6 +224,7 @@ class CreateChannelView extends React.Component {
value: broadcast,
label: 'Broadcast_Channel',
onValueChange: (value) => {
logEvent(events.CREATE_CHANNEL_TOGGLE_BROADCAST);
this.setState({
broadcast: value,
readOnly: value ? true : readOnly

View File

@ -25,6 +25,7 @@ import SelectUsers from './SelectUsers';
import styles from './styles';
import SafeAreaView from '../../containers/SafeAreaView';
import { goRoom } from '../../utils/goRoom';
import { logEvent, events } from '../../utils/log';
class CreateChannelView extends React.Component {
propTypes = {
@ -129,6 +130,16 @@ class CreateChannelView extends React.Component {
);
};
selectChannel = ({ value }) => {
logEvent(events.CREATE_DISCUSSION_SELECT_CHANNEL);
this.setState({ channel: { rid: value } });
}
selectUsers = ({ value }) => {
logEvent(events.CREATE_DISCUSSION_SELECT_USERS);
this.setState({ users: value });
}
render() {
const { name, users } = this.state;
const {
@ -149,7 +160,7 @@ class CreateChannelView extends React.Component {
userId={user.id}
token={user.token}
initial={this.channel && { text: RocketChat.getRoomTitle(this.channel) }}
onChannelSelect={({ value }) => this.setState({ channel: { rid: value } })}
onChannelSelect={this.selectChannel}
theme={theme}
/>
<TextInput
@ -165,7 +176,7 @@ class CreateChannelView extends React.Component {
userId={user.id}
token={user.token}
selected={users}
onUserSelect={({ value }) => this.setState({ users: value })}
onUserSelect={this.selectUsers}
theme={theme}
/>
<TextInput

View File

@ -16,7 +16,7 @@ import StatusBar from '../../containers/StatusBar';
import ActivityIndicator from '../../containers/ActivityIndicator';
import { CloseModalButton } from '../../containers/HeaderButton';
import debounce from '../../utils/debounce';
import log from '../../utils/log';
import log, { logEvent, events } from '../../utils/log';
import Options from './Options';
import { withTheme } from '../../theme';
import { themes } from '../../constants/colors';
@ -115,6 +115,12 @@ class DirectoryView extends React.Component {
changeType = (type) => {
this.setState({ type, data: [] }, () => this.search());
if (type === 'users') {
logEvent(events.DIRECTORY_SEARCH_USERS);
} else if (type === 'channels') {
logEvent(events.DIRECTORY_SEARCH_CHANNELS);
}
}
toggleWorkspace = () => {

View File

@ -12,6 +12,7 @@ import RocketChat from '../lib/rocketchat';
import { withTheme } from '../theme';
import { themes } from '../constants/colors';
import FormContainer, { FormContainerInner } from '../containers/FormContainer';
import { logEvent, events } from '../utils/log';
class ForgotPasswordView extends React.Component {
static navigationOptions = ({ route }) => ({
@ -56,6 +57,7 @@ class ForgotPasswordView extends React.Component {
}
resetPassword = async() => {
logEvent(events.FP_FORGOT_PASSWORD);
const { email, invalidEmail } = this.state;
if (invalidEmail || !email) {
return;
@ -69,6 +71,7 @@ class ForgotPasswordView extends React.Component {
showErrorAlert(I18n.t('Forgot_password_If_this_email_is_registered'), I18n.t('Alert'));
}
} catch (e) {
logEvent(events.FP_FORGOT_PASSWORD_F);
const msg = (e.data && e.data.error) || I18n.t('There_was_an_error_while_action', { action: I18n.t('resetting_password') });
showErrorAlert(msg, I18n.t('Alert'));
}

View File

@ -6,7 +6,6 @@ import {
import { connect } from 'react-redux';
import equal from 'deep-equal';
import { logEvent, events } from '../utils/log';
import sharedStyles from './Styles';
import Button from '../containers/Button';
import I18n from '../i18n';
@ -103,7 +102,6 @@ class LoginView extends React.Component {
}
forgotPassword = () => {
logEvent(events.FORGOT_PASSWORD);
const { navigation, Site_Name } = this.props;
navigation.navigate('ForgotPasswordView', { title: Site_Name });
}

View File

@ -14,7 +14,7 @@ import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import sharedStyles from './Styles';
import I18n from '../i18n';
import log from '../utils/log';
import log, { logEvent, events } from '../utils/log';
import SearchBox from '../containers/SearchBox';
import { CustomIcon } from '../lib/Icons';
import { CloseModalButton } from '../containers/HeaderButton';
@ -133,11 +133,13 @@ class NewMessageView extends React.Component {
}
createChannel = () => {
logEvent(events.NEW_MSG_CREATE_CHANNEL);
const { navigation } = this.props;
navigation.navigate('SelectedUsersViewCreateChannel', { nextAction: () => navigation.navigate('CreateChannelView') });
}
createGroupChat = () => {
logEvent(events.NEW_MSG_CREATE_GROUP_CHAT);
const { createChannel, maxUsers, navigation } = this.props;
navigation.navigate('SelectedUsersViewCreateChannel', {
nextAction: () => createChannel({ group: true }),
@ -147,6 +149,7 @@ class NewMessageView extends React.Component {
}
goRoom = (item) => {
logEvent(events.NEW_MSG_CHAT_WITH_USER);
const { isMasterDetail, navigation } = this.props;
if (isMasterDetail) {
navigation.pop();
@ -174,6 +177,7 @@ class NewMessageView extends React.Component {
}
createDiscussion = () => {
logEvent(events.NEW_MSG_CREATE_DISCUSSION);
Navigation.navigate('CreateDiscussionView');
}

View File

@ -139,7 +139,7 @@ class NewServerView extends React.Component {
}
submit = async() => {
logEvent(events.CONNECT_TO_WORKSPACE);
logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE);
const { text, certificate } = this.state;
const { connectServer } = this.props;
let cert = null;
@ -151,7 +151,7 @@ class NewServerView extends React.Component {
try {
await FileSystem.copyAsync({ from: certificate.path, to: certificatePath });
} catch (e) {
logEvent(events.CONNECT_TO_WORKSPACE_FAIL);
logEvent(events.NEWSERVER_CONNECT_TO_WORKSPACE_F);
log(e);
}
cert = {
@ -169,7 +169,7 @@ class NewServerView extends React.Component {
}
connectOpen = () => {
logEvent(events.JOIN_OPEN_WORKSPACE);
logEvent(events.NEWSERVER_JOIN_OPEN_WORKSPACE);
this.setState({ connectingOpen: true });
const { connectServer } = this.props;
connectServer('https://open.rocket.chat');

View File

@ -70,17 +70,17 @@ class OnboardingView extends React.Component {
}
connectServer = () => {
logEvent(events.JOIN_A_WORKSPACE);
logEvent(events.ONBOARD_JOIN_A_WORKSPACE);
const { navigation } = this.props;
navigation.navigate('NewServerView');
}
createWorkspace = async() => {
logEvent(events.CREATE_NEW_WORKSPACE);
logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE);
try {
await Linking.openURL('https://cloud.rocket.chat/trial');
} catch {
logEvent(events.CREATE_NEW_WORKSPACE_FAIL);
logEvent(events.ONBOARD_CREATE_NEW_WORKSPACE_F);
}
}

View File

@ -18,7 +18,7 @@ import { LISTENER } from '../../containers/Toast';
import EventEmitter from '../../utils/events';
import RocketChat from '../../lib/rocketchat';
import RCTextInput from '../../containers/TextInput';
import log from '../../utils/log';
import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import Button from '../../containers/Button';
import Avatar from '../../containers/Avatar';
@ -223,8 +223,10 @@ class ProfileView extends React.Component {
try {
if (avatar.url) {
try {
logEvent(events.PROFILE_SAVE_AVATAR);
await RocketChat.setAvatarFromService(avatar);
} catch (e) {
logEvent(events.PROFILE_SAVE_AVATAR_F);
this.setState({ saving: false, currentPassword: null });
return this.handleError(e, 'setAvatarFromService', 'changing_avatar');
}
@ -233,6 +235,7 @@ class ProfileView extends React.Component {
const result = await RocketChat.saveUserProfile(params, customFields);
if (result.success) {
logEvent(events.PROFILE_SAVE_CHANGES);
if (customFields) {
setUser({ customFields, ...params });
} else {
@ -243,6 +246,7 @@ class ProfileView extends React.Component {
}
this.setState({ saving: false });
} catch (e) {
logEvent(events.PROFILE_SAVE_CHANGES_F);
this.setState({ saving: false, currentPassword: null });
this.handleError(e, 'saveUserProfile', 'saving_profile');
}
@ -281,13 +285,20 @@ class ProfileView extends React.Component {
includeBase64: true
};
try {
logEvent(events.PROFILE_PICK_AVATAR);
const response = await ImagePicker.openPicker(options);
this.setAvatar({ url: response.path, data: `data:image/jpeg;base64,${ response.data }`, service: 'upload' });
} catch (error) {
logEvent(events.PROFILE_PICK_AVATAR_F);
console.warn(error);
}
}
pickImageWithURL = (avatarUrl) => {
logEvent(events.PROFILE_PICK_AVATAR_WITH_URL);
this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' });
}
renderAvatarButton = ({
key, child, onPress, disabled = false
}) => {
@ -331,7 +342,7 @@ class ProfileView extends React.Component {
})}
{this.renderAvatarButton({
child: <CustomIcon name='link' size={30} color={themes[theme].bodyText} />,
onPress: () => this.setAvatar({ url: avatarUrl, data: avatarUrl, service: 'url' }),
onPress: () => this.pickImageWithURL(avatarUrl),
disabled: !avatarUrl,
key: 'profile-view-avatar-url-button'
})}

View File

@ -114,7 +114,7 @@ class RegisterView extends React.Component {
}
submit = async() => {
logEvent(events.DEFAULT_SIGN_UP);
logEvent(events.REGISTER_DEFAULT_SIGN_UP);
if (!this.valid()) {
return;
}
@ -150,7 +150,7 @@ class RegisterView extends React.Component {
return loginRequest({ user: email, password });
}
if (e.data?.error) {
logEvent(events.DEFAULT_SIGN_UP_FAIL);
logEvent(events.REGISTER_DEFAULT_SIGN_UP_F);
showErrorAlert(e.data.error, I18n.t('Oops'));
}
}

View File

@ -10,6 +10,7 @@ import { withTheme } from '../../../theme';
import EventEmitter from '../../../utils/events';
import { KEY_COMMAND, handleCommandOpenServerDropdown } from '../../../commands';
import { isTablet } from '../../../utils/deviceInfo';
import { logEvent, events } from '../../../utils/log';
class RoomsListHeaderView extends PureComponent {
static propTypes = {
@ -53,6 +54,7 @@ class RoomsListHeaderView extends PureComponent {
}
onPress = () => {
logEvent(events.RL_TOGGLE_SERVER_DROPDOWN);
const {
showServerDropdown, showSortDropdown, close, open, closeSort
} = this.props;

View File

@ -23,6 +23,7 @@ import { KEY_COMMAND, handleCommandSelectServer } from '../../commands';
import { isTablet, isIOS } from '../../utils/deviceInfo';
import { localAuthenticate } from '../../utils/localAuthentication';
import { showConfirmationAlert } from '../../utils/info';
import { logEvent, events } from '../../utils/log';
import { headerHeight } from '../../containers/Header';
import { goRoom } from '../../utils/goRoom';
@ -134,6 +135,7 @@ class ServerDropdown extends Component {
}
addServer = () => {
logEvent(events.RL_ADD_SERVER);
const { server } = this.props;
this.close();
setTimeout(() => {
@ -147,6 +149,7 @@ class ServerDropdown extends Component {
} = this.props;
this.close();
if (currentServer !== server) {
logEvent(events.RL_CHANGE_SERVER);
const userId = await RNUserDefaults.get(`${ RocketChat.TOKEN_KEY }-${ server }`);
if (isMasterDetail) {
goRoom({ item: {}, isMasterDetail });

View File

@ -10,7 +10,7 @@ import styles from '../styles';
import Touch from '../../../utils/touch';
import RocketChat from '../../../lib/rocketchat';
import { setPreference } from '../../../actions/sortPreferences';
import log from '../../../utils/log';
import log, { logEvent, events } from '../../../utils/log';
import I18n from '../../../i18n';
import { CustomIcon } from '../../../lib/Icons';
import { withTheme } from '../../../theme';
@ -65,31 +65,37 @@ class Sort extends PureComponent {
setSortPreference(param);
RocketChat.saveSortPreference(param);
} catch (e) {
logEvent(events.RL_SORT_CHANNELS_FAIL);
log(e);
}
}
sortByName = () => {
logEvent(events.RL_SORT_CHANNELS_BY_NAME);
this.setSortPreference({ sortBy: 'alphabetical' });
this.close();
}
sortByActivity = () => {
logEvent(events.RL_SORT_CHANNELS_BY_ACTIVITY);
this.setSortPreference({ sortBy: 'activity' });
this.close();
}
toggleGroupByType = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_TYPE);
const { groupByType } = this.props;
this.setSortPreference({ groupByType: !groupByType });
}
toggleGroupByFavorites = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_FAVORITE);
const { showFavorites } = this.props;
this.setSortPreference({ showFavorites: !showFavorites });
}
toggleUnread = () => {
logEvent(events.RL_GROUP_CHANNELS_BY_UNREAD);
const { showUnread } = this.props;
this.setSortPreference({ showUnread: !showUnread });
}

View File

@ -18,7 +18,7 @@ import database from '../../lib/database';
import RocketChat from '../../lib/rocketchat';
import RoomItem, { ROW_HEIGHT } from '../../presentation/RoomItem';
import styles from './styles';
import log from '../../utils/log';
import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import SortDropdown from './SortDropdown';
import ServerDropdown from './ServerDropdown';
@ -357,9 +357,7 @@ class RoomsListView extends React.Component {
<Item
title='new'
iconName='create'
onPress={isMasterDetail
? () => navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' })
: () => navigation.navigate('NewMessageStackNavigator')}
onPress={this.goToNewMessage}
testID='rooms-list-view-create-channel'
/>
<Item
@ -496,6 +494,7 @@ class RoomsListView extends React.Component {
}
initSearching = () => {
logEvent(events.RL_SEARCH);
const { openSearchHeader } = this.props;
this.internalSetState({ searching: true }, () => {
openSearchHeader();
@ -583,6 +582,7 @@ class RoomsListView extends React.Component {
}
toggleSort = () => {
logEvent(events.RL_TOGGLE_SORT_DROPDOWN);
const { toggleSortDropdown } = this.props;
this.scrollToTop();
@ -592,6 +592,7 @@ class RoomsListView extends React.Component {
};
toggleFav = async(rid, favorite) => {
logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.toggleFavorite(rid, !favorite);
@ -609,11 +610,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
logEvent(events.RL_TOGGLE_FAVORITE_FAIL);
log(e);
}
};
toggleRead = async(rid, isRead) => {
logEvent(isRead ? events.RL_UNREAD_CHANNEL : events.RL_READ_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.toggleRead(isRead, rid);
@ -631,11 +634,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
logEvent(events.RL_TOGGLE_READ_F);
log(e);
}
};
hideChannel = async(rid, type) => {
logEvent(events.RL_HIDE_CHANNEL);
try {
const db = database.active;
const result = await RocketChat.hideRoom(rid, type);
@ -651,11 +656,13 @@ class RoomsListView extends React.Component {
});
}
} catch (e) {
logEvent(events.RL_HIDE_CHANNEL_F);
log(e);
}
};
goDirectory = () => {
logEvent(events.RL_NAVIGATE_TO_DIRECTORY);
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
navigation.navigate('ModalStackNavigator', { screen: 'DirectoryView' });
@ -665,6 +672,7 @@ class RoomsListView extends React.Component {
};
goRoom = ({ item, isMasterDetail }) => {
logEvent(events.RL_GO_TO_ROOM);
const { item: currentItem } = this.state;
const { rooms } = this.props;
if (currentItem?.rid === item.rid || rooms?.includes(item.rid)) {
@ -724,6 +732,17 @@ class RoomsListView extends React.Component {
}
}
goToNewMessage = () => {
logEvent(events.RL_NAVIGATE_TO_NEW_MSG);
const { navigation, isMasterDetail } = this.props;
if (isMasterDetail) {
navigation.navigate('ModalStackNavigator', { screen: 'NewMessageView' });
} else {
navigation.navigate('NewMessageStackNavigator');
}
}
handleCommands = ({ event }) => {
const { navigation, server, isMasterDetail } = this.props;
const { input } = event;

View File

@ -11,7 +11,7 @@ import RocketChat from '../lib/rocketchat';
import UserItem from '../presentation/UserItem';
import Loading from '../containers/Loading';
import I18n from '../i18n';
import log from '../utils/log';
import log, { logEvent, events } from '../utils/log';
import SearchBox from '../containers/SearchBox';
import sharedStyles from './Styles';
import { Item, CustomHeaderButtons } from '../containers/HeaderButton';
@ -184,8 +184,10 @@ class SelectedUsersView extends React.Component {
return showErrorAlert(I18n.t('Max_number_of_users_allowed_is_number', { maxUsers }), I18n.t('Oops'));
}
logEvent(events.SELECTED_USERS_ADD_USER);
addUser(user);
} else {
logEvent(events.SELECTED_USERS_REMOVE_USER);
removeUser(user);
}
}

View File

@ -8,7 +8,7 @@ import { Q } from '@nozbe/watermelondb';
import Avatar from '../../containers/Avatar';
import Status from '../../containers/Status/Status';
import log from '../../utils/log';
import log, { logEvent, events } from '../../utils/log';
import I18n from '../../i18n';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import { CustomIcon } from '../../lib/Icons';
@ -18,7 +18,6 @@ import { themes } from '../../constants/colors';
import database from '../../lib/database';
import { withTheme } from '../../theme';
import { getUserSelector } from '../../selectors/login';
import Navigation from '../../lib/Navigation';
import SafeAreaView from '../../containers/SafeAreaView';
const Separator = React.memo(({ theme }) => <View style={[styles.separator, { borderColor: themes[theme].separatorColor }]} />);
@ -135,6 +134,7 @@ class Sidebar extends Component {
}
sidebarNavigate = (route) => {
logEvent(events[`SIDEBAR_NAVIGATE_TO_${ route.replace('StackNavigator', '').replace('View', '').toUpperCase() }`]);
const { navigation } = this.props;
navigation.navigate(route);
}
@ -165,7 +165,7 @@ class Sidebar extends Component {
<SidebarItem
text={I18n.t('Admin_Panel')}
left={<CustomIcon name='settings' size={20} color={themes[theme].titleText} />}
onPress={() => Navigation.navigate(routeName)}
onPress={() => this.sidebarNavigate(routeName)}
testID='sidebar-settings'
current={this.currentItemKey === routeName}
/>
@ -210,7 +210,7 @@ class Sidebar extends Component {
text={user.statusText || I18n.t('Edit_Status')}
left={<Status style={styles.status} size={12} status={user && user.status} />}
right={<CustomIcon name='edit' size={20} color={themes[theme].titleText} />}
onPress={() => Navigation.navigate('StatusView')}
onPress={() => this.sidebarNavigate('StatusView')}
testID='sidebar-custom-status'
/>
);