Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

created function to allow change default values, fix loading search users #14177

Merged
merged 10 commits into from
Apr 22, 2019
10 changes: 4 additions & 6 deletions app/discussion/client/views/creationDialog/CreateDiscussion.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,11 @@
<input type="text" id="{{name}}" class="rc-tags__input" placeholder="{{_ placeholder}}" name="{{name}}" autocomplete="off" {{disabled}} />
</div>
</div>
{{#with config}} {{#if autocomplete 'isShowing'}}
<div class="dropdown-in">
{{#if autocomplete 'isLoaded'}}
{{> popupList data=config items=items}}
{{#with config}}
{{#if autocomplete 'isShowing'}}
{{> popupList data=config items=items ready=(autocomplete 'isLoaded')}}
{{/if}}
</div>
{{/if}} {{/with}}
{{/with}}
</label>
<div class="rc-input__description">{{ description }}</div>
</div>
Expand Down
67 changes: 34 additions & 33 deletions app/emoji/client/emojiParser.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,62 @@
import s from 'underscore.string';

import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { getUserPreference } from '../../utils';
import { callbacks } from '../../callbacks';
import { emoji } from '../lib/rocketchat';
import { isSetNotNull } from './function-isSet';
import s from 'underscore.string';

/*
* emojiParser is a function that will replace emojis
* @param {Object} message - The message object
*/
callbacks.add('renderMessage', (message) => {
if (isSetNotNull(() => getUserPreference(Meteor.userId(), 'useEmojis')) &&
!getUserPreference(Meteor.userId(), 'useEmojis')) {
return message;

Tracker.autorun(() => {
if (!getUserPreference(Meteor.userId(), 'useEmojis')) {
return callbacks.remove('renderMessage', 'emoji');
}
callbacks.add('renderMessage', (message) => {
if (s.trim(message.html)) {
// &#39; to apostrophe (') for emojis such as :')
message.html = message.html.replace(/&#39;/g, '\'');

// '<br>' to ' <br> ' for emojis such at line breaks
message.html = message.html.replace(/<br>/g, ' <br> ');

if (s.trim(message.html)) {
// &#39; to apostrophe (') for emojis such as :')
message.html = message.html.replace(/&#39;/g, '\'');
message.html = Object.entries(emoji.packages).reduce((value, [, emojiPackage]) => emojiPackage.render(value), message.html);

// '<br>' to ' <br> ' for emojis such at line breaks
message.html = message.html.replace(/<br>/g, ' <br> ');
const checkEmojiOnly = $(`<div>${ message.html }</div>`);
let emojiOnly = true;

Object.keys(emoji.packages).forEach((emojiPackage) => {
message.html = emoji.packages[emojiPackage].render(message.html);
});

const checkEmojiOnly = $(`<div>${ message.html }</div>`);
let emojiOnly = true;
for (const childNode in checkEmojiOnly[0].childNodes) {
if (checkEmojiOnly[0].childNodes.hasOwnProperty(childNode)) {
const child = $(checkEmojiOnly[0].childNodes[childNode]);
for (let i = 0, len = checkEmojiOnly[0].childNodes.length; i < len; i++) {
const childNode = checkEmojiOnly[0].childNodes[i];

if (child.hasClass('emoji') || child.hasClass('emojione')) {
checkEmojiOnly[0].childNodes[childNode] = child.addClass('big');
if (childNode.classList && (childNode.classList.contains('emoji') || childNode.classList.contains('emojione'))) {
childNode.classList.add('big');
continue;
}

if (s.trim(child.text()) === '') {
if (s.trim(childNode.innerText) === '') {
continue;
}

emojiOnly = false;
break;
}
}

if (emojiOnly) {
message.html = checkEmojiOnly.unwrap().html();
}
if (emojiOnly) {
message.html = checkEmojiOnly.unwrap().html();
}

// apostrophe (') back to &#39;
message.html = message.html.replace(/\'/g, '&#39;');
// apostrophe (') back to &#39;
message.html = message.html.replace(/\'/g, '&#39;');

// apostrophe ' <br> ' back to '<br>'
message.html = message.html.replace(/ <br> /g, '<br>');
}
// apostrophe ' <br> ' back to '<br>'
message.html = message.html.replace(/ <br> /g, '<br>');
}

return message;
}, callbacks.priority.LOW, 'emoji');
return message;
}, callbacks.priority.LOW, 'emoji');
});
45 changes: 28 additions & 17 deletions app/highlight-words/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@
* Highlights is a named function that will process Highlights
* @param {Object} message - The message object
*/
import _ from 'underscore';
import s from 'underscore.string';

import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { callbacks } from '../../callbacks';
import { getUserPreference } from '../../utils';
import _ from 'underscore';
import s from 'underscore.string';
import { highlightWords } from './helper';
import { highlightWords, getRegexHighlight, getRegexHighlightUrl } from './helper';

function HighlightWordsClient(message) {
let msg = message;
if (!_.isString(message)) {
if (s.trim(message.html)) {
msg = message.html;
} else {
return message;
}
Tracker.autorun(() => {
const toHighlight = (getUserPreference(Meteor.userId(), 'highlights') || []).filter((highlight) => !s.isBlank(highlight)).map((highlight) => ({
highlight,
regex: getRegexHighlight(highlight),
urlRegex: getRegexHighlightUrl(highlight),
}));

if (!toHighlight.length) {
return callbacks.remove('renderMessage', 'highlight-words');
}

const to_highlight = getUserPreference(Meteor.user(), 'highlights');
msg = highlightWords(msg, to_highlight);
function HighlightWordsClient(message) {
let msg = message;

message.html = msg;
return message;
}
if (!_.isString(message)) {
if (!s.trim(message.html)) {
return message;
}
msg = message.html;
}

callbacks.add('renderMessage', HighlightWordsClient, callbacks.priority.MEDIUM + 1, 'highlight-words');
message.html = highlightWords(msg, toHighlight);
return message;
}
callbacks.add('renderMessage', HighlightWordsClient, callbacks.priority.MEDIUM + 1, 'highlight-words');
});
44 changes: 15 additions & 29 deletions app/highlight-words/client/helper.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,28 @@
import s from 'underscore.string';

export const checkHighlightedWordsInUrls = (msg, highlight) => {
const urlRegex = new RegExp(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)(${ s.escapeRegExp(highlight) })\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)`, 'gmi');
const urlMatches = msg.match(urlRegex);

return urlMatches;
};
export const checkHighlightedWordsInUrls = (msg, urlRegex) => msg.match(urlRegex);

export const removeHighlightedUrls = (msg, highlight, urlMatches) => {
const highlightRegex = new RegExp(highlight, 'gmi');

urlMatches.forEach((match) => {
const highlightRegex = new RegExp(highlight, 'gmi');
return urlMatches.reduce((msg, match) => {
const withTemplate = match.replace(highlightRegex, `<span class="highlight-text">${ highlight }</span>`);
const regexWithTemplate = new RegExp(withTemplate, 'i');

msg = msg.replace(regexWithTemplate, match);
});

return msg;
return msg.replace(regexWithTemplate, match);
}, msg);
};

export const highlightWords = (msg, to_highlight) => {
const highlightTemplate = '$1<span class="highlight-text">$2</span>$3';
const highlightTemplate = '$1<span class="highlight-text">$2</span>$3';

if (Array.isArray(to_highlight)) {
to_highlight.forEach((highlight) => {
if (!s.isBlank(highlight)) {
const regex = new RegExp(`(^|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(${ s.escapeRegExp(highlight) })($|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(?![^<]*>|[^<>]*<\\/)`, 'gmi');
const urlMatches = checkHighlightedWordsInUrls(msg, highlight);
export const getRegexHighlight = (highlight) => new RegExp(`(^|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(${ s.escapeRegExp(highlight) })($|\\b|[\\s\\n\\r\\t.,،'\\\"\\+!?:-])(?![^<]*>|[^<>]*<\\/)`, 'gmi');

msg = msg.replace(regex, highlightTemplate);
export const getRegexHighlightUrl = (highlight) => new RegExp(`https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)(${ s.escapeRegExp(highlight) })\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)`, 'gmi');

if (urlMatches) {
msg = removeHighlightedUrls(msg, highlight, urlMatches);
}
}
});
}
export const highlightWords = (msg, highlights) => highlights.reduce((msg, { highlight, regex, urlRegex }) => {
const urlMatches = checkHighlightedWordsInUrls(msg, urlRegex);
if (!urlMatches) {
return msg.replace(regex, highlightTemplate);

return msg;
};
}
return removeHighlightedUrls(msg.replace(regex, highlightTemplate), highlight, urlMatches);
}, msg);
26 changes: 21 additions & 5 deletions app/highlight-words/tests/helper.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,48 @@

import 'babel-polyfill';
import assert from 'assert';
import { highlightWords } from '../client/helper';
import { highlightWords, getRegexHighlight, getRegexHighlightUrl } from '../client/helper';

describe('helper', () => {
describe('highlightWords', () => {
it('highlights the correct words', () => {
const res = highlightWords('here is some word', ['word']);
const res = highlightWords('here is some word', ['word'].map((highlight) => ({
highlight,
regex: getRegexHighlight(highlight),
urlRegex: getRegexHighlightUrl(highlight),
})));

assert.equal(res, 'here is some <span class="highlight-text">word</span>');
});

describe('handles links', () => {
it('not highlighting one link', () => {
const res = highlightWords('here we go https://somedomain.com/here-some.word/pulls more words after', ['word']);
const res = highlightWords('here we go https://somedomain.com/here-some.word/pulls more words after', ['word'].map((highlight) => ({
highlight,
regex: getRegexHighlight(highlight),
urlRegex: getRegexHighlightUrl(highlight),
})));

assert.equal(res, 'here we go https://somedomain.com/here-some.word/pulls more words after');
});

it('not highlighting two links', () => {
const msg = 'here https://somedomain.com/here-some-foo/pulls more words after http://www.domain.com/some.foo/bar words after';
const res = highlightWords(msg, ['foo']);
const res = highlightWords(msg, ['foo'].map((highlight) => ({
highlight,
regex: getRegexHighlight(highlight),
urlRegex: getRegexHighlightUrl(highlight),
})));

assert.equal(res, msg);
});

it('not highlighting link but keep words on message highlighted', () => {
const res = highlightWords('here we go https://somedomain.com/here-some.foo/pulls more foo after', ['foo']);
const res = highlightWords('here we go https://somedomain.com/here-some.foo/pulls more foo after', ['foo'].map((highlight) => ({
highlight,
regex: getRegexHighlight(highlight),
urlRegex: getRegexHighlightUrl(highlight),
})));

assert.equal(res, 'here we go https://somedomain.com/here-some.foo/pulls more <span class="highlight-text">foo</span> after');
});
Expand Down
42 changes: 28 additions & 14 deletions app/lib/client/lib/formatDate.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,34 @@
import moment from 'moment';

import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';

import { getUserPreference, t } from '../../../utils';
import { settings } from '../../../settings';
import moment from 'moment';

let lastDay = t('yesterday');
let clockMode;
let sameDay;
const dayFormat = ['h:mm A', 'H:mm'];

Meteor.startup(() => Tracker.autorun(() => {
clockMode = getUserPreference(Meteor.userId(), 'clockMode', false);
sameDay = dayFormat[clockMode - 1] || 'h:mm A';
lastDay = t('yesterday');
}));

export const formatTime = (time) => {
tassoevan marked this conversation as resolved.
Show resolved Hide resolved
switch (getUserPreference(Meteor.userId(), 'clockMode', false)) {
switch (clockMode) {
case 1:
return moment(time).format('h:mm A');
case 2:
tassoevan marked this conversation as resolved.
Show resolved Hide resolved
return moment(time).format('H:mm');
return moment(time).format(sameDay);
default:
return moment(time).format(settings.get('Message_TimeFormat'));
}
};

export const formatDateAndTime = (time) => {
switch (getUserPreference(Meteor.userId(), 'clockMode', false)) {
switch (clockMode) {
case 1:
return moment(time).format('MMMM D, Y h:mm A');
case 2:
Expand All @@ -25,15 +38,16 @@ export const formatDateAndTime = (time) => {
}
};

export const timeAgo = (time) => {
const now = new Date();
const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);

return (
(now.getDate() === time.getDate() && moment(time).format('LT')) ||
(yesterday.getDate() === time.getDate() && t('yesterday')) ||
moment(time).format('L')
);
const sameElse = function(now) {
const diff = Math.ceil(this.diff(now, 'years', true));
return diff < 0 ? 'MMM D YYYY' : 'MMM D';
};

export const timeAgo = (date) => moment(date).calendar(null, {
lastDay: `[${ lastDay }]`,
sameDay,
lastWeek: 'dddd',
sameElse,
});

export const formatDate = (time) => moment(time).format(settings.get('Message_DateFormat'));
Loading