Chore: Move client helpers (#23178)
parent
651167594c
commit
a4a2fedcc5
@ -1,80 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { ChatPermissions } from './lib/ChatPermissions'; |
||||
import * as Models from '../../models'; |
||||
import { AuthorizationUtils } from '../lib/AuthorizationUtils'; |
||||
|
||||
function atLeastOne(permissions = [], scope, userId) { |
||||
userId = userId || Meteor.userId(); |
||||
const user = Models.Users.findOneById(userId, { fields: { roles: 1 } }); |
||||
|
||||
return permissions.some((permissionId) => { |
||||
if (user && user.roles) { |
||||
if (AuthorizationUtils.isPermissionRestrictedForRoleList(permissionId, user.roles)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
const permission = ChatPermissions.findOne(permissionId, { fields: { roles: 1 } }); |
||||
const roles = (permission && permission.roles) || []; |
||||
|
||||
return roles.some((roleName) => { |
||||
const role = Models.Roles.findOne(roleName, { fields: { scope: 1 } }); |
||||
const roleScope = role && role.scope; |
||||
const model = Models[roleScope]; |
||||
|
||||
return model && model.isUserInRole && model.isUserInRole(userId, roleName, scope); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function all(permissions = [], scope, userId) { |
||||
userId = userId || Meteor.userId(); |
||||
const user = Models.Users.findOneById(userId, { fields: { roles: 1 } }); |
||||
|
||||
return permissions.every((permissionId) => { |
||||
if (user && user.roles) { |
||||
if (AuthorizationUtils.isPermissionRestrictedForRoleList(permissionId, user.roles)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
const permission = ChatPermissions.findOne(permissionId, { fields: { roles: 1 } }); |
||||
const roles = (permission && permission.roles) || []; |
||||
|
||||
return roles.some((roleName) => { |
||||
const role = Models.Roles.findOne(roleName, { fields: { scope: 1 } }); |
||||
const roleScope = role && role.scope; |
||||
const model = Models[roleScope]; |
||||
|
||||
return model && model.isUserInRole && model.isUserInRole(userId, roleName, scope); |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
function _hasPermission(permissions, scope, strategy, userId) { |
||||
userId = userId || Meteor.userId(); |
||||
if (!userId) { |
||||
return false; |
||||
} |
||||
|
||||
if (!Models.AuthzCachedCollection.ready.get()) { |
||||
return false; |
||||
} |
||||
|
||||
permissions = [].concat(permissions); |
||||
return strategy(permissions, scope, userId); |
||||
} |
||||
|
||||
Template.registerHelper('hasPermission', function(permission, scope) { |
||||
return _hasPermission(permission, scope, atLeastOne); |
||||
}); |
||||
Template.registerHelper('userHasAllPermission', function(userId, permission, scope) { |
||||
return _hasPermission(permission, scope, all, userId); |
||||
}); |
||||
|
||||
export const hasAllPermission = (permissions, scope) => _hasPermission(permissions, scope, all); |
||||
export const hasAtLeastOnePermission = (permissions, scope) => _hasPermission(permissions, scope, atLeastOne); |
||||
export const userHasAllPermission = (permissions, scope, userId) => _hasPermission(permissions, scope, all, userId); |
||||
export const hasPermission = hasAllPermission; |
||||
@ -0,0 +1,82 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { ChatPermissions } from './lib/ChatPermissions'; |
||||
import * as Models from '../../models/client'; |
||||
import { AuthorizationUtils } from '../lib/AuthorizationUtils'; |
||||
import { IUser } from '../../../definition/IUser'; |
||||
import { IRole } from '../../../definition/IRole'; |
||||
import { IPermission } from '../../../definition/IPermission'; |
||||
|
||||
const isValidScope = (scope: IRole['scope']): scope is keyof typeof Models => |
||||
typeof scope === 'string' && scope in Models; |
||||
|
||||
const createPermissionValidator = (quantifier: (predicate: (permissionId: IPermission['_id']) => boolean) => boolean) => |
||||
(permissionIds: IPermission['_id'][], scope: IRole['scope'], userId: IUser['_id']): boolean => { |
||||
const user: IUser | null = Models.Users.findOneById(userId, { fields: { roles: 1 } }); |
||||
|
||||
const checkEachPermission = quantifier.bind(permissionIds); |
||||
|
||||
return checkEachPermission((permissionId) => { |
||||
if (user?.roles) { |
||||
if (AuthorizationUtils.isPermissionRestrictedForRoleList(permissionId, user.roles)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
const permission: IPermission | null = ChatPermissions.findOne(permissionId, { fields: { roles: 1 } }); |
||||
const roles = permission?.roles ?? []; |
||||
|
||||
return roles.some((roleName) => { |
||||
const role = Models.Roles.findOne(roleName, { fields: { scope: 1 } }); |
||||
const roleScope = role?.scope; |
||||
|
||||
if (!isValidScope(roleScope)) { |
||||
return false; |
||||
} |
||||
|
||||
const model = Models[roleScope]; |
||||
return model.isUserInRole && model.isUserInRole(userId, roleName, scope); |
||||
}); |
||||
}); |
||||
}; |
||||
|
||||
const atLeastOne = createPermissionValidator(Array.prototype.some); |
||||
|
||||
const all = createPermissionValidator(Array.prototype.every); |
||||
|
||||
const validatePermissions = ( |
||||
permissions: IPermission['_id'] | IPermission['_id'][], |
||||
scope: IRole['scope'], |
||||
predicate: (permissionIds: IPermission['_id'][], scope: IRole['scope'], userId: IUser['_id']) => boolean, |
||||
userId?: IUser['_id'] | null, |
||||
): boolean => { |
||||
userId = userId ?? Meteor.userId(); |
||||
|
||||
if (!userId) { |
||||
return false; |
||||
} |
||||
|
||||
if (!Models.AuthzCachedCollection.ready.get()) { |
||||
return false; |
||||
} |
||||
|
||||
return predicate(([] as IPermission['_id'][]).concat(permissions), scope, userId); |
||||
}; |
||||
|
||||
export const hasAllPermission = ( |
||||
permissions: IPermission['_id'] | IPermission['_id'][], |
||||
scope?: IRole['scope'], |
||||
): boolean => validatePermissions(permissions, scope, all); |
||||
|
||||
export const hasAtLeastOnePermission = ( |
||||
permissions: IPermission['_id'] | IPermission['_id'][], |
||||
scope?: IRole['scope'], |
||||
): boolean => validatePermissions(permissions, scope, atLeastOne); |
||||
|
||||
export const userHasAllPermission = ( |
||||
permissions: IPermission['_id'] | IPermission['_id'][], |
||||
scope?: IRole['scope'], |
||||
userId?: IUser['_id'] | null, |
||||
): boolean => validatePermissions(permissions, scope, all, userId); |
||||
|
||||
export const hasPermission = hasAllPermission; |
||||
@ -1,4 +1,3 @@ |
||||
export { EmojiPicker } from './lib/EmojiPicker'; |
||||
export { renderEmoji } from './lib/emojiRenderer'; |
||||
export { emoji } from '../lib/rocketchat'; |
||||
export { createEmojiMessageRenderer } from './emojiParser'; |
||||
|
||||
@ -1,27 +0,0 @@ |
||||
import { Blaze } from 'meteor/blaze'; |
||||
import { Template } from 'meteor/templating'; |
||||
import { HTML } from 'meteor/htmljs'; |
||||
|
||||
import { emoji } from '../../lib/rocketchat'; |
||||
import { isSetNotNull } from '../function-isSet'; |
||||
|
||||
export const renderEmoji = function(_emoji) { |
||||
if (isSetNotNull(() => emoji.list[_emoji].emojiPackage)) { |
||||
const { emojiPackage } = emoji.list[_emoji]; |
||||
return emoji.packages[emojiPackage].render(_emoji); |
||||
} |
||||
}; |
||||
|
||||
Blaze.registerHelper('renderEmoji', renderEmoji); |
||||
|
||||
Template.registerHelper('renderEmoji', new Template('renderEmoji', function() { |
||||
const view = this; |
||||
const _emoji = Blaze.getData(view); |
||||
|
||||
if (isSetNotNull(() => emoji.list[_emoji].emojiPackage)) { |
||||
const { emojiPackage } = emoji.list[_emoji]; |
||||
return new HTML.Raw(emoji.packages[emojiPackage].render(_emoji)); |
||||
} |
||||
|
||||
return ''; |
||||
})); |
||||
@ -1,12 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { ChatMessage } from '../../models'; |
||||
import { Notifications } from '../../notifications'; |
||||
|
||||
Meteor.startup(function() { |
||||
Notifications.onLogged('Users:Deleted', ({ userId }) => |
||||
ChatMessage.remove({ |
||||
'u._id': userId, |
||||
}), |
||||
); |
||||
}); |
||||
@ -1,53 +0,0 @@ |
||||
import moment from 'moment'; |
||||
import mem from 'mem'; |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import { getUserPreference, t } from '../../../utils'; |
||||
import { settings } from '../../../settings'; |
||||
|
||||
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] || settings.get('Message_TimeFormat'); |
||||
lastDay = t('yesterday'); |
||||
})); |
||||
|
||||
export const formatTime = (time) => { |
||||
switch (clockMode) { |
||||
case 1: |
||||
case 2: |
||||
return moment(time).format(sameDay); |
||||
default: |
||||
return moment(time).format(settings.get('Message_TimeFormat')); |
||||
} |
||||
}; |
||||
|
||||
export const formatDateAndTime = (time) => { |
||||
switch (clockMode) { |
||||
case 1: |
||||
return moment(time).format('MMMM D, Y h:mm A'); |
||||
case 2: |
||||
return moment(time).format('MMMM D, Y H:mm'); |
||||
default: |
||||
return moment(time).format(settings.get('Message_TimeAndDateFormat')); |
||||
} |
||||
}; |
||||
|
||||
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 = mem((time) => moment(time).format(settings.get('Message_DateFormat')), { maxAge: 5000 }); |
||||
@ -1,22 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import { slashCommands, APIClient } from '../../../../utils'; |
||||
|
||||
// Track logins and when they login, get the commands
|
||||
(() => { |
||||
let oldUserId = null; |
||||
|
||||
Tracker.autorun(() => { |
||||
const newUserId = Meteor.userId(); |
||||
if (oldUserId === null && newUserId) { |
||||
APIClient.v1.get('commands.list').then(function _loadedCommands(result) { |
||||
result.commands.forEach((command) => { |
||||
slashCommands.commands[command.command] = command; |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
oldUserId = Meteor.userId(); |
||||
}); |
||||
})(); |
||||
@ -1,42 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import { UserRoles, RoomRoles, ChatMessage } from '../../../models'; |
||||
import { handleError } from '../../../utils'; |
||||
import { Notifications } from '../../../notifications'; |
||||
|
||||
Meteor.startup(function() { |
||||
Tracker.autorun(function() { |
||||
if (Meteor.userId()) { |
||||
Meteor.call('getUserRoles', (error, results) => { |
||||
if (error) { |
||||
return handleError(error); |
||||
} |
||||
|
||||
for (const record of results) { |
||||
UserRoles.upsert({ _id: record._id }, record); |
||||
} |
||||
}); |
||||
|
||||
Notifications.onLogged('roles-change', function(role) { |
||||
if (role.type === 'added') { |
||||
if (role.scope) { |
||||
RoomRoles.upsert({ rid: role.scope, 'u._id': role.u._id }, { $setOnInsert: { u: role.u }, $addToSet: { roles: role._id } }); |
||||
} else { |
||||
UserRoles.upsert({ _id: role.u._id }, { $addToSet: { roles: role._id }, $set: { username: role.u.username } }); |
||||
ChatMessage.update({ 'u._id': role.u._id }, { $addToSet: { roles: role._id } }, { multi: true }); |
||||
} |
||||
} else if (role.type === 'removed') { |
||||
if (role.scope) { |
||||
RoomRoles.update({ rid: role.scope, 'u._id': role.u._id }, { $pull: { roles: role._id } }); |
||||
} else { |
||||
UserRoles.update({ _id: role.u._id }, { $pull: { roles: role._id } }); |
||||
ChatMessage.update({ 'u._id': role.u._id }, { $pull: { roles: role._id } }, { multi: true }); |
||||
} |
||||
} else if (role.type === 'changed') { |
||||
ChatMessage.update({ roles: role._id }, { $inc: { rerender: 1 } }, { multi: true }); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
}); |
||||
@ -1,11 +1,11 @@ |
||||
import { Template } from 'meteor/templating'; |
||||
|
||||
import { callWithErrorHandling } from '../../../../client/lib/utils/callWithErrorHandling'; |
||||
import './messageBoxFollow.html'; |
||||
import { call } from '../../../ui-utils/client'; |
||||
|
||||
Template.messageBoxFollow.events({ |
||||
'click .js-follow'() { |
||||
const { tmid } = this; |
||||
call('followMessage', { mid: tmid }); |
||||
callWithErrorHandling('followMessage', { mid: tmid }); |
||||
}, |
||||
}); |
||||
|
||||
@ -1,4 +1,4 @@ |
||||
<template name="messagePopupEmoji"> |
||||
{{> renderEmoji _id}} |
||||
{{{renderEmoji _id}}} |
||||
{{_id}} |
||||
</template> |
||||
|
||||
@ -1,9 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
const url = new URL(window.location); |
||||
const keys = new Set(); |
||||
|
||||
export const getConfig = (key) => { |
||||
keys.add(key); |
||||
return url.searchParams.get(key) || Meteor._localStorage.getItem(`rc-config-${ key }`); |
||||
}; |
||||
@ -1,17 +0,0 @@ |
||||
import { Tracker } from 'meteor/tracker'; |
||||
import { FlowRouter } from 'meteor/kadira:flow-router'; |
||||
import { ReactiveVar } from 'meteor/reactive-var'; |
||||
|
||||
export const Layout = new class RocketChatLayout { |
||||
constructor() { |
||||
this.embedded = new ReactiveVar(); |
||||
Tracker.autorun(() => { |
||||
this.layout = FlowRouter.getQueryParam('layout'); |
||||
this.embedded.set(this.layout === 'embedded'); |
||||
}); |
||||
} |
||||
|
||||
isEmbedded() { |
||||
return this.embedded.get(); |
||||
} |
||||
}(); |
||||
@ -1,26 +0,0 @@ |
||||
import { Blaze } from 'meteor/blaze'; |
||||
|
||||
import { getUserAvatarURL } from '../../../utils/lib/getUserAvatarURL'; |
||||
|
||||
Blaze.registerHelper('avatarUrlFromUsername', getUserAvatarURL); |
||||
|
||||
export const getAvatarAsPng = function(username, cb) { |
||||
const image = new Image(); |
||||
image.src = getUserAvatarURL(username); |
||||
image.onload = function() { |
||||
const canvas = document.createElement('canvas'); |
||||
canvas.width = image.width; |
||||
canvas.height = image.height; |
||||
const context = canvas.getContext('2d'); |
||||
context.drawImage(image, 0, 0); |
||||
try { |
||||
return cb(canvas.toDataURL('image/png')); |
||||
} catch (e) { |
||||
return cb(''); |
||||
} |
||||
}; |
||||
image.onerror = function() { |
||||
return cb(''); |
||||
}; |
||||
return image.onerror; |
||||
}; |
||||
@ -1,28 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { handleError } from '../../../utils/client/lib/handleError'; |
||||
|
||||
/** |
||||
* Wraps a Meteor method into a Promise. |
||||
* This is particularly useful for creating information dialogs after execution of a Meteor method |
||||
* @param {The Meteor method to be calls} method |
||||
* @param {the method's parameters} params |
||||
*/ |
||||
export const call = (method, ...params) => new Promise((resolve, reject) => { |
||||
Meteor.call(method, ...params, (err, result) => { |
||||
if (err) { |
||||
handleError(err); |
||||
return reject(err); |
||||
} |
||||
return resolve(result); |
||||
}); |
||||
}); |
||||
|
||||
export const callMethod = (method, ...params) => new Promise((resolve, reject) => { |
||||
Meteor.call(method, ...params, (err, result) => { |
||||
if (err) { |
||||
return reject(err); |
||||
} |
||||
return resolve(result); |
||||
}); |
||||
}); |
||||
@ -1,21 +0,0 @@ |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
import { settings } from '../../../settings'; |
||||
|
||||
export const fireGlobalEvent = function _fireGlobalEvent(eventName, params) { |
||||
window.dispatchEvent(new CustomEvent(eventName, { detail: params })); |
||||
|
||||
Tracker.autorun((computation) => { |
||||
const enabled = settings.get('Iframe_Integration_send_enable'); |
||||
if (enabled === undefined) { |
||||
return; |
||||
} |
||||
computation.stop(); |
||||
if (enabled) { |
||||
parent.postMessage({ |
||||
eventName, |
||||
data: params, |
||||
}, settings.get('Iframe_Integration_send_target_origin')); |
||||
} |
||||
}); |
||||
}; |
||||
@ -1,15 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { Rooms } from '../../../models/client'; |
||||
|
||||
export const getUidDirectMessage = (rid, userId = Meteor.userId()) => { |
||||
const room = Rooms.findOne({ _id: rid }, { fields: { uids: 1 } }); |
||||
|
||||
if (!room || !room.uids || room.uids.length > 2) { |
||||
return false; |
||||
} |
||||
|
||||
const other = room && room.uids.filter((uid) => uid !== userId); |
||||
|
||||
return other && other[0]; |
||||
}; |
||||
@ -1,23 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
import { MessageAction } from './MessageAction'; |
||||
import { Rooms, Users } from '../../../models/client'; |
||||
|
||||
export const prependReplies = async (msg, replies = [], mention = false) => { |
||||
const { username } = Users.findOne({ _id: Meteor.userId() }, { fields: { username: 1 } }); |
||||
|
||||
const chunks = await Promise.all(replies.map(async ({ _id, rid, u }) => { |
||||
const permalink = await MessageAction.getPermaLink(_id); |
||||
const room = Rooms.findOne(rid, { fields: { t: 1 } }); |
||||
|
||||
let chunk = `[ ](${ permalink })`; |
||||
if (room.t === 'd' && u.username !== username && mention) { |
||||
chunk += ` @${ u.username }`; |
||||
} |
||||
|
||||
return chunk; |
||||
})); |
||||
|
||||
chunks.push(msg); |
||||
return chunks.join(' '); |
||||
}; |
||||
@ -1,7 +0,0 @@ |
||||
// http://stackoverflow.com/a/14824756
|
||||
|
||||
const ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF'; |
||||
const rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC'; |
||||
const rtlRegExp = new RegExp(`^[^${ ltrChars }]*[${ rtlChars }]`); |
||||
|
||||
export const isRTL = (text) => rtlRegExp.test(text); |
||||
@ -1,63 +0,0 @@ |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
|
||||
import { t } from '../../../utils/client'; |
||||
import { modal } from './modal'; |
||||
|
||||
export const warnUserDeletionMayRemoveRooms = async function(userId, callbackFn, { warningKey, confirmButtonKey, closeOnConfirm = false, skipModalIfEmpty = false, shouldChangeOwner, shouldBeRemoved }) { |
||||
let warningText = warningKey ? t(warningKey) : false; |
||||
|
||||
if (shouldBeRemoved.length + shouldChangeOwner.length === 0 && skipModalIfEmpty) { |
||||
callbackFn(); |
||||
return; |
||||
} |
||||
|
||||
if (shouldChangeOwner.length > 0) { |
||||
let newText; |
||||
|
||||
if (shouldChangeOwner.length === 1) { |
||||
newText = TAPi18n.__('A_new_owner_will_be_assigned_automatically_to_the__roomName__room', { roomName: shouldChangeOwner.pop() }); |
||||
} else if (shouldChangeOwner.length <= 5) { |
||||
newText = TAPi18n.__('A_new_owner_will_be_assigned_automatically_to_those__count__rooms__rooms__', { count: shouldChangeOwner.length, rooms: shouldChangeOwner.join(', ') }); |
||||
} else { |
||||
newText = TAPi18n.__('A_new_owner_will_be_assigned_automatically_to__count__rooms', { count: shouldChangeOwner.length }); |
||||
} |
||||
|
||||
if (warningText) { |
||||
warningText = `${ warningText }<p> </p><p>${ newText }</p>`; |
||||
} else { |
||||
warningText = newText; |
||||
} |
||||
} |
||||
|
||||
if (shouldBeRemoved.length > 0) { |
||||
let newText; |
||||
|
||||
if (shouldBeRemoved.length === 1) { |
||||
newText = TAPi18n.__('The_empty_room__roomName__will_be_removed_automatically', { roomName: shouldBeRemoved.pop() }); |
||||
} else if (shouldBeRemoved.length <= 5) { |
||||
newText = TAPi18n.__('__count__empty_rooms_will_be_removed_automatically__rooms__', { count: shouldBeRemoved.length, rooms: shouldBeRemoved.join(', ') }); |
||||
} else { |
||||
newText = TAPi18n.__('__count__empty_rooms_will_be_removed_automatically', { count: shouldBeRemoved.length }); |
||||
} |
||||
|
||||
if (warningText) { |
||||
warningText = `${ warningText }<p> </p><p>${ newText }</p>`; |
||||
} else { |
||||
warningText = newText; |
||||
} |
||||
} |
||||
|
||||
modal.open({ |
||||
title: t('Are_you_sure'), |
||||
text: warningText, |
||||
type: 'warning', |
||||
showCancelButton: true, |
||||
confirmButtonColor: '#DD6B55', |
||||
confirmButtonText: t(confirmButtonKey || 'Yes_delete_it'), |
||||
cancelButtonText: t('Cancel'), |
||||
closeOnConfirm, |
||||
html: true, |
||||
}, () => { |
||||
callbackFn(); |
||||
}); |
||||
}; |
||||
@ -1,22 +0,0 @@ |
||||
import { TAPi18n, TAPi18next } from 'meteor/rocketchat:tap-i18n'; |
||||
|
||||
import { settings } from '../../../settings'; |
||||
|
||||
export function applyCustomTranslations() { |
||||
let CustomTranslations = settings.get('Custom_Translations'); |
||||
if (typeof CustomTranslations === 'string' && CustomTranslations.trim() !== '') { |
||||
try { |
||||
CustomTranslations = JSON.parse(CustomTranslations); |
||||
|
||||
for (const lang in CustomTranslations) { |
||||
if (CustomTranslations.hasOwnProperty(lang)) { |
||||
const translations = CustomTranslations[lang]; |
||||
TAPi18next.addResourceBundle(lang, 'project', translations); |
||||
} |
||||
} |
||||
TAPi18n._language_changed_tracker.changed(); |
||||
} catch (e) { |
||||
console.error('Invalid setting Custom_Translations', e); |
||||
} |
||||
} |
||||
} |
||||
@ -1,18 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
|
||||
export const baseURI = (() => { |
||||
if (document.baseURI) { return document.baseURI; } |
||||
|
||||
// Should be exactly one tag:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
|
||||
const base = document.getElementsByTagName('base'); |
||||
|
||||
// Return location from BASE tag.
|
||||
if (base.length > 0) { return base[0].href; } |
||||
|
||||
// Else use implementation of documentURI:
|
||||
// http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-baseURI
|
||||
return document.URL; |
||||
})(); |
||||
|
||||
Meteor.absoluteUrl.defaultOptions = { ...Meteor.absoluteUrl.defaultOptions, rootUrl: baseURI }; |
||||
@ -1,41 +0,0 @@ |
||||
import { Meteor } from 'meteor/meteor'; |
||||
import moment from 'moment'; |
||||
|
||||
import { hasPermission } from '../../../authorization/client'; |
||||
import { settings } from '../../../settings/client'; |
||||
|
||||
export const canDeleteMessage = ({ rid, ts, uid }) => { |
||||
const userId = Meteor.userId(); |
||||
|
||||
const forceDelete = hasPermission('force-delete-message', rid); |
||||
if (forceDelete) { |
||||
return true; |
||||
} |
||||
|
||||
const isDeleteAllowed = settings.get('Message_AllowDeleting'); |
||||
if (!isDeleteAllowed) { |
||||
return false; |
||||
} |
||||
|
||||
const allowed = hasPermission('delete-message', rid); |
||||
|
||||
const deleteOwn = allowed || (uid === userId && hasPermission('delete-own-message')); |
||||
if (!allowed && !deleteOwn) { |
||||
return false; |
||||
} |
||||
|
||||
const blockDeleteInMinutes = settings.get('Message_AllowDeleting_BlockDeleteInMinutes'); |
||||
if (blockDeleteInMinutes != null && blockDeleteInMinutes !== 0) { |
||||
let msgTs; |
||||
if (ts != null) { |
||||
msgTs = moment(ts); |
||||
} |
||||
let currentTsDiff; |
||||
if (msgTs != null) { |
||||
currentTsDiff = moment().diff(msgTs, 'minutes'); |
||||
} |
||||
return currentTsDiff < blockDeleteInMinutes; |
||||
} |
||||
|
||||
return true; |
||||
}; |
||||
@ -1,32 +0,0 @@ |
||||
import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; |
||||
import _ from 'underscore'; |
||||
import toastr from 'toastr'; |
||||
import { escapeHTML } from '@rocket.chat/string-helpers'; |
||||
|
||||
export const handleError = function(error, useToastr = true) { |
||||
if (error.xhr) { |
||||
error = error.xhr.responseJSON || {}; |
||||
} |
||||
|
||||
if (_.isObject(error.details)) { |
||||
for (const key in error.details) { |
||||
if (error.details.hasOwnProperty(key)) { |
||||
error.details[key] = TAPi18n.__(error.details[key]); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (useToastr) { |
||||
if (error.toastrShowed) { |
||||
return; |
||||
} |
||||
const details = Object.entries(error.details || {}) |
||||
.reduce((obj, [key, value]) => ({ ...obj, [key]: escapeHTML(value) }), {}); |
||||
const message = TAPi18n.__(error.error || error.message, details); |
||||
const title = details.errorTitle && TAPi18n.__(details.errorTitle); |
||||
|
||||
return toastr.error(message, title); |
||||
} |
||||
|
||||
return escapeHTML(TAPi18n.__(error.error || error.message, error.details)); |
||||
}; |
||||
@ -1,14 +0,0 @@ |
||||
import { Tracker } from 'meteor/tracker'; |
||||
|
||||
export const waitUntilFind = <T>(fn: () => T | undefined): Promise<T> => new Promise((resolve) => { |
||||
Tracker.autorun((c) => { |
||||
const result = fn(); |
||||
|
||||
if (result === undefined) { |
||||
return; |
||||
} |
||||
|
||||
c.stop(); |
||||
resolve(result); |
||||
}); |
||||
}); |
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue