Merge branch '1.3' of github.com:RocketChat/Rocket.Chat into 1.3

pull/4218/head
Marcelo Schmidt 9 years ago
commit 7e2da6eabf
No known key found for this signature in database
GPG Key ID: CA48C21A7B66097E
  1. 1
      .meteor/.gitignore
  2. 2
      packages/rocketchat-authorization/client/hasPermission.coffee
  3. 20
      packages/rocketchat-channel-settings/client/views/channelSettings.coffee
  4. 1
      packages/rocketchat-channel-settings/client/views/channelSettings.html
  5. 6
      packages/rocketchat-channel-settings/package.js
  6. 7
      packages/rocketchat-channel-settings/server/functions/saveRoomReadOnly.coffee
  7. 7
      packages/rocketchat-channel-settings/server/functions/saveRoomSystemMessages.coffee
  8. 8
      packages/rocketchat-channel-settings/server/methods/saveRoomSettings.coffee
  9. 34
      packages/rocketchat-channel-settings/server/models/Rooms.coffee
  10. 4
      packages/rocketchat-channel-settings/server/startup.js
  11. 4
      packages/rocketchat-importer-hipchat/package.js
  12. 4
      packages/rocketchat-importer-slack/package.js
  13. 2
      packages/rocketchat-importer/package.js
  14. 15
      packages/rocketchat-lib/client/lib/roomTypes.coffee
  15. 9
      packages/rocketchat-lib/i18n/en.i18n.json
  16. 3
      packages/rocketchat-lib/server/functions/addUserToRoom.js
  17. 15
      packages/rocketchat-lib/server/functions/createRoom.js
  18. 4
      packages/rocketchat-lib/server/methods/createChannel.coffee
  19. 2
      packages/rocketchat-lib/server/methods/joinRoom.coffee
  20. 3
      packages/rocketchat-lib/server/models/Messages.coffee
  21. 5
      packages/rocketchat-lib/server/models/Rooms.coffee
  22. 10
      packages/rocketchat-slashcommands-topic/topic.js
  23. 10
      packages/rocketchat-theme/assets/stylesheets/base.less
  24. 2
      packages/rocketchat-theme/assets/stylesheets/rtl.less
  25. 2
      packages/rocketchat-theme/assets/stylesheets/utils/_colors.import.less
  26. 14
      packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.coffee
  27. 15
      packages/rocketchat-ui-admin/admin/rooms/adminRoomInfo.html
  28. 2
      packages/rocketchat-ui-admin/admin/rooms/adminRooms.coffee
  29. 1
      packages/rocketchat-ui-admin/publications/adminRooms.js
  30. 3
      packages/rocketchat-ui-flextab/flex-tab/tabs/membersList.html
  31. 2
      packages/rocketchat-ui-message/message/messageBox.coffee
  32. 45
      packages/rocketchat-ui-message/message/messageBox.html
  33. 3
      packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.coffee
  34. 4
      packages/rocketchat-ui-sidenav/side-nav/createChannelFlex.html
  35. 3
      packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.coffee
  36. 6
      packages/rocketchat-ui-sidenav/side-nav/createCombinedFlex.html
  37. 3
      packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.coffee
  38. 4
      packages/rocketchat-ui-sidenav/side-nav/privateGroupsFlex.html
  39. 13
      packages/rocketchat-ui/views/app/room.coffee
  40. 4
      server/methods/loadHistory.coffee
  41. 2
      server/methods/loadMissedMessages.coffee
  42. 4
      server/startup/roomPublishes.coffee

@ -1 +1,2 @@
dev_bundle
local

@ -9,7 +9,7 @@ atLeastOne = (permissions, scope) ->
all = (permissions, scope) ->
return _.every permissions, (permissionId) ->
permission = ChatPermissions.findOne permissionId
return _.some permission.roles, (roleName) ->
return permission and _.some permission.roles, (roleName) ->
role = RocketChat.models.Roles.findOne roleName
roleScope = role?.scope
return RocketChat.models[roleScope]?.isUserInRole?(Meteor.userId(), roleName, scope)

