summaryrefslogtreecommitdiffstats
path: root/web/react/utils
diff options
context:
space:
mode:
Diffstat (limited to 'web/react/utils')
-rw-r--r--web/react/utils/async_client.jsx4
-rw-r--r--web/react/utils/client.jsx16
-rw-r--r--web/react/utils/constants.jsx2
-rw-r--r--web/react/utils/markdown.jsx9
-rw-r--r--web/react/utils/text_formatting.jsx10
-rw-r--r--web/react/utils/utils.jsx50
6 files changed, 82 insertions, 9 deletions
diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx
index b1bc71d54..75dd35e3f 100644
--- a/web/react/utils/async_client.jsx
+++ b/web/react/utils/async_client.jsx
@@ -132,7 +132,7 @@ export function getChannel(id) {
callTracker['getChannel' + id] = utils.getTimestamp();
client.getChannel(id,
- function getChannelSuccess(data, textStatus, xhr) {
+ (data, textStatus, xhr) => {
callTracker['getChannel' + id] = 0;
if (xhr.status === 304 || !data) {
@@ -145,7 +145,7 @@ export function getChannel(id) {
member: data.member
});
},
- function getChannelFailure(err) {
+ (err) => {
callTracker['getChannel' + id] = 0;
dispatchError(err, 'getChannel');
}
diff --git a/web/react/utils/client.jsx b/web/react/utils/client.jsx
index bc73f3c64..bf117b3b3 100644
--- a/web/react/utils/client.jsx
+++ b/web/react/utils/client.jsx
@@ -34,7 +34,7 @@ function handleError(methodName, xhr, status, err) {
if (oldError && oldError.connErrorCount) {
errorCount += oldError.connErrorCount;
- connectError = 'We cannot reach the Mattermost service. The service may be down or misconfigured. Please contact an administrator to make sure the WebSocket port is configured properly.';
+ connectError = 'Please check connection, Mattermost unreachable. If issue persists, ask administrator to check WebSocket port.';
}
e = {message: connectError, connErrorCount: errorCount};
@@ -328,6 +328,20 @@ export function getConfig(success, error) {
});
}
+export function getAnalytics(teamId, name, success, error) {
+ $.ajax({
+ url: '/api/v1/admin/analytics/' + teamId + '/' + name,
+ dataType: 'json',
+ contentType: 'application/json',
+ type: 'GET',
+ success,
+ error: (xhr, status, err) => {
+ var e = handleError('getAnalytics', xhr, status, err);
+ error(e);
+ }
+ });
+}
+
export function saveConfig(config, success, error) {
$.ajax({
url: '/api/v1/admin/save_config',
diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx
index c20d84f40..0e89b9470 100644
--- a/web/react/utils/constants.jsx
+++ b/web/react/utils/constants.jsx
@@ -98,6 +98,7 @@ module.exports = {
POST_LOADING: 'loading',
POST_FAILED: 'failed',
POST_DELETED: 'deleted',
+ POST_TYPE_JOIN_LEAVE: 'join_leave',
RESERVED_TEAM_NAMES: [
'www',
'web',
@@ -132,6 +133,7 @@ module.exports = {
OFFLINE_ICON_SVG: "<svg version='1.1' id='Layer_1' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:cc='http://creativecommons.org/ns#' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:svg='http://www.w3.org/2000/svg' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' sodipodi:docname='TRASH_1_4.svg' inkscape:version='0.48.4 r9939' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='12px' height='12px' viewBox='0 0 12 12' enable-background='new 0 0 12 12' xml:space='preserve'><sodipodi:namedview inkscape:cy='139.7898' inkscape:cx='26.358185' inkscape:zoom='1.18' showguides='true' showgrid='false' id='namedview6' guidetolerance='10' gridtolerance='10' objecttolerance='10' borderopacity='1' bordercolor='#666666' pagecolor='#ffffff' inkscape:current-layer='Layer_1' inkscape:window-maximized='1' inkscape:window-y='-8' inkscape:window-x='-8' inkscape:window-height='705' inkscape:window-width='1366' inkscape:guide-bbox='true' inkscape:pageshadow='2' inkscape:pageopacity='0'><sodipodi:guide position='50.036793,85.991376' orientation='1,0' id='guide2986'></sodipodi:guide><sodipodi:guide position='58.426196,66.216355' orientation='0,1' id='guide3047'></sodipodi:guide></sodipodi:namedview><g><g><path fill='#cccccc' d='M6.002,7.143C5.645,7.363,5.167,7.52,4.502,7.52c-2.493,0-2.5-2.02-2.5-2.02S1.029,5.607,0.775,6.004C0.41,6.577,0.15,7.716,0.049,8.545c-0.025,0.145-0.057,0.537-0.05,0.598c0.162,1.295,2.237,2.321,4.375,2.357c0.043,0.001,0.085,0.001,0.127,0.001c0.043,0,0.084,0,0.127-0.001c1.879-0.023,3.793-0.879,4.263-2h-2.89L6.002,7.143L6.002,7.143z M4.501,5.488c1.372,0,2.483-1.117,2.483-2.494c0-1.378-1.111-2.495-2.483-2.495c-1.371,0-2.481,1.117-2.481,2.495C2.02,4.371,3.13,5.488,4.501,5.488z M7.002,6.5v2h5v-2H7.002z'/></g></g></svg>",
MENU_ICON: "<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'width='4px' height='16px' viewBox='0 0 8 32' enable-background='new 0 0 8 32' xml:space='preserve'> <g> <circle cx='4' cy='4.062' r='4'/> <circle cx='4' cy='16' r='4'/> <circle cx='4' cy='28' r='4'/> </g> </svg>",
COMMENT_ICON: "<svg version='1.1' id='Layer_2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'width='15px' height='15px' viewBox='1 1.5 15 15' enable-background='new 1 1.5 15 15' xml:space='preserve'> <g> <g> <path fill='#211B1B' d='M14,1.5H3c-1.104,0-2,0.896-2,2v8c0,1.104,0.896,2,2,2h1.628l1.884,3l1.866-3H14c1.104,0,2-0.896,2-2v-8 C16,2.396,15.104,1.5,14,1.5z M15,11.5c0,0.553-0.447,1-1,1H8l-1.493,2l-1.504-1.991L5,12.5H3c-0.552,0-1-0.447-1-1v-8 c0-0.552,0.448-1,1-1h11c0.553,0,1,0.448,1,1V11.5z'/> </g> </g> </svg>",
+ UPDATE_TYPING_MS: 5000,
THEMES: {
default: {
type: 'Mattermost',
diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx
index 01cc309b8..ad11a95ac 100644
--- a/web/react/utils/markdown.jsx
+++ b/web/react/utils/markdown.jsx
@@ -121,8 +121,11 @@ export class MattermostMarkdownRenderer extends marked.Renderer {
paragraph(text) {
let outText = text;
+ // required so markdown does not strip '_' from @user_names
+ outText = TextFormatting.doFormatMentions(text);
+
if (!('emoticons' in this.options) || this.options.emoticon) {
- outText = TextFormatting.doFormatEmoticons(text);
+ outText = TextFormatting.doFormatEmoticons(outText);
}
if (this.formattingOptions.singleline) {
@@ -136,7 +139,7 @@ export class MattermostMarkdownRenderer extends marked.Renderer {
return `<table class="markdown__table"><thead>${header}</thead><tbody>${body}</tbody></table>`;
}
- text(text) {
- return TextFormatting.doFormatText(text, this.formattingOptions);
+ text(txt) {
+ return TextFormatting.doFormatText(txt, this.formattingOptions);
}
}
diff --git a/web/react/utils/text_formatting.jsx b/web/react/utils/text_formatting.jsx
index 4b6d87254..9f1a5a53f 100644
--- a/web/react/utils/text_formatting.jsx
+++ b/web/react/utils/text_formatting.jsx
@@ -47,8 +47,8 @@ export function doFormatText(text, options) {
const tokens = new Map();
// replace important words and phrases with tokens
- output = autolinkUrls(output, tokens);
output = autolinkAtMentions(output, tokens);
+ output = autolinkUrls(output, tokens);
output = autolinkHashtags(output, tokens);
if (!('emoticons' in options) || options.emoticon) {
@@ -78,6 +78,13 @@ export function doFormatEmoticons(text) {
return output;
}
+export function doFormatMentions(text) {
+ const tokens = new Map();
+ let output = autolinkAtMentions(text, tokens);
+ output = replaceTokens(output, tokens);
+ return output;
+}
+
export function sanitizeHtml(text) {
let output = text;
@@ -188,6 +195,7 @@ function autolinkAtMentions(text, tokens) {
let output = text;
output = output.replace(/(^|\s)(@([a-z0-9.\-_]*))/gi, replaceAtMentionWithToken);
+
return output;
}
diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx
index 7a876d518..3140a5d77 100644
--- a/web/react/utils/utils.jsx
+++ b/web/react/utils/utils.jsx
@@ -8,6 +8,7 @@ var PreferenceStore = require('../stores/preference_store.jsx');
var TeamStore = require('../stores/team_store.jsx');
var Constants = require('../utils/constants.jsx');
var ActionTypes = Constants.ActionTypes;
+var Client = require('./client.jsx');
var AsyncClient = require('./async_client.jsx');
var client = require('./client.jsx');
var Autolinker = require('autolinker');
@@ -210,11 +211,15 @@ export function displayDateTime(ticks) {
}
interval = Math.floor(seconds / 60);
- if (interval > 1) {
+ if (interval >= 2) {
return interval + ' minutes ago';
}
- return '1 minute ago';
+ if (interval >= 1) {
+ return '1 minute ago';
+ }
+
+ return 'just now';
}
export function displayCommentDateTime(ticks) {
@@ -1009,3 +1014,44 @@ export function windowWidth() {
export function windowHeight() {
return $(window).height();
}
+
+export function openDirectChannelToUser(user, successCb, errorCb) {
+ const channelName = this.getDirectChannelName(UserStore.getCurrentId(), user.id);
+ let channel = ChannelStore.getByName(channelName);
+
+ const preference = PreferenceStore.setPreference(Constants.Preferences.CATEGORY_DIRECT_CHANNEL_SHOW, user.id, 'true');
+ AsyncClient.savePreferences([preference]);
+
+ if (channel) {
+ if ($.isFunction(successCb)) {
+ successCb(channel, true);
+ }
+ } else {
+ channel = {
+ name: channelName,
+ last_post_at: 0,
+ total_msg_count: 0,
+ type: 'D',
+ display_name: user.username,
+ teammate_id: user.id,
+ status: UserStore.getStatus(user.id)
+ };
+
+ Client.createDirectChannel(
+ channel,
+ user.id,
+ (data) => {
+ AsyncClient.getChannel(data.id);
+ if ($.isFunction(successCb)) {
+ successCb(data, false);
+ }
+ },
+ () => {
+ window.location.href = TeamStore.getCurrentTeamUrl() + '/channels/' + channelName;
+ if ($.isFunction(errorCb)) {
+ errorCb();
+ }
+ }
+ );
+ }
+}