Browse Source

feat: avatar type can be changed between gravatar & initials

Signed-off-by: Jonathan <theflametrooper@gmail.com>
Jonathan 5 years ago
parent
commit
bfcc50732f

+ 38 - 1
backend/logic/actions/users.js

@@ -518,6 +518,7 @@ module.exports = {
 					email: {
 						address: user.email.address
 					},
+					avatar: user.avatar,
 					username: user.username,
 					name: user.name,
 					location: user.location,
@@ -735,7 +736,7 @@ module.exports = {
 			}
 		});
 	}),
-
+	
 	/**
 	 * Updates a user's bio
 	 *
@@ -772,6 +773,42 @@ module.exports = {
 		});
 	}),
 
+	/**
+	 * Updates the type of a user's avatar
+	 *
+	 * @param {Object} session - the session object automatically added by socket.io
+	 * @param {String} updatingUserId - the updating user's id
+	 * @param {String} newType - the new type
+	 * @param {Function} cb - gets called with the result
+	 */
+	updateAvatarType: hooks.loginRequired((session, updatingUserId, newType, cb) => {
+		async.waterfall([
+			(next) => {
+				if (updatingUserId === session.userId) return next(null, true);
+				db.models.user.findOne({ _id: session.userId }, next);
+			},
+
+			(user, next) => {
+				if (user !== true && (!user || user.role !== 'admin')) return next('Invalid permissions.');
+				db.models.user.findOne({ _id: updatingUserId }, next);
+			},
+
+			(user, next) => {
+				if (!user) return next('User not found.');
+				db.models.user.updateOne({ _id: updatingUserId }, {$set: { "avatar.type": newType }}, { runValidators: true }, next);
+			}
+		], async (err) => {
+			if (err && err !== true) {
+				err = await utils.getError(err);
+				logger.error("UPDATE_AVATAR_TYPE", `Couldn't update avatar type for user "${updatingUserId}" to type "${newType}". "${err}"`);
+				cb({ status: 'failure', message: err });
+			} else {
+				logger.success("UPDATE_AVATAR_TYPE", `Updated avatar type for user "${updatingUserId}" to type "${newType}".`);
+				cb({ status: 'success', message: 'Avatar type updated successfully' });
+			}
+		});
+	}),
+
 	/**
 	 * Updates a user's role
 	 *

+ 1 - 1
backend/logic/app.js

@@ -203,7 +203,7 @@ module.exports = class extends coreClass {
 					// generate the url for gravatar avatar
 					(user, next) => {
 						this.utils.createGravatar(user.email.address).then(url => {
-							user.avatar = url;
+							user.avatar = { type: "gravatar", url };
 							next(null, user);
 						});
 					},

+ 4 - 1
backend/logic/db/schemas/user.js

@@ -6,7 +6,10 @@ module.exports = {
 		verificationToken: String,
 		address: String
 	},
-	avatar: { type: String },
+	avatar: {
+		type: { type: String, enum: ["gravatar", "initials"] },
+		url: { type: String, required: false }
+	},
 	services: {
 		password: {
 			password: String,

+ 42 - 4
frontend/components/User/Settings.vue

@@ -59,7 +59,19 @@
 						v-model="user.bio"
 					/>
 				</p>
-				<button class="button is-primary" @click="saveChangesProfile()">
+				<div class="control is-expanded avatar-select">
+					<label>Avatar</label>
+					<div class="select">
+						<select v-model="user.avatar.type">
+							<option value="gravatar">Using Gravatar</option>
+							<option value="initials">Based on initials</option>
+						</select>
+					</div>
+				</div>
+				<button
+					class="button is-primary"
+					@click="saveChangesToProfile()"
+				>
 					Save changes
 				</button>
 			</div>
@@ -84,7 +96,10 @@
 						v-model="user.email.address"
 					/>
 				</p>
-				<button class="button is-primary" @click="saveChangesAccount()">
+				<button
+					class="button is-primary"
+					@click="saveChangesToAccount()"
+				>
 					Save changes
 				</button>
 			</div>
@@ -277,12 +292,13 @@ export default {
 		switchTab(tabName) {
 			this.activeTab = tabName;
 		},
-		saveChangesProfile() {
+		saveChangesToProfile() {
 			this.changeName();
 			this.changeLocation();
 			this.changeBio();
+			this.changeAvatarType();
 		},
-		saveChangesAccount() {
+		saveChangesToAccount() {
 			this.changeUsername();
 			this.changeEmail();
 		},
@@ -418,6 +434,18 @@ export default {
 				}
 			);
 		},
+		changeAvatarType() {
+			const { type } = this.user.avatar;
+
+			return this.socket.emit(
+				"users.updateAvatarType",
+				this.userId,
+				type,
+				res => {
+					new Toast({ content: res.message, timeout: 8000 });
+				}
+			);
+		},
 		changePassword() {
 			const { newPassword } = this;
 			if (!validation.isLength(newPassword, 6, 200))
@@ -618,6 +646,16 @@ export default {
 	}
 }
 
+.avatar-select {
+	display: flex;
+	flex-direction: column;
+	align-items: flex-start;
+
+	.select:after {
+		border-color: $musareBlue;
+	}
+}
+
 .night-mode {
 	label {
 		color: #ddd !important;

+ 2 - 2
frontend/components/User/Show.vue

@@ -9,8 +9,8 @@
 				<img
 					class="profile-picture"
 					:src="
-						user.avatar
-							? `${user.avatar}?d=${notes}&s=250`
+						user.avatar.url && user.avatar.type === 'gravatar'
+							? `${user.avatar.url}?d=${notes}&s=250`
 							: '/assets/notes.png'
 					"
 					onerror="this.src='/assets/notes.png'; this.onerror=''"