@ -33,6 +33,16 @@ Template.channelSettings.helpers
canDeleteRoom: ->
roomType = ChatRoom.findOne(@rid, { fields: { t: 1 }})?.t
return roomType? and RocketChat.authz.hasAtLeastOnePermission("delete-#{roomType}", @rid)
readOnly: ->
return ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
readOnlyDescription: ->
readOnly = ChatRoom.findOne(@rid, { fields: { ro: 1 }})?.ro
if readOnly is true
return t('True')
else
return t('False')
Template.channelSettings.events
'click .delete': ->
@ -145,6 +155,16 @@ Template.channelSettings.onCreated ->
return handleError err if err
toastr.success TAPi18n.__ 'Room_type_changed_successfully'
ro:
type: 'boolean'
label: 'Read_only'
canView: (room) => room.t isnt 'd'
canEdit: (room) => RocketChat.authz.hasAllPermission('set-readonly', room._id)
save: (value, room) ->
Meteor.call 'saveRoomSettings', room._id, 'readOnly', value, (err, result) ->
return handleError err if err
toastr.success TAPi18n.__ 'Read_only_changed_successfully'
archived:
type: 'boolean'
label: 'Room_archivation_state_true'

@ -8,6 +8,7 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'coffeescript',
'ecmascript',
'reactive-var',
'tracker',
'templating',
@ -29,9 +30,12 @@ Package.onUse(function(api) {
'server/functions/saveRoomType.coffee',
'server/functions/saveRoomTopic.coffee',
'server/functions/saveRoomName.coffee',
'server/functions/saveRoomReadOnly.coffee',
'server/functions/saveRoomDescription.coffee',
'server/functions/saveRoomSystemMessages.coffee',
'server/methods/saveRoomSettings.coffee',
'server/models/Messages.coffee',
'server/models/Rooms.coffee'
'server/models/Rooms.coffee',
'server/startup.js'
], 'server');
});

@ -0,0 +1,7 @@
RocketChat.saveRoomReadOnly = (rid, readOnly, user) ->
unless Match.test rid, String
throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomReadOnly' }
update = RocketChat.models.Rooms.setReadOnlyById rid, readOnly
return update

@ -0,0 +1,7 @@
RocketChat.saveRoomSystemMessages = (rid, systemMessages, user) ->
unless Match.test rid, String
throw new Meteor.Error 'invalid-room', 'Invalid room', { function: 'RocketChat.saveRoomSystemMessages' }
update = RocketChat.models.Rooms.setSystemMessagesById rid, systemMessages
return update

@ -6,7 +6,7 @@ Meteor.methods
unless Match.test rid, String
throw new Meteor.Error 'error-invalid-room', 'Invalid room', { method: 'saveRoomSettings' }
if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'default', 'joinCode']
if setting not in ['roomName', 'roomTopic', 'roomDescription', 'roomType', 'readOnly', 'systemMessages', 'default', 'joincode']
throw new Meteor.Error 'error-invalid-settings', 'Invalid settings provided', { method: 'saveRoomSettings' }
unless RocketChat.authz.hasPermission(Meteor.userId(), 'edit-room', rid)
@ -36,6 +36,12 @@ Meteor.methods
else
message = TAPi18n.__('Private_Group')
RocketChat.models.Messages.createRoomSettingsChangedWithTypeRoomIdMessageAndUser 'room_changed_privacy', rid, message, Meteor.user()
when 'readOnly'
if value isnt room.ro
RocketChat.saveRoomReadOnly rid, value, Meteor.user()
when 'systemMessages'
if value isnt room.sysMes
RocketChat.saveRoomSystemMessages rid, value, Meteor.user()
when 'joinCode'
RocketChat.models.Rooms.setJoinCodeById rid, String(value)
when 'default'

@ -7,3 +7,37 @@ RocketChat.models.Rooms.setDescriptionById = (_id, description) ->
description: description
return @update query, update
RocketChat.models.Rooms.setReadOnlyById = (_id, readOnly) ->
query =
_id: _id
update =
$set:
ro: readOnly
if readOnly
# we want to mute all users without the post-readonly permission
usernames = @findOne(query, { fields: { usernames: 1 }})
users = RocketChat.models.Users.findUsersByUsernames usernames?.usernames, {fields: {username: 1}}
users.forEach (user) ->
if RocketChat.authz.hasPermission(user._id, 'post-readonly') is false
# create a new array if necessary
update.$set.muted = [] if !update.$set.muted
update.$set.muted.push user.username
else
# remove the muted user array
update.$unset = {muted: ""}
return @update query, update
RocketChat.models.Rooms.setSystemMessagesById = (_id, systemMessages) ->
query =
_id: _id
update =
$set:
sysMes: systemMessages
return @update query, update

