summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorGeorge Goldberg <george@gberg.me>2017-02-24 17:34:21 +0000
committerGitHub <noreply@github.com>2017-02-24 17:34:21 +0000
commit97cc0a0d73dcacfefcdff785c802762e2a0a60d6 (patch)
treec584bb28511980bde3bf09a6fffc1f8feacf9ddf /webapp
parentf182d196fffc9da89ad63bdbd7bbb2e41da3146e (diff)
downloadchat-97cc0a0d73dcacfefcdff785c802762e2a0a60d6.tar.gz
chat-97cc0a0d73dcacfefcdff785c802762e2a0a60d6.tar.bz2
chat-97cc0a0d73dcacfefcdff785c802762e2a0a60d6.zip
PLT-5071: Client side component of Telemetry. (#5516)
Diffstat (limited to 'webapp')
-rw-r--r--webapp/actions/analytics_actions.jsx12
-rw-r--r--webapp/actions/channel_actions.jsx4
-rw-r--r--webapp/actions/diagnostics_actions.jsx8
-rw-r--r--webapp/actions/global_actions.jsx9
-rw-r--r--webapp/actions/post_actions.jsx3
-rw-r--r--webapp/client/browser_web_client.jsx35
-rw-r--r--webapp/client/client.jsx167
-rw-r--r--webapp/components/create_post.jsx1
-rw-r--r--webapp/components/create_team/components/display_name.jsx8
-rw-r--r--webapp/components/create_team/components/team_url.jsx10
-rw-r--r--webapp/components/logged_in.jsx16
-rw-r--r--webapp/components/root.jsx21
-rw-r--r--webapp/components/sidebar.jsx9
-rw-r--r--webapp/components/sidebar_right.jsx5
-rw-r--r--webapp/components/signup/components/signup_email.jsx11
-rw-r--r--webapp/components/signup/components/signup_ldap.jsx8
-rw-r--r--webapp/components/team_sidebar/components/team_button.jsx2
-rw-r--r--webapp/components/tutorial/tutorial_intro_screens.jsx26
-rw-r--r--webapp/components/tutorial/tutorial_tip.jsx31
-rw-r--r--webapp/components/user_settings/user_settings_general.jsx12
-rw-r--r--webapp/components/webrtc/webrtc_controller.jsx5
-rw-r--r--webapp/i18n/en.json3
-rw-r--r--webapp/utils/constants.jsx3
23 files changed, 280 insertions, 129 deletions
diff --git a/webapp/actions/analytics_actions.jsx b/webapp/actions/analytics_actions.jsx
deleted file mode 100644
index 924afdaed..000000000
--- a/webapp/actions/analytics_actions.jsx
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
-// See License.txt for license information.
-
-import Client from 'client/web_client.jsx';
-
-export function track(category, action, label, property, value) {
- Client.track(category, action, label, property, value);
-}
-
-export function trackPage() {
- Client.trackPage();
-}
diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx
index 08d8f1486..3528b4480 100644
--- a/webapp/actions/channel_actions.jsx
+++ b/webapp/actions/channel_actions.jsx
@@ -10,6 +10,7 @@ import * as ChannelUtils from 'utils/channel_utils.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import {loadProfilesAndTeamMembersForDMSidebar} from 'actions/user_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
@@ -171,6 +172,7 @@ export function openDirectChannelToUser(user, success, error) {
const channel = ChannelStore.getByName(channelName);
if (channel) {
+ trackEvent('api', 'api_channels_join_direct');
PreferenceStore.setPreference(Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, user.id, 'true');
loadProfilesAndTeamMembersForDMSidebar();
@@ -224,10 +226,12 @@ export function openDirectChannelToUser(user, success, error) {
}
export function markFavorite(channelId) {
+ trackEvent('api', 'api_channels_favorited');
AsyncClient.savePreference(Preferences.CATEGORY_FAVORITE_CHANNEL, channelId, 'true');
}
export function unmarkFavorite(channelId) {
+ trackEvent('api', 'api_channels_unfavorited');
const pref = {
user_id: UserStore.getCurrentId(),
category: Preferences.CATEGORY_FAVORITE_CHANNEL,
diff --git a/webapp/actions/diagnostics_actions.jsx b/webapp/actions/diagnostics_actions.jsx
new file mode 100644
index 000000000..b093d8e8b
--- /dev/null
+++ b/webapp/actions/diagnostics_actions.jsx
@@ -0,0 +1,8 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import Client from 'client/web_client.jsx';
+
+export function trackEvent(category, event, properties) {
+ Client.trackEvent(category, event, properties);
+}
diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx
index 5def48858..efff5076a 100644
--- a/webapp/actions/global_actions.jsx
+++ b/webapp/actions/global_actions.jsx
@@ -17,6 +17,7 @@ import {loadProfilesAndTeamMembersForDMSidebar} from 'actions/user_actions.jsx';
import {loadChannelsForCurrentUser} from 'actions/channel_actions.jsx';
import {stopPeriodicStatusUpdates} from 'actions/status_actions.jsx';
import * as WebsocketActions from 'actions/websocket_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Constants from 'utils/constants.jsx';
const ActionTypes = Constants.ActionTypes;
@@ -28,7 +29,6 @@ import * as Utils from 'utils/utils.jsx';
import en from 'i18n/en.json';
import * as I18n from 'i18n/i18n.jsx';
-import {trackPage} from 'actions/analytics_actions.jsx';
import {browserHistory} from 'react-router/es6';
export function emitChannelClickEvent(channel) {
@@ -53,7 +53,6 @@ export function emitChannelClickEvent(channel) {
AsyncClient.getChannelStats(chan.id, true);
AsyncClient.viewChannel(chan.id, oldChannelId);
loadPosts(chan.id);
- trackPage();
});
// Mark previous and next channel as read
@@ -94,6 +93,10 @@ export function emitInitialLoad(callback) {
global.window.mm_config = data.client_cfg;
global.window.mm_license = data.license_cfg;
+ if (global.window && global.window.analytics) {
+ global.window.analytics.identify(global.window.mm_config.DiagnosticId);
+ }
+
UserStore.setNoAccounts(data.no_accounts);
if (data.user && data.user.id) {
@@ -515,6 +518,8 @@ export function emitSearchMentionsEvent(user) {
terms = termKeys.join(' ');
}
+ trackEvent('api', 'api_posts_search_mention');
+
AppDispatcher.handleServerAction({
type: ActionTypes.RECEIVED_SEARCH_TERM,
term: terms,
diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx
index 81ef73fc5..ad05a69db 100644
--- a/webapp/actions/post_actions.jsx
+++ b/webapp/actions/post_actions.jsx
@@ -9,6 +9,7 @@ import UserStore from 'stores/user_store.jsx';
import {loadStatusesForChannel} from 'actions/status_actions.jsx';
import {loadNewDMIfNeeded} from 'actions/user_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Client from 'client/web_client.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
@@ -64,10 +65,12 @@ export function handleNewPost(post, msg) {
}
export function flagPost(postId) {
+ trackEvent('api', 'api_posts_flagged');
AsyncClient.savePreference(Preferences.CATEGORY_FLAGGED_POST, postId, 'true');
}
export function unflagPost(postId, success) {
+ trackEvent('api', 'api_posts_unflagged');
const pref = {
user_id: UserStore.getCurrentId(),
category: Preferences.CATEGORY_FLAGGED_POST,
diff --git a/webapp/client/browser_web_client.jsx b/webapp/client/browser_web_client.jsx
index f5d7f6c80..ef543ca34 100644
--- a/webapp/client/browser_web_client.jsx
+++ b/webapp/client/browser_web_client.jsx
@@ -4,6 +4,7 @@
import Client from './client.jsx';
import TeamStore from 'stores/team_store.jsx';
+import UserStore from 'stores/user_store.jsx';
import BrowserStore from 'stores/browser_store.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
@@ -29,16 +30,22 @@ class WebClientClass extends Client {
onTeamStoreChanged() {
this.setTeamId(TeamStore.getCurrentId());
}
-
- track(category, action, label, property, value) {
- if (global.window && global.window.analytics) {
- global.window.analytics.track(action, {category, label, property, value});
- }
- }
-
- trackPage() {
+ trackEvent(category, event, props) {
if (global.window && global.window.analytics) {
- global.window.analytics.page();
+ const properties = Object.assign({category, type: event, user_id: UserStore.getCurrentId()}, props);
+ const options = {
+ context: {
+ ip: '0.0.0.0'
+ },
+ page: {
+ path: '',
+ referrer: '',
+ search: '',
+ title: '',
+ url: ''
+ }
+ };
+ global.window.analytics.track('event', properties, options);
}
}
@@ -74,7 +81,7 @@ class WebClientClass extends Client {
password,
token,
(data) => {
- this.track('api', 'api_users_login_success', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login_success');
BrowserStore.signalLogin();
if (success) {
@@ -82,7 +89,7 @@ class WebClientClass extends Client {
}
},
(err) => {
- this.track('api', 'api_users_login_fail', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login_fail');
if (error) {
error(err);
}
@@ -96,7 +103,8 @@ class WebClientClass extends Client {
password,
token,
(data) => {
- this.track('api', 'api_users_login_success', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login_success');
+ this.trackEvent('api', 'api_users_login_ldap_success');
BrowserStore.signalLogin();
if (success) {
@@ -104,7 +112,8 @@ class WebClientClass extends Client {
}
},
(err) => {
- this.track('api', 'api_users_login_fail', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login_fail');
+ this.trackEvent('api', 'api_users_login_ldap_fail');
if (error) {
error(err);
}
diff --git a/webapp/client/client.jsx b/webapp/client/client.jsx
index 478abdcde..24eb7eabb 100644
--- a/webapp/client/client.jsx
+++ b/webapp/client/client.jsx
@@ -144,11 +144,7 @@ export default class Client {
}
}
- track(category, action, label, property, value) { // eslint-disable-line no-unused-vars
- // NO-OP for inherited classes to override
- }
-
- trackPage() {
+ trackEvent(category, event, properties) { // eslint-disable-line no-unused-vars
// NO-OP for inherited classes to override
}
@@ -197,8 +193,6 @@ export default class Client {
console.error(e); // eslint-disable-line no-console
}
- this.track('api', 'api_weberror', methodName, 'message', msg);
-
this.handleError(err, res);
if (errorCallback) {
@@ -425,7 +419,7 @@ export default class Client {
attach('license', license, license.name).
end(this.handleResponse.bind(this, 'uploadLicenseFile', success, error));
- this.track('api', 'api_license_upload');
+ this.trackEvent('api', 'api_license_upload');
}
importSlack(fileData, success, error) {
@@ -472,7 +466,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'adminResetPassword', success, error));
- this.track('api', 'api_admin_reset_password');
+ this.trackEvent('api', 'api_admin_reset_password');
}
ldapSyncNow(success, error) {
@@ -523,7 +517,7 @@ export default class Client {
send(team).
end(this.handleResponse.bind(this, 'createTeam', success, error));
- this.track('api', 'api_users_create', '', 'email', team.name);
+ this.trackEvent('api', 'api_teams_create');
}
updateTeam(team, success, error) {
@@ -535,7 +529,7 @@ export default class Client {
send(team).
end(this.handleResponse.bind(this, 'updateTeam', success, error));
- this.track('api', 'api_teams_update_name');
+ this.trackEvent('api', 'api_teams_update_name', {team_id: this.getTeamId()});
}
getAllTeams(success, error) {
@@ -635,7 +629,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'inviteMembers', success, error));
- this.track('api', 'api_teams_invite_members');
+ this.trackEvent('api', 'api_teams_invite_members', {team_id: this.getTeamId()});
}
addUserToTeam(teamId, userId, success, error) {
@@ -652,7 +646,7 @@ export default class Client {
send({user_id: userId}).
end(this.handleResponse.bind(this, 'addUserToTeam', success, error));
- this.track('api', 'api_teams_invite_members');
+ this.trackEvent('api', 'api_teams_invite_members', {team_id: nonEmptyTeamId});
}
addUserToTeamFromInvite(data, hash, inviteId, success, error) {
@@ -664,7 +658,7 @@ export default class Client {
send({hash, data, invite_id: inviteId}).
end(this.handleResponse.bind(this, 'addUserToTeam', success, error));
- this.track('api', 'api_teams_invite_members');
+ this.trackEvent('api', 'api_teams_invite_members');
}
removeUserFromTeam(teamId, userId, success, error) {
@@ -681,7 +675,7 @@ export default class Client {
send({user_id: userId}).
end(this.handleResponse.bind(this, 'removeUserFromTeam', success, error));
- this.track('api', 'api_teams_remove_members');
+ this.trackEvent('api', 'api_teams_remove_members', {team_id: nonEmptyTeamId});
}
getInviteInfo(inviteId, success, error) {
@@ -713,6 +707,14 @@ export default class Client {
url += '&iid=' + encodeURIComponent(inviteId);
}
+ if (emailHash) {
+ this.trackEvent('api', 'api_users_create_email');
+ } else if (inviteId) {
+ this.trackEvent('api', 'api_users_create_link');
+ } else {
+ this.trackEvent('api', 'api_users_create_spontaneous');
+ }
+
request.
post(url).
set(this.defaultHeaders).
@@ -721,7 +723,7 @@ export default class Client {
send(user).
end(this.handleResponse.bind(this, 'createUser', success, error));
- this.track('api', 'api_users_create', '', 'email', user.email);
+ this.trackEvent('api', 'api_users_create');
}
updateUser(user, type, success, error) {
@@ -734,9 +736,9 @@ export default class Client {
end(this.handleResponse.bind(this, 'updateUser', success, error));
if (type) {
- this.track('api', 'api_users_update_' + type);
+ this.trackEvent('api', 'api_users_update_' + type);
} else {
- this.track('api', 'api_users_update');
+ this.trackEvent('api', 'api_users_update');
}
}
@@ -754,7 +756,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updatePassword', success, error));
- this.track('api', 'api_users_newpassword');
+ this.trackEvent('api', 'api_users_newpassword');
}
updateUserNotifyProps(notifyProps, success, error) {
@@ -766,7 +768,7 @@ export default class Client {
send(notifyProps).
end(this.handleResponse.bind(this, 'updateUserNotifyProps', success, error));
- this.track('api', 'api_users_update_notification_settings');
+ this.trackEvent('api', 'api_users_update_notification_settings');
}
updateUserRoles(userId, newRoles, success, error) {
@@ -782,7 +784,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updateUserRoles', success, error));
- this.track('api', 'api_users_update_user_roles');
+ this.trackEvent('api', 'api_users_update_roles');
}
updateTeamMemberRoles(teamId, userId, newRoles, success, error) {
@@ -799,7 +801,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updateTeamMemberRoles', success, error));
- this.track('api', 'api_teams_update_member_roles');
+ this.trackEvent('api', 'api_teams_update_member_roles', {team_id: teamId});
}
updateActive(userId, active, success, error) {
@@ -815,7 +817,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updateActive', success, error));
- this.track('api', 'api_users_update_active');
+ this.trackEvent('api', 'api_users_update_active');
}
sendPasswordReset(email, success, error) {
@@ -830,7 +832,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'sendPasswordReset', success, error));
- this.track('api', 'api_users_send_password_reset');
+ this.trackEvent('api', 'api_users_send_password_reset');
}
resetPassword(code, newPassword, success, error) {
@@ -846,7 +848,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'resetPassword', success, error));
- this.track('api', 'api_users_reset_password');
+ this.trackEvent('api', 'api_users_reset_password');
}
emailToOAuth(email, password, token, service, success, error) {
@@ -858,7 +860,7 @@ export default class Client {
send({password, email, token, service}).
end(this.handleResponse.bind(this, 'emailToOAuth', success, error));
- this.track('api', 'api_users_email_to_oauth');
+ this.trackEvent('api', 'api_users_email_to_oauth');
}
oauthToEmail(email, password, success, error) {
@@ -874,7 +876,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'oauthToEmail', success, error));
- this.track('api', 'api_users_oauth_to_email');
+ this.trackEvent('api', 'api_users_oauth_to_email');
}
emailToLdap(email, password, token, ldapId, ldapPassword, success, error) {
@@ -893,7 +895,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'emailToLdap', success, error));
- this.track('api', 'api_users_email_to_ldap');
+ this.trackEvent('api', 'api_users_email_to_ldap');
}
ldapToEmail(email, emailPassword, token, ldapPassword, success, error) {
@@ -911,7 +913,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'ldapToEmail', success, error));
- this.track('api', 'api_users_oauth_to_email');
+ this.trackEvent('api', 'api_users_ldap_to_email');
}
getInitialLoad(success, error) {
@@ -962,19 +964,20 @@ export default class Client {
login(loginId, password, mfaToken, success, error) {
this.doLogin({login_id: loginId, password, token: mfaToken}, success, error);
- this.track('api', 'api_users_login', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login');
}
loginById(id, password, mfaToken, success, error) {
this.doLogin({id, password, token: mfaToken}, success, error);
- this.track('api', 'api_users_login', '', 'id', id);
+ this.trackEvent('api', 'api_users_login');
}
loginByLdap(loginId, password, mfaToken, success, error) {
this.doLogin({login_id: loginId, password, token: mfaToken, ldap_only: 'true'}, success, error);
- this.track('api', 'api_users_login', '', 'login_id', loginId);
+ this.trackEvent('api', 'api_users_login');
+ this.trackEvent('api', 'api_users_login_ldap');
}
doLogin(outgoingData, success, error) {
@@ -1014,7 +1017,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'logout', success, error));
- this.track('api', 'api_users_logout');
+ this.trackEvent('api', 'api_users_logout');
}
checkMfa(loginId, success, error) {
@@ -1030,7 +1033,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'checkMfa', success, error));
- this.track('api', 'api_users_oauth_to_email');
+ this.trackEvent('api', 'api_users_oauth_to_email');
}
generateMfaSecret(success, error) {
@@ -1086,6 +1089,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getProfiles', success, error));
+
+ this.trackEvent('api', 'api_profiles_get');
}
getProfilesInTeam(teamId, offset, limit, success, error) {
@@ -1095,6 +1100,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getProfilesInTeam', success, error));
+
+ this.trackEvent('api', 'api_profiles_get_in_team', {team_id: teamId});
}
getProfilesInChannel(channelId, offset, limit, success, error) {
@@ -1104,6 +1111,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getProfilesInChannel', success, error));
+
+ this.trackEvent('api', 'api_profiles_get_in_channel', {team_id: this.getTeamId(), channel_id: channelId});
}
getProfilesNotInChannel(channelId, offset, limit, success, error) {
@@ -1113,6 +1122,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getProfilesNotInChannel', success, error));
+
+ this.trackEvent('api', 'api_profiles_get_not_in_channel', {team_id: this.getTeamId(), channel_id: channelId});
}
getProfilesByIds(userIds, success, error) {
@@ -1123,6 +1134,8 @@ export default class Client {
accept('application/json').
send(userIds).
end(this.handleResponse.bind(this, 'getProfilesByIds', success, error));
+
+ this.trackEvent('api', 'api_profiles_get_by_ids');
}
searchUsers(term, teamId, options, success, error) {
@@ -1190,6 +1203,8 @@ export default class Client {
accept('application/json').
send({channel_id: id}).
end(this.handleResponse.bind(this, 'setActiveChannel', success, error));
+
+ this.trackEvent('api', 'api_channels_set_active', {channel_id: id});
}
verifyEmail(uid, hid, success, error) {
@@ -1234,7 +1249,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'uploadProfileImage', success, error));
- this.track('api', 'api_users_update_profile_picture');
+ this.trackEvent('api', 'api_users_update_profile_picture');
}
// Channel Routes Section
@@ -1248,7 +1263,7 @@ export default class Client {
send(channel).
end(this.handleResponse.bind(this, 'createChannel', success, error));
- this.track('api', 'api_channels_create', channel.type, 'name', channel.name);
+ this.trackEvent('api', 'api_channels_create', {team_id: this.getTeamId()});
}
createDirectChannel(userId, success, error) {
@@ -1259,6 +1274,8 @@ export default class Client {
accept('application/json').
send({user_id: userId}).
end(this.handleResponse.bind(this, 'createDirectChannel', success, error));
+
+ this.trackEvent('api', 'api_channels_create_direct', {team_id: this.getTeamId()});
}
updateChannel(channel, success, error) {
@@ -1270,7 +1287,7 @@ export default class Client {
send(channel).
end(this.handleResponse.bind(this, 'updateChannel', success, error));
- this.track('api', 'api_channels_update');
+ this.trackEvent('api', 'api_channels_update', {team_id: this.getTeamId(), channel_id: channel.id});
}
updateChannelHeader(channelId, header, success, error) {
@@ -1287,7 +1304,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updateChannel', success, error));
- this.track('api', 'api_channels_header');
+ this.trackEvent('api', 'api_channels_header', {team_id: this.getTeamId(), channel_id: channelId});
}
updateChannelPurpose(channelId, purpose, success, error) {
@@ -1304,7 +1321,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'updateChannelPurpose', success, error));
- this.track('api', 'api_channels_purpose');
+ this.trackEvent('api', 'api_channels_purpose', {team_id: this.getTeamId(), channel_id: channelId});
}
updateChannelNotifyProps(data, success, error) {
@@ -1325,7 +1342,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'leaveChannel', success, error));
- this.track('api', 'api_channels_leave');
+ this.trackEvent('api', 'api_channels_leave', {team_id: this.getTeamId(), channel_id: channelId});
}
joinChannel(channelId, success, error) {
@@ -1336,7 +1353,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'joinChannel', success, error));
- this.track('api', 'api_channels_join');
+ this.trackEvent('api', 'api_channels_join', {team_id: this.getTeamId(), channel_id: channelId});
}
joinChannelByName(name, success, error) {
@@ -1347,7 +1364,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'joinChannelByName', success, error));
- this.track('api', 'api_channels_join_name');
+ this.trackEvent('api', 'api_channels_join_name', {team_id: this.getTeamId()});
}
deleteChannel(channelId, success, error) {
@@ -1358,7 +1375,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'deleteChannel', success, error));
- this.track('api', 'api_channels_delete');
+ this.trackEvent('api', 'api_channels_delete', {team_id: this.getTeamId(), channel_id: channelId});
}
viewChannel(channelId, prevChannelId = '', time = 0, success, error) {
@@ -1410,7 +1427,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'getChannel', success, error));
- this.track('api', 'api_channel_get');
+ this.trackEvent('api', 'api_channel_get', {team_id: this.getTeamId(), channel_id: channelId});
}
// SCHEDULED FOR DEPRECATION IN 3.7 - use getMoreChannelsPage instead
@@ -1421,6 +1438,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getMoreChannels', success, error));
+
+ this.trackEvent('api', 'api_channels_more', {team_id: this.getTeamId()});
}
getMoreChannelsPage(offset, limit, success, error) {
@@ -1430,6 +1449,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getMoreChannelsPage', success, error));
+
+ this.trackEvent('api', 'api_channels_more_page', {team_id: this.getTeamId()});
}
searchMoreChannels(term, success, error) {
@@ -1524,7 +1545,7 @@ export default class Client {
send({user_id: userId}).
end(this.handleResponse.bind(this, 'addChannelMember', success, error));
- this.track('api', 'api_channels_add_member');
+ this.trackEvent('api', 'api_channels_add_member', {team_id: this.getTeamId(), channel_id: channelId});
}
removeChannelMember(channelId, userId, success, error) {
@@ -1536,7 +1557,7 @@ export default class Client {
send({user_id: userId}).
end(this.handleResponse.bind(this, 'removeChannelMember', success, error));
- this.track('api', 'api_channels_remove_member');
+ this.trackEvent('api', 'api_channels_remove_member', {team_id: this.getTeamId(), channel_id: channelId});
}
updateChannelMemberRoles(channelId, userId, newRoles, success, error) {
@@ -1574,7 +1595,7 @@ export default class Client {
send({command, ...commandArgs}).
end(this.handleResponse.bind(this, 'executeCommand', success, error));
- this.track('api', 'api_integrations_used');
+ this.trackEvent('api', 'api_integrations_used');
}
addCommand(command, success, error) {
@@ -1586,7 +1607,7 @@ export default class Client {
send(command).
end(this.handleResponse.bind(this, 'addCommand', success, error));
- this.track('api', 'api_integrations_created');
+ this.trackEvent('api', 'api_integrations_created');
}
editCommand(command, success, error) {
@@ -1598,7 +1619,7 @@ export default class Client {
send(command).
end(this.handleResponse.bind(this, 'editCommand', success, error));
- this.track('api', 'api_integrations_created');
+ this.trackEvent('api', 'api_integrations_created');
}
deleteCommand(commandId, success, error) {
@@ -1610,7 +1631,7 @@ export default class Client {
send({id: commandId}).
end(this.handleResponse.bind(this, 'deleteCommand', success, error));
- this.track('api', 'api_integrations_deleted');
+ this.trackEvent('api', 'api_integrations_deleted');
}
listTeamCommands(success, error) {
@@ -1643,14 +1664,10 @@ export default class Client {
send({...post, create_at: 0}).
end(this.handleResponse.bind(this, 'createPost', success, error));
- this.track('api', 'api_posts_create', post.channel_id, 'length', post.message.length);
-
- if (post.message.match(/\s#./)) {
- this.track('api', 'api_posts_hashtag');
- }
+ this.trackEvent('api', 'api_posts_create', {team_id: this.getTeamId(), channel_id: post.channel_id});
- if (post.message.match(/\s@./)) {
- this.track('api', 'api_posts_mentions');
+ if (post.parent_id != null && post.parent_id !== '') {
+ this.trackEvent('api', 'api_posts_replied', {team_id: this.getTeamId(), channel_id: post.channel_id});
}
}
@@ -1663,6 +1680,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getPermalinkTmp', success, error));
+
+ this.trackEvent('api', 'api_channels_permalink', {team_id: this.getTeamId()});
}
getPostById(postId, success, error) {
@@ -1692,7 +1711,7 @@ export default class Client {
send(post).
end(this.handleResponse.bind(this, 'updatePost', success, error));
- this.track('api', 'api_posts_update');
+ this.trackEvent('api', 'api_posts_update', {team_id: this.getTeamId(), channel_id: post.channel_id});
}
deletePost(channelId, postId, success, error) {
@@ -1703,7 +1722,7 @@ export default class Client {
accept('application/json').
end(this.handleResponse.bind(this, 'deletePost', success, error));
- this.track('api', 'api_posts_delete');
+ this.trackEvent('api', 'api_posts_delete', {team_id: this.getTeamId(), channel_id: channelId});
}
search(terms, isOrSearch, success, error) {
@@ -1719,7 +1738,7 @@ export default class Client {
send(data).
end(this.handleResponse.bind(this, 'search', success, error));
- this.track('api', 'api_posts_search');
+ this.trackEvent('api', 'api_posts_search', {team_id: this.getTeamId()});
}
getPostsPage(channelId, offset, limit, success, error) {
@@ -1747,6 +1766,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getPostsBefore', success, error));
+
+ this.trackEvent('api', 'api_posts_get_before', {team_id: this.getTeamId(), channel_id: channelId});
}
getPostsAfter(channelId, postId, offset, numPost, success, error) {
@@ -1756,6 +1777,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getPostsAfter', success, error));
+
+ this.trackEvent('api', 'api_posts_get_after', {team_id: this.getTeamId(), channel_id: channelId});
}
getFlaggedPosts(offset, limit, success, error) {
@@ -1765,6 +1788,8 @@ export default class Client {
type('application/json').
accept('application/json').
end(this.handleResponse.bind(this, 'getFlaggedPosts', success, error));
+
+ this.trackEvent('api', 'api_posts_get_flagged', {team_id: this.getTeamId()});
}
getFileInfosForPost(channelId, postId, success, error) {
@@ -1789,6 +1814,8 @@ export default class Client {
// Routes for Files
uploadFile(file, filename, channelId, clientId, success, error) {
+ this.trackEvent('api', 'api_files_upload', {team_id: this.getTeamId(), channel_id: channelId});
+
return request.
post(`${this.getTeamFilesRoute()}/upload`).
set(this.defaultHeaders).
@@ -1855,7 +1882,7 @@ export default class Client {
send(app).
end(this.handleResponse.bind(this, 'registerOAuthApp', success, error));
- this.track('api', 'api_apps_register');
+ this.trackEvent('api', 'api_apps_register');
}
allowOAuth2(responseType, clientId, redirectUri, state, scope, success, error) {
@@ -1890,6 +1917,8 @@ export default class Client {
accept('application/json').
send({id}).
end(this.handleResponse.bind(this, 'deleteOAuthApp', success, error));
+
+ this.trackEvent('api', 'api_apps_delete');
}
getOAuthAppInfo(id, success, error) {
@@ -1943,7 +1972,7 @@ export default class Client {
send(hook).
end(this.handleResponse.bind(this, 'addIncomingHook', success, error));
- this.track('api', 'api_integrations_created');
+ this.trackEvent('api', 'api_integrations_created', {team_id: this.getTeamId()});
}
deleteIncomingHook(hookId, success, error) {
@@ -1955,7 +1984,7 @@ export default class Client {
send({id: hookId}).
end(this.handleResponse.bind(this, 'deleteIncomingHook', success, error));
- this.track('api', 'api_integrations_deleted');
+ this.trackEvent('api', 'api_integrations_deleted', {team_id: this.getTeamId()});
}
listIncomingHooks(success, error) {
@@ -1976,7 +2005,7 @@ export default class Client {
send(hook).
end(this.handleResponse.bind(this, 'addOutgoingHook', success, error));
- this.track('api', 'api_integrations_created');
+ this.trackEvent('api', 'api_integrations_created', {team_id: this.getTeamId()});
}
deleteOutgoingHook(hookId, success, error) {
@@ -1988,7 +2017,7 @@ export default class Client {
send({id: hookId}).
end(this.handleResponse.bind(this, 'deleteOutgoingHook', success, error));
- this.track('api', 'api_integrations_deleted');
+ this.trackEvent('api', 'api_integrations_deleted', {team_id: this.getTeamId()});
}
listOutgoingHooks(success, error) {
@@ -2069,6 +2098,8 @@ export default class Client {
attach('image', image, image.name).
field('emoji', JSON.stringify(emoji)).
end(this.handleResponse.bind(this, 'addEmoji', success, error));
+
+ this.trackEvent('api', 'api_emoji_custom_add');
}
deleteEmoji(id, success, error) {
@@ -2078,6 +2109,8 @@ export default class Client {
accept('application/json').
send({id}).
end(this.handleResponse.bind(this, 'deleteEmoji', success, error));
+
+ this.trackEvent('api', 'api_emoji_custom_delete');
}
getCustomEmojiImageUrl(id) {
@@ -2127,6 +2160,8 @@ export default class Client {
accept('application/json').
send(reaction).
end(this.handleResponse.bind(this, 'saveReaction', success, error));
+
+ this.trackEvent('api', 'api_reactions_save', {team_id: this.getTeamId(), channel_id: channelId, post_id: reaction.post_id});
}
deleteReaction(channelId, reaction, success, error) {
@@ -2136,6 +2171,8 @@ export default class Client {
accept('application/json').
send(reaction).
end(this.handleResponse.bind(this, 'deleteReaction', success, error));
+
+ this.trackEvent('api', 'api_reactions_delete', {team_id: this.getTeamId(), channel_id: channelId, post_id: reaction.post_id});
}
listReactions(channelId, postId, success, error) {
diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx
index 581ed16a0..7bdcf6888 100644
--- a/webapp/components/create_post.jsx
+++ b/webapp/components/create_post.jsx
@@ -497,6 +497,7 @@ export default class CreatePost extends React.Component {
placement='top'
screens={screens}
overlayClass='tip-overlay--chat'
+ diagnosticsTag='tutorial_tip_1_sending_messages'
/>
);
}
diff --git a/webapp/components/create_team/components/display_name.jsx b/webapp/components/create_team/components/display_name.jsx
index 29077bd24..aeb8afbb9 100644
--- a/webapp/components/create_team/components/display_name.jsx
+++ b/webapp/components/create_team/components/display_name.jsx
@@ -1,7 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import {track} from 'actions/analytics_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Constants from 'utils/constants.jsx';
import {cleanUpUrlable} from 'utils/url.jsx';
@@ -22,6 +22,10 @@ export default class TeamSignupDisplayNamePage extends React.Component {
this.state = {};
}
+ componentDidMount() {
+ trackEvent('signup', 'signup_team_01_name');
+ }
+
submitNext(e) {
e.preventDefault();
@@ -60,8 +64,6 @@ export default class TeamSignupDisplayNamePage extends React.Component {
}
render() {
- track('signup', 'signup_team_02_name');
-
var nameError = null;
var nameDivClass = 'form-group';
if (this.state.nameError) {
diff --git a/webapp/components/create_team/components/team_url.jsx b/webapp/components/create_team/components/team_url.jsx
index 2ab143d7f..c8a60cdf9 100644
--- a/webapp/components/create_team/components/team_url.jsx
+++ b/webapp/components/create_team/components/team_url.jsx
@@ -2,7 +2,7 @@
// See License.txt for license information.
import {checkIfTeamExists, createTeam} from 'actions/team_actions.jsx';
-import {track} from 'actions/analytics_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Constants from 'utils/constants.jsx';
import * as URL from 'utils/url.jsx';
@@ -27,6 +27,10 @@ export default class TeamUrl extends React.Component {
};
}
+ componentDidMount() {
+ trackEvent('signup', 'signup_team_02_url');
+ }
+
submitBack(e) {
e.preventDefault();
this.props.state.wizard = 'display_name';
@@ -106,7 +110,7 @@ export default class TeamUrl extends React.Component {
createTeam(teamSignup.team,
() => {
- track('signup', 'signup_team_08_complete');
+ trackEvent('signup', 'signup_team_03_complete');
},
(err) => {
this.setState({nameError: err.message});
@@ -126,8 +130,6 @@ export default class TeamUrl extends React.Component {
}
render() {
- track('signup', 'signup_team_03_url');
-
let nameError = null;
let nameDivClass = 'form-group';
if (this.state.nameError) {
diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx
index 9282e74ca..8d7a00653 100644
--- a/webapp/components/logged_in.jsx
+++ b/webapp/components/logged_in.jsx
@@ -26,7 +26,6 @@ export default class LoggedIn extends React.Component {
super(params);
this.onUserChanged = this.onUserChanged.bind(this);
- this.setupUser = this.setupUser.bind(this);
// Because current CSS requires the root tag to have specific stuff
$('#root').attr('class', 'channel-view');
@@ -45,9 +44,7 @@ export default class LoggedIn extends React.Component {
user: UserStore.getCurrentUser()
};
- if (this.state.user) {
- this.setupUser(this.state.user);
- } else {
+ if (!this.state.user) {
GlobalActions.emitUserLoggedOutEvent('/login');
}
}
@@ -56,21 +53,10 @@ export default class LoggedIn extends React.Component {
return this.state.user != null;
}
- setupUser(user) {
- // Update segment indentify
- if (global.window.mm_config.SegmentDeveloperKey != null && global.window.mm_config.SegmentDeveloperKey !== '') {
- global.window.analytics.identify(user.id, {
- createdAt: user.create_at,
- id: user.id
- });
- }
- }
-
onUserChanged() {
// Grab the current user
const user = UserStore.getCurrentUser();
if (!Utils.areObjectsEqual(this.state.user, user)) {
- this.setupUser(user);
this.setState({
user
});
diff --git a/webapp/components/root.jsx b/webapp/components/root.jsx
index 465df5d79..4e7c19452 100644
--- a/webapp/components/root.jsx
+++ b/webapp/components/root.jsx
@@ -14,6 +14,7 @@ import $ from 'jquery';
import {browserHistory} from 'react-router/es6';
import UserStore from 'stores/user_store.jsx';
import BrowserStore from 'stores/browser_store.jsx';
+import Constants from 'utils/constants.jsx';
export default class Root extends React.Component {
constructor(props) {
@@ -26,12 +27,26 @@ export default class Root extends React.Component {
this.localizationChanged = this.localizationChanged.bind(this);
this.redirectIfNecessary = this.redirectIfNecessary.bind(this);
+ const segmentKey = Constants.DIAGNOSTICS_SEGMENT_KEY;
+
// Ya....
/*eslint-disable */
- if (window.mm_config.SegmentDeveloperKey != null && window.mm_config.SegmentDeveloperKey !== "") {
+ if (segmentKey != null && segmentKey !== '' && window.mm_config.DiagnosticsEnabled) {
!function(){var analytics=global.window.analytics=global.window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","group","track","ready","alias","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="3.0.1";
- analytics.load(window.mm_config.SegmentDeveloperKey);
- analytics.page();
+ analytics.load(segmentKey);
+
+ analytics.page('ApplicationLoaded', {
+ path: '',
+ referrer: '',
+ search: '',
+ title: '',
+ url: '',
+ },
+ {
+ context: {
+ ip: '0.0.0.0'
+ },
+ });
}}();
}
/*eslint-enable */
diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx
index 08962682d..048122897 100644
--- a/webapp/components/sidebar.jsx
+++ b/webapp/components/sidebar.jsx
@@ -21,6 +21,7 @@ import * as Utils from 'utils/utils.jsx';
import * as ChannelUtils from 'utils/channel_utils.jsx';
import * as ChannelActions from 'actions/channel_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Constants from 'utils/constants.jsx';
import {FormattedMessage, FormattedHTMLMessage} from 'react-intl';
@@ -363,6 +364,7 @@ export default class Sidebar extends React.Component {
showMoreChannelsModal() {
this.setState({showMoreChannelsModal: true});
+ trackEvent('ui', 'ui_channels_more_public');
}
hideMoreChannelsModal() {
@@ -378,6 +380,7 @@ export default class Sidebar extends React.Component {
}
showMoreDirectChannelsModal() {
+ trackEvent('ui', 'ui_channels_more_direct');
this.setState({showDirectChannelsModal: true});
}
@@ -448,6 +451,7 @@ export default class Sidebar extends React.Component {
placement='right'
screens={screens}
overlayClass='tip-overlay--sidebar'
+ diagnosticsTag='tutorial_tip_2_channels'
/>
);
}
@@ -566,6 +570,7 @@ export default class Sidebar extends React.Component {
<Link
to={link}
className={rowClass}
+ onClick={this.trackChannelSelectedEvent}
>
{icon}
{channel.display_name}
@@ -577,6 +582,10 @@ export default class Sidebar extends React.Component {
);
}
+ trackChannelSelectedEvent() {
+ trackEvent('ui', 'ui_channel_selected');
+ }
+
render() {
// Check if we have all info needed to render
if (this.state.currentTeam == null || this.state.currentUser == null) {
diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx
index da7ff818d..fb120337a 100644
--- a/webapp/components/sidebar_right.jsx
+++ b/webapp/components/sidebar_right.jsx
@@ -12,6 +12,7 @@ import PreferenceStore from 'stores/preference_store.jsx';
import WebrtcStore from 'stores/webrtc_store.jsx';
import {getFlaggedPosts} from 'actions/post_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -71,6 +72,10 @@ export default class SidebarRight extends React.Component {
const isOpen = this.state.searchVisible || this.state.postRightVisible;
const willOpen = nextState.searchVisible || nextState.postRightVisible;
+ if (!isOpen && willOpen) {
+ trackEvent('ui', 'ui_rhs_opened');
+ }
+
if (isOpen !== willOpen) {
PostStore.jumpPostsViewSidebarOpen();
}
diff --git a/webapp/components/signup/components/signup_email.jsx b/webapp/components/signup/components/signup_email.jsx
index 8325c9f56..cf4ff0a95 100644
--- a/webapp/components/signup/components/signup_email.jsx
+++ b/webapp/components/signup/components/signup_email.jsx
@@ -4,8 +4,9 @@
import LoadingScreen from 'components/loading_screen.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
+
import BrowserStore from 'stores/browser_store.jsx';
-import {track} from 'actions/analytics_actions.jsx';
import {getInviteInfo} from 'actions/team_actions.jsx';
import {loginById, createUserWithInvite} from 'actions/user_actions.jsx';
@@ -37,6 +38,10 @@ export default class SignupEmail extends React.Component {
this.state = this.getInviteInfo();
}
+ componentDidMount() {
+ trackEvent('signup', 'signup_user_01_welcome');
+ }
+
getInviteInfo() {
let data = this.props.location.query.d;
let hash = this.props.location.query.h;
@@ -117,7 +122,7 @@ export default class SignupEmail extends React.Component {
}
handleSignupSuccess(user, data) {
- track('signup', 'signup_user_02_complete');
+ trackEvent('signup', 'signup_user_02_complete');
loginById(
data.id,
user.password,
@@ -401,8 +406,6 @@ export default class SignupEmail extends React.Component {
}
render() {
- track('signup', 'signup_user_01_welcome');
-
let serverError = null;
if (this.state.serverError) {
serverError = (
diff --git a/webapp/components/signup/components/signup_ldap.jsx b/webapp/components/signup/components/signup_ldap.jsx
index bf98d0461..0e02d5db7 100644
--- a/webapp/components/signup/components/signup_ldap.jsx
+++ b/webapp/components/signup/components/signup_ldap.jsx
@@ -4,9 +4,9 @@
import FormError from 'components/form_error.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
-import {track} from 'actions/analytics_actions.jsx';
import {addUserToTeamFromInvite} from 'actions/team_actions.jsx';
import {webLoginByLdap} from 'actions/user_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import * as Utils from 'utils/utils.jsx';
@@ -39,6 +39,10 @@ export default class SignupLdap extends React.Component {
});
}
+ componentDidMount() {
+ trackEvent('signup', 'signup_user_01_welcome');
+ }
+
handleLdapIdChange(e) {
this.setState({
ldapId: e.target.value
@@ -107,8 +111,6 @@ export default class SignupLdap extends React.Component {
}
render() {
- track('signup', 'signup_user_01_welcome');
-
let ldapIdPlaceholder;
if (global.window.mm_config.LdapLoginFieldName) {
ldapIdPlaceholder = global.window.mm_config.LdapLoginFieldName;
diff --git a/webapp/components/team_sidebar/components/team_button.jsx b/webapp/components/team_sidebar/components/team_button.jsx
index 6fbf8aef9..894567538 100644
--- a/webapp/components/team_sidebar/components/team_button.jsx
+++ b/webapp/components/team_sidebar/components/team_button.jsx
@@ -3,6 +3,7 @@
import Constants from 'utils/constants.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import {switchTeams} from 'actions/team_actions.jsx';
import React from 'react';
@@ -19,6 +20,7 @@ export default class TeamButton extends React.Component {
handleSwitch(e) {
e.preventDefault();
+ trackEvent('ui', 'ui_team_sidebar_switch_team');
switchTeams(this.props.url);
}
diff --git a/webapp/components/tutorial/tutorial_intro_screens.jsx b/webapp/components/tutorial/tutorial_intro_screens.jsx
index a0b6118d3..c266191b8 100644
--- a/webapp/components/tutorial/tutorial_intro_screens.jsx
+++ b/webapp/components/tutorial/tutorial_intro_screens.jsx
@@ -6,6 +6,7 @@ import TeamStore from 'stores/team_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
import * as GlobalActions from 'actions/global_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import {Constants, Preferences} from 'utils/constants.jsx';
@@ -31,10 +32,23 @@ export default class TutorialIntroScreens extends React.Component {
this.handleNext = this.handleNext.bind(this);
this.createScreen = this.createScreen.bind(this);
this.createCircles = this.createCircles.bind(this);
+ this.skipTutorial = this.skipTutorial.bind(this);
this.state = {currentScreen: 0};
}
handleNext() {
+ switch (this.state.currentScreen) {
+ case 0:
+ trackEvent('tutorial', 'tutorial_screen_1_welcome_to_mattermost_next');
+ break;
+ case 1:
+ trackEvent('tutorial', 'tutorial_screen_2_how_mattermost_works_next');
+ break;
+ case 2:
+ trackEvent('tutorial', 'tutorial_screen_3_youre_all_set_next');
+ break;
+ }
+
if (this.state.currentScreen < 2) {
this.setState({currentScreen: this.state.currentScreen + 1});
return;
@@ -53,6 +67,18 @@ export default class TutorialIntroScreens extends React.Component {
skipTutorial(e) {
e.preventDefault();
+ switch (this.state.currentScreen) {
+ case 0:
+ trackEvent('tutorial', 'tutorial_screen_1_welcome_to_mattermost_skip');
+ break;
+ case 1:
+ trackEvent('tutorial', 'tutorial_screen_2_how_mattermost_works_skip');
+ break;
+ case 2:
+ trackEvent('tutorial', 'tutorial_screen_3_youre_all_set_skip');
+ break;
+ }
+
AsyncClient.savePreference(
Preferences.TUTORIAL_STEP,
UserStore.getCurrentId(),
diff --git a/webapp/components/tutorial/tutorial_tip.jsx b/webapp/components/tutorial/tutorial_tip.jsx
index 7b613fe51..e78668b10 100644
--- a/webapp/components/tutorial/tutorial_tip.jsx
+++ b/webapp/components/tutorial/tutorial_tip.jsx
@@ -4,6 +4,7 @@
import UserStore from 'stores/user_store.jsx';
import PreferenceStore from 'stores/preference_store.jsx';
import * as AsyncClient from 'utils/async_client.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import Constants from 'utils/constants.jsx';
@@ -25,6 +26,7 @@ export default class TutorialTip extends React.Component {
this.handleNext = this.handleNext.bind(this);
this.toggle = this.toggle.bind(this);
+ this.skipTutorial = this.skipTutorial.bind(this);
this.state = {currentScreen: 0, show: false};
}
@@ -48,6 +50,22 @@ export default class TutorialTip extends React.Component {
return;
}
+ if (this.props.diagnosticsTag) {
+ let tag = this.props.diagnosticsTag;
+
+ if (this.props.screens.length > 1) {
+ tag += '_' + (this.state.currentScreen + 1).toString();
+ }
+
+ if (this.state.currentScreen === this.props.screens.length - 1) {
+ tag += '_okay';
+ } else {
+ tag += '_next';
+ }
+
+ trackEvent('tutorial', tag);
+ }
+
this.closeRightSidebar();
this.toggle();
}
@@ -62,6 +80,15 @@ export default class TutorialTip extends React.Component {
skipTutorial(e) {
e.preventDefault();
+ if (this.props.diagnosticsTag) {
+ let tag = this.props.diagnosticsTag;
+ if (this.props.screens.length > 1) {
+ tag += '_' + this.state.currentScreen;
+ }
+ tag += '_skip';
+ trackEvent('tutorial', tag);
+ }
+
AsyncClient.savePreference(
Preferences.TUTORIAL_STEP,
UserStore.getCurrentId(),
@@ -174,7 +201,8 @@ TutorialTip.defaultProps = {
TutorialTip.propTypes = {
screens: React.PropTypes.array.isRequired,
placement: React.PropTypes.string.isRequired,
- overlayClass: React.PropTypes.string
+ overlayClass: React.PropTypes.string,
+ diagnosticsTag: React.PropTypes.string
};
export function createMenuTip(toggleFunc, onBottom) {
@@ -207,6 +235,7 @@ export function createMenuTip(toggleFunc, onBottom) {
placement={placement}
screens={screens}
overlayClass={'tip-overlay--header--' + arrow}
+ diagnosticsTag='tutorial_tip_3_main_menu'
/>
</div>
);
diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general.jsx
index d79507511..f9c624aa0 100644
--- a/webapp/components/user_settings/user_settings_general.jsx
+++ b/webapp/components/user_settings/user_settings_general.jsx
@@ -16,6 +16,7 @@ import * as Utils from 'utils/utils.jsx';
import {intlShape, injectIntl, defineMessages, FormattedMessage, FormattedHTMLMessage, FormattedDate} from 'react-intl';
import {updateUser, uploadProfileImage} from 'actions/user_actions.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
const holders = defineMessages({
usernameReserved: {
@@ -127,6 +128,8 @@ class UserSettingsGeneralTab extends React.Component {
user.username = username;
+ trackEvent('settings', 'user_settings_update', {field: 'username'});
+
this.submitUser(user, Constants.UserUpdateEvents.USERNAME, false);
}
@@ -143,6 +146,8 @@ class UserSettingsGeneralTab extends React.Component {
user.nickname = nickname;
+ trackEvent('settings', 'user_settings_update', {field: 'username'});
+
this.submitUser(user, Constants.UserUpdateEvents.NICKNAME, false);
}
@@ -161,6 +166,8 @@ class UserSettingsGeneralTab extends React.Component {
user.first_name = firstName;
user.last_name = lastName;
+ trackEvent('settings', 'user_settings_update', {field: 'fullname'});
+
this.submitUser(user, Constants.UserUpdateEvents.FULLNAME, false);
}
@@ -189,6 +196,7 @@ class UserSettingsGeneralTab extends React.Component {
}
user.email = email;
+ trackEvent('settings', 'user_settings_update', {field: 'email'});
this.submitUser(user, Constants.UserUpdateEvents.EMAIL, true);
}
@@ -228,6 +236,8 @@ class UserSettingsGeneralTab extends React.Component {
return;
}
+ trackEvent('settings', 'user_settings_update', {field: 'picture'});
+
const {formatMessage} = this.props.intl;
const picture = this.state.picture;
@@ -268,6 +278,8 @@ class UserSettingsGeneralTab extends React.Component {
user.position = position;
+ trackEvent('settings', 'user_settings_update', {field: 'position'});
+
this.submitUser(user, Constants.UserUpdateEvents.Position, false);
}
diff --git a/webapp/components/webrtc/webrtc_controller.jsx b/webapp/components/webrtc/webrtc_controller.jsx
index b8d3d4db6..0fab0d2e7 100644
--- a/webapp/components/webrtc/webrtc_controller.jsx
+++ b/webapp/components/webrtc/webrtc_controller.jsx
@@ -13,6 +13,7 @@ import SearchBox from '../search_bar.jsx';
import WebrtcHeader from './components/webrtc_header.jsx';
import ConnectingScreen from 'components/loading_screen.jsx';
+import {trackEvent} from 'actions/diagnostics_actions.jsx';
import * as WebrtcActions from 'actions/webrtc_actions.jsx';
import * as Utils from 'utils/utils.jsx';
@@ -600,6 +601,8 @@ export default class WebrtcController extends React.Component {
}
onFailed() {
+ trackEvent('api', 'api_users_webrtc_failed');
+
this.setState({
isCalling: false,
isAnswering: false,
@@ -733,6 +736,7 @@ export default class WebrtcController extends React.Component {
}
doAnswer(jsep) {
+ trackEvent('api', 'api_users_webrtc_start');
this.videocall.createAnswer({
jsep,
stream: this.localMedia,
@@ -747,6 +751,7 @@ export default class WebrtcController extends React.Component {
}
doHangup(error, manual) {
+ trackEvent('api', 'api_users_webrtc_end');
if (this.videocall && this.state.callInProgress) {
this.videocall.send({message: {request: 'hangup'}});
this.videocall.hangup();
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index eeb29cc39..46b9c113f 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -718,9 +718,6 @@
"admin.service.readTimeoutDescription": "Maximum time allowed from when the connection is accepted to when the request body is fully read.",
"admin.service.securityDesc": "When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.",
"admin.service.securityTitle": "Enable Security Alerts: ",
- "admin.service.segmentDescription": "Segment.com is an online service that can be optionally used to track detailed system statistics. You can obtain a key by signing-up for a free account at Segment.com.",
- "admin.service.segmentExample": "E.g.: \"g3fgGOXJAQ43QV7rAh6iwQCkV4cA1Gs\"",
- "admin.service.segmentTitle": "Segment Write Key:",
"admin.service.sessionCache": "Session Cache (minutes):",
"admin.service.sessionCacheDesc": "The number of minutes to cache a session in memory.",
"admin.service.sessionDaysEx": "E.g.: \"30\"",
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index ff26a0c7f..130e116a9 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -896,7 +896,8 @@ export const Constants = {
STATUS_INTERVAL: 60000,
AUTOCOMPLETE_TIMEOUT: 100,
ANIMATION_TIMEOUT: 1000,
- SEARCH_TIMEOUT_MILLISECONDS: 100
+ SEARCH_TIMEOUT_MILLISECONDS: 100,
+ DIAGNOSTICS_SEGMENT_KEY: 'fwb7VPbFeQ7SKp3wHm1RzFUuXZudqVok'
};
export default Constants;