The communications platform that puts data protection first.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
Rocket.Chat/packages/rocketchat-ui-admin/client/admin.js

595 lines
17 KiB

/*globals jscolor, i18nDefaultQuery */
import _ from 'underscore';
import s from 'underscore.string';
import toastr from 'toastr';
const TempSettings = new Mongo.Collection(null);
RocketChat.TempSettings = TempSettings;
const getDefaultSetting = function(settingId) {
return RocketChat.settings.collectionPrivate.findOne({
_id: settingId
});
};
const setFieldValue = function(settingId, value, type, editor) {
const input = $('.page-settings').find(`[name="${ settingId }"]`);
switch (type) {
case 'boolean':
$('.page-settings').find(`[name="${ settingId }"][value="${ Number(value) }"]`).prop('checked', true).change();
break;
case 'code':
input.next()[0].CodeMirror.setValue(value);
break;
case 'color':
editor = value && value[0] === '#' ? 'color' : 'expression';
input.parents('.horizontal').find('select[name="color-editor"]').val(editor).change();
input.val(value).change();
break;
case 'roomPick':
const selectedRooms = Template.instance().selectedRooms.get();
selectedRooms[settingId] = value;
Template.instance().selectedRooms.set(selectedRooms);
TempSettings.update({ _id: settingId }, { $set: { value, changed: JSON.stringify(RocketChat.settings.collectionPrivate.findOne(settingId).value) !== JSON.stringify(value) } });
break;
default:
input.val(value).change();
}
};
Template.admin.onCreated(function() {
if (RocketChat.settings.cachedCollectionPrivate == null) {
RocketChat.settings.cachedCollectionPrivate = new RocketChat.CachedCollection({
name: 'private-settings',
eventType: 'onLogged'
});
RocketChat.settings.collectionPrivate = RocketChat.settings.cachedCollectionPrivate.collection;
RocketChat.settings.cachedCollectionPrivate.init();
}
this.selectedRooms = new ReactiveVar({});
RocketChat.settings.collectionPrivate.find().observe({
added: (data) => {
const selectedRooms = this.selectedRooms.get();
if (data.type === 'roomPick') {
selectedRooms[data._id] = data.value;
this.selectedRooms.set(selectedRooms);
}
TempSettings.insert(data);
},
changed: (data) => {
const selectedRooms = this.selectedRooms.get();
if (data.type === 'roomPick') {
selectedRooms[data._id] = data.value;
this.selectedRooms.set(selectedRooms);
}
TempSettings.update(data._id, data);
},
removed: (data) => {
const selectedRooms = this.selectedRooms.get();
if (data.type === 'roomPick') {
delete selectedRooms[data._id];
this.selectedRooms.set(selectedRooms);
}
TempSettings.remove(data._id);
}
});
});
Template.admin.onDestroyed(function() {
TempSettings.remove({});
});
Template.admin.helpers({
languages() {
const languages = TAPi18n.getLanguages();
let result = Object.keys(languages).map(key => {
const language = languages[key];
return _.extend(language, { key });
});
result = _.sortBy(result, 'key');
result.unshift({
'name': 'Default',
'en': 'Default',
'key': ''
});
return result;
},
appLanguage(key) {
const setting = RocketChat.settings.get('Language');
return setting && setting.split('-').shift().toLowerCase() === key;
},
group() {
const groupId = FlowRouter.getParam('group');
const group = RocketChat.settings.collectionPrivate.findOne({
_id: groupId,
type: 'group'
});
if (!group) {
return;
}
const settings = RocketChat.settings.collectionPrivate.find({ group: groupId }, { sort: { section: 1, sorter: 1, i18nLabel: 1 }}).fetch();
const sections = {};
Object.keys(settings).forEach(key => {
const setting = settings[key];
if (setting.i18nDefaultQuery != null) {
if (_.isString(setting.i18nDefaultQuery)) {
i18nDefaultQuery = JSON.parse(setting.i18nDefaultQuery);
} else {
i18nDefaultQuery = setting.i18nDefaultQuery;
}
if (!_.isArray(i18nDefaultQuery)) {
i18nDefaultQuery = [i18nDefaultQuery];
}
Object.keys(i18nDefaultQuery).forEach(key => {
const item = i18nDefaultQuery[key];
if (RocketChat.settings.collectionPrivate.findOne(item) != null) {
setting.value = TAPi18n.__(`${ setting._id }_Default`);
}
});
}
const settingSection = setting.section || '';
if (sections[settingSection] == null) {
sections[settingSection] = [];
}
sections[settingSection].push(setting);
});
group.sections = Object.keys(sections).map(key =>{
const value = sections[key];
return {
section: key,
settings: value
};
});
return group;
},
i18nDefaultValue() {
return TAPi18n.__(`${ this._id }_Default`);
},
isDisabled() {
let enableQuery;
if (this.blocked) {
return {
disabled: 'disabled'
};
}
if (this.enableQuery == null) {
return {};
}
if (_.isString(this.enableQuery)) {
enableQuery = JSON.parse(this.enableQuery);
} else {
enableQuery = this.enableQuery;
}
if (!_.isArray(enableQuery)) {
enableQuery = [enableQuery];
}
let found = 0;
Object.keys(enableQuery).forEach(key =>{
const item = enableQuery[key];
if (TempSettings.findOne(item) != null) {
found++;
}
});
if (found === enableQuery.length) {
return {};
} else {
return {
disabled: 'disabled'
};
}
},
isReadonly() {
if (this.readonly === true) {
return {
readonly: 'readonly'
};
}
},
canAutocomplete() {
if (this.autocomplete === false) {
return {
autocomplete: 'off'
};
}
},
hasChanges(section) {
const group = FlowRouter.getParam('group');
const query = {
group,
changed: true
};
if (section != null) {
if (section === '') {
query.$or = [
{
section: ''
}, {
section: {
$exists: false
}
}
];
} else {
query.section = section;
}
}
return TempSettings.find(query).count() > 0;
},
isSettingChanged(id) {
return TempSettings.findOne({
_id: id
}, {
fields: {
changed: 1
}
}).changed;
},
translateSection(section) {
if (section.indexOf(':') > -1) {
return section;
}
return t(section);
},
label() {
const label = this.i18nLabel || this._id;
if (label) {
return TAPi18n.__(label);
}
},
description() {
let description;
if (this.i18nDescription) {
description = TAPi18n.__(this.i18nDescription);
}
if ((description != null) && description !== this.i18nDescription) {
return description;
}
},
sectionIsCustomOAuth(section) {
return /^Custom OAuth:\s.+/.test(section);
},
callbackURL(section) {
const id = s.strRight(section, 'Custom OAuth: ').toLowerCase();
return Meteor.absoluteUrl(`_oauth/${ id }`);
},
relativeUrl(url) {
return Meteor.absoluteUrl(url);
},
selectedOption(_id, val) {
const option = RocketChat.settings.collectionPrivate.findOne({ _id });
return option && option.value === val;
},
random() {
return Random.id();
},
getEditorOptions(readOnly = false) {
return {
lineNumbers: true,
mode: this.code || 'javascript',
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
foldGutter: true,
matchBrackets: true,
autoCloseBrackets: true,
matchTags: true,
showTrailingSpace: true,
highlightSelectionMatches: true,
readOnly
};
},
setEditorOnBlur(_id) {
Meteor.defer(function() {
if (!$(`.code-mirror-box[data-editor-id="${ _id }"] .CodeMirror`)[0]) {
return;
}
const codeMirror = $(`.code-mirror-box[data-editor-id="${ _id }"] .CodeMirror`)[0].CodeMirror;
if (codeMirror.changeAdded === true) {
return;
}
const onChange = function() {
const value = codeMirror.getValue();
TempSettings.update({ _id }, { $set: { value, changed: RocketChat.settings.collectionPrivate.findOne(_id).value !== value }});
};
const onChangeDelayed = _.debounce(onChange, 500);
codeMirror.on('change', onChangeDelayed);
codeMirror.changeAdded = true;
});
},
assetAccept(fileConstraints) {
if (fileConstraints.extensions && fileConstraints.extensions.length) {
return `.${ fileConstraints.extensions.join(', .') }`;
}
},
autocompleteRoom() {
return {
limit: 10,
//inputDelay: 300
rules: [
{
//@TODO maybe change this 'collection' and/or template
collection: 'CachedChannelList',
subscription: 'channelAndPrivateAutocomplete',
field: 'name',
template: Template.roomSearch,
noMatchTemplate: Template.roomSearchEmpty,
matchAll: true,
selector(match) {
return {
name: match
};
},
sort: 'name'
}
]
};
},
selectedRooms() {
return Template.instance().selectedRooms.get()[this._id] || [];
},
getColorVariable(color) {
return color.replace(/theme-color-/, '@');
},
showResetButton() {
const setting = TempSettings.findOne({ _id: this._id }, { fields: { value: 1, packageValue: 1 }});
return this.type !== 'asset' && setting.value !== setting.packageValue && !this.blocked;
}
});
Template.admin.events({
'change .input-monitor, keyup .input-monitor': _.throttle(function(e) {
let value = s.trim($(e.target).val());
switch (this.type) {
case 'int':
value = parseInt(value);
break;
case 'boolean':
value = value === '1';
break;
case 'color':
$(e.target).siblings('.colorpicker-swatch').css('background-color', value);
}
TempSettings.update({
_id: this._id
}, {
$set: {
value,
changed: RocketChat.settings.collectionPrivate.findOne(this._id).value !== value
}
});
}, 500),
'change select[name=color-editor]'(e) {
const value = s.trim($(e.target).val());
TempSettings.update({ _id: this._id }, { $set: { editor: value }});
RocketChat.settings.collectionPrivate.update({ _id: this._id }, { $set: { editor: value }});
},
'click .rc-header__section-button .discard'() {
const group = FlowRouter.getParam('group');
const query = {
group,
changed: true
};
const settings = TempSettings.find(query, {
fields: { _id: 1, value: 1, packageValue: 1 }}).fetch();
settings.forEach(function(setting) {
const oldSetting = RocketChat.settings.collectionPrivate.findOne({ _id: setting._id }, { fields: { value: 1, type: 1, editor: 1 }});
setFieldValue(setting._id, oldSetting.value, oldSetting.type, oldSetting.editor);
});
},
'click .reset-setting'(e) {
e.preventDefault();
let settingId = $(e.target).data('setting');
if (typeof settingId === 'undefined') {
settingId = $(e.target).parent().data('setting');
}
const defaultValue = getDefaultSetting(settingId);
setFieldValue(settingId, defaultValue.packageValue, defaultValue.type, defaultValue.editor);
},
'click .reset-group'(e) {
let settings;
e.preventDefault();
const group = FlowRouter.getParam('group');
const section = $(e.target).data('section');
if (section === '') {
settings = TempSettings.find({ group, section: { $exists: false }}, { fields: { _id: 1 }}).fetch();
} else {
settings = TempSettings.find({ group, section }, { fields: { _id: 1 }}).fetch();
}
settings.forEach(function(setting) {
const defaultValue = getDefaultSetting(setting._id);
setFieldValue(setting._id, defaultValue.packageValue, defaultValue.type, defaultValue.editor);
TempSettings.update({_id: setting._id }, {
$set: {
value: defaultValue.packageValue,
changed: RocketChat.settings.collectionPrivate.findOne(setting._id).value !== defaultValue.packageValue
}
});
});
},
'click .rc-header__section-button .save'() {
const group = FlowRouter.getParam('group');
const query = { group, changed: true };
const settings = TempSettings.find(query, { fields: { _id: 1, value: 1, editor: 1 }}).fetch();
if (!_.isEmpty(settings)) {
RocketChat.settings.batchSet(settings, function(err) {
if (err) {
return handleError(err);
}
TempSettings.update({ changed: true }, { $unset: { changed: 1 }});
toastr.success(TAPi18n.__('Settings_updated'));
});
}
},
'click .rc-header__section-button .refresh-clients'() {
Meteor.call('refreshClients', function() {
toastr.success(TAPi18n.__('Clients_will_refresh_in_a_few_seconds'));
});
},
'click .rc-header__section-button .add-custom-oauth'() {
const config = {
title: TAPi18n.__('Add_custom_oauth'),
text: TAPi18n.__('Give_a_unique_name_for_the_custom_oauth'),
type: 'input',
showCancelButton: true,
closeOnConfirm: true,
inputPlaceholder: TAPi18n.__('Custom_oauth_unique_name')
};
modal.open(config, function(inputValue) {
if (inputValue === false) {
return false;
}
if (inputValue === '') {
modal.showInputError(TAPi18n.__('Name_cant_be_empty'));
return false;
}
Meteor.call('addOAuthService', inputValue, function(err) {
if (err) {
handleError(err);
}
});
});
},
'click .rc-header__section-button .refresh-oauth'() {
toastr.info(TAPi18n.__('Refreshing'));
return Meteor.call('refreshOAuthService', function(err) {
if (err) {
return handleError(err);
} else {
return toastr.success(TAPi18n.__('Done'));
}
});
},
'click .rc-header__section-button .remove-custom-oauth'() {
const name = this.section.replace('Custom OAuth: ', '');
const config = {
title: TAPi18n.__('Are_you_sure'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: TAPi18n.__('Yes_delete_it'),
cancelButtonText: TAPi18n.__('Cancel'),
closeOnConfirm: true
};
modal.open(config, function() {
Meteor.call('removeOAuthService', name);
});
},
'click .delete-asset'() {
Meteor.call('unsetAsset', this.asset);
},
'change input[type=file]'(ev) {
const e = ev.originalEvent || ev;
let files = e.target.files;
if (!files || files.length === 0) {
if (e.dataTransfer && e.dataTransfer.files) {
files = e.dataTransfer.files;
} else {
files = [];
}
}
Object.keys(files).forEach(key => {
const blob = files[key];
toastr.info(TAPi18n.__('Uploading_file'));
const reader = new FileReader();
reader.readAsBinaryString(blob);
reader.onloadend = () => {
return Meteor.call('setAsset', reader.result, blob.type, this.asset, function(err) {
if (err != null) {
handleError(err);
console.log(err);
return;
}
return toastr.success(TAPi18n.__('File_uploaded'));
});
};
});
},
'click .expand'(e) {
$(e.currentTarget).closest('.section').removeClass('section-collapsed');
$(e.currentTarget).closest('button').removeClass('expand').addClass('collapse').find('span').text(TAPi18n.__('Collapse'));
$('.CodeMirror').each(function(index, codeMirror) {
codeMirror.CodeMirror.refresh();
});
},
'click .collapse'(e) {
$(e.currentTarget).closest('.section').addClass('section-collapsed');
$(e.currentTarget).closest('button').addClass('expand').removeClass('collapse').find('span').text(TAPi18n.__('Expand'));
},
'click button.action'() {
if (this.type !== 'action') {
return;
}
Meteor.call(this.value, function(err, data) {
if (err != null) {
err.details = _.extend(err.details || {}, {
errorTitle: 'Error'
});
handleError(err);
return;
}
const args = [data.message].concat(data.params);
toastr.success(TAPi18n.__.apply(TAPi18n, args), TAPi18n.__('Success'));
});
},
'click .button-fullscreen'() {
const codeMirrorBox = $(`.code-mirror-box[data-editor-id="${ this._id }"]`);
codeMirrorBox.addClass('code-mirror-box-fullscreen content-background-color');
codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh();
},
'click .button-restore'() {
const codeMirrorBox = $(`.code-mirror-box[data-editor-id="${ this._id }"]`);
codeMirrorBox.removeClass('code-mirror-box-fullscreen content-background-color');
codeMirrorBox.find('.CodeMirror')[0].CodeMirror.refresh();
},
'autocompleteselect .autocomplete'(event, instance, doc) {
const selectedRooms = instance.selectedRooms.get();
selectedRooms[this.id] = (selectedRooms[this.id] || []).concat(doc);
instance.selectedRooms.set(selectedRooms);
const value = selectedRooms[this.id];
TempSettings.update({ _id: this.id }, { $set: { value }});
event.currentTarget.value = '';
event.currentTarget.focus();
},
'click .remove-room'(event, instance) {
const docId = this._id;
const settingId = event.currentTarget.getAttribute('data-setting');
const selectedRooms = instance.selectedRooms.get();
selectedRooms[settingId] = _.reject(selectedRooms[settingId] || [], function(setting) {
return setting._id === docId;
});
instance.selectedRooms.set(selectedRooms);
const value = selectedRooms[settingId];
TempSettings.update({ _id: settingId }, {
$set: {
value
}
});
}
});
Template.admin.onRendered(function() {
Tracker.afterFlush(function() {
SideNav.setFlex('adminFlex');
SideNav.openFlex();
});
Tracker.autorun(function() {
const hasColor = TempSettings.find({
group: FlowRouter.getParam('group'),
type: 'color'
}, { fields: { _id: 1, editor: 1 }}).fetch().length;
if (hasColor) {
Meteor.setTimeout(function() {
$('.colorpicker-input').each(function(index, el) {
if (!el._jscLinkedInstance) {
new jscolor(el); //eslint-disable-line
}
});
}, 400);
}
});
});