@ -0,0 +1,4 @@
Meteor.startup(function() {
RocketChat.models.Permissions.upsert('post-readonly', {$set: { roles: ['admin', 'owner', 'moderator'] } });
RocketChat.models.Permissions.upsert('set-readonly', {$set: { roles: ['admin', 'owner'] } });
});

@ -8,8 +8,8 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'coffeescript',
'rocketchat:lib@0.0.1',
'rocketchat:importer@0.0.1'
'rocketchat:lib',
'rocketchat:importer'
]);
api.use(['mrt:moment-timezone@0.2.1'], 'server');
api.use('rocketchat:logger', 'server');

@ -8,8 +8,8 @@ Package.describe({
Package.onUse(function(api) {
api.use([
'coffeescript',
'rocketchat:lib@0.0.1',
'rocketchat:importer@0.0.1'
'rocketchat:lib',
'rocketchat:importer'
]);
api.use(['mrt:moment-timezone@0.2.1'], 'server');
api.use('rocketchat:logger', 'server');

@ -11,7 +11,7 @@ Package.onUse(function(api) {
'templating',
'coffeescript',
'check',
'rocketchat:lib@0.0.1'
'rocketchat:lib'
]);
api.use('rocketchat:logger', 'server');

@ -27,6 +27,21 @@ RocketChat.roomTypes = new class roomTypesClient extends roomTypesCommon
canSendMessage: (roomId) ->
return ChatSubscription.find({ rid: roomId }).count() > 0
readOnly: (roomId, user) ->
fields = { ro: 1 }
# if a user has been specified then we want to see if that user has been muted in the room
if user
fields.muted = 1
room = ChatRoom.findOne({ _id: roomId }, fields : fields)
unless user
return room?.ro;
return room?.ro is true and Array.isArray(room?.muted) and room?.muted.indexOf(user.username) != -1
verifyCanSendMessage: (roomId) ->
room = ChatRoom.findOne({ _id: roomId }, { fields: { t: 1 } })
return if not room?.t?

@ -171,6 +171,7 @@
"Archive" : "Archive",
"are_also_typing" : "are also typing",
"are_typing" : "are typing",
"room_is_read_only" : "This room is read only",
"Are_you_sure" : "Are you sure?",
"Are_you_sure_you_want_to_delete_your_account" : "Are you sure you want to delete your account?",
"Assign_admin" : "Assigning admin",
@ -761,7 +762,7 @@
"Message_editing" : "Message editing",
"Message_GroupingPeriod" : "Grouping Period (in seconds)",
"Message_GroupingPeriodDescription" : "Messages will be grouped with previous message if both are from the same user and the elapsed time was less than the informed time in seconds.",
"Message_KeepHistory" : "Keep Message History",
"Message_KeepHistory" : "Keep per message editing history",
"Message_MaxAll" : "Maximum channel size for ALL message",
"Message_MaxAllowedSize" : "Maximum Allowed Message Size",
"Message_pinning" : "Message pinning",
@ -957,6 +958,10 @@
"Random" : "Random",
"Reacted_with" : "Reacted with",
"Reactions" : "Reactions",
"Read_only" : "Read Only",
"Read_only_channel" : "Read Only Channel",
"Read_only_changed_successfully" : "Read only changed successfully",
"Read_only_group" : "Read Only Group",
"Record" : "Record",
"Redirect_URI" : "Redirect URI",
"Refresh_keys" : "Refresh keys",
@ -1147,6 +1152,7 @@
"Symbols" : "Symbols",
"Sync_success" : "Sync success",
"Sync_Users" : "Sync Users",
"System_messages" : "System Messages",
"Tag" : "Tag",
"Take_it" : "Take it!",
"Test_Connection" : "Test Connection",
@ -1273,6 +1279,7 @@
"User_left_male" : "Has left the channel.",
"User_logged_out" : "User is logged out",
"User_management" : "User Management",
"User_muted" : "User Muted",
"User_muted_by" : "User <em>__user_muted__</em> muted by <em>__user_by__</em>.",
"User_not_found" : "User not found",
"User_not_found_or_incorrect_password" : "User not found or incorrect password",

@ -12,7 +12,8 @@ RocketChat.addUserToRoom = function(rid, user, inviter, silenced) {
RocketChat.callbacks.run('beforeJoinRoom', user, room);
}
RocketChat.models.Rooms.addUsernameById(rid, user.username);
var muted = room.ro && !RocketChat.authz.hasPermission(user._id, 'post-readonly');
RocketChat.models.Rooms.addUsernameById(rid, user.username, muted);
RocketChat.models.Subscriptions.createWithRoomAndUser(room, user, {
ts: now,
open: true,

@ -1,5 +1,5 @@
/* globals RocketChat */
RocketChat.createRoom = function(type, name, owner, members) {
RocketChat.createRoom = function(type, name, owner, members, readOnly) {
name = s.trim(name);
owner = s.trim(owner);
members = [].concat(members);
@ -44,6 +44,8 @@ RocketChat.createRoom = function(type, name, owner, members) {
t: 'c',
name: name,
ts: now,
ro: readOnly === true,
sysMes: readOnly !== true,
usernames: members,
u: {
_id: owner._id,
@ -52,7 +54,11 @@ RocketChat.createRoom = function(type, name, owner, members) {
});
}
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner.username, members, { ts: now });
room = RocketChat.models.Rooms.createWithTypeNameUserAndUsernames(type, name, owner.username, members, {
ts: now,
ro: readOnly === true,
sysMes: readOnly !== true
});
for (let username of members) {
let member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }});
@ -60,6 +66,11 @@ RocketChat.createRoom = function(type, name, owner, members) {
continue;
}
// make all room members muted by default, unless they have the post-readonly permission
if (readOnly === true && !RocketChat.authz.hasPermission(member._id, 'post-readonly')) {
RocketChat.models.Rooms.muteUsernameByRoomId(room._id, username);
}
let extra = { open: true };
if (username === owner.username) {

@ -1,5 +1,5 @@
Meteor.methods
createChannel: (name, members) ->
createChannel: (name, members, readOnly) ->
check name, String
check members, Match.Optional([String])
@ -10,4 +10,4 @@ Meteor.methods
if RocketChat.authz.hasPermission(Meteor.userId(), 'create-c') isnt true
throw new Meteor.Error 'error-not-allowed', "Not allowed", { method: 'createChannel' }
return RocketChat.createRoom('c', name, Meteor.user()?.username, members);
return RocketChat.createRoom('c', name, Meteor.user()?.username, members, readOnly);

@ -2,7 +2,7 @@ Meteor.methods
joinRoom: (rid, code) ->
check rid, String
check code, Match.Maybe(String)
# check code, Match.Maybe(String)
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'joinRoom' }

@ -262,6 +262,9 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base
# INSERT
createWithTypeRoomIdMessageAndUser: (type, roomId, message, user, extraData) ->
room = RocketChat.models.Rooms.findOneById roomId, { fields: { sysMes: 1 }}
if room?.sysMes is false
return
record =
t: type
rid: roomId

@ -240,7 +240,7 @@ RocketChat.models.Rooms = new class extends RocketChat.models._Base
return @update query, update
addUsernameById: (_id, username) ->
addUsernameById: (_id, username, muted) ->
query =
_id: _id
@ -248,6 +248,9 @@ RocketChat.models.Rooms = new class extends RocketChat.models._Base
$addToSet:
usernames: username
if muted
update.$addToSet.muted = username
return @update query, update
addUsernamesById: (_id, usernames) ->

@ -1,7 +1,7 @@
/*
* Join is a named function that will replace /topic commands
* @param {Object} message - The message object
*/
* Join is a named function that will replace /topic commands
* @param {Object} message - The message object
*/
function Topic(command, params, item) {
if (command === 'topic') {
@ -24,6 +24,6 @@ function Topic(command, params, item) {
}
RocketChat.slashCommands.add('topic', Topic, {
description: TAPi18n.__('Slash_Topic_Description'),
params: TAPi18n.__('Slash_Topic_Params')
description: 'Slash_Topic_Description',
params: 'Slash_Topic_Params'
});

@ -2231,8 +2231,9 @@ label.required:after {
border-left-width: 0;
&.editing {}
}
.users-typing {
.stream-info {
float: left;
clear: left;
height: 23px;
font-size: 12px;
padding: 3px;
@ -2302,7 +2303,7 @@ label.required:after {
}
&.editing {
.formatting-tips,
.users-typing {
.stream-info {
display: none;
}
.editing-commands {
@ -3457,6 +3458,11 @@ body:not(.is-cordova) {
padding-left: 10px;
.calc(width, ~"100% - 45px");
}
.icon-mute {
float: left;
color: #7f7f7f;
line-height: 20px;
}
}
button {
display: block;

@ -267,7 +267,7 @@
border-left-width: 1px;
border-right-width: 0;
}
> .users-typing {
> .stream-info {
float: right;
}
> .formatting-tips {

@ -752,7 +752,7 @@ a.github-fork {
background-color: #fff7d8;
}
}
.users-typing {
.stream-info {
color: #888888;
background: #FCFCFC;
}

@ -32,6 +32,16 @@ Template.adminRoomInfo.helpers
canDeleteRoom: ->
roomType = ChatRoom.findOne(@rid, { fields: { t: 1 }})?.t
return roomType? and RocketChat.authz.hasAtLeastOnePermission("delete-#{roomType}")
readOnly: ->
room = ChatRoom.findOne(@rid, { fields: { ro: 1 }})
return room?.ro
readOnlyDescription: ->
room = ChatRoom.findOne(@rid, { fields: { ro: 1 }})
readOnly = room?.ro
if readOnly is true
return t('True')
else
return t('False')
Template.adminRoomInfo.events
'click .delete': ->
@ -146,4 +156,8 @@ Template.adminRoomInfo.onCreated ->
return handleError(err) if err
toastr.success TAPi18n.__ 'Room_unarchived'
RocketChat.callbacks.run 'unarchiveRoom', ChatRoom.findOne(rid)
when 'readOnly'
Meteor.call 'saveRoomSettings', rid, 'readOnly', @$('input[name=readOnly]:checked').val() is 'true', (err, result) ->
return handleError err if err
toastr.success TAPi18n.__ 'Read_only_changed_successfully'
@editing.set()

@ -59,6 +59,21 @@
</div>
</li>
{{/if}}
{{#if notDirect}}
<li>
<label>{{_ "Read_only_channel"}}</label>
<div>
{{#if editing 'readOnly'}}
<label><input type="radio" name="readOnly" class="editing" value="true" checked="{{$eq readOnly true}}" /> {{_ "True"}}</label>
<label><input type="radio" name="readOnly" value="false" checked="{{$neq readOnly true}}" /> {{_ "False"}}</label>
<button type="button" class="button secondary cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
<span>{{readOnlyDescription}}{{#if canEdit}} <i class="icon-pencil" data-edit="readOnly"></i>{{/if}}</span>
{{/if}}
</div>
</li>
{{/if}}
{{#each channelSettings}}
{{> Template.dynamic template=template data=data}}
{{/each}}

@ -48,7 +48,7 @@ Template.adminRooms.onCreated ->
groups: ['adminrooms'],
id: 'admin-room',
i18nTitle: 'Room_Info',
icon: 'icon-info',
icon: 'icon-info-circled',
template: 'adminRoomInfo',
order: 1
});

@ -17,6 +17,7 @@ Meteor.publish('adminRooms', function(filter, types, limit) {
u: 1,
usernames: 1,
muted: 1,
ro: 1,
default: 1,
topic: 1,
msgs: 1,

@ -28,6 +28,9 @@
<button data-username="{{username}}" tabindex="0" title="{{username}}">
{{> avatar username=username}}
<p>{{username}} {{utcOffset}}</p>
{{#if muted}}
<i class="icon-mute" title="{{_ "User Muted"}}"></i>
{{/if}}
</button>
</li>
{{/each}}

@ -30,6 +30,8 @@ Template.messageBox.helpers
return Session.get('roomData' + this._id)?.joinCodeRequired
subscribed: ->
return RocketChat.roomTypes.verifyCanSendMessage @_id
allowedToSend: ->
return !RocketChat.roomTypes.readOnly @_id, Meteor.user()
getPopupConfig: ->
template = Template.instance()
return {

@ -2,6 +2,7 @@
{{#if subscribed}}
<form class="message-form" method="post" action="/">
{{> messagePopupConfig getPopupConfig}}
{{#if allowedToSend}}
<div class="message-input">
<div class="input-message-container">
<textarea dir="auto" name="msg" maxlength="{{maxMessageLength}}" class="input-message autogrow-short" placeholder="{{_ 'Message'}}"></textarea>
@ -53,7 +54,12 @@
</div>
{{/if}}
</div>
<div class="users-typing">
{{else}}
<div class="stream-info">
{{_ "room_is_read_only"}}
</div>
{{/if}}
<div class="stream-info">
{{#with usersTyping}}
<strong>{{users}}</strong>
{{#if multi}}
@ -71,25 +77,26 @@
{{/if}}
{{/with}}
</div>
{{#if showFormattingTips}}
<div class="formatting-tips" aria-hidden="true" dir="auto">
{{#if showMarkdown}}
<b>*{{_ "bold"}}*</b>
<i>_{{_ "italics"}}_</i>
<span>~<strike>{{_ "strike"}}</strike>~</span>
{{/if}}
{{#if showMarkdownCode}}
<code class="inline">`{{_ "inline_code"}}`</code>
<code class="inline"><span class="hidden-br"><br></span>```<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "multi"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "line"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>```</code>
{{/if}}
{{#if katexSyntax}}
<span><a href="https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX" target="_blank">{{katexSyntax}}</a></span>
{{/if}}
{{#if showMarkdown}}
<q><span class="hidden-br"><br></span>&gt;{{_ "quote"}}</q>
{{#if allowedToSend}}
{{#if showFormattingTips}}
<div class="formatting-tips" aria-hidden="true" dir="auto">
{{#if showMarkdown}}
<b>*{{_ "bold"}}*</b>
<i>_{{_ "italics"}}_</i>
<span>~<strike>{{_ "strike"}}</strike>~</span>
{{/if}}
{{#if showMarkdownCode}}
<code class="inline">`{{_ "inline_code"}}`</code>
<code class="inline"><span class="hidden-br"><br></span>```<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "multi"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>{{_ "line"}}<span class="hidden-br"><br></span><i class="icon-level-down"></i>```</code>
{{/if}}
{{#if katexSyntax}}
<span><a href="https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX" target="_blank">{{katexSyntax}}</a></span>
{{/if}}
{{#if showMarkdown}}
<q><span class="hidden-br"><br></span>&gt;{{_ "quote"}}</q>
{{/if}}
</div>
{{/if}}
</div>
{{/if}}
<div class="editing-commands" aria-hidden="true" dir="auto">
<div class="editing-commands-cancel">{{_ 'Esc_to'}} <button type="button">{{_ 'Cancel_message_input'}}</button></div>

@ -84,9 +84,10 @@ Template.createChannelFlex.events
'click .save-channel': (e, instance) ->
err = SideNav.validate()
name = instance.find('#channel-name').value.toLowerCase().trim()
readOnly = instance.find('#channel-ro').checked
instance.roomName.set name
if not err
Meteor.call 'createChannel', name, instance.selectedUsers.get(), (err, result) ->
Meteor.call 'createChannel', name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
console.log err
if err.error is 'error-invalid-name'

@ -11,6 +11,10 @@
<label for="channel-name">{{_ "Name"}}</label>
<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_channel"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="channel-members">{{_ "Select_users"}}</label>
{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}

@ -89,11 +89,12 @@ Template.createCombinedFlex.events
err = SideNav.validate()
name = instance.find('#channel-name').value.toLowerCase().trim()
privateGroup = instance.find('#channel-type').checked
readOnly = instance.find('#channel-ro').checked
createRoute = if privateGroup then 'createPrivateGroup' else 'createChannel'
successRoute = if privateGroup then 'group' else 'channel'
instance.roomName.set name
if not err
Meteor.call createRoute, name, instance.selectedUsers.get(), (err, result) ->
Meteor.call createRoute, name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
console.log err
if err.error is 'error-invalid-name'

@ -12,9 +12,13 @@
<input type="text" id="channel-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-type">Private Group</label>
<label for="channel-type">{{_ "Private_Group"}}</label>
<input type="checkbox" id="channel-type" {{privateSwitchDisabled}} {{privateSwitchChecked}}>
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_channel"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="channel-members">{{_ "Select_users"}}</label>
{{> inputAutocomplete settings=autocompleteSettings id="channel-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}

@ -80,9 +80,10 @@ Template.privateGroupsFlex.events
'click .save-pvt-group': (e, instance) ->
err = SideNav.validate()
name = instance.find('#pvt-group-name').value.toLowerCase().trim()
readOnly = instance.find('#channel-ro').checked
instance.groupName.set name
if not err
Meteor.call 'createPrivateGroup', name, instance.selectedUsers.get(), (err, result) ->
Meteor.call 'createPrivateGroup', name, instance.selectedUsers.get(), readOnly, (err, result) ->
if err
if err.error is 'error-invalid-name'
instance.error.set({ invalid: true })

@ -11,6 +11,10 @@
<label for="pvt-group-name">{{_ "Name"}}</label>
<input type="text" id="pvt-group-name" class="required" dir="auto" placeholder="{{_ 'Enter_name_here'}}">
</div>
<div class="input-line">
<label for="channel-ro">{{_ "Read_only_group"}}</label>
<input type="checkbox" id="channel-ro">
</div>
<div class="input-line">
<label for="pvt-group-members">{{_ "Select_users" }}</label>
{{> inputAutocomplete settings=autocompleteSettings id="pvt-group-members" class="search" placeholder=(_ "Search_by_username") autocomplete="off"}}

@ -7,15 +7,18 @@ isSubscribed = (_id) ->
favoritesEnabled = ->
return RocketChat.settings.get 'Favorite_Rooms'
userCanDrop = (_id) ->
return !RocketChat.roomTypes.readOnly _id, Meteor.user()
Template.room.helpers
favorite: ->
sub = ChatSubscription.findOne { rid: this._id }, { fields: { f: 1 } }
return 'icon-star favorite-room' if sub?.f? and sub.f and favoritesEnabled
return 'icon-star favorite-room' if sub?.f? and sub.f and favoritesEnabled()
return 'icon-star-empty'
favoriteLabel: ->
sub = ChatSubscription.findOne { rid: this._id }, { fields: { f: 1 } }
return "Unfavorite" if sub?.f? and sub.f and favoritesEnabled
return "Unfavorite" if sub?.f? and sub.f and favoritesEnabled()
return "Favorite"
subscribed: ->
@ -121,6 +124,9 @@ Template.room.helpers
hideAvatar: ->
return if Meteor.user()?.settings?.preferences?.hideAvatars then 'hide-avatars'
userCanDrop: ->
return userCanDrop @_id
canPreview: ->
room = Session.get('roomData' + this._id)
if room.t isnt 'c'
@ -369,7 +375,8 @@ Template.room.events
ChatMessage.update {_id: id}, {$set: {"urls.#{index}.collapsed": !collapsed}}
'dragenter .dropzone': (e) ->
e.currentTarget.classList.add 'over'
if userCanDrop this._id
e.currentTarget.classList.add 'over'
'dragleave .dropzone-overlay': (e) ->
e.currentTarget.parentNode.classList.remove 'over'

@ -3,8 +3,8 @@ Meteor.methods
check rid, String
# check end, Match.Optional(Number)
check limit, Number
check ls, Match.Optional(Date)
# check limit, Number
# check ls, Match.Optional(Date)
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'loadHistory' }

@ -2,7 +2,7 @@ Meteor.methods
loadMissedMessages: (rid, start) ->
check rid, String
check start, Number
check start, Date
if not Meteor.userId()
throw new Meteor.Error 'error-invalid-user', 'Invalid user', { method: 'loadMissedMessages' }

@ -10,8 +10,10 @@ Meteor.startup ->
topic: 1
muted: 1
archived: 1
ro: 1
jitsiTimeout: 1
description: 1
sysMes: 1
joinCodeRequired: 1
if RocketChat.authz.hasPermission(this.userId, 'view-join-code')
@ -37,8 +39,10 @@ Meteor.startup ->
topic: 1
muted: 1
archived: 1
ro: 1
jitsiTimeout: 1
description: 1
sysMes: 1
user = RocketChat.models.Users.findOneById this.userId, fields: username: 1
return RocketChat.models.Rooms.findByTypeAndNameContainingUsername 'p', identifier, user.username, options

Loading…
Cancel
Save