Skip to content

Commit

Permalink
Back-end:
Browse files Browse the repository at this point in the history
	- updated GET /users route not to return an error when some ids
	are missing in the list.
Front-end:
	- Dispaly name to interested user istead of ids.
	- Display publisher name of comment.
	- Fixed page not rerending when routing to the same router path.
	- Bug in interested list not showing "no iterested users" text
	when there are no interets.
Issues: #352 #353 #354 #355 #356
  • Loading branch information
alonttal committed May 1, 2018
1 parent 7d8d974 commit a0e5baa
Show file tree
Hide file tree
Showing 5 changed files with 176 additions and 119 deletions.
6 changes: 3 additions & 3 deletions server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,9 +491,9 @@ app.get('/users', async (req, res) => {
try {
const ids = _.castArray(req.query.id);
let users = await User.find({ _id: { $in: ids } });
if (users.length !== ids.length) { // if some ids were not found
return res.status(BAD_REQUEST).send();
}
// if (users.length !== ids.length) { // if some ids were not found
// return res.status(BAD_REQUEST).send();
// }
users = convertArrayToJsonMap(users, '_id');

return res.send({ users });
Expand Down
2 changes: 1 addition & 1 deletion views/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<v-content>
<!-- <v-container fluid> -->
<app-loader :loading="getLoadingStatus" />
<router-view/>
<router-view :key="$route.fullPath"/>
<app-snackbar :text="getSnackbarText" />
<!-- </v-container> -->
</v-content>
Expand Down
247 changes: 137 additions & 110 deletions views/src/components/sub-components/AppComments.vue
Original file line number Diff line number Diff line change
@@ -1,127 +1,154 @@
<template>
<v-container grid-list-lg style="overflow: hidden; height:100%;">
<v-layout column fill-height>
<v-flex v-if="isVerified" ref="addComments" style="min-height: 60px; max-height: 180px; overflow-y: auto;">
<v-layout fill-height>
<v-text-field v-model="text" label="Add a comment" :error-messages="errorMessages" :loading="loading" :disabled="!isVerified || loading" multi-line auto-grow hide-details :rows="1" :row-height="1" />
<v-btn color="secondary" :loading="loading" :disabled="!isVerified || loading" @click="addComment">
<v-icon>send</v-icon>
</v-btn>
</v-layout>
</v-flex>
<v-divider v-if="isVerified" class="my-3" />
<v-flex ref="chat" style="overflow-y: auto; height: 100%">
<transition-group name="scale-transition" tag="v-flex" mode="out-in">
<v-flex xs11 v-if="hasComments" v-for="(comment, i) in comments" :key="`comment-${commentsList.length - i}`" :class="{ 'offset-xs1': isMyComments(comment) }">
<div class="text-xs-left caption"> {{ formatCommentTime(comment.createdAt) }} </div>
<v-card :color="isMyComments(comment) ? myCommentColor : hisCommentColor" class="white--text">
<v-card-title>

<div>
<div class="body-2">
{{ isMyComments(comment) ? 'You' : 'user'}}
</div>
<div class="body-1">
{{ comment.text }}
</div>
</div>
</v-card-title>
</v-card>
</v-flex>
</transition-group>
<div v-if="!hasComments()" class="text-xs-center">No comments</div>
</v-flex>
<v-container grid-list-lg style="overflow: hidden; height:100%;">
<v-layout column fill-height>
<v-flex v-if="isVerified" ref="addComments" style="min-height: 60px; max-height: 180px; overflow-y: auto;">
<v-layout fill-height>
<v-text-field v-model="text" label="Add a comment" :error-messages="errorMessages" :loading="loading" :disabled="!isVerified || loading" multi-line auto-grow hide-details :rows="1" :row-height="1" />
<v-btn color="secondary" :loading="loading" :disabled="!isVerified || loading" @click="addComment">
<v-icon>send</v-icon>
</v-btn>
</v-layout>
</v-container>
</v-flex>
<v-divider v-if="isVerified" class="my-3" />
<div v-if="!usersList" class="text-xs-center">
<v-progress-circular indeterminate :size="25" :width="3" color="purple" class="my-5" />
</div>
<v-flex v-else ref="chat" style="overflow-y: auto; height: 100%">
<transition-group name="scale-transition" tag="v-flex" mode="out-in">
<v-flex xs11 v-if="hasComments" v-for="(comment, i) in comments" :key="`comment-${commentsList.length - i}`" :class="{ 'offset-xs1': isMyComments(comment) }">
<div class="text-xs-left caption"> {{ formatCommentTime(comment.createdAt) }} </div>
<v-card :color="isMyComments(comment) ? myCommentColor : hisCommentColor" class="white--text">
<v-card-title>

<div>
<div class="body-2">
{{ getPublisher(comment) }}
</div>
<div class="body-1">
{{ comment.text }}
</div>
</div>
</v-card-title>
</v-card>
</v-flex>
</transition-group>
<div v-if="!hasComments()" class="text-xs-center">No comments</div>
</v-flex>
</v-layout>
</v-container>
</template>

<script>
import { mapGetters } from 'vuex';
import { mapGetters } from 'vuex';
export default {
props: {
comments: {
type: Array,
default: [],
required: true
},
minLength: {
type: Number,
default: 10
},
onComment: {
type: Function,
default: () => new Promise.resolve() // eslint-disable-line
export default {
props: {
comments: {
type: Array,
default: [],
required: true
},
minLength: {
type: Number,
default: 10
},
onComment: {
type: Function,
default: () => new Promise.resolve() // eslint-disable-line
}
},
data() {
return {
commentsList: null,
usersList: null,
text: null,
errorMessages: [],
loading: false,
myCommentColor: 'green lighten-2',
hisCommentColor: 'blue lighten-2'
};
},
methods: {
isMyComments(comment) {
return this.isVerified && comment._createdBy === this.getUser._id;
},
hasComments() {
return this.comments.length > 0;
},
formatCommentTime(date) {
const time = (Date.now() - date) / 1000;
if (time < 60) {
return 'just now';
} else if (time >= 60 && time < 3600) {
return `${Math.floor(time / 60)} minutes ago`;
} else if (time >= 3600 && time < 86400) {
return `${Math.floor(time / 3600)} hours ago`;
}
return `${Math.floor(time / 86400)} days ago`;
},
data() {
return {
commentsList: null,
text: null,
errorMessages: [],
loading: false,
myCommentColor: 'green lighten-2',
hisCommentColor: 'blue lighten-2'
addComment() {
if (this.text.length < this.minLength) {
this.errorMessages = ['Your comment is too short'];
return;
}
this.loading = true;
this.errorMessages = [];
const comment = {
text: this.text,
_createdBy: this.getUser._id,
createdAt: Date.now()
};
this.text = null;
this.goToTop();
this.onComment(comment)
.then(() => {
this.commentsList.unshift(comment);
this.$emit('commentAdded', comment);
})
.catch((error) => {
// eslint-disable-next-line
console.log(error);
})
.then(() => {
this.loading = false;
});
},
methods: {
isMyComments(comment) {
return this.isVerified && comment._createdBy === this.getUser._id;
},
hasComments() {
return this.comments.length > 0;
},
formatCommentTime(date) {
const time = (Date.now() - date) / 1000;
if (time < 60) {
return 'just now';
} else if (time >= 60 && time < 3600) {
return `${Math.floor(time / 60)} minutes ago`;
} else if (time >= 3600 && time < 86400) {
return `${Math.floor(time / 3600)} hours ago`;
}
return `${Math.floor(time / 86400)} days ago`;
},
addComment() {
if (this.text.length < this.minLength) {
this.errorMessages = ['Your comment is too short'];
return;
}
this.loading = true;
this.errorMessages = [];
const comment = {
text: this.text,
_createdBy: this.getUser._id,
createdAt: Date.now()
};
this.text = null;
this.goToTop();
this.onComment(comment)
.then(() => {
this.commentsList.unshift(comment);
this.$emit('commentAdded', comment);
})
.catch((error) => {
// eslint-disable-next-line
console.log(error);
})
.then(() => {
this.loading = false;
});
},
goToTop() {
this.$nextTick(() => {
this.$refs.chat.scrollTop = 0;
goToTop() {
this.$nextTick(() => {
this.$refs.chat.scrollTop = 0;
});
},
fetchUsers() {
if (!this.hasComments()) {
this.usersList = [];
} else {
const id = this.commentsList.map(comment => comment._createdBy);
this.$store.dispatch('fetchUser', { id }).then((users) => {
this.usersList = users;
});
}
},
computed: {
...mapGetters(['isVerified', 'getUser'])
},
created() {
this.commentsList = this.comments;
getPublisher(comment) {
if (!this.usersList[comment._createdBy]) {
return 'User';
} else if (this.isMyComments(comment)) {
return 'You';
} else {
return `${this.usersList[comment._createdBy].firstName} ${
this.usersList[comment._createdBy].lastName}`;
}
}
};
},
computed: {
...mapGetters(['isVerified', 'getUser'])
},
created() {
this.commentsList = this.comments;
},
beforeMount() {
this.fetchUsers();
}
};
</script>

<style scoped src="../../assets/costum-scrollbar.css">
Expand Down
38 changes: 34 additions & 4 deletions views/src/components/sub-components/AppFavors.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
<template>
<div style="overflow-y: auto; height: 100%">
<v-list v-if="hasFavors">
<transition-group name="scale-transition" mode="out-in">
<div v-if="!usersList" class="text-xs-center">
<v-progress-circular indeterminate :size="25" :width="3" color="purple" class="my-5" />
</div>
<transition-group v-else name="scale-transition" mode="out-in">
<v-list-tile avatar v-for="(favor, i) in favors" :key="`interested-${i}`" @click="goToProfile(favor)">
<v-list-tile-action>
<v-icon color="amber accent-3">star</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title v-text="favor"></v-list-tile-title>
<v-list-tile-title v-text="getName(favor)"></v-list-tile-title>
</v-list-tile-content>
<v-list-tile-avatar>
<img :src="userDefaultImage">
</v-list-tile-avatar>
</v-list-tile>
</transition-group>
</v-list>
<div v-else>
<div v-if="!hasFavors()" class="text-xs-center">
No one expressed interet
</div>
</div>
Expand All @@ -35,18 +38,45 @@
},
data() {
return {
usersList: null,
userDefaultImage: userDefault
};
},
methods: {
...mapGetters(['isVerified']),
...mapGetters(['isVerified', 'getUser']),
isMyFavor(favor) {
return this.isVerified && favor === this.getUser._id;
},
hasFavors() {
return this.favors.length > 0;
},
goToProfile(favor) {
this.$router.push({ name: 'AppUserProfile', params: { id: favor } });
},
fetchUsers() {
if (!this.hasFavors()) {
this.usersList = [];
} else {
this.$store.dispatch('fetchUser', { id: this.favors }).then((users) => {
this.usersList = users;
});
}
},
getName(favor) {
if (!this.usersList[favor]) {
return 'User';
} else if (this.isMyFavor(favor)) {
return 'You';
} else {
return `${this.usersList[favor].firstName} ${
this.usersList[favor].lastName
}`;
}
}
},
beforeMount() {
this.fetchUsers();
},
mounted() {
// if (this.isVerified) {
// this.store.dispatch('getSortedFavors')
Expand Down
2 changes: 1 addition & 1 deletion views/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export default new Vuex.Store({
console.log(response.data);
commit('setUser', response.data.user);
});
}
},
},
plugins: [vuexPersistence.plugin]
});

0 comments on commit a0e5baa

Please sign in to comment.