channel info\edit

pull/8411/head
Guilherme Gazzo 8 years ago
parent 9c86a3a1fd
commit 16562611f2
  1. 10
      packages/rocketchat-channel-settings-mail-messages/client/views/channelSettingsMailMessages.html
  2. 8
      packages/rocketchat-channel-settings-mail-messages/client/views/mailMessagesInstructions.html
  3. 278
      packages/rocketchat-channel-settings/client/views/channelSettings.html
  4. 595
      packages/rocketchat-channel-settings/client/views/channelSettings.js
  5. 59
      packages/rocketchat-channel-settings/server/methods/saveRoomSettings.js
  6. 55
      packages/rocketchat-theme/client/imports/components/userInfo.css
  7. 31
      packages/rocketchat-theme/client/imports/forms/button.css

@ -1,10 +1,10 @@
<template name="channelSettingsMailMessages">
{{#if canSendEmail}}
<li>
<label>{{_ "Mail_Messages"}}</label>
<div>
<button type="button" class="button primary mail-messages">{{_ "Choose_messages"}}</button>
<label class="rc-user-info__label">
{{_ "Mail_Messages"}}
<div class="rc-user-info__description">
<button type="button" class="rc-button rc-button--outline rc-button--primary mail-messages">{{_ "Choose_messages"}}</button>
</div>
</li>
</label>
{{/if}}
</template>

@ -26,13 +26,13 @@
<div class="input-line double-col">
<label>{{_ "Additional_emails"}}</label>
<div>
<input type="text" name="to_emails" value="" />
<input type="text" name="to_emails" value="" class="rc-input__element"/>
</div>
</div>
<div class="input-line double-col">
<label>{{_ "Subject"}}</label>
<div>
<input type="text" name="subject" value="{{_ "Mail_Messages_Subject" roomName}}" />
<input type="text" name="subject" class="rc-input__element" value="{{_ "Mail_Messages_Subject" roomName}}" />
</div>
</div>
</fieldset>
@ -47,8 +47,8 @@
{{{_ "Mail_Message_No_messages_selected_select_all"}}}
</div>
<p style="margin-top: 30px">
<button type="button" class="button cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary send">{{_ "Send"}}</button>
<button class="rc-button rc-button--outline cancel">{{_ 'Cancel'}}</button>
<button class="rc-button rc-button--primary send">{{_ 'Send'}}</button>
</p>
</div>
</div>

@ -1,109 +1,187 @@
<template name="channelSettings">
<div class="list-view channel-settings">
<div class="title">
<h2>{{_ "Room_Info"}}</h2>
</div>
<form>
<ul class="list clearfix">
{{#let room=getRoom}}
{{#each toArray settings}}
{{#if editing}}
{{> channelSettingsEditing}}
{{else}}
{{> channelSettingsInfo}}
{{/if}}
</template>
<template name="channelSettingsEditing">
<div class="rc-user-info__scroll">
{{#with settings.name}}
{{#if canView}}
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}{{equal default value}}</div>
<div class="rc-input__wrapper">
<input type="text" name="name" value="{{value}}" class="rc-input__element js-input" {{./disabled}}/>
</div>
</label>
</div>
</div>
{{/if}}
{{/with}}
{{#with settings.topic}}
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}{{equal default value}}</div>
<div class="rc-input__wrapper">
<input type="text" name="topic" value="{{value}}" class="rc-input__element js-input" {{./disabled}}/>
</div>
</label>
</div>
</div>
{{/with}}
{{#if $value.canView room}}
{{#let value=(valueOf room $key)}}
<li class="{{$value.type}}">
<label>{{_ $value.label}}</label>
<div class="setting-block">
{{#if $eq $value.type 'text'}}
{{#if editing $key}}
{{#if $value.canEdit room}}
<input type="text" name="{{$key}}" value="{{value}}" class="content-background-color editing" />
{{/if}}
{{else}}
<span class='current-setting' data-edit="{{#if $value.canEdit room}}{{$key}}{{else}}false{{/if}}">{{value}}</span>
{{/if}}
{{/if}}
{{#with settings.announcement}}
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}{{equal default value}}</div>
<div class="rc-input__wrapper">
<input type="text" name="announcement" value="{{value}}" class="rc-input__element js-input" {{./disabled}}/>
</div>
</label>
</div>
</div>
{{/with}}
{{#if $eq $value.type 'markdown'}}
{{#if editing $key}}
{{#if $value.canEdit room}}
<input type="text" name="{{$key}}" value="{{unscape value}}" class="content-background-color editing" />
{{/if}}
{{else}}
<span class='current-setting' data-edit="{{#if $value.canEdit room}}{{$key}}{{else}}false{{/if}}">{{{RocketChatMarkdown value}}}</span>
{{/if}}
{{/if}}
{{#with settings.description}}
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}{{equal default value}}</div>
<div class="rc-input__wrapper">
<input type="text" name="description" value="{{value}}" class="rc-input__element js-input" {{./disabled}}/>
</div>
</label>
</div>
</div>
{{/with}}
{{#if $eq $value.type 'select'}}
{{#each toArray $value.options}}
<div class="input radio">
<input type="radio" id="{{$key}}" name="{{../$key}}" value="{{$key}}" checked="{{$eq value $key}}" disabled="{{isDisabled $key room}}" />
<label for="{{$key}}">{{_ $value}}</label>
</div>
{{/each}}
{{/if}}
{{#with settings.t}}
<div class="rc-user-info__row">
<div class="rc-switch">
<label class="rc-switch__label">
<span class="rc-switch__text">
{{_ label}}{{equal default value}}
</span>
<input type="checkbox" class="rc-switch__input js-input-check" name="readOnly" {{checked}} {{./disabled}}>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
</label>
</div>
</div>
{{/with}}
{{#if $eq $value.type 'boolean'}}
<div class="input checkbox toggle">
<input type="checkbox" id="{{$key}}" name="{{$key}}" value="{{value}}" checked="{{$eq value true}}" disabled="{{isDisabled $key room}}" />
<label for="{{$key}}"></label>
</div>
{{#if $value.canEdit room}}
{{#if $value.processing.get}}
{{> loading}}
{{/if}}
{{/if}}
{{/if}}
{{#with settings.ro}}
<div class="rc-user-info__row">
<div class="rc-switch">
<label class="rc-switch__label">
<span class="rc-switch__text">
{{_ label}}{{equal default value}}
</span>
<input type="checkbox" class="rc-switch__input js-input-check" name="ro" {{checked}} {{./disabled}}>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
</label>
</div>
</div>
{{/with}}
{{#unless $value.isToggle}}
{{#if $value.canEdit room}}
{{#if editing $key}}
<div class="buttons secondary-background-color">
<button type="button" class="button cancel">
<i class="icon-cancel"></i>
</button>
<button type="button" class="button primary save">
<i class="icon-ok success-color"></i>
</button>
</div>
{{else}}
{{#if $value.showHideValue room}}
<button type="button" class="button show">
<i class="{{#if showingValue $key}}icon-eye-off{{else}}icon-eye{{/if}}"></i>
</button>
{{/if}}
<button type="button" class="button edit">
<i class="icon-pencil" data-edit="{{$key}}"></i>
</button>
{{/if}}
{{/if}}
{{/unless}}
</div>
</li>
{{# if has $value 'message' }}
{{#let message=($value.message room)}}
{{#if message}}
<li>
<div class="alert alert-warning pending-background pending-border">
{{_ message}}
</div>
</li>
{{/if}}
{{/let}}
{{/if}}
{{/let}}
{{/if}}
{{/each}}
{{/let}}
{{#each channelSettings}}
{{> Template.dynamic template=template data=data}}
{{/each}}
</ul>
</form>
{{#if canDeleteRoom}}
<nav>
<button class="button danger delete" title="{{_ 'Delete'}}"><i class="icon-trash"></i></button>
</nav>
{{/if}}
{{#with settings.reactWhenReadOnly}}
{{#if canView}}
<div class="rc-user-info__row">
<div class="rc-switch">
<label class="rc-switch__label">
<span class="rc-switch__text">
{{_ label}}{{equal default value}}
</span>
<input type="checkbox" class="rc-switch__input js-input-check" name="reactWhenReadOnly" {{checked}} {{./disabled}}>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
</label>
</div>
</div>
{{/if}}
{{/with}}
{{#with settings.archived}}
{{#if canView}}
<div class="rc-user-info__row">
<div class="rc-switch">
<label class="rc-switch__label">
<span class="rc-switch__text">
{{_ label}}{{equal default value}}
</span>
<input type="checkbox" class="rc-switch__input js-input-check" name="archived" {{checked}} {{./disabled}}>
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
</label>
</div>
</div>
{{/if}}
{{/with}}
{{#with settings.joinCode}}
<div class="rc-user-info__row">
<div class="rc-input">
<label class="rc-input__label">
<div class="rc-input__title">{{_ label}}{{equal default value}}</div>
<div class="rc-input__wrapper">
<input type="text" name="joinCode" value="{{value}}" class="rc-input__element js-input" {{./disabled}}/>
</div>
</label>
</div>
</div>
{{/with}}
</div>
<div class="rc-user-info__flex rc-user-info__row">
<button class="rc-button rc-button--secondary js-cancel rc-button--outline" title="{{_ 'Cancel'}}">{{_ 'Cancel'}}</button>
<button class="rc-button rc-button--secondary js-reset" {{modified 'disabled'}} title="{{_ 'Reset'}}">{{_ 'Reset'}}</button>
<button class="rc-button rc-button--primary js-save" {{modified 'disabled'}} title="{{_ 'Save'}}">{{_ 'Save'}}</button>
</div>
</template>
<template name="channelSettingsInfo">
<main class="contextual-bar__container rc-user-info-wrapper">
{{# with settings=settings}}
<div class="rc-user-info">
<h3 title="{{name}}" class="rc-user-info__name">{{> icon block="rc-header__icon" icon=channelIcon}}{{ unscape name}}</h3>
</div>
<label class="rc-user-info__label">
{{_ "Description"}}
<div class="rc-user-info__description">
{{unscape description}}
</div>
</label>
<label class="rc-user-info__label">
{{_ "Announcement"}}
<div class="rc-user-info__description">
{{unscape announcement}}
</div>
</label>
<label class="rc-user-info__label">
{{_ "Topic"}}
<div class="rc-user-info__description">
{{unscape topic}}
</div>
</label>
{{/with}}
{{#each channelSettings}}
<div class="rc-user-info__row">
{{> Template.dynamic template=template data=data}}
</div>
{{/each}}
<div class="rc-user-info__flex">
{{#if canDeleteRoom}}
<button class="rc-button rc-button--outline rc-button--cancel js-delete" title="{{_ 'Delete'}}">{{> icon icon='trash'}}{{_ 'Delete'}}</button>
{{/if}}
<button class="rc-button rc-button--outline rc-button--secondary js-edit" type="submit" data-button="Edit" {{createIsDisabled}}>{{> icon icon='edit'}}{{_ "Edit"}}</button>
</div>
</main>
</template>

@ -1,203 +1,66 @@
import toastr from 'toastr';
import s from 'underscore.string';
Template.channelSettings.helpers({
getIcon(room) {
const roomType = RocketChat.models.Rooms.findOne(room._id).t;
switch (roomType) {
case 'd':
return 'at';
case 'p':
return 'lock';
case 'c':
return 'hashtag';
case 'l':
return 'livechat';
default :
return null;
}
},
toArray(obj) {
return Object.keys(obj).map((key) => {
return {
$key: key,
$value: obj[key]
};
});
},
valueOf(obj, key) {
if (key === 't') {
if (obj[key] === 'c') {
return false;
}
return true;
}
if (this.$value.getValue) {
return this.$value.getValue(obj, key);
}
return obj && obj[key];
},
showSetting(setting, room) {
if (setting.showInDirect === false) {
return room.t !== 'd';
}
return true;
},
get(settings, key) {
return settings[key];
},
settings() {
return Template.instance().settings;
},
getRoom() {
return ChatRoom.findOne(this.rid);
},
editing(field) {
return Template.instance().editing.get() === field;
},
isDisabled(field, room) {
const setting = Template.instance().settings[field];
return (typeof setting.disabled === 'function' && setting.disabled(room)) || setting.processing.get() || !RocketChat.authz.hasAllPermission('edit-room', room._id);
},
channelSettings() {
return RocketChat.ChannelSettings.getOptions(Template.currentData(), 'room');
},
unscape(value) {
return s.unescapeHTML(value);
},
canDeleteRoom() {
const room = ChatRoom.findOne(this.rid, {
fields: {
t: 1
const call = (method, ...params) => {
return new Promise((resolve, reject) => {
Meteor.call(method, ...params, (err, result)=> {
if (err) {
handleError(err);
return reject(err);
}
return resolve(result);
});
const roomType = room && room.t;
return roomType && RocketChat.authz.hasAtLeastOnePermission(`delete-${ roomType }`, this.rid);
});
};
Template.channelSettingsEditing.events({
'input .js-input'(e) {
this.value.set(e.currentTarget.value);
},
readOnly() {
const room = ChatRoom.findOne(this.rid, {
fields: {
ro: 1
}
});
return room && room.ro;
'change .js-input-check'(e) {
this.value.set(e.currentTarget.checked);
},
has(v, key) {
return !!(v && v[key]);
'click .js-reset'(e, t) {
const {settings} = t;
Object.keys(settings).forEach(key => settings[key].value.set(settings[key].default.get()));
},
readOnlyDescription() {
const room = ChatRoom.findOne(this.rid, {
fields: {
ro: 1
async 'click .js-save'(e, t) {
const {settings} = t;
Object.keys(settings).forEach(async name => {
const setting = settings[name];
const value = setting.value.get();
if (setting.default.get() !== value) {
await setting.save(value).then(() => {
setting.default.set(value);
setting.value.set(value);
}, console.log);
}
});
return t(room && room.ro ? 'True' : 'False');
},
showingValue(field) {
const { showingValue } = Template.instance().settings[field];
return showingValue && showingValue.get();
}
});
Template.channelSettings.events({
'click .delete'() {
return swal({
title: t('Are_you_sure'),
text: t('Delete_Room_Warning'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: t('Yes_delete_it'),
cancelButtonText: t('Cancel'),
closeOnConfirm: false,
html: false
}, () => {
swal.disableButtons();
Meteor.call('eraseRoom', this.rid, function(error) {
if (error) {
handleError(error);
return swal.enableButtons();
}
swal({
title: t('Deleted'),
text: t('Room_has_been_deleted'),
type: 'success',
timer: 2000,
showConfirmButton: false
});
});
});
},
'keydown input[type=text]'(e, t) {
if (e.keyCode === 13) {
e.preventDefault();
t.saveSetting();
}
},
async 'click [data-edit], click .button.edit'(e, t) {
e.preventDefault();
let input = $(e.currentTarget);
await t.showValue(this.$key, true);
if (input.hasClass('button')) {
input = $(e.currentTarget).siblings('.current-setting');
}
if (input.data('edit')) {
t.editing.set(input.data('edit'));
setTimeout((function() {
return t.$('input.editing').focus().select();
}), 100);
}
},
'click .button.show'(e, t) {
e.preventDefault();
t.showValue(this.$key);
},
'change [type="radio"]'(e, t) {
return t.editing.set($(e.currentTarget).attr('name'));
},
'change [type="checkbox"]'(e, t) {
t.editing.set($(e.currentTarget).attr('name'));
return t.saveSetting();
},
'click .cancel'(e, t) {
e.preventDefault();
t.cancelEditing(this.$key);
},
'click .save'(e, t) {
e.preventDefault();
return t.saveSetting();
}
});
Template.channelSettings.onCreated(function() {
this.room = ChatRoom.findOne(this.data && this.data.rid);
this.editing = new ReactiveVar;
Template.channelSettingsEditing.onCreated(function() {
const room = this.room = ChatRoom.findOne(this.data && this.data.rid);
this.settings = {
name: {
type: 'text',
label: 'Name',
canView(room) {
canView() {
return room.t !== 'd';
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('edit-room', room._id);
},
getValue(room) {
getValue() {
if (RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
return room.fname || room.name;
}
return room.name;
},
save(value, room) {
save(value) {
let nameValidation;
if (!RocketChat.authz.hasAllPermission('edit-room', room._id) || (room.t !== 'c' && room.t !== 'p')) {
return toastr.error(t('error-not-allowed'));
return Promise.reject(toastr.error(t('error-not-allowed')));
}
if (!RocketChat.settings.get('UI_Allow_room_names_with_special_chars')) {
try {
@ -206,17 +69,14 @@ Template.channelSettings.onCreated(function() {
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
}
if (!nameValidation.test(value)) {
return toastr.error(t('error-invalid-room-name', {
return Promise.reject(toastr.error(t('error-invalid-room-name', {
room_name: {
name: value
}
}));
})));
}
}
Meteor.call('saveRoomSettings', room._id, 'roomName', value, function(err) {
if (err) {
return handleError(err);
}
return call('saveRoomSettings', room._id, 'roomName', value).then(function() {
RocketChat.callbacks.run('roomNameChanged', {
_id: room._id,
name: value
@ -231,14 +91,11 @@ Template.channelSettings.onCreated(function() {
canView() {
return true;
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('edit-room', room._id);
},
save(value, room) {
return Meteor.call('saveRoomSettings', room._id, 'roomTopic', value, function(err) {
if (err) {
return handleError(err);
}
save(value) {
return call('saveRoomSettings', room._id, 'roomTopic', value).then(function() {
toastr.success(TAPi18n.__('Room_topic_changed_successfully'));
return RocketChat.callbacks.run('roomTopicChanged', room);
});
@ -250,14 +107,11 @@ Template.channelSettings.onCreated(function() {
canView() {
return true;
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('edit-room', room._id);
},
save(value, room) {
return Meteor.call('saveRoomSettings', room._id, 'roomAnnouncement', value, function(err) {
if (err) {
return handleError(err);
}
save(value) {
return call('saveRoomSettings', room._id, 'roomAnnouncement', value).then(() => {
toastr.success(TAPi18n.__('Room_announcement_changed_successfully'));
return RocketChat.callbacks.run('roomAnnouncementChanged', room);
});
@ -266,37 +120,39 @@ Template.channelSettings.onCreated(function() {
description: {
type: 'text',
label: 'Description',
canView(room) {
canView() {
return room.t !== 'd';
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('edit-room', room._id);
},
save(value, room) {
return Meteor.call('saveRoomSettings', room._id, 'roomDescription', value, function(err) {
if (err) {
return handleError(err);
}
save(value) {
return call('saveRoomSettings', room._id, 'roomDescription', value).then(function() {
return toastr.success(TAPi18n.__('Room_description_changed_successfully'));
});
}
},
t: {
type: 'boolean',
label: 'Private',
label() {
return this.value.get()? 'Private' : 'Public';
},
isToggle: true,
processing: new ReactiveVar(false),
disabled(room) {
getValue() {
return room.t === 'p';
},
disabled() {
return room['default'] && !RocketChat.authz.hasRole(Meteor.userId(), 'admin');
},
message(room) {
message() {
if (RocketChat.authz.hasAllPermission('edit-room', room._id) && room['default']) {
if (!RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
return 'Room_type_of_default_rooms_cant_be_changed';
}
}
},
canView(room) {
canView() {
if (['c', 'p'].includes(room.t) === false) {
return false;
} else if (room.t === 'p' && !RocketChat.authz.hasAllPermission('create-c')) {
@ -306,43 +162,40 @@ Template.channelSettings.onCreated(function() {
}
return true;
},
canEdit(room) {
canEdit() {
return (RocketChat.authz.hasAllPermission('edit-room', room._id) && !room['default']) || RocketChat.authz.hasRole(Meteor.userId(), 'admin');
},
save(value, room) {
save(value) {
const saveRoomSettings = () => {
this.processing.set(true);
value = value ? 'p' : 'c';
RocketChat.callbacks.run('roomTypeChanged', room);
return Meteor.call('saveRoomSettings', room._id, 'roomType', value, (err) => {
if (err) {
return handleError(err);
}
this.processing.set(false);
return call('saveRoomSettings', room._id, 'roomType', value).then(() => {
return toastr.success(TAPi18n.__('Room_type_changed_successfully'));
});
};
if (room['default']) {
if (RocketChat.authz.hasRole(Meteor.userId(), 'admin')) {
swal({
title: t('Room_default_change_to_private_will_be_default_no_more'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: t('Yes'),
cancelButtonText: t('Cancel'),
closeOnConfirm: true,
html: false
}, function(confirmed) {
if (confirmed) {
return saveRoomSettings();
}
return new Promise((resolve, reject)=> {
swal({
title: t('Room_default_change_to_private_will_be_default_no_more'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: t('Yes'),
cancelButtonText: t('Cancel'),
closeOnConfirm: true,
html: false
}, function(confirmed) {
if (confirmed) {
return resolve(saveRoomSettings());
}
return reject();
});
});
}
return $('.channel-settings form [name=\'t\']').prop('checked', !!room.type === 'p');
} else {
return saveRoomSettings();
// return $('.channel-settings form [name=\'t\']').prop('checked', !!room.type === 'p');
}
return saveRoomSettings();
}
},
ro: {
@ -350,21 +203,14 @@ Template.channelSettings.onCreated(function() {
label: 'Read_only',
isToggle: true,
processing: new ReactiveVar(false),
canView(room) {
canView() {
return room.t !== 'd';
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('set-readonly', room._id);
},
save(value, room) {
this.processing.set(true);
return Meteor.call('saveRoomSettings', room._id, 'readOnly', value, (err) => {
if (err) {
return handleError(err);
}
this.processing.set(false);
return toastr.success(TAPi18n.__('Read_only_changed_successfully'));
});
save(value) {
return call('saveRoomSettings', room._id, 'readOnly', value).then(() => toastr.success(TAPi18n.__('Read_only_changed_successfully')));
}
},
reactWhenReadOnly: {
@ -372,19 +218,14 @@ Template.channelSettings.onCreated(function() {
label: 'React_when_read_only',
isToggle: true,
processing: new ReactiveVar(false),
canView(room) {
return room.t !== 'd' && room.ro;
canView: () => {
return this.settings.t.value && this.settings.t.value.get() !== 'd' && this.settings.ro.value.get();
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id);
},
save(value, room) {
this.processing.set(true);
return Meteor.call('saveRoomSettings', room._id, 'reactWhenReadOnly', value, (err) => {
if (err) {
return handleError(err);
}
this.processing.set(false);
save(value) {
return call('saveRoomSettings', room._id, 'reactWhenReadOnly', value).then(() => {
return toastr.success(TAPi18n.__('React_when_read_only_changed_successfully'));
});
}
@ -394,43 +235,41 @@ Template.channelSettings.onCreated(function() {
label: 'Room_archivation_state_true',
isToggle: true,
processing: new ReactiveVar(false),
canView(room) {
return room.t !== 'd';
canView: () => {
return this.settings.t.value && this.settings.t.value.get() !== 'd';
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAtLeastOnePermission(['archive-room', 'unarchive-room'], room._id);
},
save(value, room) {
return swal({
title: t('Are_you_sure'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: value ? t('Yes_archive_it') : t('Yes_unarchive_it'),
cancelButtonText: t('Cancel'),
closeOnConfirm: false,
html: false
}, function(confirmed) {
swal.disableButtons();
if (confirmed) {
const action = value ? 'archiveRoom' : 'unarchiveRoom';
return Meteor.call(action, room._id, function(err) {
if (err) {
swal.enableButtons();
handleError(err);
}
swal({
title: value ? t('Room_archived') : t('Room_has_been_archived'),
text: value ? t('Room_has_been_archived') : t('Room_has_been_unarchived'),
type: 'success',
timer: 2000,
showConfirmButton: false
});
return RocketChat.callbacks.run(action, room);
});
} else {
return $('.channel-settings form [name=\'archived\']').prop('checked', !!room.archived);
}
save(value) {
return new Promise((resolve, reject)=>{
swal({
title: t('Are_you_sure'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: value ? t('Yes_archive_it') : t('Yes_unarchive_it'),
cancelButtonText: t('Cancel'),
closeOnConfirm: false,
html: false
}, function(confirmed) {
swal.disableButtons();
if (confirmed) {
const action = value ? 'archiveRoom' : 'unarchiveRoom';
return resolve(call(action, room._id).then(() => {
swal({
title: value ? t('Room_archived') : t('Room_has_been_archived'),
text: value ? t('Room_has_been_archived') : t('Room_has_been_unarchived'),
type: 'success',
timer: 2000,
showConfirmButton: false
});
return RocketChat.callbacks.run(action, room);
}, () => swal.enableButtons()));
}
return reject();
});
});
}
},
@ -439,26 +278,26 @@ Template.channelSettings.onCreated(function() {
label: 'Password',
showingValue: new ReactiveVar(false),
realValue: null,
canView(room) {
return room.t === 'c' && RocketChat.authz.hasAllPermission('edit-room', room._id);
canView:() => {
return this.setting.t.value && this.setting.t.value.get() === 'c' && RocketChat.authz.hasAllPermission('edit-room', room._id);
},
canEdit(room) {
canEdit() {
return RocketChat.authz.hasAllPermission('edit-room', room._id);
},
getValue(room) {
getValue() {
if (this.showingValue.get()) {
return this.realValue;
}
return room.joinCodeRequired ? '*****' : '';
},
showHideValue(room) {
showHideValue() {
return room.joinCodeRequired;
},
cancelEditing() {
this.showingValue.set(false);
this.realValue = null;
},
async showValue(room, forceShow = false) {
async showValue(_room, forceShow = false) {
if (this.showingValue.get()) {
if (forceShow) {
return;
@ -468,52 +307,166 @@ Template.channelSettings.onCreated(function() {
return null;
}
return Meteor.call('getRoomJoinCode', room._id, (error, result) => {
if (error) {
return handleError(error);
}
return call('getRoomJoinCode', room._id).then(result => {
this.realValue = result;
this.showingValue.set(true);
});
},
save(value, room) {
Meteor.call('saveRoomSettings', room._id, 'joinCode', value, function(err) {
if (err) {
return handleError(err);
}
save(value) {
return call('saveRoomSettings', room._id, 'joinCode', value).then(function() {
toastr.success(TAPi18n.__('Room_password_changed_successfully'));
return RocketChat.callbacks.run('roomCodeChanged', room);
});
}
}
};
this.saveSetting = () => {
const room = ChatRoom.findOne(this.data && this.data.rid);
const field = this.editing.get();
let value;
if (this.settings[field].type === 'select') {
value = this.$(`.channel-settings form [name=${ field }]:checked`).val();
} else if (this.settings[field].type === 'boolean') {
value = this.$(`.channel-settings form [name=${ field }]`).is(':checked');
} else {
value = this.$(`.channel-settings form [name=${ field }]`).val();
}
if (value !== room[field]) {
this.settings[field].save(value, room);
Object.keys(this.settings).forEach(key => {
const setting = this.settings[key];
const def =setting.getValue ? setting.getValue(this.room): this.room[key];
setting.default = new ReactiveVar(def);
setting.value = new ReactiveVar(def);
});
});
Template.channelSettingsEditing.helpers({
value() {
return this.value.get();
},
default() {
return this.default.get();
},
disabled() {
return !this.canEdit() ? '' : 'disabled';
},
checked() {
return !this.value.get() ? '' : 'checked';
},
modified(text = '') {
const {settings} = Template.instance();
return !Object.keys(settings).some(key => settings[key].default.get() !== settings[key].value.get()) ? text : '';
},
equal(text = '', text2 = '') {
return text !== text2 ? '*':'';
},
getIcon(room) {
const roomType = RocketChat.models.Rooms.findOne(room._id).t;
switch (roomType) {
case 'd':
return 'at';
case 'p':
return 'lock';
case 'c':
return 'hashtag';
case 'l':
return 'livechat';
default :
return null;
}
},
settings() {
return Template.instance().settings;
},
editing(field) {
return Template.instance().editing.get() === field;
},
isDisabled(field, room) {
const setting = Template.instance().settings[field];
return (typeof setting.disabled === 'function' && setting.disabled(room)) || setting.processing.get() || !RocketChat.authz.hasAllPermission('edit-room', room._id);
},
unscape(value) {
return s.unescapeHTML(value);
}
});
this.cancelEditing(field);
};
this.showValue = async(field, forceShow) => {
if (!this.settings[field].showValue) {
return;
Template.channelSettings.helpers({
editing() {
return Template.instance().editing.get();
}
});
Template.channelSettings.onCreated(function() {
this.room = ChatRoom.findOne(this.data && this.data.rid);
this.editing = new ReactiveVar(false);
});
Template.channelSettings.events({
'click .js-edit'(e, t) {
t.editing.set(true);
},
'click .js-cancel'(e, t) {
t.editing.set(false);
},
'click .js-delete'() {
return swal({
title: t('Are_you_sure'),
text: t('Delete_Room_Warning'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
confirmButtonText: t('Yes_delete_it'),
cancelButtonText: t('Cancel'),
closeOnConfirm: false,
html: false
}, () => {
swal.disableButtons();
call('eraseRoom', this.rid).then(() => {
swal({
title: t('Deleted'),
text: t('Room_has_been_deleted'),
type: 'success',
timer: 2000,
showConfirmButton: false
});
}, () => swal.enableButtons());
});
}
});
Template.channelSettingsInfo.onCreated(function() {
this.room = ChatRoom.findOne(this.data && this.data.rid);
});
Template.channelSettingsInfo.helpers({
unscape(value) {
return s.unescapeHTML(value);
},
channelSettings() {
return RocketChat.ChannelSettings.getOptions(Template.currentData(), 'room');
},
canDeleteRoom() {
const {room} = Template.instance();
const roomType = room && room.t;
return roomType && RocketChat.authz.hasAtLeastOnePermission(`delete-${ roomType }`, room._id);
},
name() {
return Template.instance().room.name;
},
description() {
return Template.instance().room.description;
},
announcement() {
return Template.instance().room.announcement;
},
topic() {
return Template.instance().room.topic;
},
users() {
return Template.instance().room.usernames;
},
channelIcon() {
const roomType = Template.instance().room.t;
switch (roomType) {
case 'd':
return 'at';
case 'p':
return 'lock';
case 'c':
return 'hashtag';
case 'l':
return 'livechat';
default :
return null;
}
const room = ChatRoom.findOne(this.data && this.data.rid);
return this.settings[field].showValue(room, forceShow);
};
this.cancelEditing = (field) => {
const { cancelEditing } = this.settings[field];
cancelEditing && cancelEditing.call(this.settings[field]);
this.editing.set();
};
}
});

@ -1,5 +1,6 @@
const fields = ['roomName', 'roomTopic', 'roomAnnouncement', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode'];
Meteor.methods({
saveRoomSettings(rid, setting, value) {
saveRoomSettings(rid, settings, value) {
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
'function': 'RocketChat.saveRoomName'
@ -10,25 +11,44 @@ Meteor.methods({
method: 'saveRoomSettings'
});
}
if (!['roomName', 'roomTopic', 'roomAnnouncement', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode'].some((s) => s === setting)) {
console.log(settings);
if (typeof settings !== 'object') {
settings = {
[settings] : value
};
}
if (!Object.keys(settings).every(key => fields.includes(key))) {
throw new Meteor.Error('error-invalid-settings', 'Invalid settings provided', {
method: 'saveRoomSettings'
});
}
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)) {
throw new Meteor.Error('error-action-not-allowed', 'Editing room is not allowed', {
method: 'saveRoomSettings',
action: 'Editing_room'
});
}
if (setting === 'default' && !RocketChat.authz.hasPermission(this.userId, 'view-room-administration')) {
throw new Meteor.Error('error-action-not-allowed', 'Viewing room administration is not allowed', {
method: 'saveRoomSettings',
action: 'Viewing_room_administration'
const room = RocketChat.models.Rooms.findOneById(rid);
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'saveRoomSettings'
});
}
const room = RocketChat.models.Rooms.findOneById(rid);
if (room != null) {
const user = Meteor.user();
Object.keys(settings).forEach(setting => {
const value = settings[setting];
if (settings === 'default' && !RocketChat.authz.hasPermission(this.userId, 'view-room-administration')) {
throw new Meteor.Error('error-action-not-allowed', 'Viewing room administration is not allowed', {
method: 'saveRoomSettings',
action: 'Viewing_room_administration'
});
}
if (setting === 'roomType' && value !== room.t && value === 'c' && !RocketChat.authz.hasPermission(this.userId, 'create-c')) {
throw new Meteor.Error('error-action-not-allowed', 'Changing a private group to a public channel is not allowed', {
method: 'saveRoomSettings',
@ -41,43 +61,47 @@ Meteor.methods({
action: 'Change_Room_Type'
});
}
});
Object.keys(settings).forEach(setting => {
const value = settings[setting];
switch (setting) {
case 'roomName':
name = RocketChat.saveRoomName(rid, value, Meteor.user());
RocketChat.saveRoomName(rid, value, user);
break;
case 'roomTopic':
if (value !== room.topic) {
RocketChat.saveRoomTopic(rid, value, Meteor.user());
RocketChat.saveRoomTopic(rid, value, user);
}
break;
case 'roomAnnouncement':
if (value !== room.announcement) {
RocketChat.saveRoomAnnouncement(rid, value, Meteor.user());
RocketChat.saveRoomAnnouncement(rid, value, user);
}
break;
case 'roomDescription':
if (value !== room.description) {
RocketChat.saveRoomDescription(rid, value, Meteor.user());
RocketChat.saveRoomDescription(rid, value, user);
}
break;
case 'roomType':
if (value !== room.t) {
RocketChat.saveRoomType(rid, value, Meteor.user());
RocketChat.saveRoomType(rid, value, user);
}
break;
case 'readOnly':
if (value !== room.ro) {
RocketChat.saveRoomReadOnly(rid, value, Meteor.user());
RocketChat.saveRoomReadOnly(rid, value, user);
}
break;
case 'reactWhenReadOnly':
if (value !== room.reactWhenReadOnly) {
RocketChat.saveReactWhenReadOnly(rid, value, Meteor.user());
RocketChat.saveReactWhenReadOnly(rid, value, user);
}
break;
case 'systemMessages':
if (value !== room.sysMes) {
RocketChat.saveRoomSystemMessages(rid, value, Meteor.user());
RocketChat.saveRoomSystemMessages(rid, value, user);
}
break;
case 'joinCode':
@ -86,7 +110,8 @@ Meteor.methods({
case 'default':
RocketChat.models.Rooms.saveDefaultById(rid, value);
}
}
});
return {
result: true,
rid: room._id

@ -55,6 +55,61 @@
font-size: 14px;
}
&__scroll {
overflow: auto;
}
&__flex {
display: flex;
& > .rc-button {
flex: 1;
margin: 0 5px;
}
}
&__block {
margin: 47px 0;
padding: 28px 0;
border-top: 1px solid #d7d7d7;
border-bottom: 1px solid #d7d7d7;
}
&__row {
display: flex;
flex-direction: row;
padding: 15px 0;
& > .rc-switch {
flex: 1;
color: #a1a1a1;
& > .rc-switch__label > .rc-switch__text {
flex: 1;
}
}
}
&__label {
display: block;
margin-bottom: 37px;
font-size: 15px;
font-weight: 400;
}
&__description {
padding: 8px 0;
color: #9ea2a8;
}
&-action {
display: flex;

@ -1,9 +1,14 @@
.rc-button {
&:not([disabled]):hover {
opacity: 0.6;
}
min-height: 40px;
margin: 0.5rem 0;
padding: var(--button-padding);
cursor: pointer;
transition: background-color 0.3s;
transition: opacity 0.3s, background-color 0.3s, color 0.3s;
text-align: center;
border-width: var(--button-border-width);
@ -18,6 +23,7 @@
color: var(--button-disabled-text-color);
border: 0;
border-color: var(--button-disabled-background);
background-color: var(--button-disabled-background);
}
@ -27,18 +33,35 @@
background-color: var(--button-primary-background);
}
&--primary.rc-button--outline {
color: var(--button-primary-background);
border-color: var(--button-primary-background);
}
&--secondary {
color: var(--button-secondary-text-color);
border: 0;
border-color: var(--button-secondary-background);
background-color: var(--button-secondary-background);
}
&--secondary.rc-button--outline {
color: var(--button-secondary-background);
border-color: var(--button-secondary-background);
}
&--cancel {
color: var(--button-primary-text-color);
border: 0;
border-color: var(--button-cancel-color);
background-color: var(--button-cancel-color);
}
&--cancel.rc-button--outline {
color: var(--button-cancel-color);
border-color: var(--button-cancel-color);
}
&--small {
padding: var(--button-padding-small);
}
@ -53,6 +76,12 @@
justify-content: center;
}
&--outline {
border-width: 2px;
border-style: solid;
background: transparent;
}
&.loading {
position: relative;

Loading…
Cancel
Save