[NEW] Broadcast Channels (#9950)

* [NEW] Broadcast Channels

* code guidelines

* fix createroom type p extradata

* fix private room can change join_code

* test to show member list

* Code cleanup

* Update message.js
pull/10535/head
Guilherme Gazzo 8 years ago committed by Rodrigo Nascimento
parent 81a3fb11cc
commit 136e9caafe
  1. 23
      packages/rocketchat-channel-settings/client/views/channelSettings.html
  2. 24
      packages/rocketchat-channel-settings/client/views/channelSettings.js
  3. 9
      packages/rocketchat-channel-settings/server/methods/saveRoomSettings.js
  4. 3
      packages/rocketchat-i18n/i18n/en.i18n.json
  5. 14
      packages/rocketchat-lib/client/defaultTabBars.js
  6. 3
      packages/rocketchat-lib/lib/RoomTypeConfig.js
  7. 6
      packages/rocketchat-lib/lib/roomTypes/private.js
  8. 17
      packages/rocketchat-lib/lib/roomTypes/public.js
  9. 5
      packages/rocketchat-lib/server/functions/createRoom.js
  10. 5
      packages/rocketchat-lib/server/methods/createChannel.js
  11. 4
      packages/rocketchat-theme/client/imports/components/header.css
  12. 9
      packages/rocketchat-theme/client/imports/forms/button.css
  13. 3
      packages/rocketchat-theme/client/imports/forms/input.css
  14. 2
      packages/rocketchat-theme/client/imports/forms/popup-list.css
  15. 22
      packages/rocketchat-theme/client/imports/forms/switch.css
  16. 2
      packages/rocketchat-ui-master/public/icons.svg
  17. 5
      packages/rocketchat-ui-message/client/message.html
  18. 16
      packages/rocketchat-ui-message/client/message.js
  19. 3
      packages/rocketchat-ui-message/client/messageBox.js
  20. 9
      packages/rocketchat-ui/client/components/popupList.html
  21. 5
      packages/rocketchat-ui/client/lib/chatMessages.js
  22. 16
      packages/rocketchat-ui/client/views/app/createChannel.html
  23. 30
      packages/rocketchat-ui/client/views/app/createChannel.js
  24. 4
      packages/rocketchat-ui/client/views/app/room.html
  25. 4
      packages/rocketchat-ui/client/views/app/room.js
  26. 2
      packages/rocketchat-ui/client/views/app/roomSearch.html
  27. 3
      server/publications/room.js

@ -163,6 +163,23 @@
</div>
{{/if}}
{{/with}}
{{#with settings.broadcast}}
{{#if canView}}
<div class="rc-user-info__row">
<div class="rc-switch rc-switch--blue">
<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="{{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">
@ -228,7 +245,11 @@
{{unscape topic}}
</div>
</label>
{{#if broadcast}}
<label class="rc-user-info__label">
<b>{{_ "Broadcast_channel"}}:</b> {{_ "Broadcast_channel_Description"}}
</label>
{{/if}}
{{/with}}
{{#each channelSettings}}
<div class="rc-user-info__row">

@ -225,7 +225,7 @@ Template.channelSettingsEditing.onCreated(function() {
return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.READ_ONLY);
},
canEdit() {
return RocketChat.authz.hasAllPermission('set-readonly', room._id);
return !room.broadcast && RocketChat.authz.hasAllPermission('set-readonly', room._id);
},
save(value) {
return call('saveRoomSettings', room._id, RoomSettingsEnum.READ_ONLY, value).then(() => toastr.success(TAPi18n.__('Read_only_changed_successfully')));
@ -237,10 +237,10 @@ Template.channelSettingsEditing.onCreated(function() {
isToggle: true,
processing: new ReactiveVar(false),
canView() {
return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.REACT_WHEN_READ_ONLY) && room.ro;
return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.REACT_WHEN_READ_ONLY);
},
canEdit() {
return RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id);
return !room.broadcast && RocketChat.authz.hasAllPermission('set-react-when-readonly', room._id);
},
save(value) {
return call('saveRoomSettings', room._id, 'reactWhenReadOnly', value).then(() => {
@ -289,6 +289,21 @@ Template.channelSettingsEditing.onCreated(function() {
});
}
},
broadcast: {
type: 'boolean',
label: 'Broadcast_channel',
isToggle: true,
processing: new ReactiveVar(false),
canView() {
return RocketChat.roomTypes.roomTypes[room.t].allowRoomSettingChange(room, RoomSettingsEnum.BROADCAST);
},
canEdit() {
return false;
},
save() {
return Promise.resolve();
}
},
joinCode: {
type: 'text',
label: 'Password',
@ -452,6 +467,9 @@ Template.channelSettingsInfo.helpers({
description() {
return Template.instance().room.description;
},
broadcast() {
return Template.instance().room.broadcast;
},
announcement() {
return Template.instance().room.announcement ? Template.instance().room.announcement.message : '';
},

@ -31,8 +31,15 @@ Meteor.methods({
});
}
const room = RocketChat.models.Rooms.findOneById(rid);
if (room.broadcast && (settings.readOnly || settings.reactWhenReadOnly)) {
throw new Meteor.Error('error-action-not-allowed', 'Editing readOnly/reactWhenReadOnly are not allowed for broadcast rooms', {
method: 'saveRoomSettings',
action: 'Editing_room'
});
}
if (!room) {
throw new Meteor.Error('error-invalid-room', 'Invalid room', {
method: 'saveRoomSettings'

@ -267,6 +267,7 @@
"Application_added": "Application added",
"Application_Name": "Application Name",
"Application_updated": "Application updated",
"Apply": "Apply",
"Apply_and_refresh_all_clients": "Apply and refresh all clients",
"Archive": "Archive",
"archive-room": "Archive Room",
@ -343,6 +344,8 @@
"BotHelpers_userFields": "User Fields",
"BotHelpers_userFields_Description": "CSV of user fields that can be accessed by bots helper methods.",
"Branch": "Branch",
"Broadcast_channel": "Broadcast Channel",
"Broadcast_channel_Description": "Only authorized users can write new messages, but the other users will be able to reply",
"Broadcast_Connected_Instances": "Broadcast Connected Instances",
"Bugsnag_api_key": "Bugsnag API Key",
"Build_Environment": "Build Environment",

@ -22,7 +22,19 @@ RocketChat.TabBar.addButton({
i18nTitle: 'Members_List',
icon: 'team',
template: 'membersList',
order: 2
order: 2,
condition() {
const rid = Session.get('openedRoom');
const room = RocketChat.models.Rooms.findOne({
_id: rid
});
if (!room || !room.broadcast) {
return true;
}
return RocketChat.authz.hasRole(Meteor.userId(), ['admin', 'moderator', 'owner'], rid);
}
});
RocketChat.TabBar.addButton({

@ -6,7 +6,8 @@ export const RoomSettingsEnum = {
READ_ONLY: 'readOnly',
REACT_WHEN_READ_ONLY: 'reactWhenReadOnly',
ARCHIVE_OR_UNARCHIVE: 'archiveOrUnarchive',
JOIN_CODE: 'joinCode'
JOIN_CODE: 'joinCode',
BROADCAST: 'broadcast'
};
export const UiTextContext = {

@ -60,6 +60,12 @@ export class PrivateRoomType extends RoomTypeConfig {
switch (setting) {
case RoomSettingsEnum.JOIN_CODE:
return false;
case RoomSettingsEnum.BROADCAST:
return room.broadcast;
case RoomSettingsEnum.READ_ONLY:
return !room.broadcast;
case RoomSettingsEnum.REACT_WHEN_READ_ONLY:
return !room.broadcast && room.ro;
default:
return true;
}

@ -1,5 +1,5 @@
/* globals openRoom */
import {RoomTypeConfig, RoomTypeRouteConfig, UiTextContext} from '../RoomTypeConfig';
import { RoomTypeConfig, RoomTypeRouteConfig, RoomSettingsEnum, UiTextContext } from '../RoomTypeConfig';
export class PublicRoomRoute extends RoomTypeRouteConfig {
constructor() {
@ -63,12 +63,21 @@ export class PublicRoomType extends RoomTypeConfig {
return RocketChat.authz.hasAtLeastOnePermission(['add-user-to-any-c-room', 'add-user-to-joined-room'], room._id);
}
allowRoomSettingChange() {
enableMembersListProfile() {
return true;
}
enableMembersListProfile() {
return true;
allowRoomSettingChange(room, setting) {
switch (setting) {
case RoomSettingsEnum.BROADCAST:
return room.broadcast;
case RoomSettingsEnum.READ_ONLY:
return !room.broadcast;
case RoomSettingsEnum.REACT_WHEN_READ_ONLY:
return !room.broadcast && room.ro;
default:
return true;
}
}
getUiText(context) {

@ -20,6 +20,11 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData
members.push(owner.username);
}
if (extraData.broadcast) {
readOnly = true;
delete extraData.reactWhenReadOnly;
}
const now = new Date();
let room = Object.assign({
name,

@ -1,5 +1,5 @@
Meteor.methods({
createChannel(name, members, readOnly = false, customFields = {}) {
createChannel(name, members, readOnly = false, customFields = {}, extraData = {}) {
check(name, String);
check(members, Match.Optional([String]));
@ -10,7 +10,6 @@ Meteor.methods({
if (!RocketChat.authz.hasPermission(Meteor.userId(), 'create-c')) {
throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'createChannel' });
}
return RocketChat.createRoom('c', name, Meteor.user() && Meteor.user().username, members, readOnly, {customFields});
return RocketChat.createRoom('c', name, Meteor.user() && Meteor.user().username, members, readOnly, {customFields, ...extraData});
}
});

@ -9,6 +9,10 @@
margin: 0 -0.5rem;
display: flex;
flex: 0 0 auto;
padding: var(--header-padding);
white-space: nowrap;

@ -140,6 +140,15 @@
border-radius: 50%;
}
}
&-broadcast {
margin: 10px 0;
padding: 0 1rem;
&__icon {
margin: 0 5px;
}
}
}
@media (width < 780px) {

@ -112,6 +112,9 @@
}
&--error {
.rc-tags {
border-color: var(--input-error-color);
}
& .rc-input {
&__element {
border-color: var(--input-error-color);

@ -1,6 +1,8 @@
.rc-popup-list {
position: absolute;
z-index: 1;
width: 100%;
padding: 0 4px;

@ -28,6 +28,17 @@
&__input {
display: none;
&:checked {
& + .rc-switch__button {
border-color: #26d198;
background-color: var(--rc-color-success);
& .rc-switch__button-inside {
transform: translate3d(13px, 1px, 0);
}
}
}
&:disabled {
& + .rc-switch__button {
cursor: default;
@ -40,17 +51,6 @@
cursor: default;
}
}
&:checked {
& + .rc-switch__button {
border-color: #26d198;
background-color: var(--rc-color-success);
& .rc-switch__button-inside {
transform: translate3d(13px, 1px, 0);
}
}
}
}
&__button {

@ -99,6 +99,8 @@
<symbol viewBox="0 0 512 512" id="icon-clock"><path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm216 248c0 118.7-96.1 216-216 216-118.7 0-216-96.1-216-216 0-118.7 96.1-216 216-216 118.7 0 216 96.1 216 216zm-148.9 88.3l-81.2-59c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h14c6.6 0 12 5.4 12 12v146.3l70.5 51.3c5.4 3.9 6.5 11.4 2.6 16.8l-8.2 11.3c-3.9 5.3-11.4 6.5-16.8 2.6z"/></symbol>
<symbol viewBox="0 0 512 512" id="icon-sort-amount-down"><path d="M204.485 392l-84 84.485c-4.686 4.686-12.284 4.686-16.971 0l-84-84.485c-4.686-4.686-4.686-12.284 0-16.97l7.07-7.071c4.686-4.686 12.284-4.686 16.971 0L95 419.887V44c0-6.627 5.373-12 12-12h10c6.627 0 12 5.373 12 12v375.887l51.444-51.928c4.686-4.686 12.284-4.686 16.971 0l7.07 7.071c4.687 4.686 4.687 12.284 0 16.97zM384 308v-8c0-6.627-5.373-12-12-12H268c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h104c6.627 0 12-5.373 12-12zm64-96v-8c0-6.627-5.373-12-12-12H268c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h168c6.627 0 12-5.373 12-12zm64-96v-8c0-6.627-5.373-12-12-12H268c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h232c6.627 0 12-5.373 12-12zM320 404v-8c0-6.627-5.373-12-12-12h-40c-6.627 0-12 5.373-12 12v8c0 6.627 5.373 12 12 12h40c6.627 0 12-5.373 12-12z"/></symbol>
<symbol viewBox="0 0 576 512" id="icon-edit-rounded"><path d="M417.8 315.5l20-20c3.8-3.8 10.2-1.1 10.2 4.2V464c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V112c0-26.5 21.5-48 48-48h292.3c5.3 0 8 6.5 4.2 10.2l-20 20c-1.1 1.1-2.7 1.8-4.2 1.8H48c-8.8 0-16 7.2-16 16v352c0 8.8 7.2 16 16 16h352c8.8 0 16-7.2 16-16V319.7c0-1.6.6-3.1 1.8-4.2zm145.9-191.2L251.2 436.8l-99.9 11.1c-13.4 1.5-24.7-9.8-23.2-23.2l11.1-99.9L451.7 12.3c16.4-16.4 43-16.4 59.4 0l52.6 52.6c16.4 16.4 16.4 43 0 59.4zm-93.6 48.4L403.4 106 169.8 339.5l-8.3 75.1 75.1-8.3 233.5-233.6zm71-85.2l-52.6-52.6c-3.8-3.8-10.2-4-14.1 0L426 83.3l66.7 66.7 48.4-48.4c3.9-3.8 3.9-10.2 0-14.1z"/></symbol>
<symbol id="icon-reply" viewBox="0 0 576 512"><path d="M11.093 251.65l175.998 184C211.81 461.494 256 444.239 256 408v-87.84c154.425 1.812 219.063 16.728 181.19 151.091-8.341 29.518 25.447 52.232 49.68 34.51C520.16 481.421 576 426.17 576 331.19c0-171.087-154.548-201.035-320-203.02V40.016c0-36.27-44.216-53.466-68.91-27.65L11.093 196.35c-14.791 15.47-14.791 39.83 0 55.3zm23.127-33.18l176-184C215.149 29.31 224 32.738 224 40v120c157.114 0 320 11.18 320 171.19 0 74.4-40 122.17-76.02 148.51C519.313 297.707 395.396 288 224 288v120c0 7.26-8.847 10.69-13.78 5.53l-176-184a7.978 7.978 0 0 1 0-11.06z"/></symbol>
<symbol id="icon-clipboard" viewBox="0 0 384 512"><path d="M336 64h-88.581c.375-2.614.581-5.283.581-8 0-30.879-25.122-56-56-56s-56 25.121-56 56c0 2.717.205 5.386.581 8H48C21.49 64 0 85.49 0 112v352c0 26.51 21.49 48 48 48h288c26.51 0 48-21.49 48-48V112c0-26.51-21.49-48-48-48zm16 400c0 8.822-7.178 16-16 16H48c-8.822 0-16-7.178-16-16V112c0-8.822 7.178-16 16-16h48v20c0 6.627 5.373 12 12 12h168c6.627 0 12-5.373 12-12V96h48c8.822 0 16 7.178 16 16v352zM192 32c13.255 0 24 10.745 24 24s-10.745 24-24 24-24-10.745-24-24 10.745-24 24-24"/></symbol>
<symbol id="icon-cube" viewBox="0 0 512 512"><path d="M239.1 6.3l-208 78c-18.7 7-31.1 25-31.1 45v225.1c0 18.2 10.3 34.8 26.5 42.9l208 104c13.5 6.8 29.4 6.8 42.9 0l208-104c16.3-8.1 26.5-24.8 26.5-42.9V129.3c0-20-12.4-37.9-31.1-44.9l-208-78C262 2.2 250 2.2 239.1 6.3zM256 34.2l224 84v.3l-224 97.1-224-97.1v-.3l224-84zM32 153.4l208 90.1v224.7l-208-104V153.4zm240 314.8V243.5l208-90.1v210.9L272 468.2z"/></symbol>
<symbol id="icon-circle-cross" viewBox="0 0 256 256"><path d="M183.191,174.141c2.5,2.498,2.5,6.552,0,9.05c-1.249,1.25-2.889,1.875-4.525,1.875c-1.638,0-3.277-0.625-4.525-1.875 l-46.142-46.142L81.856,183.19c-1.249,1.25-2.888,1.875-4.525,1.875c-1.638,0-3.277-0.625-4.525-1.875c-2.5-2.498-2.5-6.552,0-9.05 l46.143-46.143L72.806,81.856c-2.5-2.499-2.5-6.552,0-9.05c2.497-2.5,6.553-2.5,9.05,0l46.142,46.142l46.142-46.142 c2.497-2.5,6.553-2.5,9.051,0c2.5,2.499,2.5,6.552,0,9.05l-46.143,46.142L183.191,174.141z M256,128C256,57.42,198.58,0,128,0 C57.42,0,0,57.42,0,128c0,70.58,57.42,128,128,128C198.58,256,256,198.58,256,128z M243.2,128c0,63.521-51.679,115.2-115.2,115.2 c-63.522,0-115.2-51.679-115.2-115.2C12.8,64.478,64.478,12.8,128,12.8C191.521,12.8,243.2,64.478,243.2,128z" fill="#ef0e0e"/></symbol>
<symbol id="icon-circle-check" viewBox="0 0 32 32"><g><path d="M16,0C7.163,0,0,7.163,0,16c0,8.837,7.163,16,16,16c8.836,0,16-7.164,16-16C32,7.163,24.836,0,16,0z M16,30 C8.268,30,2,23.732,2,16C2,8.268,8.268,2,16,2s14,6.268,14,14C30,23.732,23.732,30,16,30z" fill="#2db730"/><path d="M23.3,10.393L13.012,20.589l-4.281-4.196c-0.394-0.391-1.034-0.391-1.428,0 c-0.395,0.391-0.395,1.024,0,1.414l4.999,4.899c0.41,0.361,1.023,0.401,1.428,0l10.999-10.899c0.394-0.39,0.394-1.024,0-1.414 C24.334,10.003,23.695,10.003,23.3,10.393z" fill="#2db730"/></g><g/><g/><g/><g/><g/><g/></symbol>

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 61 KiB

@ -111,6 +111,11 @@
</li>
{{/each}}
</ul>
{{# if broadcast}}
{{#with u}}
<button type="button" class="rc-button rc-button--outline rc-button--primary rc-button-broadcast js-reply-broadcast" name="button">{{> icon block="rc-button-broadcast__icon" icon="reply"}} {{_'Reply'}} </button>
{{/with}}
{{/if}}
<ul class="reactions {{hideReactions}}">
{{#each reaction in reactions}}
<li data-emoji="{{reaction.emoji}}" {{markUserReaction reaction}}>

@ -6,6 +6,10 @@ Template.message.helpers({
encodeURI(text) {
return encodeURI(text);
},
broadcast() {
const instance = Template.instance();
return this.u._id !== Meteor.userId() && instance.room && instance.room.broadcast;
},
isIgnored() {
return this.ignored;
},
@ -48,12 +52,12 @@ Template.message.helpers({
});
},
isGroupable() {
if (this.groupable === false) {
if (Template.instance().room.broadcast || this.groupable === false) {
return 'false';
}
},
isSequential() {
return this.groupable !== false;
return this.groupable !== false && !Template.instance().room.broadcast;
},
sequentialClass() {
if (this.groupable !== false) {
@ -316,6 +320,14 @@ Template.message.onCreated(function() {
this.wasEdited = (msg.editedAt != null) && !RocketChat.MessageTypes.isSystemMessage(msg);
this.room = RocketChat.models.Rooms.findOne({
_id: msg.rid
}, {
fields: {
broadcast: 1
}
});
return this.body = (() => {
const isSystemMessage = RocketChat.MessageTypes.isSystemMessage(msg);
const messageType = RocketChat.MessageTypes.getType(msg)||{};

@ -649,8 +649,6 @@ Template.messageBox.onRendered(function() {
}).on('autogrow', () => {
this.data && this.data.onResize && this.data.onResize();
}).focus()[0];
chatMessages[RocketChat.openedRoom].restoreText(RocketChat.openedRoom);
});
Template.messageBox.onCreated(function() {
@ -685,6 +683,7 @@ Meteor.startup(function() {
setTimeout(()=> {
if (chatMessages[RocketChat.openedRoom].input) {
chatMessages[RocketChat.openedRoom].input.focus();
chatMessages[RocketChat.openedRoom].restoreText(RocketChat.openedRoom);
}
}, 200);
});

@ -26,3 +26,12 @@
{{/if}}
</li>
</template>
<template name="popupList_item_channel">
<li class="rc-popup-list__item">
<span class="rc-popup-list__item-image">
{{>avatar username=item.name}}
</span>
<span class="rc-popup-list__item-name">{{{modifier item.name}}}</span>
</li>
</template>

@ -2,6 +2,9 @@
import s from 'underscore.string';
import moment from 'moment';
import toastr from 'toastr';
const reply = id => id && `[ ](${ RocketChat.MessageAction.getPermaLink(id) }) `;
this.ChatMessages = class ChatMessages {
init(node) {
this.editing = {};
@ -399,7 +402,7 @@ this.ChatMessages = class ChatMessages {
}
restoreText(rid) {
const text = localStorage.getItem(`messagebox_${ rid }`);
const text = reply(FlowRouter.getQueryParam('reply')) || localStorage.getItem(`messagebox_${ rid }`);
if (typeof text === 'string' && this.input) {
this.input.value = text;
}

@ -26,7 +26,7 @@
</div>
<div class="rc-switch">
<label class="rc-switch__label">
<input type="checkbox" class="rc-switch__input" name="readOnly">
<input type="checkbox" class="rc-switch__input" name="readOnly" checked={{readOnly}} disabled="{{broadcast}}">
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
@ -36,6 +36,20 @@
</label>
<span class="rc-switch__description">{{readOnlyDescription}}</span>
</div>
<div class="rc-switch">
<label class="rc-switch__label">
<input type="checkbox" class="rc-switch__input" name="broadcast">
<span class="rc-switch__button">
<span class="rc-switch__button-inside"></span>
</span>
<span class="rc-switch__text">
{{_"Broadcast_channel"}}
</span>
</label>
<span class="rc-switch__description">
{{_"Broadcast_channel_Description"}}
</span>
</div>
</div>
<div class="create-channel__inputs">
<div class="rc-input {{#if invalidChannel}}rc-input--error{{/if}}">

@ -83,6 +83,12 @@ Template.createChannel.helpers({
typeDescription() {
return t(Template.instance().type.get() === 'p' ? t('Just_invited_people_can_access_this_channel') : t('Everyone_can_access_this_channel'));
},
broadcast() {
return Template.instance().broadcast.get();
},
readOnly() {
return Template.instance().readOnly.get();
},
readOnlyDescription() {
return t(Template.instance().readOnly.get() ? t('Only_authorized_users_can_write_new_messages') : t('All_users_in_the_channel_can_write_new_messages'));
},
@ -113,8 +119,8 @@ Template.createChannel.helpers({
extensionsConfig() {
const instance = Template.instance();
return {
validations : Template.instance().extensions_validations,
submits: Template.instance().extensions_submits,
validations : instance.extensions_validations,
submits: instance.extensions_submits,
change: instance.change
};
},
@ -154,6 +160,10 @@ Template.createChannel.events({
t.type.set(e.target.checked ? e.target.value : 'd');
t.change();
},
'change [name="broadcast"]'(e, t) {
t.broadcast.set(e.target.checked);
t.change();
},
'change [name="readOnly"]'(e, t) {
t.readOnly.set(e.target.checked);
},
@ -188,6 +198,7 @@ Template.createChannel.events({
const name = e.target.name.value;
const type = instance.type.get();
const readOnly = instance.readOnly.get();
const broadcast = instance.broadcast.get();
const isPrivate = type === 'p';
if (instance.invalid.get() || instance.inUse.get()) {
@ -200,7 +211,7 @@ Template.createChannel.events({
const extraData = Object.keys(instance.extensions_submits)
.reduce((result, key) => {
return { ...result, ...instance.extensions_submits[key](instance) };
}, {});
}, {broadcast});
Meteor.call(isPrivate ? 'createPrivateGroup' : 'createChannel', name, instance.selectedUsers.get().map(user => user.username), readOnly, {}, extraData, function(err, result) {
if (err) {
@ -235,13 +246,13 @@ Template.createChannel.onRendered(function() {
users.set(usersArr);
});
});
/* global AutoComplete Deps */
/* global AutoComplete */
Template.createChannel.onCreated(function() {
this.selectedUsers = new ReactiveVar([]);
const filter = {exceptions :[Meteor.user().username].concat(this.selectedUsers.get().map(u => u.username))};
// this.onViewRead:??y(function() {
Deps.autorun(() => {
Tracker.autorun(() => {
filter.exceptions = [Meteor.user().username].concat(this.selectedUsers.get().map(u => u.username));
});
this.extensions_validations = {};
@ -249,6 +260,7 @@ Template.createChannel.onCreated(function() {
this.name = new ReactiveVar('');
this.type = new ReactiveVar('p');
this.readOnly = new ReactiveVar(false);
this.broadcast = new ReactiveVar(false);
this.inUse = new ReactiveVar(undefined);
this.invalid = new ReactiveVar(false);
this.extensions_invalid = new ReactiveVar(false);
@ -257,6 +269,14 @@ Template.createChannel.onCreated(function() {
Object.keys(this.extensions_validations).map(key => this.extensions_validations[key]).forEach(f => (valid = f(this) && valid));
this.extensions_invalid.set(!valid);
}, 300);
Tracker.autorun(() => {
const broadcast = this.broadcast.get();
if (broadcast) {
this.readOnly.set(true);
}
});
this.userFilter = new ReactiveVar('');
this.tokensRequired = new ReactiveVar(false);
this.checkChannel = _.debounce((name) => {

@ -112,9 +112,7 @@
</li>
{{/if}}
{{/if}}
{{#each messagesHistory}}
{{#nrr nrrargs 'message' .}}{{/nrr}}
{{/each}}
{{#each messagesHistory}}{{#nrr nrrargs 'message' .}}{{/nrr}}{{/each}}
{{#if hasMoreNext}}
<li class="load-more">
{{#if isLoading}}

@ -381,6 +381,10 @@ let lastTouchY = null;
let lastScrollTop;
Template.room.events({
'click .js-reply-broadcast'() {
const message = this._arguments[1];
RocketChat.roomTypes.openRouteLink('d', {name: this._arguments[1].u.username}, {...FlowRouter.current().queryParams, reply: message._id});
},
'click, touchend'(e, t) {
Meteor.setTimeout(() => t.sendToBottomIfNecessaryDebounced(), 100);
},

@ -2,5 +2,5 @@
<i class="{{roomIcon}} {{userStatus}}"></i> {{name}}
</template>
<template name="roomSearchEmpty">
<p>{{_ "Nothing_found"}}.</p>
<p class="{{class}}">{{_ "Nothing_found"}}.</p>
</template>

@ -33,7 +33,8 @@ const fields = {
reactWhenReadOnly: 1,
sentiment: 1,
tokenpass: 1,
streamingOptions: 1
streamingOptions: 1,
broadcast: 1
};
const roomMap = (record) => {

Loading…
Cancel
Save