Team invitation
This commit is contained in:
parent
3a76e84286
commit
e4e2c3a19d
@ -30,7 +30,7 @@
|
|||||||
// These show only once
|
// These show only once
|
||||||
|
|
||||||
.alertify-logs {
|
.alertify-logs {
|
||||||
z-index: 10000; // alertify logs
|
z-index: 100001; // alertify logs should be in front of alertify modals
|
||||||
@media print {
|
@media print {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
@ -339,7 +339,7 @@
|
|||||||
.alertify-logs {
|
.alertify-logs {
|
||||||
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 99999; // alertify logs
|
z-index: 100001; // alertify logs (just in front of alertify modals
|
||||||
|
|
||||||
&.bottom, &:not(.top) {
|
&.bottom, &:not(.top) {
|
||||||
bottom: 16px;
|
bottom: 16px;
|
||||||
@ -459,8 +459,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.cp-ownership {
|
||||||
|
& > label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-share-column {
|
||||||
.cp-share-grid, .cp-share-list {
|
.cp-share-grid, .cp-share-list {
|
||||||
.avatar_main(50px);
|
.avatar_main(40px);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@ -513,6 +520,9 @@
|
|||||||
color: @colortheme_alertify-primary-text;
|
color: @colortheme_alertify-primary-text;
|
||||||
order: -1 !important;
|
order: -1 !important;
|
||||||
}
|
}
|
||||||
|
.cp-share-friend-avatar {
|
||||||
|
min-height: 40px;
|
||||||
|
}
|
||||||
.cp-share-friend-name {
|
.cp-share-friend-name {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -525,11 +535,6 @@
|
|||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cp-ownership {
|
|
||||||
& > label {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ define([
|
|||||||
var Msg = {};
|
var Msg = {};
|
||||||
|
|
||||||
var createData = Msg.createData = function (proxy, hash) {
|
var createData = Msg.createData = function (proxy, hash) {
|
||||||
return {
|
var data = {
|
||||||
channel: hash || Hash.createChannelId(),
|
channel: hash || Hash.createChannelId(),
|
||||||
displayName: proxy['cryptpad.username'],
|
displayName: proxy['cryptpad.username'],
|
||||||
profile: proxy.profile && proxy.profile.view,
|
profile: proxy.profile && proxy.profile.view,
|
||||||
@ -19,6 +19,8 @@ define([
|
|||||||
notifications: Util.find(proxy, ['mailboxes', 'notifications', 'channel']),
|
notifications: Util.find(proxy, ['mailboxes', 'notifications', 'channel']),
|
||||||
avatar: proxy.profile && proxy.profile.avatar
|
avatar: proxy.profile && proxy.profile.avatar
|
||||||
};
|
};
|
||||||
|
if (hash === false) { delete data.channel; }
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
var getFriend = Msg.getFriend = function (proxy, pubkey) {
|
var getFriend = Msg.getFriend = function (proxy, pubkey) {
|
||||||
|
|||||||
@ -146,18 +146,6 @@ define([
|
|||||||
}, function () {
|
}, function () {
|
||||||
});
|
});
|
||||||
var $div = $(removeCol.div);
|
var $div = $(removeCol.div);
|
||||||
var others1 = removeCol.others;
|
|
||||||
$div.append(h('div.cp-share-grid', others1));
|
|
||||||
$div.find('.cp-share-friend').click(function () {
|
|
||||||
var sel = $(this).hasClass('cp-selected');
|
|
||||||
if (!sel) {
|
|
||||||
$(this).addClass('cp-selected');
|
|
||||||
} else {
|
|
||||||
var order = $(this).attr('data-order');
|
|
||||||
order = order ? 'order:'+order : '';
|
|
||||||
$(this).removeClass('cp-selected').attr('style', order);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// When clicking on the remove button, we check the selected users.
|
// When clicking on the remove button, we check the selected users.
|
||||||
// If you try to remove yourself, we'll display an additional warning message
|
// If you try to remove yourself, we'll display an additional warning message
|
||||||
var btnMsg = pending ? Messages.owner_removePendingButton : Messages.owner_removeButton;
|
var btnMsg = pending ? Messages.owner_removePendingButton : Messages.owner_removeButton;
|
||||||
@ -244,18 +232,6 @@ define([
|
|||||||
//console.log(arguments);
|
//console.log(arguments);
|
||||||
});
|
});
|
||||||
$div2 = $(addCol.div);
|
$div2 = $(addCol.div);
|
||||||
var others2 = addCol.others;
|
|
||||||
$div2.append(h('div.cp-share-grid', others2));
|
|
||||||
$div2.find('.cp-share-friend').click(function () {
|
|
||||||
var sel = $(this).hasClass('cp-selected');
|
|
||||||
if (!sel) {
|
|
||||||
$(this).addClass('cp-selected');
|
|
||||||
} else {
|
|
||||||
var order = $(this).attr('data-order');
|
|
||||||
order = order ? 'order:'+order : '';
|
|
||||||
$(this).removeClass('cp-selected').attr('style', order);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// When clicking on the add button, we get the selected users.
|
// When clicking on the add button, we get the selected users.
|
||||||
var addButton = h('button.no-margin', Messages.owner_addButton);
|
var addButton = h('button.no-margin', Messages.owner_addButton);
|
||||||
$(addButton).click(function () {
|
$(addButton).click(function () {
|
||||||
@ -724,6 +700,19 @@ define([
|
|||||||
onSelect();
|
onSelect();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(div).append(h('div.cp-share-grid', others));
|
||||||
|
$div.on('click', '.cp-share-friend', function () {
|
||||||
|
var sel = $(this).hasClass('cp-selected');
|
||||||
|
if (!sel) {
|
||||||
|
$(this).addClass('cp-selected');
|
||||||
|
} else {
|
||||||
|
var order = $(this).attr('data-order');
|
||||||
|
order = order ? 'order:'+order : '';
|
||||||
|
$(this).removeClass('cp-selected').attr('style', order);
|
||||||
|
}
|
||||||
|
onSelect();
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
others: others,
|
others: others,
|
||||||
div: div
|
div: div
|
||||||
@ -749,7 +738,7 @@ define([
|
|||||||
// Replace "copy link" by "share with friends" if at least one friend is selected
|
// Replace "copy link" by "share with friends" if at least one friend is selected
|
||||||
// Also create the "share with friends" button if it doesn't exist
|
// Also create the "share with friends" button if it doesn't exist
|
||||||
var refreshButtons = function () {
|
var refreshButtons = function () {
|
||||||
var $nav = $div.parents('.alertify').find('nav');
|
var $nav = $div.closest('.alertify').find('nav');
|
||||||
|
|
||||||
var friendMode = $div.find('.cp-share-friend.cp-selected').length;
|
var friendMode = $div.find('.cp-share-friend.cp-selected').length;
|
||||||
if (friendMode) {
|
if (friendMode) {
|
||||||
@ -759,6 +748,7 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
config.noInclude = true;
|
||||||
var friendsList = UIElements.getFriendsList(Messages.share_linkFriends, config, refreshButtons);
|
var friendsList = UIElements.getFriendsList(Messages.share_linkFriends, config, refreshButtons);
|
||||||
var friendDiv = friendsList.div;
|
var friendDiv = friendsList.div;
|
||||||
$div.append(friendDiv);
|
$div.append(friendDiv);
|
||||||
@ -784,7 +774,6 @@ define([
|
|||||||
friends: teams
|
friends: teams
|
||||||
}, refreshButtons);
|
}, refreshButtons);
|
||||||
$div.append(teamsList.div);
|
$div.append(teamsList.div);
|
||||||
$(teamsList.div).append(h('div.cp-share-grid', teamsList.others));
|
|
||||||
|
|
||||||
var shareButtons = [{
|
var shareButtons = [{
|
||||||
className: 'primary cp-share-with-friends',
|
className: 'primary cp-share-with-friends',
|
||||||
@ -870,19 +859,9 @@ define([
|
|||||||
$(el).attr('data-order', i).css('order', i);
|
$(el).attr('data-order', i).css('order', i);
|
||||||
});
|
});
|
||||||
// Display them
|
// Display them
|
||||||
|
$(friendDiv).find('.cp-share-grid').detach();
|
||||||
$(friendDiv).append(h('div.cp-share-grid', others));
|
$(friendDiv).append(h('div.cp-share-grid', others));
|
||||||
$div.append(UI.dialog.getButtons(shareButtons, config.onClose));
|
$div.append(UI.dialog.getButtons(shareButtons, config.onClose));
|
||||||
$div.find('.cp-share-friend').click(function () {
|
|
||||||
var sel = $(this).hasClass('cp-selected');
|
|
||||||
if (!sel) {
|
|
||||||
$(this).addClass('cp-selected');
|
|
||||||
} else {
|
|
||||||
var order = $(this).attr('data-order');
|
|
||||||
order = order ? 'order:'+order : '';
|
|
||||||
$(this).removeClass('cp-selected').attr('style', order);
|
|
||||||
}
|
|
||||||
refreshButtons();
|
|
||||||
});
|
|
||||||
refreshButtons();
|
refreshButtons();
|
||||||
});
|
});
|
||||||
return div;
|
return div;
|
||||||
@ -903,7 +882,6 @@ define([
|
|||||||
var friendsUIClass = hasFriends ? '.cp-share-columns' : '';
|
var friendsUIClass = hasFriends ? '.cp-share-columns' : '';
|
||||||
|
|
||||||
var mainShareColumn = h('div.cp-share-column.contains-nav', [
|
var mainShareColumn = h('div.cp-share-column.contains-nav', [
|
||||||
hasFriends ? h('p', Messages.share_description) : undefined,
|
|
||||||
h('label', Messages.share_linkAccess),
|
h('label', Messages.share_linkAccess),
|
||||||
h('br'),
|
h('br'),
|
||||||
UI.createRadio('cp-share-editable', 'cp-share-editable-true',
|
UI.createRadio('cp-share-editable', 'cp-share-editable-true',
|
||||||
@ -1195,6 +1173,78 @@ define([
|
|||||||
return UI.dialog.customModal(link, {buttons: linkButtons});
|
return UI.dialog.customModal(link, {buttons: linkButtons});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UIElements.createInviteTeamModal = function (config) {
|
||||||
|
var common = config.common;
|
||||||
|
var hasFriends = Object.keys(config.friends || {}).length !== 0;
|
||||||
|
var friendsList = hasFriends ? createShareWithFriends(config) : undefined;
|
||||||
|
|
||||||
|
if (!hasFriends) {
|
||||||
|
return void UI.alert('No friend to invite'); // XXX
|
||||||
|
}
|
||||||
|
var privateData = common.getMetadataMgr().getPrivateData();
|
||||||
|
var team = privateData.teams[config.teamId];
|
||||||
|
if (!team) { return void UI.warn(Messages.error); }
|
||||||
|
|
||||||
|
var module = config.module || common.makeUniversal('team', { onEvent: function () {} });
|
||||||
|
|
||||||
|
var $div;
|
||||||
|
var refreshButton = function () {
|
||||||
|
if (!$div) { return; }
|
||||||
|
var $modal = $div.closest('.alertify');
|
||||||
|
var $nav = $modal.find('nav');
|
||||||
|
var $btn = $nav.find('button.primary');
|
||||||
|
var selected = $div.find('.cp-share-friend.cp-selected').length;
|
||||||
|
if (selected) {
|
||||||
|
$btn.prop('disabled', '');
|
||||||
|
} else {
|
||||||
|
$btn.prop('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var list = UIElements.getFriendsList('Pick the friends you want to invite to the team', { // XXX
|
||||||
|
common: common,
|
||||||
|
friends: config.friends,
|
||||||
|
}, refreshButton);
|
||||||
|
$div = $(list.div);
|
||||||
|
refreshButton();
|
||||||
|
|
||||||
|
var buttons = [{
|
||||||
|
className: 'cancel',
|
||||||
|
name: Messages.cancel,
|
||||||
|
onClick: function () {},
|
||||||
|
keys: [27]
|
||||||
|
}, {
|
||||||
|
className: 'primary',
|
||||||
|
name: 'INVITE', // XXX
|
||||||
|
onClick: function () {
|
||||||
|
var $sel = $div.find('.cp-share-friend.cp-selected');
|
||||||
|
var sel = $sel.toArray();
|
||||||
|
if (!sel.length) { return; }
|
||||||
|
|
||||||
|
var friends = sel.forEach(function (el) {
|
||||||
|
var curve = $(el).attr('data-curve');
|
||||||
|
module.execCommand('INVITE_TO_TEAM', {
|
||||||
|
teamId: config.teamId,
|
||||||
|
user: config.friends[curve]
|
||||||
|
}, function (obj) {
|
||||||
|
if (obj && obj.error) {
|
||||||
|
console.error(obj.error);
|
||||||
|
return UI.warn(Messages.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
keys: [13]
|
||||||
|
}];
|
||||||
|
|
||||||
|
var content = h('div', [
|
||||||
|
h('h4', 'Invite friends to your team: '+ team.name),
|
||||||
|
list.div
|
||||||
|
]);
|
||||||
|
|
||||||
|
var modal = UI.dialog.customModal(content, {buttons: buttons});
|
||||||
|
UI.openCustomModal(modal);
|
||||||
|
};
|
||||||
|
|
||||||
UIElements.createButton = function (common, type, rightside, data, callback) {
|
UIElements.createButton = function (common, type, rightside, data, callback) {
|
||||||
var AppConfig = common.getAppConfig();
|
var AppConfig = common.getAppConfig();
|
||||||
var button;
|
var button;
|
||||||
@ -3503,27 +3553,7 @@ define([
|
|||||||
var content = h('div.cp-share-modal', [
|
var content = h('div.cp-share-modal', [
|
||||||
setHTML(h('p'), text)
|
setHTML(h('p'), text)
|
||||||
]);
|
]);
|
||||||
var buttons = [{
|
UI.proposal(content, todo);
|
||||||
name: Messages.friendRequest_later,
|
|
||||||
onClick: function () {},
|
|
||||||
keys: [27]
|
|
||||||
}, {
|
|
||||||
className: 'primary',
|
|
||||||
name: Messages.friendRequest_accept,
|
|
||||||
onClick: function () {
|
|
||||||
todo(true);
|
|
||||||
},
|
|
||||||
keys: [13]
|
|
||||||
}, {
|
|
||||||
className: 'primary',
|
|
||||||
name: Messages.friendRequest_decline,
|
|
||||||
onClick: function () {
|
|
||||||
todo(false);
|
|
||||||
},
|
|
||||||
keys: [[13, 'ctrl']]
|
|
||||||
}];
|
|
||||||
var modal = UI.dialog.customModal(content, {buttons: buttons});
|
|
||||||
UI.openCustomModal(modal);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
UIElements.displayAddOwnerModal = function (common, data) {
|
UIElements.displayAddOwnerModal = function (common, data) {
|
||||||
@ -3648,27 +3678,85 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var buttons = [{
|
UI.proposal(div, todo);
|
||||||
name: Messages.friendRequest_later,
|
};
|
||||||
onClick: function () {},
|
|
||||||
keys: [27]
|
UIElements.getVerifiedFriend = function (common, curve, name) {
|
||||||
}, {
|
var priv = common.getMetadataMgr().getPrivateData();
|
||||||
className: 'primary',
|
var verified = h('p');
|
||||||
name: Messages.friendRequest_accept,
|
var $verified = $(verified);
|
||||||
onClick: function () {
|
|
||||||
todo(true);
|
if (priv.friends && priv.friends[curve]) {
|
||||||
},
|
$verified.addClass('cp-notifications-requestedit-verified');
|
||||||
keys: [13]
|
var f = priv.friends[curve];
|
||||||
}, {
|
$verified.append(h('span.fa.fa-certificate'));
|
||||||
className: 'primary',
|
var $avatar = $(h('span.cp-avatar')).appendTo($verified);
|
||||||
name: Messages.friendRequest_decline,
|
$verified.append(h('p', Messages._getKey('requestEdit_fromFriend', [f.displayName])));
|
||||||
onClick: function () {
|
common.displayAvatar($avatar, f.avatar, f.displayName);
|
||||||
todo(false);
|
} else {
|
||||||
},
|
$verified.append(Messages._getKey('requestEdit_fromStranger', [name]));
|
||||||
keys: [[13, 'ctrl']]
|
}
|
||||||
}];
|
return verified;
|
||||||
var modal = UI.dialog.customModal(div, {buttons: buttons});
|
};
|
||||||
UI.openCustomModal(modal);
|
|
||||||
|
UIElements.displayInviteTeamModal = function (common, data) {
|
||||||
|
var priv = common.getMetadataMgr().getPrivateData();
|
||||||
|
var user = common.getMetadataMgr().getUserData();
|
||||||
|
var sframeChan = common.getSframeChannel();
|
||||||
|
var msg = data.content.msg;
|
||||||
|
|
||||||
|
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
|
||||||
|
var teamName = Util.fixHTML(Util.find(msg, ['content', 'team', 'metadata', 'name']) || '');
|
||||||
|
|
||||||
|
var verified = UIElements.getVerifiedFriend(common, msg.author, name);
|
||||||
|
|
||||||
|
//var text = Messages._getKey('', [name, title]); // XXX
|
||||||
|
var text = name + " has invited you to join the team <b>" + teamName +"</b>";
|
||||||
|
|
||||||
|
var div = h('div', [
|
||||||
|
UI.setHTML(h('p'), text),
|
||||||
|
verified
|
||||||
|
]);
|
||||||
|
|
||||||
|
var module = common.makeUniversal('team');
|
||||||
|
|
||||||
|
var answer = function (yes) {
|
||||||
|
common.mailbox.sendTo("INVITE_TO_TEAM_ANSWER", {
|
||||||
|
answer: yes,
|
||||||
|
teamChannel: msg.content.team.channel,
|
||||||
|
user: {
|
||||||
|
displayName: user.name,
|
||||||
|
avatar: user.avatar,
|
||||||
|
profile: user.profile,
|
||||||
|
notifications: user.notifications,
|
||||||
|
curvePublic: user.curvePublic,
|
||||||
|
edPublic: priv.edPublic
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
channel: msg.content.user.notifications,
|
||||||
|
curvePublic: msg.content.user.curvePublic
|
||||||
|
});
|
||||||
|
common.mailbox.dismiss(data, function (err) {
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
var todo = function (yes) {
|
||||||
|
if (yes) {
|
||||||
|
// ACCEPT
|
||||||
|
module.execCommand('JOIN_TEAM', {
|
||||||
|
team: msg.content.team
|
||||||
|
}, function (obj) {
|
||||||
|
if (obj && obj.error) { return void UI.warn(Messages.error); }
|
||||||
|
answer(true);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DECLINE
|
||||||
|
answer(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
UI.proposal(div, todo);
|
||||||
};
|
};
|
||||||
|
|
||||||
return UIElements;
|
return UIElements;
|
||||||
|
|||||||
@ -145,22 +145,10 @@ define([
|
|||||||
var link = h('a', {
|
var link = h('a', {
|
||||||
href: '#'
|
href: '#'
|
||||||
}, Messages.requestEdit_viewPad);
|
}, Messages.requestEdit_viewPad);
|
||||||
var verified = h('p');
|
|
||||||
var $verified = $(verified);
|
|
||||||
|
|
||||||
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
|
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
|
||||||
var title = Util.fixHTML(msg.content.title);
|
var title = Util.fixHTML(msg.content.title);
|
||||||
|
var verified = UIElements.getVerifiedFriend(common, msg.author, name);
|
||||||
if (priv.friends && priv.friends[msg.author]) {
|
|
||||||
$verified.addClass('cp-notifications-requestedit-verified');
|
|
||||||
var f = priv.friends[msg.author];
|
|
||||||
$verified.append(h('span.fa.fa-certificate'));
|
|
||||||
var $avatar = $(h('span.cp-avatar')).appendTo($verified);
|
|
||||||
$verified.append(h('p', Messages._getKey('requestEdit_fromFriend', [f.displayName])));
|
|
||||||
common.displayAvatar($avatar, f.avatar, f.displayName);
|
|
||||||
} else {
|
|
||||||
$verified.append(Messages._getKey('requestEdit_fromStranger', [name]));
|
|
||||||
}
|
|
||||||
|
|
||||||
var div = h('div', [
|
var div = h('div', [
|
||||||
UI.setHTML(h('p'), Messages._getKey('requestEdit_confirm', [title, name])),
|
UI.setHTML(h('p'), Messages._getKey('requestEdit_confirm', [title, name])),
|
||||||
@ -268,6 +256,42 @@ define([
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
handlers['INVITE_TO_TEAM'] = function (common, data) {
|
||||||
|
var content = data.content;
|
||||||
|
var msg = content.msg;
|
||||||
|
|
||||||
|
// Display the notification
|
||||||
|
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
|
||||||
|
var teamName = Util.fixHTML(Util.find(msg, ['content', 'team', 'metadata', 'name']) || '');
|
||||||
|
content.getFormatText = function () {
|
||||||
|
var text = name + " has invited you to join the team <b>" + teamName +"</b>";
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
if (!content.archived) {
|
||||||
|
content.handler = function () {
|
||||||
|
UIElements.displayInviteTeamModal(common, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers['INVITE_TO_TEAM_ANSWER'] = function (common, data) {
|
||||||
|
var content = data.content;
|
||||||
|
var msg = content.msg;
|
||||||
|
|
||||||
|
// Display the notification
|
||||||
|
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
|
||||||
|
var teamName = Util.fixHTML(Util.find(msg, ['content', 'team', 'metadata', 'name']) || '');
|
||||||
|
var key = 'owner_request_' + (msg.content.answer ? 'accepted' : 'declined');
|
||||||
|
content.getFormatText = function () {
|
||||||
|
//return Messages._getKey(key, [name, title]); // XXX
|
||||||
|
return name +' has ' + (msg.content.answer ? 'accepted' : 'declined') + ' your offer to join the team <b>' + teamName + '</b>';
|
||||||
|
};
|
||||||
|
if (!content.archived) {
|
||||||
|
content.dismissHandler = defaultDismiss(common, data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
define([
|
define([
|
||||||
'/common/common-messaging.js',
|
'/common/common-messaging.js',
|
||||||
'/common/common-hash.js',
|
'/common/common-hash.js',
|
||||||
], function (Messaging, Hash) {
|
'/common/common-util.js',
|
||||||
|
], function (Messaging, Hash, Util) {
|
||||||
|
|
||||||
var getRandomTimeout = function (ctx) {
|
var getRandomTimeout = function (ctx) {
|
||||||
var lag = ctx.store.realtime.getLag().lag || 0;
|
var lag = ctx.store.realtime.getLag().lag || 0;
|
||||||
@ -309,6 +310,72 @@ define([
|
|||||||
cb(false);
|
cb(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var invitedTo = {};
|
||||||
|
handlers['INVITE_TO_TEAM'] = function (ctx, box, data, cb) {
|
||||||
|
var msg = data.msg;
|
||||||
|
var content = msg.content;
|
||||||
|
|
||||||
|
if (msg.author !== content.user.curvePublic) { return void cb(true); }
|
||||||
|
if (!content.team) {
|
||||||
|
console.log('Remove invalid notification');
|
||||||
|
return void cb(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invitedTo[content.team.channel]) { return void cb(true); }
|
||||||
|
|
||||||
|
var myTeams = Util.find(ctx, ['store', 'proxy', 'teams'])
|
||||||
|
var alreadyMember = Object.keys(myTeams).some(function (k) {
|
||||||
|
var team = myTeams[k];
|
||||||
|
return team.channel === content.team.channel;
|
||||||
|
});
|
||||||
|
if (alreadyMember) { return void cb(true); }
|
||||||
|
|
||||||
|
invitedTo[content.team.channel] = true;
|
||||||
|
|
||||||
|
cb(false);
|
||||||
|
};
|
||||||
|
removeHandlers['INVITE_TO_TEAM'] = function (ctx, box, data) {
|
||||||
|
var channel = Util.find(data, ['content', 'team', 'channel']);
|
||||||
|
delete invitedTo[channel];
|
||||||
|
};
|
||||||
|
|
||||||
|
handlers['INVITE_TO_TEAM_ANSWER'] = function (ctx, box, data, cb) {
|
||||||
|
var msg = data.msg;
|
||||||
|
var content = msg.content;
|
||||||
|
|
||||||
|
if (msg.author !== content.user.curvePublic) { return void cb(true); }
|
||||||
|
if (!content.teamChannel) {
|
||||||
|
console.log('Remove invalid notification');
|
||||||
|
return void cb(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
var myTeams = Util.find(ctx, ['store', 'proxy', 'teams'])
|
||||||
|
var teamId;
|
||||||
|
var team;
|
||||||
|
Object.keys(myTeams).some(function (k) {
|
||||||
|
var _team = myTeams[k];
|
||||||
|
if (_team.channel === content.teamChannel) {
|
||||||
|
teamId = k;
|
||||||
|
team = _team;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!teamId) { return void cb(true); }
|
||||||
|
|
||||||
|
content.team = team;
|
||||||
|
|
||||||
|
if (!content.answer) {
|
||||||
|
// If they declined the invitation, remove them from the roster (as a pending member)
|
||||||
|
try {
|
||||||
|
var module = ctx.store.modules['team'];
|
||||||
|
module.removeFromTeam(teamId, msg.author);
|
||||||
|
} catch (e) { console.error(e); }
|
||||||
|
}
|
||||||
|
|
||||||
|
cb(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
add: function (ctx, box, data, cb) {
|
add: function (ctx, box, data, cb) {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -310,8 +310,8 @@ define([
|
|||||||
// If you're allowed to edit the roster, try to update your data
|
// If you're allowed to edit the roster, try to update your data
|
||||||
if (!rosterData.edit) { return; }
|
if (!rosterData.edit) { return; }
|
||||||
var data = {};
|
var data = {};
|
||||||
var myData = Messaging.createData(ctx.store.proxy);
|
var myData = Messaging.createData(ctx.store.proxy, false);
|
||||||
delete myData.channel;
|
myData.pending = false;
|
||||||
data[ctx.store.proxy.curvePublic] = myData;
|
data[ctx.store.proxy.curvePublic] = myData;
|
||||||
roster.describe(data, function (err) {
|
roster.describe(data, function (err) {
|
||||||
if (!err) { return; }
|
if (!err) { return; }
|
||||||
@ -448,6 +448,19 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var joinTeam = function (ctx, data, cId, cb) {
|
||||||
|
var team = data.team;
|
||||||
|
if (!team.hash || !team.channel || !team.password
|
||||||
|
|| !team.keys || !team.metadata) { return void cb({error: 'EINVAL'}); }
|
||||||
|
var id = Util.createRandomInteger();
|
||||||
|
ctx.store.proxy.teams[id] = team;
|
||||||
|
ctx.onReadyHandlers[id] = [];
|
||||||
|
openChannel(ctx, team, id, function (obj) {
|
||||||
|
if (!(obj && obj.error)) { console.debug('Team joined:' + id); }
|
||||||
|
cb(obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var getTeamRoster = function (ctx, data, cId, cb) {
|
var getTeamRoster = function (ctx, data, cId, cb) {
|
||||||
var teamId = data.teamId;
|
var teamId = data.teamId;
|
||||||
if (!teamId) { return void cb({error: 'EINVAL'}); }
|
if (!teamId) { return void cb({error: 'EINVAL'}); }
|
||||||
@ -499,6 +512,43 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO send guest keys only in the future
|
||||||
|
var getInviteData = function (ctx, teamId) {
|
||||||
|
var teamData = Util.find(ctx, ['store', 'proxy', 'teams', teamId]);
|
||||||
|
if (!teamData) { return; }
|
||||||
|
var data = Util.clone(teamData);
|
||||||
|
delete data.owner;
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
var inviteToTeam = function (ctx, data, cId, cb) {
|
||||||
|
var teamId = data.teamId;
|
||||||
|
if (!teamId) { return void cb({error: 'EINVAL'}); }
|
||||||
|
var team = ctx.teams[teamId];
|
||||||
|
if (!team) { return void cb ({error: 'ENOENT'}); }
|
||||||
|
if (!team.roster) { return void cb({error: 'NO_ROSTER'}); }
|
||||||
|
var user = data.user;
|
||||||
|
if (!user || !user.curvePublic || !user.notifications) { return void cb({error: 'MISSING_DATA'}); }
|
||||||
|
delete user.channel;
|
||||||
|
delete user.lastKnownHash;
|
||||||
|
user.pending = true;
|
||||||
|
|
||||||
|
var obj = {};
|
||||||
|
obj[user.curvePublic] = user;
|
||||||
|
team.roster.add(obj, function (err) {
|
||||||
|
if (err && err !== 'NO_CHANGE') { return void cb({error: err}); }
|
||||||
|
ctx.store.mailbox.sendTo('INVITE_TO_TEAM', {
|
||||||
|
user: Messaging.createData(ctx.store.proxy, false),
|
||||||
|
team: getInviteData(ctx, teamId)
|
||||||
|
}, {
|
||||||
|
channel: user.notifications,
|
||||||
|
curvePublic: user.curvePublic
|
||||||
|
}, function (obj) {
|
||||||
|
cb(obj);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// XXX Listen for changes to the roster pad to know if you've been removed
|
// XXX Listen for changes to the roster pad to know if you've been removed
|
||||||
// XXX onReady, if you've been removed, leave the team
|
// XXX onReady, if you've been removed, leave the team
|
||||||
var removeUser = function (ctx, data, cId, cb) {
|
var removeUser = function (ctx, data, cId, cb) {
|
||||||
@ -584,7 +634,8 @@ define([
|
|||||||
pinPads: cfg.pinPads,
|
pinPads: cfg.pinPads,
|
||||||
emit: emit,
|
emit: emit,
|
||||||
onReadyHandlers: {},
|
onReadyHandlers: {},
|
||||||
teams: {}
|
teams: {},
|
||||||
|
updateMetadata: cfg.updateMetadata
|
||||||
};
|
};
|
||||||
|
|
||||||
var teams = store.proxy.teams = store.proxy.teams || {};
|
var teams = store.proxy.teams = store.proxy.teams || {};
|
||||||
@ -608,7 +659,8 @@ define([
|
|||||||
Object.keys(teams).forEach(function (id) {
|
Object.keys(teams).forEach(function (id) {
|
||||||
t[id] = {
|
t[id] = {
|
||||||
name: teams[id].metadata.name,
|
name: teams[id].metadata.name,
|
||||||
edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic'])
|
edPublic: Util.find(teams[id], ['keys', 'drive', 'edPublic']),
|
||||||
|
avatar: Util.find(teams[id], ['metadata', 'avatar'])
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return t;
|
return t;
|
||||||
@ -616,6 +668,22 @@ define([
|
|||||||
team.getTeams = function () {
|
team.getTeams = function () {
|
||||||
return Object.keys(ctx.teams);
|
return Object.keys(ctx.teams);
|
||||||
};
|
};
|
||||||
|
team.removeFromTeam = function (teamId, curve) {
|
||||||
|
if (!teams[teamId]) { return; }
|
||||||
|
if (ctx.onReadyHandlers[teamId]) {
|
||||||
|
ctx.onReadyHandlers[teamId].push({cb : function () {
|
||||||
|
ctx.teams[teamId].roster.remove([curve], function (err) {
|
||||||
|
if (err && err !== 'NO_CHANGE') { console.error(err); }
|
||||||
|
});
|
||||||
|
}});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!ctx.teams[teamId]) { return void console.error("TEAM MODULE ERROR"); }
|
||||||
|
ctx.teams[teamId].roster.remove([curve], function (err) {
|
||||||
|
if (err && err !== 'NO_CHANGE') { console.error(err); }
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
team.removeClient = function (clientId) {
|
team.removeClient = function (clientId) {
|
||||||
removeClient(ctx, clientId);
|
removeClient(ctx, clientId);
|
||||||
};
|
};
|
||||||
@ -644,6 +712,12 @@ define([
|
|||||||
if (cmd === 'DESCRIBE_USER') {
|
if (cmd === 'DESCRIBE_USER') {
|
||||||
return void describeUser(ctx, data, clientId, cb);
|
return void describeUser(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
if (cmd === 'INVITE_TO_TEAM') {
|
||||||
|
return void inviteToTeam(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
|
if (cmd === 'JOIN_TEAM') {
|
||||||
|
return void joinTeam(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
if (cmd === 'REMOVE_USER') {
|
if (cmd === 'REMOVE_USER') {
|
||||||
return void removeUser(ctx, data, clientId, cb);
|
return void removeUser(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -167,9 +167,11 @@ define([
|
|||||||
// Universal direct channel
|
// Universal direct channel
|
||||||
var modules = {};
|
var modules = {};
|
||||||
funcs.makeUniversal = function (type, cfg) {
|
funcs.makeUniversal = function (type, cfg) {
|
||||||
modules[type] = {
|
if (cfg && cfg.onEvent) {
|
||||||
onEvent: cfg.onEvent || function () {}
|
modules[type] = {
|
||||||
};
|
onEvent: cfg.onEvent || function () {}
|
||||||
|
};
|
||||||
|
}
|
||||||
var sframeChan = funcs.getSframeChannel();
|
var sframeChan = funcs.getSframeChannel();
|
||||||
return {
|
return {
|
||||||
execCommand: function (cmd, data, cb) {
|
execCommand: function (cmd, data, cb) {
|
||||||
|
|||||||
@ -397,7 +397,7 @@ define([
|
|||||||
var theirRole = ROLES.indexOf(data.role) || 0;
|
var theirRole = ROLES.indexOf(data.role) || 0;
|
||||||
// If they're a member and I have a higher role than them, I can promote them to admin
|
// If they're a member and I have a higher role than them, I can promote them to admin
|
||||||
if (!isMe && myRole > theirRole && theirRole === 0) {
|
if (!isMe && myRole > theirRole && theirRole === 0) {
|
||||||
var promote = h('fa.fa-angle-double-up', {
|
var promote = h('span.fa.fa-angle-double-up', {
|
||||||
title: 'Promote' // XXX
|
title: 'Promote' // XXX
|
||||||
});
|
});
|
||||||
$(promote).click(function () {
|
$(promote).click(function () {
|
||||||
@ -410,7 +410,7 @@ define([
|
|||||||
// If I'm not a member and I have an equal or higher role than them, I can demote them
|
// If I'm not a member and I have an equal or higher role than them, I can demote them
|
||||||
// (if they're not already a MEMBER)
|
// (if they're not already a MEMBER)
|
||||||
if (!isMe && myRole >= theirRole && theirRole > 0) {
|
if (!isMe && myRole >= theirRole && theirRole > 0) {
|
||||||
var demote = h('fa.fa-angle-double-down', {
|
var demote = h('span.fa.fa-angle-double-down', {
|
||||||
title: 'Demote' // XXX
|
title: 'Demote' // XXX
|
||||||
});
|
});
|
||||||
$(demote).click(function () {
|
$(demote).click(function () {
|
||||||
@ -422,7 +422,7 @@ define([
|
|||||||
}
|
}
|
||||||
// If I'm not a member and I have an equal or higher role than them, I can remove them
|
// If I'm not a member and I have an equal or higher role than them, I can remove them
|
||||||
if (!isMe && myRole > 0 && myRole >= theirRole) {
|
if (!isMe && myRole > 0 && myRole >= theirRole) {
|
||||||
var remove = h('fa.fa-times', {
|
var remove = h('span.fa.fa-times', {
|
||||||
title: 'Remove' // XXX
|
title: 'Remove' // XXX
|
||||||
});
|
});
|
||||||
$(remove).click(function () {
|
$(remove).click(function () {
|
||||||
@ -460,8 +460,8 @@ define([
|
|||||||
APP.refreshRoster = function (common, roster) {
|
APP.refreshRoster = function (common, roster) {
|
||||||
if (!roster || typeof(roster) !== "object" || Object.keys(roster) === 0) { return; }
|
if (!roster || typeof(roster) !== "object" || Object.keys(roster) === 0) { return; }
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
var privateData = metadataMgr.getPrivateData();
|
var userData = metadataMgr.getUserData();
|
||||||
var me = roster[privateData.curvePublic];
|
var me = roster[userData.curvePublic] || {};
|
||||||
var owner = Object.keys(roster).filter(function (k) {
|
var owner = Object.keys(roster).filter(function (k) {
|
||||||
return roster[k].role === "OWNER";
|
return roster[k].role === "OWNER";
|
||||||
}).map(function (k) {
|
}).map(function (k) {
|
||||||
@ -479,7 +479,35 @@ define([
|
|||||||
});
|
});
|
||||||
// XXX LEAVE the team button
|
// XXX LEAVE the team button
|
||||||
// XXX INVITE to the team button
|
// XXX INVITE to the team button
|
||||||
|
var header = h('div.cp-app-team-roster-header');
|
||||||
|
var $header = $(header);
|
||||||
|
|
||||||
|
// If you're an admin or an owner, you can invite your friends to the team
|
||||||
|
// TODO and acquaintances later?
|
||||||
|
if (me && (me.role === 'ADMIN' || me.role === 'OWNER')) {
|
||||||
|
var invite = h('button.btn.btn-primary', 'INVITE A FRIEND');
|
||||||
|
var inviteFriends = common.getFriends();
|
||||||
|
Object.keys(inviteFriends).forEach(function (curve) {
|
||||||
|
// Keep only friends that are not already in the team and that you can contact
|
||||||
|
// via their mailbox
|
||||||
|
if (roster[curve] && !roster[curve].pending) {
|
||||||
|
delete inviteFriends[curve];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var inviteCfg = {
|
||||||
|
teamId: APP.team,
|
||||||
|
common: common,
|
||||||
|
friends: inviteFriends,
|
||||||
|
module: APP.module
|
||||||
|
};
|
||||||
|
$(invite).click(function () {
|
||||||
|
UIElements.createInviteTeamModal(inviteCfg);
|
||||||
|
});
|
||||||
|
$header.append(invite);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
header,
|
||||||
h('h3', 'OWNER'), // XXX
|
h('h3', 'OWNER'), // XXX
|
||||||
h('div', owner),
|
h('div', owner),
|
||||||
h('h3', 'ADMINS'), // XXX
|
h('h3', 'ADMINS'), // XXX
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user