mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 10:01:40 -05:00
344 lines
12 KiB
JavaScript
344 lines
12 KiB
JavaScript
import Users from './collection.js';
|
|
import md5 from 'crypto-js/md5';
|
|
|
|
Users.avatar = {
|
|
|
|
/**
|
|
* `cleantString` remove starting and trailing whitespaces
|
|
* and lowercase the input
|
|
* @param {String} string input string that may contain leading and trailing
|
|
* whitespaces and uppercase letters
|
|
* @return {String} output cleaned string
|
|
*/
|
|
cleanString: function (string) {
|
|
return string.trim().toLowerCase()
|
|
},
|
|
|
|
/**
|
|
* `isHash` check if a string match the MD5 form :
|
|
* 32 chars string containing letters from `a` to `f`
|
|
* and digits from `0` to `9`
|
|
* @param {String} string that might be a hash
|
|
* @return {Boolean}
|
|
*/
|
|
isHash: function (string) {
|
|
var self = this
|
|
return /^[a-f0-9]{32}$/i.test(self.cleanString(string))
|
|
},
|
|
|
|
/**
|
|
* `hash` takes an input and run it through `CryptoJS.MD5`
|
|
* @see https://atmospherejs.com/jparker/crypto-md5
|
|
* @param {String} string input string
|
|
* @return {String} md5 hash of the input
|
|
*/
|
|
hash: function (string) {
|
|
var self = this;
|
|
// eslint-disable-next-line babel/new-cap
|
|
return md5(self.cleanString(string)).toString()
|
|
},
|
|
|
|
/**
|
|
* `imageUrl` will provide the url for the avatar, given an email or a hash
|
|
* and a set of options to be passed to the gravatar API
|
|
* @see https://en.gravatar.com/site/implement/images/
|
|
* @param {String} emailOrHash email or pregenerated MD5 hash to query
|
|
* gravatar with.
|
|
* @param {Object} options options to be passed to gravatar in the query
|
|
* string. The `secure` will be used to determine which base url to use.
|
|
* @return {String} complete url to the avatar
|
|
*/
|
|
imageUrl: function (emailOrHash, options) {
|
|
var self = this
|
|
options = options || {}
|
|
|
|
// Want HTTPS ?
|
|
var url = options.secure
|
|
? 'https://secure.gravatar.com/avatar/'
|
|
: 'http://www.gravatar.com/avatar/'
|
|
delete options.secure
|
|
|
|
// Is it an MD5 already ?
|
|
url += self.isHash(emailOrHash)
|
|
? emailOrHash
|
|
: self.hash(emailOrHash)
|
|
|
|
// Have any options to pass ?
|
|
var params = _.map(options, function (val, key) {
|
|
return key + '=' + encodeURIComponent(val)
|
|
}).join('&')
|
|
|
|
return (params.length > 0)
|
|
? url + '?' + params
|
|
: url
|
|
},
|
|
|
|
// Default functionality. You can override these options by calling
|
|
// Users.avatar.setOptions (do not set this.options directly)
|
|
|
|
options: {
|
|
|
|
// Determines the type of fallback to use when no image can be found via
|
|
// linked services (Gravatar included):
|
|
// 'default image' (the default option, which will show either the image
|
|
// specified by defaultImageUrl, the package's default image, or a Gravatar
|
|
// default image)
|
|
// OR
|
|
// 'initials' (show the user's initials).
|
|
fallbackType: '',
|
|
|
|
// Default avatar image's URL. It can be a relative path
|
|
// (relative to website's base URL, e.g. 'images/defaultthis.png').
|
|
defaultImageUrl: 'http://www.gravatar.com/avatar/?d=identicon',
|
|
|
|
// This property name will be used to fetch an avatar url from the user's profile
|
|
// (e.g. 'avatar'). If this property is set and a property of that name exists
|
|
// on the user's profile (e.g. user.profile.avatar) that property will be used
|
|
// as the avatar url.
|
|
customImageProperty: '',
|
|
|
|
// Gravatar default option to use (overrides default image URL)
|
|
// Options are available at:
|
|
// https://secure.gravatar.com/site/implement/images/#default-image
|
|
gravatarDefault: '',
|
|
|
|
// This property is used to prefix the CSS classes of the DOM elements.
|
|
// If no value is set, then the default CSS class assigned to all DOM elements are prefixed with 'avatar' as default.
|
|
// If a value is set to, 'foo' for example, the resulting CSS classes are prefixed with 'foo'.
|
|
cssClassPrefix: '',
|
|
|
|
// This property defines the various image sizes available
|
|
imageSizes: {
|
|
'large': 80,
|
|
'small': 30,
|
|
'extra-small': 20
|
|
},
|
|
|
|
// Default background color when displaying the initials.
|
|
// Can also be set to a function to map an user object to a background color.
|
|
backgroundColor: '#aaa',
|
|
|
|
// Default text color when displaying the initials.
|
|
// Can also be set to a function to map an user object to a text color.
|
|
textColor: '#fff',
|
|
|
|
// Generate the required CSS and include it in the head of your application.
|
|
// Setting this to false will exclude the generated CSS and leave the
|
|
// avatar unstyled by the package.
|
|
generateCSS: true
|
|
},
|
|
|
|
// Sets the Avatar options. You must use this setter function rather than assigning directly to
|
|
// this.options, otherwise the stylesheet won't be generated.
|
|
|
|
setOptions: function(options) {
|
|
this.options = _.extend(this.options, options);
|
|
},
|
|
|
|
// Returns the cssClassPrefix property from options
|
|
getCssClassPrefix: function () {
|
|
return this.options.cssClassPrefix ? this.options.cssClassPrefix : 'avatar';
|
|
},
|
|
|
|
// Returns a background color for initials
|
|
getBackgroundColor: function (user) {
|
|
if (_.isString(this.options.backgroundColor))
|
|
return this.options.backgroundColor;
|
|
else if (_.isFunction(this.options.backgroundColor))
|
|
return this.options.backgroundColor(user);
|
|
},
|
|
|
|
// Returns a text color for initials
|
|
getTextColor: function (user) {
|
|
if (_.isString(this.options.textColor))
|
|
return this.options.textColor;
|
|
else if (_.isFunction(this.options.textColor))
|
|
return this.options.textColor(user);
|
|
},
|
|
|
|
// Get the initials of the user
|
|
getInitials: function (user) {
|
|
|
|
var initials = '';
|
|
var name = '';
|
|
var parts = [];
|
|
|
|
if (user && user.profile && user.profile.firstName) {
|
|
initials = user.profile.firstName.charAt(0).toUpperCase();
|
|
|
|
if (user.profile.lastName) {
|
|
initials += user.profile.lastName.charAt(0).toUpperCase();
|
|
}
|
|
else if (user.profile.familyName) {
|
|
initials += user.profile.familyName.charAt(0).toUpperCase();
|
|
}
|
|
else if (user.profile.secondName) {
|
|
initials += user.profile.secondName.charAt(0).toUpperCase();
|
|
}
|
|
}
|
|
else {
|
|
if (user && user.profile && user.profile.name) {
|
|
name = user.profile.name;
|
|
}
|
|
else if (user && user.username) {
|
|
name = user.username;
|
|
}
|
|
|
|
parts = name.split(' ');
|
|
// Limit getInitials to first and last initial to avoid problems with
|
|
// very long multi-part names (e.g. 'Jose Manuel Garcia Galvez')
|
|
initials = _.first(parts).charAt(0).toUpperCase();
|
|
if (parts.length > 1) {
|
|
initials += _.last(parts).charAt(0).toUpperCase();
|
|
}
|
|
}
|
|
|
|
return initials;
|
|
},
|
|
|
|
// Get the url of the user's avatar
|
|
// XXX: this.getUrl is a reactive function only when no user argument is specified.
|
|
getUrl: function (user) {
|
|
|
|
// Default to the currently logged in user, unless otherwise specified.
|
|
if (!user) return null;
|
|
|
|
var url = '';
|
|
var defaultUrl, svc;
|
|
|
|
if (user) {
|
|
svc = this.getService(user);
|
|
if (svc === 'twitter') {
|
|
// use larger image (200x200 is smallest custom option)
|
|
url = user.services.twitter.profile_image_url_https.replace('_normal.', '_200x200.');
|
|
}
|
|
else if (svc === 'facebook') {
|
|
// use larger image (~200x200)
|
|
url = 'https://graph.facebook.com/' + user.services.facebook.id + '/picture/?type=large';
|
|
}
|
|
else if (svc === 'google') {
|
|
url = user.services.google.picture;
|
|
}
|
|
else if (svc === 'github') {
|
|
url = 'https://avatars.githubusercontent.com/' + user.services.github.username + '?s=200';
|
|
}
|
|
else if (svc === 'instagram') {
|
|
url = user.services.instagram.profile_picture;
|
|
}
|
|
else if (svc === 'linkedin') {
|
|
url = user.services.linkedin.pictureUrl;
|
|
}
|
|
else if (svc === 'custom') {
|
|
url = this.getCustomUrl(user);
|
|
}
|
|
else if (svc === 'none') {
|
|
defaultUrl = this.options.defaultImageUrl;
|
|
// If it's a relative path (no '//' anywhere), complete the URL
|
|
if (defaultUrl.indexOf('//') === -1) {
|
|
// remove starting slash if it exists
|
|
if (defaultUrl.charAt(0) === '/') defaultUrl = defaultUrl.substr(1);
|
|
// Then add the relative path to the server's base URL
|
|
defaultUrl = Meteor.absoluteUrl(defaultUrl);
|
|
}
|
|
url = this.getGravatarUrl(user, defaultUrl);
|
|
}
|
|
}
|
|
|
|
return url;
|
|
},
|
|
|
|
getService: function (user) {
|
|
var services = user && user.services || {};
|
|
if (this.getCustomUrl(user)) { return 'custom'; }
|
|
var service = _.find([['twitter', 'profile_image_url_https'], ['facebook', 'id'], ['google', 'picture'], ['github', 'username'], ['instagram', 'profile_picture'], ['linkedin', 'pictureUrl']], function(s) { return !!services[s[0]] && s[1].length && !!services[s[0]][s[1]]; });
|
|
if(!service)
|
|
return 'none';
|
|
else
|
|
return service[0];
|
|
},
|
|
|
|
computeUrl: function(prop, user) {
|
|
if (typeof prop === 'function') {
|
|
prop = prop.call(user);
|
|
}
|
|
if (prop && typeof prop === 'string') {
|
|
return prop;
|
|
}
|
|
},
|
|
|
|
getDescendantProp: function (obj, desc) {
|
|
var arr = desc.split('.');
|
|
while(arr.length && (obj = obj[arr.shift()]));
|
|
return obj;
|
|
},
|
|
|
|
getCustomUrl: function (user) {
|
|
|
|
var customProp = user && this.options.customImageProperty;
|
|
if (typeof customProp === 'function') {
|
|
return this.computeUrl(customProp, user);
|
|
} else if (customProp) {
|
|
return this.computeUrl(this.getDescendantProp(user, customProp), user);
|
|
}
|
|
},
|
|
|
|
getGravatarUrl: function (user, defaultUrl) {
|
|
var gravatarDefault;
|
|
var validGravatars = ['404', 'mm', 'identicon', 'monsterid', 'wavatar', 'retro', 'blank'];
|
|
|
|
// Initials are shown when Gravatar returns 404.
|
|
if (this.options.fallbackType !== 'initials') {
|
|
var valid = _.contains(validGravatars, this.options.gravatarDefault);
|
|
gravatarDefault = valid ? this.options.gravatarDefault : defaultUrl;
|
|
}
|
|
else {
|
|
gravatarDefault = '404';
|
|
}
|
|
|
|
var emailOrHash = this.getUserEmail(user) || Users.getEmailHash(user);
|
|
// var secure = true;
|
|
var options = {
|
|
// NOTE: Gravatar's default option requires a publicly accessible URL,
|
|
// so it won't work when your app is running on localhost and you're
|
|
// using an image with either the standard default image URL or a custom
|
|
// defaultImageUrl that is a relative path (e.g. 'images/defaultthis.png').
|
|
size: 200, // use 200x200 like twitter and facebook above (might be useful later)
|
|
default: gravatarDefault,
|
|
secure: true
|
|
};
|
|
return emailOrHash ? this.imageUrl(emailOrHash, options) : null;
|
|
|
|
},
|
|
|
|
// Get the user's email address
|
|
getUserEmail: function (user) {
|
|
var emails = _.pluck(user.emails, 'address');
|
|
return emails[0] || null;
|
|
},
|
|
|
|
// Returns the size class to use for an avatar
|
|
getSizeClass: function(context) {
|
|
// Defaults are 'large', 'small', 'extra-small', but user can add new ones
|
|
return this.options.imageSizes[context.size] ? this.getCssClassPrefix() + '-' + context.size : '';
|
|
},
|
|
|
|
// Returns the shape class for an avatar
|
|
getShapeClass: function (context) {
|
|
var valid = ['rounded', 'circle'];
|
|
return _.contains(valid, context.shape) ? this.getCssClassPrefix() + '-' + context.shape : '';
|
|
},
|
|
|
|
// Returns the custom class(es) for an avatar
|
|
getCustomClasses: function (context) {
|
|
return context.class ? context.class : '';
|
|
},
|
|
|
|
// Returns the initials text for an avatar
|
|
getInitialsText: function(user, context) {
|
|
return context.initials || this.getInitials(user);
|
|
}
|
|
|
|
};
|
|
|
|
// This will be replaced if the user calls setOptions in their own code
|
|
Users.avatar.setOptions({});
|