Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Subgroups #8873

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .meteor/packages
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,4 @@ steffo:meteor-accounts-saml
todda00:friendly-slugs
yasaricli:slugify
yasinuslu:blaze-meta
rocketchat:subgroups
1 change: 1 addition & 0 deletions .meteor/versions
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ rocketchat:sms@0.0.1
rocketchat:spotify@0.0.1
rocketchat:statistics@0.0.1
rocketchat:streamer@0.5.0
rocketchat:subgroups@0.0.1
rocketchat:theme@0.0.1
rocketchat:tooltip@0.0.1
rocketchat:tutum@0.0.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ Template.channelSettings.helpers({

Template.channelSettings.events({
'click .delete'() {
let hasSubGroups = Meteor.call('hasSubGroups', Session.get('openedRoom'));
return swal({
title: t('Are_you_sure'),
text: t('Delete_Room_Warning'),
text: hasSubGroups ? t("Delete_Room_Warning_With_SubGroups") : t('Delete_Room_Warning'),
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#DD6B55',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ RocketChat.saveRoomName = function(rid, displayName, user, sendMessage = true) {
'function': 'RocketChat.saveRoomdisplayName'
});
}
if (room.subGroup) {
throw new Meteor.Error('error-not-allowed-subgroup-name', 'Can\'t change subgroup names', {
'function': 'RocketChat.saveRoomdisplayName'
});
}
if (displayName === room.name) {
return;
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@
"create-user": "Create User",
"create-user_description": "Permission to create users",
"Create_A_New_Channel": "Create a New Channel",
"Create_Subgroup": "Create a Subgroup",
"Create_new": "Create new",
"Created_at": "Created at",
"Created_at_s_by_s": "Created at <strong>%s</strong> by <strong>%s</strong>",
Expand Down Expand Up @@ -472,6 +473,7 @@
"Delete_message": "Delete message",
"Delete_my_account": "Delete my account",
"Delete_Room_Warning": "Deleting a room will delete all messages posted within the room. This cannot be undone.",
"Delete_Room_Warning_With_SubGroups": "Deleting a room will delete all messages posted within the room, all subgroups, and the messages posted in the subgroups. This cannot be undone.",
"Delete_User_Warning": "Deleting a user will delete all messages from that user as well. This cannot be undone.",
"Deleted": "Deleted!",
"Department": "Department",
Expand Down Expand Up @@ -565,6 +567,7 @@
"Empty_title": "Empty title",
"Enable": "Enable",
"Enable_Desktop_Notifications": "Enable Desktop Notifications",
"Enable_Subgroups": "Enable Subgroups",
"Enable_Svg_Favicon": "Enable SVG favicon",
"Enable_two-factor_authentication": "Enable two-factor authentication",
"Enabled": "Enabled",
Expand Down Expand Up @@ -640,6 +643,7 @@
"error-missing-unsubscribe-link": "You must provide the [unsubscribe] link.",
"error-no-tokens-for-this-user": "There are no tokens for this user",
"error-not-allowed": "Not allowed",
"error-not-allowed-subgroup-name": "You cannot change a subgroup name",
"error-not-authorized": "Not authorized",
"error-push-disabled": "Push is disabled",
"error-remove-last-owner": "This is the last owner. Please set a new owner before removing this one.",
Expand Down Expand Up @@ -776,6 +780,7 @@
"Hide_roles": "Hide Roles",
"Hide_room": "Hide Room",
"Hide_Room_Warning": "Are you sure you want to hide the room \"%s\"?",
"Hide_subgroups_by_default": "Hide Subgroups by default",
"Hide_Unread_Room_Status": "Hide Unread Room Status",
"Hide_usernames": "Hide Usernames",
"Highlights": "Highlights",
Expand Down Expand Up @@ -1712,6 +1717,10 @@
"Stream_Cast_Address": "Stream Cast Address",
"Stream_Cast_Address_Description": "IP or Host of your Rocket.Chat central Stream Cast. E.g. `192.168.1.1:3000` or `localhost:4000`",
"strike": "strike",
"Subgroups": "Subgroups",
"Subgroup_name": "Subgroup Name",
"Subgroup_topic": "Subgroup Topic (optional)",
"Subgroup_description": "Subgroup Description (optional)",
"Subject": "Subject",
"Submit": "Submit",
"Success": "Success",
Expand Down Expand Up @@ -1905,6 +1914,7 @@
"User_logged_out": "User is logged out",
"User_management": "User Management",
"User_mentions_only": "User mentions only",
"User_must_be_in_parent_room": "User must be in parent room",
"User_muted": "User Muted",
"User_muted_by": "User <em>__user_muted__</em> muted by <em>__user_by__</em>.",
"User_not_found": "User not found",
Expand Down
16 changes: 10 additions & 6 deletions packages/rocketchat-katex/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions packages/rocketchat-lib/server/methods/addUsersToRoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,34 @@ Meteor.methods({
method: 'addUsersToRoom'
});
}
if (room.subGroup) {
let originalSub = RocketChat.models.Subscriptions.findOne({
'rid': room.originalRoomId,
'u.username': username
});
if (!originalSub) {
throw new Meteor.Error('User_must_be_in_parent_room', 'User must be in parent room', {
method: 'addUserToRoom'
});
}
}

RocketChat.addUserToRoom(data.rid, newUser, user);

if (room.subGroup) {
let sub = RocketChat.models.Subscriptions.update({
'rid': data.rid
},
{
$set:
{
'subGroup': true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was e. g. interesting to know whether the thread will be a separate room type or remain in the same type as the parent

'subGroupName': room.subGroupName,
'originalRoomId': room.originalRoomId
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which property shall be used to form the hierarchy - or whether a hierarchy shall exist after all and not only some sort of "tagging"

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it was interesting to know whether the subroom is just a room within a room or whether it is started from a message (which actually made it a thread)

}
},
{ multi: true });
}
});

return true;
Expand Down
25 changes: 25 additions & 0 deletions packages/rocketchat-subgroups/client/subGroup.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template name="subGroups">
<div class="flex-tab__header">
<div class="list-view animated">
<div class="title">
<h2>{{_ "Create_Subgroup"}}</h2>
</div>
</div>
</div>
<div class="flex-tab__result">
<div class="search-form">
<div class="input-line">
<input type="text" id="group-name" class="content-background-color" placeholder="{{_ "Subgroup_name"}}" />
</div>
<div class="input-line">
<input type="text" id="topic" class="content-background-color" placeholder="{{_ "Subgroup_topic"}}" />
</div>
<div class="input-line">
<input type="text" id="description" class="content-background-color" placeholder="{{_ "Subgroup_description"}}" />
</div>
<nav>
<button class='button primary create-group'><span>{{_ "Create_Subgroup"}}</span></button>
</nav>
</div>
</div>
</template>
36 changes: 36 additions & 0 deletions packages/rocketchat-subgroups/client/subGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import toastr from 'toastr';

Template.subGroups.events({
'click .create-group': function() {

let groupName = $('#group-name').val().trim();
let groupTopic = $('#topic').val().trim();
let groupDescription = $('#description').val().trim();

if (groupName.length === 0) {
return toastr.warning("Please enter a subgroup name");
} else {
Meteor.call('createSubGroup', groupName, groupTopic, groupDescription, Session.get('openedRoom'), Meteor.user(), (err, resp) => {
if (!err) {
$('#group-name').val('');
$('#topic').val('');
$('#description').val('');
toastr.success("Subgroup Created!");
return FlowRouter.go("/group/" + resp + "/");
} else {
if (err.error === 'error-duplicate-channel-name') {
return toastr.warning("This group name already exists");
} else if (err.error === 'error-subgroup-must-join-group-first') {
return toastr.warning("You must join this channel first");
} else if (err.error === 'error-subgroup-no-nested-subgroups') {
return toastr.warning("You cannot create a group from a group");
} else if (err.error === 'error-invalid-name') {
return toastr.warning("Group names can only contain letters, numbers, hyphens, and underscores (no spaces)");
} else {
return toastr.error("Something went wrong");
}
}
});
}
}
});
16 changes: 16 additions & 0 deletions packages/rocketchat-subgroups/client/tabBar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Meteor.startup(function() {
return Tracker.autorun(function() {
if (RocketChat.settings.get('Enable_Subgroups')) {
RocketChat.TabBar.addButton({
groups: ['channel', 'group'],
id: 'subGroups',
i18nTitle: 'Create_Subgroup',
template: 'subGroups',
order: 3,
subGroups: true
});
} else {
RocketChat.TabBar.removeButton('subGroups');
}
});
});
29 changes: 29 additions & 0 deletions packages/rocketchat-subgroups/package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
Package.describe({
name: 'rocketchat:subgroups',
version: '0.0.1',
summary: 'Channel subgroups',
git: ''
});

Package.onUse(function(api) {
api.use([
'mongo',
'jquery',
'templating',
'ecmascript',
'rocketchat:lib'
]);

api.addFiles([
'client/subGroup.html',
'client/subGroup.js',
'client/tabBar.js'
], 'client');

api.addFiles([
'server/createSubGroup.js',
'server/settings.js',
'server/hasSubGroups.js'
], 'server')

});
57 changes: 57 additions & 0 deletions packages/rocketchat-subgroups/server/createSubGroup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
Meteor.methods({
createSubGroup: function(groupName, groupTopic, groupDescription, roomId, user) {

let username = user.username;
let currentRoom = RocketChat.models.Rooms.findOneById(roomId);
let currentName = currentRoom.name;
let currentSub = RocketChat.models.Subscriptions.findOne({'rid': roomId, 'u.username': username});
let nameValidation;

try {
nameValidation = new RegExp('^' + RocketChat.settings.get('UTF8_Names_Validation') + '$');
} catch (error) {
nameValidation = new RegExp('^[0-9a-zA-Z-_.]+$');
}

if (!nameValidation.test(groupName)) {
throw new Meteor.Error('error-invalid-name', 'Invalid name', { function: 'Meteor.createSubGroup' });
}

if (!currentRoom || !currentSub) {
throw new Meteor.Error('error-subgroup-must-join-group-first', 'Must join a channel before creating a subgroup', { function: 'createSubGroup' });
}

if (currentSub.subGroup) {
throw new Meteor.Error('error-subgroup-no-nested-subgroups', 'You cannot create a subgroup of a subgroup', { function: 'createSubGroup' });
}

let newName = `${currentName}_${groupName}`
let newRoom = RocketChat.createRoom('p', newName, username, [username]);

// update new room
RocketChat.models.Rooms.update({
'_id': newRoom.rid
}, {
$set: {
'subGroup': true,
'topic': groupTopic,
'description': groupDescription,
'subGroupName': groupName,
'originalRoomId': roomId
}
});

// update the owner's subscriptions
RocketChat.models.Subscriptions.update({
'rid': newRoom.rid
}, {
$set: {
'subGroup': true,
'subGroupName': groupName,
'originalRoomId': roomId
}
});

return RocketChat.models.Rooms.findOne({'_id': newRoom.rid}).name;
}
});
11 changes: 11 additions & 0 deletions packages/rocketchat-subgroups/server/hasSubGroups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Meteor.methods({
hasSubGroups(rid) {
if (!rid) {
return false;
}
const subs = RocketChat.models.Rooms.find({
'originalRoomId': rid
}).count();
return subs;
}
});
5 changes: 5 additions & 0 deletions packages/rocketchat-subgroups/server/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RocketChat.settings.addGroup('General', function() {
this.section('Subgroups', function() {
this.add('Enable_Subgroups', false, { type: 'boolean', public: true });
});
});
12 changes: 12 additions & 0 deletions packages/rocketchat-ui-account/client/accountPreferences.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,18 @@ <h1>{{_ "Messages"}}</h1>
</div>
</div>
</div>
<div class="section">
<h1>{{_ "Subgroups"}}</h1>
<div class="section-content border-component-color">
<div class="input-line double-col" id="hideSubgroups">
<label>{{_ "Hide_subgroups_by_default"}}</label>
<div>
<label><input type="radio" name="hideSubgroups" value="1" checked="{{checked 'hideSubgroups' true}}" /> {{_ "True"}}</label>
<label><input type="radio" name="hideSubgroups" value="0" checked="{{checked 'hideSubgroups' false true}}" /> {{_ "False"}}</label>
</div>
</div>
</div>
</div>
<div class="section">
<h1>{{_ "Highlights"}}</h1>
<div class="section-content border-component-color">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ Template.accountPreferences.onCreated(function() {
data.viewMode = parseInt($('#viewMode').find('select').val());
data.hideUsernames = $('#hideUsernames').find('input:checked').val();
data.hideRoles = $('#hideRoles').find('input:checked').val();
data.hideSubgroups = $('#hideSubgroups').find('input:checked').val();
data.hideFlexTab = $('#hideFlexTab').find('input:checked').val();
data.hideAvatars = $('#hideAvatars').find('input:checked').val();
data.mergeChannels = $('#mergeChannels').find('input:checked').val();
Expand Down
Loading