Update team name and add an avatar to the team
parent
bd8df41fde
commit
1b9a8828e9
|
@ -14,7 +14,9 @@ define([
|
|||
'/customize/application_config.js',
|
||||
'/customize/pages.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
'css!/customize/fonts/cptools/style.css'
|
||||
'css!/customize/fonts/cptools/style.css',
|
||||
'/bower_components/croppie/croppie.min.js',
|
||||
'css!/bower_components/croppie/croppie.css',
|
||||
], function ($, Config, Util, Hash, Language, UI, Constants, Feedback, h, MediaTag, Clipboard,
|
||||
Messages, AppConfig, Pages, NThen) {
|
||||
var UIElements = {};
|
||||
|
@ -1937,6 +1939,84 @@ define([
|
|||
});
|
||||
}
|
||||
};
|
||||
var transformAvatar = function (file, cb) {
|
||||
if (file.type === 'image/gif') { return void cb(file); }
|
||||
var $croppie = $('<div>', {
|
||||
'class': 'cp-app-profile-resizer'
|
||||
});
|
||||
|
||||
if (typeof ($croppie.croppie) !== "function") {
|
||||
console.warn('fuck');
|
||||
return void cb(file);
|
||||
}
|
||||
|
||||
var todo = function () {
|
||||
UI.confirm($croppie[0], function (yes) {
|
||||
if (!yes) { return; }
|
||||
$croppie.croppie('result', {
|
||||
type: 'blob',
|
||||
size: {width: 300, height: 300}
|
||||
}).then(function(blob) {
|
||||
blob.lastModifiedDate = new Date();
|
||||
blob.name = 'avatar';
|
||||
cb(blob);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
$croppie.croppie({
|
||||
url: e.target.result,
|
||||
viewport: { width: 100, height: 100 },
|
||||
boundary: { width: 400, height: 300 },
|
||||
});
|
||||
todo();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
UIElements.addAvatar = function (common, cb) {
|
||||
var AVATAR_SIZE_LIMIT = 0.5;
|
||||
var allowedMediaTypes = [
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'image/jpg',
|
||||
'image/gif',
|
||||
];
|
||||
var fmConfig = {
|
||||
noHandlers: true,
|
||||
noStore: true,
|
||||
body: $('body'),
|
||||
onUploaded: cb
|
||||
};
|
||||
var FM = common.createFileManager(fmConfig);
|
||||
var accepted = ".gif,.jpg,.jpeg,.png";
|
||||
var data = {
|
||||
FM: FM,
|
||||
filter: function (file) {
|
||||
var sizeMB = Util.bytesToMegabytes(file.size);
|
||||
var type = file.type;
|
||||
// We can't resize .gif so we have to display an error if it is too big
|
||||
if (sizeMB > AVATAR_SIZE_LIMIT && type === 'image/gif') {
|
||||
UI.log(Messages._getKey('profile_uploadSizeError', [
|
||||
Messages._getKey('formattedMB', [AVATAR_SIZE_LIMIT])
|
||||
]));
|
||||
return false;
|
||||
}
|
||||
// Display an error if the image type is not allowed
|
||||
if (allowedMediaTypes.indexOf(type) === -1) {
|
||||
UI.log(Messages._getKey('profile_uploadTypeError', [
|
||||
accepted.split(',').join(', ')
|
||||
]));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
transformer: transformAvatar,
|
||||
accept: accepted
|
||||
};
|
||||
return data;
|
||||
};
|
||||
|
||||
/* Create a usage bar which keeps track of how much storage space is used
|
||||
by your CryptDrive. The getPinnedUsage RPC is one of the heavier calls,
|
||||
|
|
|
@ -132,6 +132,7 @@ define([
|
|||
realtime: lm.realtime,
|
||||
handleSharedFolder: function (sfId, rt) { handleSharedFolder(ctx, id, sfId, rt); },
|
||||
sharedFolders: {}, // equivalent of store.sharedFolders in async-store
|
||||
roster: roster
|
||||
};
|
||||
|
||||
if (cId) { team.clients.push(cId); }
|
||||
|
@ -447,6 +448,32 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
var getTeamMetadata = 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 state = team.roster.getState() || {};
|
||||
cb(state.metadata || {});
|
||||
};
|
||||
|
||||
var setTeamMetadata = 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'}); }
|
||||
team.roster.metadata(data.metadata, function (err) {
|
||||
if (err) { return void cb({error: err}); }
|
||||
var localTeam = ctx.store.proxy.teams[teamId];
|
||||
if (localTeam) {
|
||||
localTeam.metadata = data.metadata
|
||||
}
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
// Remove a client from all the team they're subscribed to
|
||||
var removeClient = function (ctx, cId) {
|
||||
Object.keys(ctx.onReadyHandlers).forEach(function (teamId) {
|
||||
|
@ -565,6 +592,12 @@ define([
|
|||
if (cmd === 'OPEN_TEAM_CHAT') {
|
||||
return void openTeamChat(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'GET_TEAM_METADATA') {
|
||||
return void getTeamMetadata(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'SET_TEAM_METADATA') {
|
||||
return void setTeamMetadata(ctx, data, clientId, cb);
|
||||
}
|
||||
if (cmd === 'CREATE_TEAM') {
|
||||
return void createTeam(ctx, data, clientId, cb);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,6 @@ define([
|
|||
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
'less!/profile/app-profile.less',
|
||||
'/bower_components/croppie/croppie.min.js',
|
||||
'css!/bower_components/croppie/croppie.css',
|
||||
], function (
|
||||
$,
|
||||
Crypto,
|
||||
|
@ -233,48 +231,6 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
var AVATAR_SIZE_LIMIT = 0.5;
|
||||
var allowedMediaTypes = [
|
||||
'image/png',
|
||||
'image/jpeg',
|
||||
'image/jpg',
|
||||
'image/gif',
|
||||
];
|
||||
var transformAvatar = function (file, cb) {
|
||||
if (file.type === 'image/gif') { return void cb(file); }
|
||||
var $croppie = $('<div>', {
|
||||
'class': 'cp-app-profile-resizer'
|
||||
});
|
||||
|
||||
if (typeof ($croppie.croppie) !== "function") {
|
||||
return void cb(file);
|
||||
}
|
||||
|
||||
var todo = function () {
|
||||
UI.confirm($croppie[0], function (yes) {
|
||||
if (!yes) { return; }
|
||||
$croppie.croppie('result', {
|
||||
type: 'blob',
|
||||
size: {width: 300, height: 300}
|
||||
}).then(function(blob) {
|
||||
blob.lastModifiedDate = new Date();
|
||||
blob.name = 'avatar';
|
||||
cb(blob);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
$croppie.croppie({
|
||||
url: e.target.result,
|
||||
viewport: { width: 100, height: 100 },
|
||||
boundary: { width: 400, height: 300 },
|
||||
});
|
||||
todo();
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
};
|
||||
var displayAvatar = function (val) {
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var $span = APP.$avatar;
|
||||
|
@ -316,59 +272,28 @@ define([
|
|||
displayAvatar();
|
||||
if (APP.readOnly) { return; }
|
||||
|
||||
var fmConfig = {
|
||||
noHandlers: true,
|
||||
noStore: true,
|
||||
body: $('body'),
|
||||
onUploaded: function (ev, data) {
|
||||
var old = common.getMetadataMgr().getUserData().avatar;
|
||||
var todo = function () {
|
||||
APP.module.execCommand("SET", {
|
||||
key: 'avatar',
|
||||
value: data.url
|
||||
}, function () {
|
||||
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
|
||||
if (err || err2) { return void UI.log(err || err2); }
|
||||
displayAvatar(data.url);
|
||||
});
|
||||
});
|
||||
};
|
||||
if (old) {
|
||||
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
||||
var data = UIElements.addAvatar(common, function (ev, data) {
|
||||
var old = common.getMetadataMgr().getUserData().avatar;
|
||||
var todo = function () {
|
||||
APP.module.execCommand("SET", {
|
||||
key: 'avatar',
|
||||
value: data.url
|
||||
}, function () {
|
||||
sframeChan.query("Q_PROFILE_AVATAR_ADD", data.url, function (err, err2) {
|
||||
if (err || err2) { return void UI.log(err || err2); }
|
||||
todo();
|
||||
displayAvatar(data.url);
|
||||
});
|
||||
return;
|
||||
}
|
||||
todo();
|
||||
});
|
||||
};
|
||||
if (old) {
|
||||
sframeChan.query("Q_PROFILE_AVATAR_REMOVE", old, function (err, err2) {
|
||||
if (err || err2) { return void UI.log(err || err2); }
|
||||
todo();
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
APP.FM = common.createFileManager(fmConfig);
|
||||
var accepted = ".gif,.jpg,.jpeg,.png";
|
||||
var data = {
|
||||
FM: APP.FM,
|
||||
filter: function (file) {
|
||||
var sizeMB = Util.bytesToMegabytes(file.size);
|
||||
var type = file.type;
|
||||
// We can't resize .gif so we have to display an error if it is too big
|
||||
if (sizeMB > AVATAR_SIZE_LIMIT && type === 'image/gif') {
|
||||
UI.log(Messages._getKey('profile_uploadSizeError', [
|
||||
Messages._getKey('formattedMB', [AVATAR_SIZE_LIMIT])
|
||||
]));
|
||||
return false;
|
||||
}
|
||||
// Display an error if the image type is not allowed
|
||||
if (allowedMediaTypes.indexOf(type) === -1) {
|
||||
UI.log(Messages._getKey('profile_uploadTypeError', [
|
||||
accepted.split(',').join(', ')
|
||||
]));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
transformer: transformAvatar,
|
||||
accept: accepted
|
||||
};
|
||||
todo();
|
||||
});
|
||||
var $upButton = common.createButton('upload', false, data);
|
||||
$upButton.text(Messages.profile_upload);
|
||||
$upButton.prepend($('<span>', {'class': 'fa fa-upload'}));
|
||||
|
|
|
@ -34,6 +34,13 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cp-team-list-avatar {
|
||||
.avatar_main(30px);
|
||||
}
|
||||
.cp-team-avatar {
|
||||
.avatar_main(300px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ define([
|
|||
'/common/drive-ui.js',
|
||||
'/common/common-util.js',
|
||||
'/common/common-interface.js',
|
||||
'/common/common-ui-elements.js',
|
||||
'/common/common-feedback.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
'/common/sframe-common.js',
|
||||
|
@ -22,6 +23,7 @@ define([
|
|||
DriveUI,
|
||||
Util,
|
||||
UI,
|
||||
UIElements,
|
||||
Feedback,
|
||||
nThen,
|
||||
SFCommon,
|
||||
|
@ -109,6 +111,10 @@ define([
|
|||
'chat': [
|
||||
'cp-team-chat'
|
||||
],
|
||||
'admin': [
|
||||
'cp-team-name',
|
||||
'cp-team-avatar'
|
||||
],
|
||||
};
|
||||
|
||||
var create = {};
|
||||
|
@ -124,7 +130,7 @@ define([
|
|||
APP.$rightside.find('.'+c).show();
|
||||
});
|
||||
};
|
||||
var createLeftSide = APP.createLeftSide = function (common, team) {
|
||||
var createLeftSide = APP.createLeftSide = function (common, team, teamAdmin) {
|
||||
APP.$leftside.empty();
|
||||
var $categories = $('<div>', {'class': 'cp-sidebarlayout-categories'})
|
||||
.appendTo(APP.$leftside);
|
||||
|
@ -133,6 +139,8 @@ define([
|
|||
var active = team ? 'drive' : 'list';
|
||||
|
||||
Object.keys(categories).forEach(function (key) {
|
||||
if (key === 'admin' && !teamAdmin) { return; }
|
||||
|
||||
var $category = $('<div>', {'class': 'cp-sidebarlayout-category cp-team-cat-'+key}).appendTo($categories);
|
||||
if (key === 'general') { $category.append($('<span>', {'class': 'fa fa-info-circle'})); }
|
||||
if (key === 'list') { $category.append($('<span>', {'class': 'fa fa-list cp-team-cat-list'})); }
|
||||
|
@ -141,6 +149,7 @@ define([
|
|||
if (key === 'members') { $category.append($('<span>', {'class': 'fa fa-users'})); }
|
||||
if (key === 'chat') { $category.append($('<span>', {'class': 'fa fa-comments'})); }
|
||||
if (key === 'drive') { $category.append($('<span>', {'class': 'fa fa-hdd-o'})); }
|
||||
if (key === 'admin') { $category.append($('<span>', {'class': 'fa fa-cogs'})); }
|
||||
|
||||
if (key === active) {
|
||||
$category.addClass('cp-leftside-active');
|
||||
|
@ -172,7 +181,7 @@ define([
|
|||
showCategories(categories[active]);
|
||||
};
|
||||
|
||||
var buildUI = APP.buildUI = function (common, team) {
|
||||
var buildUI = APP.buildUI = function (common, team, teamAdmin) {
|
||||
var $rightside = APP.$rightside;
|
||||
$rightside.empty();
|
||||
var addItem = function (cssClass) {
|
||||
|
@ -187,7 +196,7 @@ define([
|
|||
categories[cat].forEach(addItem);
|
||||
}
|
||||
|
||||
createLeftSide(common, team);
|
||||
createLeftSide(common, team, teamAdmin);
|
||||
};
|
||||
|
||||
// Team APP
|
||||
|
@ -226,9 +235,16 @@ define([
|
|||
|
||||
// Rightside elements
|
||||
|
||||
var makeBlock = function (key, getter) {
|
||||
var makeBlock = function (key, getter, full) {
|
||||
var safeKey = key.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
||||
|
||||
create[key] = function (common) {
|
||||
var $div = $('<div>', {'class': 'cp-team-' + key + ' cp-sidebarlayout-element'});
|
||||
if (full) {
|
||||
$('<label>').text(Messages['team_'+safeKey+'Title'] || key).appendTo($div);
|
||||
$('<span>', {'class': 'cp-sidebarlayout-description'})
|
||||
.text(Messages['team_'+safeKey+'Hint'] || 'Coming soon...').appendTo($div);
|
||||
}
|
||||
getter(common, function (content) {
|
||||
$div.append(content);
|
||||
}, $div);
|
||||
|
@ -254,18 +270,21 @@ define([
|
|||
Object.keys(obj).forEach(function (id) {
|
||||
var team = obj[id];
|
||||
var a = h('a', 'Open');
|
||||
var avatar = h('span.cp-avatar.cp-team-list-avatar');
|
||||
lis.push(h('li', h('ul', [
|
||||
h('li', avatar), // XXX
|
||||
h('li', 'Name: ' + team.metadata.name), // XXX
|
||||
h('li', 'ID: ' + id), // XXX
|
||||
h('li', a) // XXX
|
||||
])));
|
||||
common.displayAvatar($(avatar), team.metadata.avatar, team.metadata.name);
|
||||
$(a).click(function () {
|
||||
APP.module.execCommand('SUBSCRIBE', id, function () {
|
||||
sframeChan.query('Q_SET_TEAM', id, function (err) {
|
||||
if (err) { return void console.error(err); }
|
||||
APP.team = id;
|
||||
APP.teamEdPublic = Util.find(team, ['keys', 'drive', 'edPublic']);
|
||||
buildUI(common, true);
|
||||
buildUI(common, true, team.owner);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -350,6 +369,105 @@ define([
|
|||
});
|
||||
});
|
||||
|
||||
makeBlock('name', function (common, cb) {
|
||||
var $inputBlock = $('<div>', {'class': 'cp-sidebarlayout-input-block'});
|
||||
var $input = $('<input>', {
|
||||
'type': 'text',
|
||||
'id': 'cp-settings-displayname',
|
||||
'placeholder': Messages.anonymous}).appendTo($inputBlock);
|
||||
var $save = $('<button>', {'class': 'btn btn-primary'}).text(Messages.settings_save).appendTo($inputBlock);
|
||||
|
||||
var $ok = $('<span>', {'class': 'fa fa-check', title: Messages.saved}).hide();
|
||||
var $spinner = $('<span>', {'class': 'fa fa-spinner fa-pulse'}).hide();
|
||||
|
||||
var md;
|
||||
|
||||
var todo = function () {
|
||||
var newName = $input.val();
|
||||
if (newName === md.name) { return; }
|
||||
md.name = newName;
|
||||
$spinner.show();
|
||||
APP.module.execCommand('SET_TEAM_METADATA', {
|
||||
teamId: APP.team,
|
||||
metadata: md
|
||||
}, function () {
|
||||
$spinner.hide();
|
||||
$ok.show();
|
||||
});
|
||||
};
|
||||
|
||||
APP.module.execCommand('GET_TEAM_METADATA', {
|
||||
teamId: APP.team
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
md = obj;
|
||||
$input.val(obj.name);
|
||||
$input.on('keyup', function (e) {
|
||||
if ($input.val() !== obj.name) { $ok.hide(); }
|
||||
if (e.which === 13) { todo(); }
|
||||
});
|
||||
$save.click(todo);
|
||||
var content = [
|
||||
$inputBlock[0],
|
||||
$ok[0],
|
||||
$spinner[0]
|
||||
];
|
||||
cb(content);
|
||||
});
|
||||
}, true);
|
||||
|
||||
makeBlock('avatar', function (common, cb) {
|
||||
// Upload
|
||||
var avatar = h('div.cp-team-avatar.cp-avatar');
|
||||
var $avatar = $(avatar);
|
||||
var md;
|
||||
var data = UIElements.addAvatar(common, function (ev, data) {
|
||||
if (!data.url) { return void UI.warn(Messages.error); }
|
||||
md.avatar = data.url;
|
||||
APP.module.execCommand('SET_TEAM_METADATA', {
|
||||
teamId: APP.team,
|
||||
metadata: md
|
||||
}, function () {
|
||||
$avatar.empty();
|
||||
common.displayAvatar($avatar, data.url);
|
||||
});
|
||||
});
|
||||
var $upButton = common.createButton('upload', false, data);
|
||||
$upButton.text(Messages.profile_upload);
|
||||
$upButton.prepend($('<span>', {'class': 'fa fa-upload'}));
|
||||
|
||||
APP.module.execCommand('GET_TEAM_METADATA', {
|
||||
teamId: APP.team
|
||||
}, function (obj) {
|
||||
if (obj && obj.error) {
|
||||
return void UI.warn(Messages.error);
|
||||
}
|
||||
var val = obj.avatar;
|
||||
md = obj;
|
||||
if (!val) {
|
||||
var $img = $('<img>', {
|
||||
src: '/customize/images/avatar.png',
|
||||
title: Messages.profile_avatar,
|
||||
alt: 'Avatar'
|
||||
});
|
||||
var mt = h('media-tag', $img[0]);
|
||||
$avatar.append(mt);
|
||||
} else {
|
||||
common.displayAvatar($avatar, val);
|
||||
}
|
||||
|
||||
// Display existing + button
|
||||
var content = [
|
||||
avatar,
|
||||
h('br'),
|
||||
$upButton[0]
|
||||
];
|
||||
cb(content);
|
||||
});
|
||||
}, true);
|
||||
|
||||
var onEvent = function (obj) {
|
||||
var ev = obj.ev;
|
||||
var data = obj.data;
|
||||
|
|
Loading…
Reference in New Issue