Merge branch 'staging' of github.com:xwiki-labs/cryptpad into staging

pull/1/head
ansuz 5 years ago
commit e5cb3250d8

@ -2,6 +2,7 @@
@import (reference) "./colortheme-all.less"; @import (reference) "./colortheme-all.less";
@import (reference) "./tools.less"; @import (reference) "./tools.less";
@import (reference) './icon-colors.less'; @import (reference) './icon-colors.less';
@import (reference) "./avatar.less";
.creation_vars( .creation_vars(
@color: @colortheme_default-color, @color: @colortheme_default-color,
@ -62,7 +63,7 @@
outline: none; outline: none;
width: 700px; width: 700px;
max-width: 90vw; max-width: 90vw;
height: 500px; height: 550px;
max-height: calc(~"100vh - 20px"); max-height: calc(~"100vh - 20px");
margin: 50px; margin: 50px;
flex-shrink: 0; flex-shrink: 0;
@ -175,15 +176,47 @@
color: @colortheme_form-color; color: @colortheme_form-color;
} }
.cp-creation-team { .cp-creation-teams {
.cp-dropdown-container { display: none !important;
.cp-creation-teams-grid {
display: flex;
flex-wrap: wrap;
padding: 0 2px;
flex: 1; flex: 1;
min-width: 0; }
margin-left: 10px; .cp-creation-team {
margin-right: 10px; .avatar_main(25px);
button, .cp-dropdown-content { width: 140px;
height: 35px;
display: flex;
justify-content: center;
align-items: center;
padding: 5px;
cursor: default;
font: @colortheme_app-font;
color: @colortheme_modal-fg;
margin: 0 1px;
.tools_unselectable();
&.cp-selected {
background-color: @colortheme_alertify-primary;
color: @colortheme_alertify-primary-text;
}
.cp-creation-team-avatar {
.fa {
font-size: 25px;
}
}
.cp-creation-team-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: 100%; width: 100%;
text-align: center;
line-height: 18px;
} }
border: 1px solid @colortheme_alertify-primary;
} }
} }

@ -16,6 +16,7 @@ define(function () {
tokenKey: 'loginToken', tokenKey: 'loginToken',
displayPadCreationScreen: 'displayPadCreationScreen', displayPadCreationScreen: 'displayPadCreationScreen',
deprecatedKey: 'deprecated', deprecatedKey: 'deprecated',
MAX_TEAMS_SLOTS: 3,
// Sub // Sub
plan: 'CryptPad_plan', plan: 'CryptPad_plan',
// Apps // Apps

@ -81,10 +81,13 @@ define([
}; };
Msg.updateMyData = function (store, curve) { Msg.updateMyData = function (store, curve) {
var myData = createData(store.proxy); var myData = createData(store.proxy, false);
if (store.proxy.friends) { if (store.proxy.friends) {
store.proxy.friends.me = myData; store.proxy.friends.me = myData;
} }
if (store.modules['team']) {
store.modules['team'].updateMyData(myData);
}
var todo = function (friend) { var todo = function (friend) {
if (!friend || !friend.notifications) { return; } if (!friend || !friend.notifications) { return; }
myData.channel = friend.channel; myData.channel = friend.channel;

@ -2881,57 +2881,49 @@ define([
// Team pad // Team pad
var team; var team;
var teamExists = privateData.teams && Object.keys(privateData.teams).length; var teamExists = privateData.teams && Object.keys(privateData.teams).length;
var $teamBlock; var teamValue;
// storeInTeam can be // storeInTeam can be
// * a team ID ==> store in the team drive, and the team will be the owner // * a team ID ==> store in the team drive, and the team will be the owner
// * -1 ==> store in the user drive, and the user will be the owner // * -1 ==> store in the user drive, and the user will be the owner
// * undefined ==> ask // * undefined ==> ask
if (teamExists && privateData.enableTeams) { if (teamExists && privateData.enableTeams) {
var teamOptions = Object.keys(privateData.teams).map(function (teamId) { var teams = Object.keys(privateData.teams).map(function (id) {
var t = privateData.teams[teamId]; var data = privateData.teams[id];
return { var avatar = h('span.cp-creation-team-avatar.cp-avatar');
tag: 'a', UIElements.displayAvatar(common, $(avatar), data.avatar, data.name);
attributes: { return h('div.cp-creation-team', {
'data-value': teamId, 'data-id': id,
'href': '#' title: data.name,
}, },[
content: Util.fixHTML(t.name) avatar,
}; h('span.cp-creation-team-name', data.name)
}); ]);
teamOptions.unshift({ });
tag: 'a', teams.unshift(h('div.cp-creation-team', {
attributes: { 'data-id': '-1',
'data-value': '-1', title: Messages.settings_cat_drive
'href': '#' }, [
}, h('span.cp-creation-team-avatar.fa.fa-hdd-o'),
content: Messages.settings_cat_drive h('span.cp-creation-team-name', Messages.settings_cat_drive)
}); ]));
teamOptions.unshift({ team = h('div.cp-creation-teams', [
tag: 'a',
attributes: {
'data-value': '',
'href': '#'
},
content: ' '
});
var teamDropdownConfig = {
text: " ", // Button initial text
options: teamOptions, // Entries displayed in the menu
isSelect: true,
common: common
};
$teamBlock = UIElements.createDropdown(teamDropdownConfig);
$teamBlock.find('a').click(function () {
var id = $(this).attr('data-value');
$teamBlock.setValue(id);
});
team = h('div.cp-creation-team', [
Messages.team_pcsSelectLabel, Messages.team_pcsSelectLabel,
$teamBlock[0], h('div.cp-creation-teams-grid', teams),
createHelper('#', Messages.team_pcsSelectHelp) createHelper('#', Messages.team_pcsSelectHelp)
]); ]);
var $team = $(team);
$team.find('.cp-creation-team').click(function () {
if ($(this).hasClass('cp-selected')) {
teamValue = undefined;
return void $(this).removeClass('cp-selected');
}
$team.find('.cp-creation-team').removeClass('cp-selected');
$(this).addClass('cp-selected');
teamValue = $(this).attr('data-id');
});
if (privateData.storeInTeam) { if (privateData.storeInTeam) {
$teamBlock.setValue(privateData.storeInTeam); $team.find('[data-id="'+privateData.storeInTeam+'"]').addClass('cp-selected');
teamValue = privateData.storeInTeam;
} }
} }
@ -3208,9 +3200,9 @@ define([
var templateId = $template.data('id') || undefined; var templateId = $template.data('id') || undefined;
// Team // Team
var team; var team;
if ($teamBlock && $teamBlock.getValue()) { if (teamValue) {
team = privateData.teams[$teamBlock.getValue()] || {}; team = privateData.teams[teamValue] || {};
team.id = Number($teamBlock.getValue()); team.id = Number(teamValue);
} }
return { return {
@ -3746,8 +3738,15 @@ define([
console.log(err); console.log(err);
}); });
}; };
var MAX_TEAMS_SLOTS = Constants.MAX_TEAMS_SLOTS;
var todo = function (yes) { var todo = function (yes) {
var priv = common.getMetadataMgr().getPrivateData();
var numberOfTeams = Object.keys(priv.teams || {}).length;
if (yes) { if (yes) {
if (numberOfTeams >= MAX_TEAMS_SLOTS) {
return void UI.alert(Messages._getKey('team_maxTeams', [MAX_TEAMS_SLOTS]));
}
// ACCEPT // ACCEPT
module.execCommand('JOIN_TEAM', { module.execCommand('JOIN_TEAM', {
team: msg.content.team team: msg.content.team

@ -321,7 +321,16 @@ define([
return void cb(true); return void cb(true);
} }
if (invitedTo[content.team.channel]) { return void cb(true); } var invited = invitedTo[content.team.channel];
if (invited) {
console.log('removing old invitation');
cb(false, invited);
invitedTo[content.team.channel] = {
type: box.type,
hash: data.hash
};
return;
}
var myTeams = Util.find(ctx, ['store', 'proxy', 'teams']) || {}; var myTeams = Util.find(ctx, ['store', 'proxy', 'teams']) || {};
var alreadyMember = Object.keys(myTeams).some(function (k) { var alreadyMember = Object.keys(myTeams).some(function (k) {
@ -330,7 +339,10 @@ define([
}); });
if (alreadyMember) { return void cb(true); } if (alreadyMember) { return void cb(true); }
invitedTo[content.team.channel] = true; invitedTo[content.team.channel] = {
type: box.type,
hash: data.hash
};
cb(false); cb(false);
}; };
@ -349,6 +361,10 @@ define([
return void cb(true); return void cb(true);
} }
if (invitedTo[content.teamChannel] && content.pending) {
return void cb(true, invitedTo[content.teamChannel]);
}
cb(false); cb(false);
}; };

@ -258,6 +258,11 @@ proxy.mailboxes = {
hash: hash hash: hash
}; };
Handlers.add(ctx, box, message, function (dismissed, toDismiss) { Handlers.add(ctx, box, message, function (dismissed, toDismiss) {
if (toDismiss) { // List of other messages to remove
dismiss(ctx, toDismiss, '', function () {
console.log('Notification handled automatically');
});
}
if (dismissed) { // This message should be removed if (dismissed) { // This message should be removed
dismiss(ctx, { dismiss(ctx, {
type: type, type: type,
@ -267,11 +272,6 @@ proxy.mailboxes = {
}); });
return; return;
} }
if (toDismiss) { // List of other messages to remove
dismiss(ctx, toDismiss, '', function () {
console.log('Notification handled automatically');
});
}
box.content[hash] = msg; box.content[hash] = msg;
showMessage(ctx, type, message, null, function (obj) { showMessage(ctx, type, message, null, function (obj) {
if (!box.ready) { return; } if (!box.ready) { return; }

@ -477,6 +477,7 @@ define([
sending: false, sending: false,
messages: [], messages: [],
clients: data.clients || [], clients: data.clients || [],
onUserlistUpdate: data.onUserlistUpdate || function () {},
mapId: {}, mapId: {},
}; };
@ -584,10 +585,32 @@ define([
}); });
}; };
var getOnlineList = function (ctx, chanId) {
var channel = ctx.channels[chanId];
if (!channel) { return; }
var online = []; // Store online members to avoid duplicates
// Add ourselves
var myData = createData(ctx.store.proxy, false);
online.push(myData.curvePublic);
channel.wc.members.forEach(function (nId) {
if (nId === ctx.store.network.historyKeeper) { return; }
var data = channel.mapId[nId] || {};
if (!data.curvePublic) { return; }
if (online.indexOf(data.curvePublic) !== -1) { return; }
online.push(data.curvePublic);
});
return online;
};
// Display green status if one member is not me // Display green status if one member is not me
var getStatus = function (ctx, chanId, cb) { var getStatus = function (ctx, chanId, cb) {
var channel = ctx.channels[chanId]; var channel = ctx.channels[chanId];
if (!channel) { return void cb('NO_SUCH_CHANNEL'); } if (!channel) { return void cb('NO_SUCH_CHANNEL'); }
if (channel.onUserlistUpdate) {
channel.onUserlistUpdate();
}
var proxy = ctx.store.proxy; var proxy = ctx.store.proxy;
var online = channel.wc.members.some(function (nId) { var online = channel.wc.members.some(function (nId) {
if (nId === ctx.store.network.historyKeeper) { return; } if (nId === ctx.store.network.historyKeeper) { return; }
@ -781,7 +804,7 @@ define([
openChannel(ctx, chanData); openChannel(ctx, chanData);
}; };
var openTeamChat = function (ctx, clientId, data, _cb) { var openTeamChat = function (ctx, clientId, data, onUpdate, _cb) {
var chatData = data; var chatData = data;
var chanId = chatData.channel; var chanId = chatData.channel;
var secret = chatData.secret; var secret = chatData.secret;
@ -820,6 +843,7 @@ define([
return encryptor.decrypt(msg, vKey); return encryptor.decrypt(msg, vKey);
}, },
clients: [clientId], clients: [clientId],
onUserlistUpdate: onUpdate,
onReady: cb onReady: cb
}; };
openChannel(ctx, chanData); openChannel(ctx, chanData);
@ -927,6 +951,10 @@ define([
onFriendRemoved(ctx, curvePublic, chanId); onFriendRemoved(ctx, curvePublic, chanId);
}; };
messenger.getOnlineList = function (chanId) {
return getOnlineList(ctx, chanId);
};
messenger.storeValidateKey = function (chan, key) { messenger.storeValidateKey = function (chan, key) {
ctx.validateKeys[chan] = key; ctx.validateKeys[chan] = key;
}; };
@ -945,8 +973,8 @@ define([
}); });
}; };
messenger.openTeamChat = function (data, cId, cb) { messenger.openTeamChat = function (data, onUpdate, cId, cb) {
openTeamChat(ctx, cId, data, cb); openTeamChat(ctx, cId, data, onUpdate, cb);
}; };
messenger.removeClient = function (clientId) { messenger.removeClient = function (clientId) {
@ -964,9 +992,6 @@ define([
if (cmd === 'GET_USERLIST') { if (cmd === 'GET_USERLIST') {
return void getUserList(ctx, data, cb); return void getUserList(ctx, data, cb);
} }
if (cmd === 'OPEN_TEAM_CHAT') {
return void openTeamChat(ctx, clientId, data, cb);
}
if (cmd === 'OPEN_PAD_CHAT') { if (cmd === 'OPEN_PAD_CHAT') {
return void openPadChat(ctx, clientId, data, cb); return void openPadChat(ctx, clientId, data, cb);
} }

@ -544,7 +544,18 @@ define([
if (!team) { return void cb ({error: 'ENOENT'}); } if (!team) { return void cb ({error: 'ENOENT'}); }
if (!team.roster) { return void cb({error: 'NO_ROSTER'}); } if (!team.roster) { return void cb({error: 'NO_ROSTER'}); }
var state = team.roster.getState() || {}; var state = team.roster.getState() || {};
cb(state.members || {}); var members = state.members || {};
// Add online status (using messenger data)
var chatData = team.getChatData();
var online = ctx.store.messenger.getOnlineList(chatData.channel) || [];
online.forEach(function (curve) {
if (members[curve]) {
members[curve].online = true;
}
});
cb(members);
}; };
var getTeamMetadata = function (ctx, data, cId, cb) { var getTeamMetadata = function (ctx, data, cId, cb) {
@ -635,13 +646,12 @@ define([
var state = team.roster.getState(); var state = team.roster.getState();
var userData = state.members[data.curvePublic]; var userData = state.members[data.curvePublic];
console.error(userData);
team.roster.remove([data.curvePublic], function (err) { team.roster.remove([data.curvePublic], function (err) {
if (err) { return void cb({error: err}); } if (err) { return void cb({error: err}); }
// The user has been removed, send them a notification // The user has been removed, send them a notification
if (!userData || !userData.notifications) { return cb(); } if (!userData || !userData.notifications) { return cb(); }
console.log('send notif');
ctx.store.mailbox.sendTo('KICKED_FROM_TEAM', { ctx.store.mailbox.sendTo('KICKED_FROM_TEAM', {
pending: data.pending,
user: Messaging.createData(ctx.store.proxy, false), user: Messaging.createData(ctx.store.proxy, false),
teamChannel: getInviteData(ctx, teamId).channel, teamChannel: getInviteData(ctx, teamId).channel,
teamName: getInviteData(ctx, teamId).metadata.name teamName: getInviteData(ctx, teamId).metadata.name
@ -711,7 +721,10 @@ define([
var openTeamChat = function (ctx, data, cId, cb) { var openTeamChat = function (ctx, data, cId, cb) {
var team = ctx.teams[data.teamId]; var team = ctx.teams[data.teamId];
if (!team) { return void cb({error: 'ENOENT'}); } if (!team) { return void cb({error: 'ENOENT'}); }
ctx.store.messenger.openTeamChat(team.getChatData(), cId, cb); var onUpdate = function () {
ctx.emit('ROSTER_CHANGE', data.teamId, team.clients);
};
ctx.store.messenger.openTeamChat(team.getChatData(), onUpdate, cId, cb);
}; };
Team.init = function (cfg, waitFor, emit) { Team.init = function (cfg, waitFor, emit) {
@ -748,6 +761,7 @@ define([
var t = {}; var t = {};
Object.keys(teams).forEach(function (id) { Object.keys(teams).forEach(function (id) {
t[id] = { t[id] = {
owner: teams[id].owner,
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']) avatar: Util.find(teams[id], ['metadata', 'avatar'])
@ -775,6 +789,17 @@ define([
}); });
}; };
team.updateMyData = function (data) {
Object.keys(ctx.teams).forEach(function (id) {
var team = ctx.teams[id];
if (!team.roster) { return; }
var obj = {};
obj[data.curvePublic] = data;
team.roster.describe(obj, function (err) {
if (err) { console.error(err); }
});
});
};
team.removeClient = function (clientId) { team.removeClient = function (clientId) {
removeClient(ctx, clientId); removeClient(ctx, clientId);
}; };

@ -821,7 +821,9 @@ define([
UI.errorLoadingScreen(errorText); UI.errorLoadingScreen(errorText);
throw new Error(errorText); throw new Error(errorText);
} }
} else { }
if (!proxy.metadata || typeof(proxy.metadata.title) === "undefined") {
console.error("UPDATE TITLE");
Title.updateTitle(Title.defaultTitle); Title.updateTitle(Title.defaultTitle);
} }

@ -19,6 +19,16 @@
@roster-bg-color: #efefef; @roster-bg-color: #efefef;
#cp-sidebarlayout-container { #cp-sidebarlayout-container {
@media screen and (max-width: 900px) {
.cp-app-drive-toolbar-leftside {
.cp-dropdown-button-title span:last-child {
display: none;
}
.cp-toolbar-share-button span:last-child {
display: none;
}
}
}
div#cp-sidebarlayout-rightside.cp-rightside-drive { div#cp-sidebarlayout-rightside.cp-rightside-drive {
padding: 0; padding: 0;
& > .cp-team-chat { & > .cp-team-chat {
@ -39,8 +49,46 @@
} }
} }
.cp-team-list-avatar { .cp-team-list {
.avatar_main(30px); .cp-team-list-container {
display: flex;
align-items: center;
justify-content: space-evenly;
flex-wrap: wrap;
}
.cp-team-list-team {
.tools_unselectable();
background-color: @roster-bg-color;
display: flex;
align-items: center;
flex-flow: column;
width: 300px;
max-width: 90%;
height: 400px;
padding: 20px;
margin: 5px;
.cp-team-list-avatar {
.avatar_main(200px);
}
.cp-team-list-name {
flex: 1;
min-width: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width: 500px;
font-size: 25px;
display: inline-flex;
align-items: center;
&.empty {
white-space: initial;
text-align: center;
}
}
.cp-team-list-open {
width: 100%;
}
}
} }
.cp-team-avatar { .cp-team-avatar {
.avatar_main(300px); .avatar_main(300px);
@ -60,6 +108,16 @@
.cp-avatar { .cp-avatar {
margin-right: 10px; margin-right: 10px;
} }
.cp-team-member-status {
margin-left: 5px;
width: 5px;
height: 50px;
display: inline-block;
background-color: red;
&.online {
background-color: green;
}
}
.cp-team-member-name { .cp-team-member-name {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;

@ -6,6 +6,7 @@ define([
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-ui-elements.js', '/common/common-ui-elements.js',
'/common/common-feedback.js', '/common/common-feedback.js',
'/common/common-constants.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/common/sframe-common.js', '/common/sframe-common.js',
'/common/proxy-manager.js', '/common/proxy-manager.js',
@ -25,6 +26,7 @@ define([
UI, UI,
UIElements, UIElements,
Feedback, Feedback,
Constants,
nThen, nThen,
SFCommon, SFCommon,
ProxyManager, ProxyManager,
@ -177,6 +179,8 @@ define([
}); });
if (active === 'drive') { if (active === 'drive') {
APP.$rightside.addClass('cp-rightside-drive'); APP.$rightside.addClass('cp-rightside-drive');
} else {
APP.$rightside.removeClass('cp-rightside-drive');
} }
showCategories(categories[active]); showCategories(categories[active]);
}; };
@ -264,25 +268,44 @@ define([
]); ]);
}); });
var MAX_TEAMS_SLOTS = Constants.MAX_TEAMS_SLOTS;
var refreshList = function (common, cb) { var refreshList = function (common, cb) {
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
var content = []; var content = [];
content.push(h('h3', 'Your teams'));
APP.module.execCommand('LIST_TEAMS', null, function (obj) { APP.module.execCommand('LIST_TEAMS', null, function (obj) {
if (!obj) { return; } if (!obj) { return; }
if (obj.error) { return void console.error(obj.error); } if (obj.error) { return void console.error(obj.error); }
var lis = []; var list = [];
Object.keys(obj).forEach(function (id) { var keys = Object.keys(obj).slice(0,3);
var slots = '('+Math.min(keys.length, MAX_TEAMS_SLOTS)+'/'+MAX_TEAMS_SLOTS+')';
for (var i = keys.length; i < MAX_TEAMS_SLOTS; i++) {
obj[i] = {
empty: true
};
keys.push(i);
}
content.push(h('h3', Messages.team_listTitle + ' ' + slots));
keys.forEach(function (id) {
var team = obj[id]; var team = obj[id];
var a = h('a', Messages.team_listLoad); if (team.empty) {
var avatar = h('span.cp-avatar.cp-team-list-avatar'); list.push(h('div.cp-team-list-team.empty', [
lis.push(h('li', h('ul', [ // XXX UI h('span.cp-team-list-name.empty', Messages.team_listSlot)
h('li', avatar), ]));
h('li', team.metadata.name), return;
h('li', a) }
]))); var btn;
var avatar = h('span.cp-avatar');
list.push(h('div.cp-team-list-team', [
h('span.cp-team-list-avatar', avatar),
h('span.cp-team-list-name', {
title: team.metadata.name
}, team.metadata.name),
btn = h('button.cp-team-list-open.btn.btn-primary', Messages.team_listLoad)
]));
common.displayAvatar($(avatar), team.metadata.avatar, team.metadata.name); common.displayAvatar($(avatar), team.metadata.avatar, team.metadata.name);
$(a).click(function () { $(btn).click(function () {
APP.module.execCommand('SUBSCRIBE', id, function () { APP.module.execCommand('SUBSCRIBE', id, function () {
sframeChan.query('Q_SET_TEAM', id, function (err) { sframeChan.query('Q_SET_TEAM', id, function (err) {
if (err) { return void console.error(err); } if (err) { return void console.error(err); }
@ -293,7 +316,7 @@ define([
}); });
}); });
}); });
content.push(h('ul', lis)); content.push(h('div.cp-team-list-container', list));
cb(content); cb(content);
}); });
return content; return content;
@ -303,7 +326,20 @@ define([
}); });
makeBlock('create', function (common, cb) { makeBlock('create', function (common, cb) {
var metadataMgr = common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
var content = []; var content = [];
var isOwner = Object.keys(privateData.teams || {}).some(function (id) {
return privateData.teams[id].owner;
});
if (Object.keys(privateData.teams || {}).length >= 3 || isOwner) {
content.push(h('div.alert.alert-warning', {
role:'alert'
}, isOwner ? Messages.team_maxOwner : Messages._getKey('team_maxTeams', [MAX_TEAMS_SLOTS])));
return void cb(content);
}
content.push(h('h3', Messages.team_createLabel)); content.push(h('h3', Messages.team_createLabel));
content.push(h('label', Messages.team_createName)); content.push(h('label', Messages.team_createName));
var input = h('input', {type:'text'}); var input = h('input', {type:'text'});
@ -393,6 +429,8 @@ define([
common.displayAvatar($(avatar), data.avatar, data.displayName); common.displayAvatar($(avatar), data.avatar, data.displayName);
// Name // Name
var name = h('span.cp-team-member-name', data.displayName); var name = h('span.cp-team-member-name', data.displayName);
// Status
var status = h('span.cp-team-member-status'+(data.online ? '.online' : ''));
// Actions // Actions
var actions = h('span.cp-team-member-actions'); var actions = h('span.cp-team-member-actions');
var $actions = $(actions); var $actions = $(actions);
@ -400,7 +438,7 @@ define([
var myRole = me ? (ROLES.indexOf(me.role) || 0) : -1; var myRole = me ? (ROLES.indexOf(me.role) || 0) : -1;
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 && !data.pending) {
var promote = h('span.fa.fa-angle-double-up', { var promote = h('span.fa.fa-angle-double-up', {
title: Messages.team_rosterPromote title: Messages.team_rosterPromote
}); });
@ -413,7 +451,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 && !data.pending) {
var demote = h('span.fa.fa-angle-double-down', { var demote = h('span.fa.fa-angle-double-down', {
title: Messages.team_rosterDemote title: Messages.team_rosterDemote
}); });
@ -432,6 +470,7 @@ define([
$(remove).click(function () { $(remove).click(function () {
$(remove).hide(); $(remove).hide();
APP.module.execCommand('REMOVE_USER', { APP.module.execCommand('REMOVE_USER', {
pending: data.pending,
teamId: APP.team, teamId: APP.team,
curvePublic: data.curvePublic, curvePublic: data.curvePublic,
}, function (obj) { }, function (obj) {
@ -449,7 +488,8 @@ define([
var content = [ var content = [
avatar, avatar,
name, name,
actions actions,
status,
]; ];
var div = h('div.cp-team-roster-member', { var div = h('div.cp-team-roster-member', {
title: data.displayName title: data.displayName
@ -486,6 +526,12 @@ define([
}).map(function (k) { }).map(function (k) {
return makeMember(common, roster[k], me); return makeMember(common, roster[k], me);
}); });
var pending = Object.keys(roster).filter(function (k) {
if (!roster[k].pending) { return; }
return roster[k].role === "MEMBER" || !roster[k].role;
}).map(function (k) {
return makeMember(common, roster[k], me);
});
var header = h('div.cp-app-team-roster-header'); var header = h('div.cp-app-team-roster-header');
var $header = $(header); var $header = $(header);
@ -538,7 +584,9 @@ define([
h('h3', Messages.team_admins), h('h3', Messages.team_admins),
h('div', admins), h('div', admins),
h('h3', Messages.team_members), h('h3', Messages.team_members),
h('div', members) h('div', members),
h('h3', Messages.team_pending || 'PENDING'), // XXX
h('div', pending)
]; ];
}; };
makeBlock('roster', function (common, cb) { makeBlock('roster', function (common, cb) {
@ -576,6 +624,7 @@ define([
var todo = function () { var todo = function () {
var newName = $input.val(); var newName = $input.val();
if (!newName.trim()) { return; }
$spinner.show(); $spinner.show();
APP.module.execCommand('GET_TEAM_METADATA', { APP.module.execCommand('GET_TEAM_METADATA', {
teamId: APP.team teamId: APP.team

Loading…
Cancel
Save