forked from kaverti/website
Marketplace Upload WIP
This commit is contained in:
parent
88d99b37eb
commit
602754bf36
|
@ -752,6 +752,7 @@ blockquote {
|
|||
<router-link class="navbar-item " to='/settings' v-if="!$store.state.experimentsStore.newsettings">Settings</router-link>
|
||||
<router-link to='/inventory' class="navbar-item">Inventory</router-link>
|
||||
<router-link to='/transactions' class="navbar-item">Transactions</router-link>
|
||||
<router-link to='/friends' class="navbar-item">Friends</router-link>
|
||||
<router-link class="navbar-item is-hidden-desktop" to='/notifications'>Notifications</router-link>
|
||||
<router-link to='/admin' class="navbar-item" v-if='$store.state.admin'>Admin Panel</router-link>
|
||||
<router-link class="navbar-item is-active" to='/premium'>Upgrade</router-link>
|
||||
|
|
|
@ -1,495 +1,506 @@
|
|||
<template>
|
||||
<div class='notification_button'>
|
||||
<div
|
||||
class='notification_button__overlay'
|
||||
:class='{ "notification_button__overlay--show" : showMenu}'
|
||||
@click='setShowMenu(false)'
|
||||
></div>
|
||||
<b-button
|
||||
:class='{ "notification_button__button--shake": shake }'
|
||||
<div class='notification_button'>
|
||||
<div
|
||||
class='notification_button__overlay'
|
||||
:class='{ "notification_button__overlay--show" : showMenu}'
|
||||
@click='setShowMenu(false)'
|
||||
></div>
|
||||
<b-button
|
||||
:class='{ "notification_button__button--shake": shake }'
|
||||
style=""
|
||||
@click='setShowMenu(!showMenu)'
|
||||
>
|
||||
@click='setShowMenu(!showMenu)'
|
||||
>
|
||||
<i class="far fa-bell"></i>
|
||||
<span
|
||||
class='notification_button__button__count'
|
||||
:class='{
|
||||
<span
|
||||
class='notification_button__button__count'
|
||||
:class='{
|
||||
"notification_button__button__count--none": !unreadCount,
|
||||
"notification_button__button__count--two_figure": unreadCount > 9,
|
||||
"notification_button__button__count--three_figure": unreadCount > 99
|
||||
}'
|
||||
>{{unreadCountText}}</span>
|
||||
</b-button>
|
||||
>{{unreadCountText}}</span>
|
||||
</b-button>
|
||||
<div
|
||||
class='notification_button__menu_group'
|
||||
:class='{ "notification_button__menu_group--show" : showMenu}'
|
||||
>
|
||||
<div class='notification_button__triangle'></div>
|
||||
<div class='notification_button__menu'>
|
||||
<div
|
||||
:key='"notification-" + index'
|
||||
v-for='(notification, index) in postNotifications'
|
||||
class='notification_button__menu__item'
|
||||
:class='{
|
||||
class='notification_button__menu_group'
|
||||
:class='{ "notification_button__menu_group--show" : showMenu}'
|
||||
>
|
||||
<div class='notification_button__triangle'></div>
|
||||
<div class='notification_button__menu'>
|
||||
<div
|
||||
:key='"notification-" + index'
|
||||
v-for='(notification, index) in postNotifications'
|
||||
class='notification_button__menu__item'
|
||||
:class='{
|
||||
"notification_button__menu__item--uninteracted": !notification.interacted,
|
||||
"notification_button__menu__item--no_border": index > 2
|
||||
}'
|
||||
|
||||
@click='click(notification)'
|
||||
>
|
||||
@click='click(notification)'
|
||||
>
|
||||
|
||||
<div class='notification_button__menu__item__header'>
|
||||
<span v-if='notification.type === "mention"'>New mention</span>
|
||||
<span v-else-if='notification.type === "reply"'>Reply to your post</span>
|
||||
<span>
|
||||
<div class='notification_button__menu__item__header'>
|
||||
<span v-if='notification.type === "mention"'>New mention</span>
|
||||
<span v-else-if='notification.type === "reply"'>Reply to your post</span>
|
||||
<span>
|
||||
<span class='notification_button__menu__item__header__date'>{{notification.createdAt | formatDate }}</span>
|
||||
<span
|
||||
class='notification_button__menu__item__header__close'
|
||||
@click.stop='deleteNotification(notification.id)'
|
||||
>×</span>
|
||||
class='notification_button__menu__item__header__close'
|
||||
@click.stop='deleteNotification(notification.id)'
|
||||
>×</span>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<div>
|
||||
<span v-if='isYouOrDeleted(notification.PostNotification.User)'>
|
||||
{{ notification.PostNotification.User ? 'You' : '[deleted]' }}
|
||||
</span>
|
||||
<span class='notification_button__menu__item__link' v-else>
|
||||
<span class='notification_button__menu__item__link' v-else>
|
||||
{{notification.PostNotification.User.username}}
|
||||
</span>
|
||||
|
||||
wrote
|
||||
"{{notification.PostNotification.Post.content | stripTags | truncate(50)}}"
|
||||
</div>
|
||||
wrote
|
||||
"{{notification.PostNotification.Post.content | stripTags | truncate(50)}}"
|
||||
</div>
|
||||
<div>
|
||||
<span v-if='isYouOrDeleted(notification.PostNotification.User)'>
|
||||
{{ notification.MessageNotification.User ? 'You' : '[deleted]' }}
|
||||
</span>
|
||||
<span class='notification_button__menu__item__link' v-else>
|
||||
{{notification.MessageNotification.User.username}}
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class='notification_button__menu__empty' v-if='!notifications.length'>
|
||||
wrote
|
||||
"{{notification.MessageNotification.message | stripTags | truncate(50)}}"
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class='notification_button__menu__empty' v-if='!notifications.length'>
|
||||
<h1><i class="fal fa-bell"></i></h1>
|
||||
No notifications, for now!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
No notifications, for now!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AjaxErrorHandler from '../assets/js/errorHandler'
|
||||
import AjaxErrorHandler from '../assets/js/errorHandler'
|
||||
|
||||
export default {
|
||||
name: 'NotificationButton',
|
||||
data () {
|
||||
return {
|
||||
unreadCount: 0,
|
||||
notifications: [],
|
||||
export default {
|
||||
name: 'NotificationButton',
|
||||
data () {
|
||||
return {
|
||||
unreadCount: 0,
|
||||
notifications: [],
|
||||
|
||||
showMenu: false,
|
||||
shake: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
unreadCountText () {
|
||||
if(this.unreadCount > 99) {
|
||||
return '99+'
|
||||
} else {
|
||||
return this.unreadCount
|
||||
}
|
||||
},
|
||||
postNotifications () {
|
||||
return this.notifications.filter(n => n.PostNotification.Post);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isYouOrDeleted (user) {
|
||||
return !user || user.username === this.$store.state.username
|
||||
},
|
||||
setShowMenu (val) {
|
||||
this.showMenu = val
|
||||
showMenu: false,
|
||||
shake: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
unreadCountText () {
|
||||
if(this.unreadCount > 99) {
|
||||
return '99+'
|
||||
} else {
|
||||
return this.unreadCount
|
||||
}
|
||||
},
|
||||
postNotifications () {
|
||||
return this.notifications.filter(n => n.PostNotification.Post);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isYouOrDeleted (user) {
|
||||
return !user || user.username === this.$store.state.username
|
||||
},
|
||||
setShowMenu (val) {
|
||||
this.showMenu = val
|
||||
|
||||
if(val) {
|
||||
this.resetUnreadCount()
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.emojiIndex++
|
||||
}, 200)
|
||||
}
|
||||
},
|
||||
getIndexById (id) {
|
||||
let index
|
||||
if(val) {
|
||||
this.resetUnreadCount()
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.emojiIndex++
|
||||
}, 200)
|
||||
}
|
||||
},
|
||||
getIndexById (id) {
|
||||
let index
|
||||
|
||||
this.notifications.forEach((notification, i) => {
|
||||
if(notification.id === id) {
|
||||
index = i
|
||||
}
|
||||
})
|
||||
this.notifications.forEach((notification, i) => {
|
||||
if(notification.id === id) {
|
||||
index = i
|
||||
}
|
||||
})
|
||||
|
||||
return index
|
||||
},
|
||||
getNotifications () {
|
||||
this.axios
|
||||
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification')
|
||||
.then(res => {
|
||||
this.notifications = res.data.Notifications
|
||||
this.unreadCount = res.data.unreadCount
|
||||
})
|
||||
.catch(e => {
|
||||
this.showConn(e)
|
||||
})
|
||||
},
|
||||
resetUnreadCount () {
|
||||
this.axios
|
||||
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification')
|
||||
.then(() => {
|
||||
this.unreadCount = 0
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
deleteNotification (id) {
|
||||
let index = this.getIndexById(id)
|
||||
return index
|
||||
},
|
||||
getNotifications () {
|
||||
this.axios
|
||||
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification')
|
||||
.then(res => {
|
||||
this.notifications = res.data.Notifications
|
||||
this.unreadCount = res.data.unreadCount
|
||||
})
|
||||
.catch(e => {
|
||||
this.showConn(e)
|
||||
})
|
||||
},
|
||||
resetUnreadCount () {
|
||||
this.axios
|
||||
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification')
|
||||
.then(() => {
|
||||
this.unreadCount = 0
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
deleteNotification (id) {
|
||||
let index = this.getIndexById(id)
|
||||
|
||||
this.axios
|
||||
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification/' + id)
|
||||
.then(() => {
|
||||
this.notifications.splice(index, 1)
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
setInteracted (id) {
|
||||
let index = this.getIndexById(id)
|
||||
let item = this.notifications[index]
|
||||
this.axios
|
||||
.delete(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification/' + id)
|
||||
.then(() => {
|
||||
this.notifications.splice(index, 1)
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
setInteracted (id) {
|
||||
let index = this.getIndexById(id)
|
||||
let item = this.notifications[index]
|
||||
|
||||
this.axios
|
||||
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification/' + id)
|
||||
.then(() => {
|
||||
this.$set(
|
||||
this.notifications,
|
||||
index,
|
||||
Object.assign(item, { interacted: true })
|
||||
)
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
click (notification) {
|
||||
if(!notification.interacted) {
|
||||
this.setInteracted(notification.id)
|
||||
}
|
||||
this.axios
|
||||
.put(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'users/notification/' + id)
|
||||
.then(() => {
|
||||
this.$set(
|
||||
this.notifications,
|
||||
index,
|
||||
Object.assign(item, { interacted: true })
|
||||
)
|
||||
})
|
||||
.catch(AjaxErrorHandler(this.$store))
|
||||
},
|
||||
click (notification) {
|
||||
if(!notification.interacted) {
|
||||
this.setInteracted(notification.id)
|
||||
}
|
||||
|
||||
if(notification.type === 'mention' || notification.type === 'reply') {
|
||||
this.$router.push('/p/' + notification.PostNotification.Post.id)
|
||||
} else if(notification.type === 'reply') {
|
||||
this.$router.push('/p/' + notification.PostNotification.Post.id)
|
||||
}
|
||||
if(notification.type === 'mention' || notification.type === 'reply') {
|
||||
this.$router.push('/p/' + notification.PostNotification.Post.id)
|
||||
} else if(notification.type === 'reply') {
|
||||
this.$router.push('/p/' + notification.PostNotification.Post.id)
|
||||
}
|
||||
|
||||
this.setShowMenu(false)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if(this.$store.state.username) this.getNotifications()
|
||||
this.setShowMenu(false)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if(this.$store.state.username) this.getNotifications()
|
||||
|
||||
this.$socket.on('notification', notification => {
|
||||
this.unreadCount++
|
||||
this.notifications.unshift(notification)
|
||||
this.$socket.on('notification', notification => {
|
||||
this.unreadCount++
|
||||
this.notifications.unshift(notification)
|
||||
|
||||
this.shake = true
|
||||
setTimeout(() => {
|
||||
this.shake = false
|
||||
}, 1000)
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
'$store.state.username': 'getNotifications'
|
||||
}
|
||||
}
|
||||
this.shake = true
|
||||
setTimeout(() => {
|
||||
this.shake = false
|
||||
}, 1000)
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
'$store.state.username': 'getNotifications'
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
@import '../assets/scss/variables.scss';
|
||||
@import '../assets/scss/variables.scss';
|
||||
|
||||
@keyframes shake {
|
||||
0% {
|
||||
position: relative;
|
||||
left: 0;
|
||||
}
|
||||
25% {
|
||||
position: relative;
|
||||
left: -1rem;
|
||||
}
|
||||
75% {
|
||||
position: relative;
|
||||
left: 1rem;
|
||||
}
|
||||
100% {
|
||||
left: 0rem;
|
||||
}
|
||||
}
|
||||
@keyframes shake {
|
||||
0% {
|
||||
position: relative;
|
||||
left: 0;
|
||||
}
|
||||
25% {
|
||||
position: relative;
|
||||
left: -1rem;
|
||||
}
|
||||
75% {
|
||||
position: relative;
|
||||
left: 1rem;
|
||||
}
|
||||
100% {
|
||||
left: 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
.notification_button {
|
||||
position: relative;
|
||||
.notification_button {
|
||||
position: relative;
|
||||
|
||||
@at-root #{&}__overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
@at-root #{&}__overlay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
|
||||
@at-root #{&}--show {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
@at-root #{&}--show {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__menu_group {
|
||||
position: relative;
|
||||
top: -3rem;
|
||||
@at-root #{&}__menu_group {
|
||||
position: relative;
|
||||
top: -3rem;
|
||||
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s, top 0.2s;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s, top 0.2s;
|
||||
|
||||
@at-root #{&}--show {
|
||||
pointer-events: all;
|
||||
opacity: 1;
|
||||
top: -2.5rem;
|
||||
}
|
||||
}
|
||||
@at-root #{&}--show {
|
||||
pointer-events: all;
|
||||
opacity: 1;
|
||||
top: -2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__triangle {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: #fafafa;
|
||||
transform: rotate(45deg);
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
border-radius: 0.125rem 0 0 0;
|
||||
border: 1.5px solid $color__gray--darkest;
|
||||
left: calc(50% - 1rem /2);
|
||||
clip-path: polygon(0 0, 100% 0%, 0 100%);
|
||||
z-index: 8;
|
||||
}
|
||||
@at-root #{&}__menu {
|
||||
left: calc(-50% - 1.25rem);
|
||||
position: absolute;
|
||||
top: 2.9rem;
|
||||
background-color: #fafafa;
|
||||
width: 20rem;
|
||||
border-radius: 0.25rem;
|
||||
border: 1.5px solid $color__gray--darkest;
|
||||
box-shadow: 0 0.25rem 1rem rgba(#000, 0.125);
|
||||
min-height: 8rem;
|
||||
max-height: 15rem;
|
||||
overflow-y: auto;
|
||||
z-index: 7;
|
||||
@at-root #{&}__triangle {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background-color: #fafafa;
|
||||
transform: rotate(45deg);
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
border-radius: 0.125rem 0 0 0;
|
||||
border: 1.5px solid $color__gray--darkest;
|
||||
left: calc(50% - 1rem /2);
|
||||
clip-path: polygon(0 0, 100% 0%, 0 100%);
|
||||
z-index: 8;
|
||||
}
|
||||
@at-root #{&}__menu {
|
||||
left: calc(-50% - 1.25rem);
|
||||
position: absolute;
|
||||
top: 2.9rem;
|
||||
background-color: #fafafa;
|
||||
width: 20rem;
|
||||
border-radius: 0.25rem;
|
||||
border: 1.5px solid $color__gray--darkest;
|
||||
box-shadow: 0 0.25rem 1rem rgba(#000, 0.125);
|
||||
min-height: 8rem;
|
||||
max-height: 15rem;
|
||||
overflow-y: auto;
|
||||
z-index: 7;
|
||||
|
||||
@at-root #{&}__empty {
|
||||
background-color: #fafafa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
height: 8rem;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
transition: none;
|
||||
color: $color__gray--darkest;
|
||||
@at-root #{&}__empty {
|
||||
background-color: #fafafa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 2rem;
|
||||
height: 8rem;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
transition: none;
|
||||
color: $color__gray--darkest;
|
||||
|
||||
span {
|
||||
font-size: 2rem;
|
||||
color: $color__gray--darker;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
span {
|
||||
font-size: 2rem;
|
||||
color: $color__gray--darker;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__item {
|
||||
@at-root #{&}--no_border:last-child {
|
||||
border: none;
|
||||
}
|
||||
@at-root #{&}__item {
|
||||
@at-root #{&}--no_border:last-child {
|
||||
border: none;
|
||||
}
|
||||
|
||||
padding: 0.5rem;
|
||||
border-bottom: thin solid $color__gray--primary;
|
||||
cursor: default;
|
||||
background-color: #fff;
|
||||
padding: 0.5rem;
|
||||
border-bottom: thin solid $color__gray--primary;
|
||||
cursor: default;
|
||||
background-color: #fff;
|
||||
|
||||
transition: background-color 0.2s;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background-color: $color__lightgray--primary;
|
||||
}
|
||||
&:hover {
|
||||
background-color: $color__lightgray--primary;
|
||||
}
|
||||
|
||||
|
||||
@at-root #{&}--uninteracted {
|
||||
background-color: rgba(13, 71, 161, 0.1);
|
||||
border-bottom-color: $color__gray--darkest;
|
||||
@at-root #{&}--uninteracted {
|
||||
background-color: rgba(13, 71, 161, 0.1);
|
||||
border-bottom-color: $color__gray--darkest;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(13, 71, 161, 0.2);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
background-color: rgba(13, 71, 161, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__link {
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
@at-root #{&}__link {
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@at-root #{&}__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.9rem;
|
||||
@at-root #{&}__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.9rem;
|
||||
|
||||
@at-root #{&}__date {
|
||||
color: $color__text--secondary;
|
||||
}
|
||||
@at-root #{&}__close {
|
||||
background-color: $color__gray--darkest;
|
||||
height: 0.9rem;
|
||||
width: 0.9rem;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
border-radius: 100%;
|
||||
margin-left: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
top: 0.0625rem;
|
||||
line-height: 1;
|
||||
transition: all 0.2s;
|
||||
@at-root #{&}__date {
|
||||
color: $color__text--secondary;
|
||||
}
|
||||
@at-root #{&}__close {
|
||||
background-color: $color__gray--darkest;
|
||||
height: 0.9rem;
|
||||
width: 0.9rem;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
border-radius: 100%;
|
||||
margin-left: 0.25rem;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
top: 0.0625rem;
|
||||
line-height: 1;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__button {
|
||||
position: relative;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
transition: border 0.4s, padding 0.4s;
|
||||
@at-root #{&}__button {
|
||||
position: relative;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
transition: border 0.4s, padding 0.4s;
|
||||
|
||||
@at-root #{&}--shake {
|
||||
animation-name: shake;
|
||||
animation-iteration-count: 4;
|
||||
animation-duration: 0.25s;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
@at-root #{&}--shake {
|
||||
animation-name: shake;
|
||||
animation-iteration-count: 4;
|
||||
animation-duration: 0.25s;
|
||||
animation-timing-function: ease-in-out;
|
||||
}
|
||||
|
||||
@at-root #{&}__icon {
|
||||
font-size: 1.5rem;
|
||||
position: relative;
|
||||
top: -0.125rem;
|
||||
}
|
||||
@at-root #{&}__icon {
|
||||
font-size: 1.5rem;
|
||||
position: relative;
|
||||
top: -0.125rem;
|
||||
}
|
||||
|
||||
@at-root #{&}__count {
|
||||
position: absolute;
|
||||
background-color: $color__blue--primary;
|
||||
line-height: 1;
|
||||
margin-left: 0.25rem;
|
||||
color: #fff;
|
||||
border-radius: 100%;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
justify-content: center;
|
||||
left: 0.8rem;
|
||||
top: -0.2rem;
|
||||
@at-root #{&}__count {
|
||||
position: absolute;
|
||||
background-color: $color__blue--primary;
|
||||
line-height: 1;
|
||||
margin-left: 0.25rem;
|
||||
color: #fff;
|
||||
border-radius: 100%;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem;
|
||||
font-size: 0.9rem;
|
||||
justify-content: center;
|
||||
left: 0.8rem;
|
||||
top: -0.2rem;
|
||||
|
||||
transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
|
||||
@at-root #{&}--none {
|
||||
opacity: 0;
|
||||
}
|
||||
@at-root #{&}--two_figure {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
@at-root #{&}--three_figure {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@at-root #{&}--none {
|
||||
opacity: 0;
|
||||
}
|
||||
@at-root #{&}--two_figure {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
@at-root #{&}--three_figure {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.notification_button__menu_group {
|
||||
left: calc(3.5rem - 100vw);
|
||||
width: calc(100vw - 0.25rem);
|
||||
}
|
||||
.notification_button__menu {
|
||||
width: 100%;
|
||||
left: unset;
|
||||
right: unset ;
|
||||
@media (max-width: 600px) {
|
||||
.notification_button__menu_group {
|
||||
left: calc(3.5rem - 100vw);
|
||||
width: calc(100vw - 0.25rem);
|
||||
}
|
||||
.notification_button__menu {
|
||||
width: 100%;
|
||||
left: unset;
|
||||
right: unset ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 870px) {
|
||||
//Because the notification button is
|
||||
//actually a child of the hamburger menu
|
||||
//it 'pops up' when the overlay is showing
|
||||
//so we cover it with its own overlay
|
||||
//hacky but it works...
|
||||
.notification_button__button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
border-radius: 0.25rem;
|
||||
height: 100%;
|
||||
background-color: hsla(215, 13%, 25%, 0.5);
|
||||
transition: all 0.4s;
|
||||
}
|
||||
.header__group--show .notification_button {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
@media (max-width: 870px) {
|
||||
//Because the notification button is
|
||||
//actually a child of the hamburger menu
|
||||
//it 'pops up' when the overlay is showing
|
||||
//so we cover it with its own overlay
|
||||
//hacky but it works...
|
||||
.notification_button__button::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
width: 100%;
|
||||
border-radius: 0.25rem;
|
||||
height: 100%;
|
||||
background-color: hsla(215, 13%, 25%, 0.5);
|
||||
transition: all 0.4s;
|
||||
}
|
||||
.header__group--show .notification_button {
|
||||
cursor: default;
|
||||
pointer-events: none;
|
||||
|
||||
@at-root #{&}__button {
|
||||
border: none;
|
||||
@at-root #{&}__button {
|
||||
border: none;
|
||||
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
&::before {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notification_button {
|
||||
position: fixed;
|
||||
right: 0.5rem;
|
||||
width: 2.4rem;
|
||||
top: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
.notification_button {
|
||||
position: fixed;
|
||||
right: 0.5rem;
|
||||
width: 2.4rem;
|
||||
top: 0.5rem;
|
||||
border-radius: 0.25rem;
|
||||
|
||||
@at-root #{&}__button {
|
||||
border: none;
|
||||
}
|
||||
@at-root #{&}__button {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@at-root #{&}__menu_group {
|
||||
left: calc(3.5rem - 100vw);
|
||||
width: calc(100vw - 0.25rem);
|
||||
}
|
||||
@at-root #{&}__menu_group {
|
||||
left: calc(3.5rem - 100vw);
|
||||
width: calc(100vw - 0.25rem);
|
||||
}
|
||||
|
||||
@at-root #{&}__menu {
|
||||
left: unset;
|
||||
right: 0.5rem;
|
||||
@at-root #{&}__menu {
|
||||
left: unset;
|
||||
right: 0.5rem;
|
||||
|
||||
@at-root #{&}__empty {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
@at-root #{&}__empty {
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
@at-root #{&}__triangle {
|
||||
left: unset;
|
||||
right: 1.55rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@at-root #{&}__triangle {
|
||||
left: unset;
|
||||
right: 1.55rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
<style>
|
||||
.vertical-alt {
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
-ms-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.limit{
|
||||
margin-top: 0.5rem;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<main>
|
||||
<div class="section">
|
||||
<div class="">
|
||||
<h1>Friends:</h1>
|
||||
<scroll-load
|
||||
key='user-row'
|
||||
class='columns is-multiline'
|
||||
v-if='users.length'
|
||||
:loading='loading'
|
||||
@loadNext='fetchData'
|
||||
>
|
||||
<div class="column is-4" v-for='user in users' :key='"user-row" + user.friend2.id' v-show="user"><div class="card">
|
||||
<div class="card-content">
|
||||
<div class="media">
|
||||
<div class="media-content">
|
||||
<img width=75% style="padding-top: 10px; padding-bottom: 10px;"
|
||||
:src = '"http://localhost/user/avatars/full/" + user.friend2.picture + ".png"'
|
||||
>
|
||||
<p class="title is-4"><router-link :to="'/u/' + user.friend2.username">{{user.friend2.username}}</router-link></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content limit" v-if="user.friend2.description">
|
||||
{{user.friend2.description | truncate(70)}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</scroll-load>
|
||||
</div>
|
||||
<p name='fade' mode='out-in'>
|
||||
<center><loading-message key='loading' v-if='loading'></loading-message></center>
|
||||
<center><div class='overlay_message' v-if='!loading && !users.length'>
|
||||
This user doesn't have any friends yet :(
|
||||
</div></center></p>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
<script>
|
||||
import LoadingMessage from '../LoadingMessage';
|
||||
import ScrollLoad from '../ScrollLoad';
|
||||
import throttle from 'lodash.throttle';
|
||||
import AjaxErrorHandler from '../../assets/js/errorHandler';
|
||||
|
||||
export default {
|
||||
name: 'Inventory',
|
||||
components: {
|
||||
LoadingMessage,
|
||||
ScrollLoad
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
search: '',
|
||||
users: [],
|
||||
|
||||
loading: true,
|
||||
offset: 0,
|
||||
limit: 15,
|
||||
|
||||
roleOptions: [
|
||||
{ name: 'Admins', value: 'admin' },
|
||||
{ name: 'Users', value: 'user' }
|
||||
],
|
||||
roleSelected: ['admin', 'user'],
|
||||
|
||||
tableSort: {
|
||||
column: 'username',
|
||||
sort: 'desc'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
fetchData () {
|
||||
if(this.offset === null) return;
|
||||
|
||||
let url = process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'relationships/get/' + this.$route.params.username + `?
|
||||
sort=${this.tableSort.column}
|
||||
&order=${this.tableSort.sort}
|
||||
&offset=${this.offset}
|
||||
&inventory=true
|
||||
`;
|
||||
if(this.roleSelected.length === 1) {
|
||||
url += '&role=' + this.roleSelected[0];
|
||||
}
|
||||
if(this.search.length) {
|
||||
url += '&search=' + encodeURIComponent(this.search.trim());
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
this.axios
|
||||
.get(url)
|
||||
.then(res => {
|
||||
this.users.push(...res.data);
|
||||
this.loading = /*loading =*/ false;
|
||||
|
||||
//If returned data is less than the limit
|
||||
//then there must be no more pages to paginate
|
||||
if(res.data.length < this.limit) {
|
||||
this.offset = null;
|
||||
} else {
|
||||
this.offset+= this.limit;
|
||||
}
|
||||
})
|
||||
.catch(e => {
|
||||
AjaxErrorHandler(this.$store)(e);
|
||||
this.loading = /*loading =*/ false;
|
||||
});
|
||||
},
|
||||
resetFetchData () {
|
||||
this.offset = 0;
|
||||
this.users = [];
|
||||
|
||||
this.fetchData();
|
||||
}
|
||||
},
|
||||
getNewerUsers () {
|
||||
this.loadingNewer = true
|
||||
|
||||
this.axios
|
||||
.get(process.env.VUE_APP_APIENDPOINT + process.env.VUE_APP_APIVERSION + '/' + 'user/' + this.$route.params.username + '?limit=' + this.newUsers + '&inventory=true')
|
||||
.then(res => {
|
||||
this.loadingNewer = false
|
||||
this.newUsers = 0
|
||||
|
||||
this.threads.unshift(res.data)
|
||||
})
|
||||
.catch((e) => {
|
||||
this.loadingNewer = false
|
||||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
},
|
||||
mounted () {
|
||||
this.fetchData();
|
||||
},
|
||||
watch: {
|
||||
tableSort: 'resetFetchData',
|
||||
roleSelected: 'resetFetchData',
|
||||
search: throttle(function () {
|
||||
this.resetFetchData();
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -39,6 +39,7 @@
|
|||
</a>
|
||||
</b-upload>
|
||||
</b-field>
|
||||
<b-button>Submit</b-button>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -24,16 +24,18 @@
|
|||
:loading='loading'
|
||||
@loadNext='fetchData'
|
||||
>
|
||||
<div class="column is-4" v-for='user in users' :key='"user-row" + user.id' v-show="user && !user.hidden"><div class="card">
|
||||
<div class="column is-4" v-for='user in users' :key='"user-row" + user.friend2.id' v-show="user"><div class="card">
|
||||
<div class="card-content">
|
||||
<br>
|
||||
<div class="media">
|
||||
<div class="media-content">
|
||||
<img width=75% style="padding-top: 10px; padding-bottom: 10px;"
|
||||
:src = '"http://localhost/user/avatars/full/" + user.friend2.picture + ".png"'
|
||||
>
|
||||
<p class="title is-4"><router-link :to="'/u/' + user.friend2.username">{{user.friend2.username}}</router-link></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content limit">
|
||||
<div class="content limit" v-if="user.friend2.description">
|
||||
{{user.friend2.description | truncate(70)}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,7 +46,7 @@
|
|||
<p name='fade' mode='out-in'>
|
||||
<center><loading-message key='loading' v-if='loading'></loading-message></center>
|
||||
<center><div class='overlay_message' v-if='!loading && !users.length'>
|
||||
This user doesn't have any purchased Marketplace Items yet.
|
||||
This user doesn't have any friends yet :(
|
||||
</div></center></p>
|
||||
</div>
|
||||
</main>
|
||||
|
@ -103,7 +105,7 @@ export default {
|
|||
this.axios
|
||||
.get(url)
|
||||
.then(res => {
|
||||
this.users.push(...res.data.Inventories);
|
||||
this.users.push(...res.data);
|
||||
this.loading = /*loading =*/ false;
|
||||
|
||||
//If returned data is less than the limit
|
||||
|
|
|
@ -106,6 +106,7 @@ const Recovery = () => import('./components/routes/Recovery')
|
|||
|
||||
const Chat = () => import('./components/routes/Chat')
|
||||
const Conversation = () => import('./components/routes/Conversation')
|
||||
const Friends = () => import('./components/routes/Friends')
|
||||
|
||||
const DeveloperPortal = () => import('./components/routes/DeveloperPortal')
|
||||
const DeveloperDocs = () => import('./components/routes/DeveloperDocs')
|
||||
|
@ -245,6 +246,7 @@ const router = new VueRouter({
|
|||
{ path: '/connection', component: ConnectionProblems },
|
||||
{ path: '/maintenance', component: Maintenance },
|
||||
{ path: '/contributors', component: Contributors },
|
||||
{ path: '/friends', component: Friends },
|
||||
{ path: '/forums', redirect: '/category/all', component: Index },
|
||||
{ path: '/search/:q', component: Search },
|
||||
{ path: '/search/users/:q', component: SearchUsersThreads, name: 'search/users' },
|
||||
|
|
|
@ -35,6 +35,18 @@ let Errors = {
|
|||
'You have already sent a friend request to this person, or you are currently friends.',
|
||||
400
|
||||
],
|
||||
marketplaceNotFound: [
|
||||
'We could not find your requested Marketplace resource',
|
||||
400
|
||||
],
|
||||
uploadFile: [
|
||||
'Please upload a file',
|
||||
400
|
||||
],
|
||||
marketplaceAdminOnly: [
|
||||
'Only admins can perform this action in the Marketplace',
|
||||
401
|
||||
],
|
||||
needToBeFriend: [
|
||||
'You need to be friends with this person to do this action.',
|
||||
401
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface, Sequelize) => {
|
||||
return queryInterface.createTable('MessageNotifications', {
|
||||
id: {
|
||||
type: Sequelize.BIGINT,
|
||||
primaryKey: true,
|
||||
autoIncrement: true
|
||||
},
|
||||
createdAt: Sequelize.DATE,
|
||||
updatedAt: Sequelize.DATE,
|
||||
|
||||
UserId: Sequelize.BIGINT,
|
||||
message: Sequelize.TEXT,
|
||||
NotificationId: Sequelize.BIGINT
|
||||
}, {
|
||||
charset: 'utf8mb4'
|
||||
})
|
||||
},
|
||||
|
||||
down: (queryInterface, Sequelize) => {
|
||||
return queryInterface.dropTable('MessageNotifications');
|
||||
}
|
||||
};
|
|
@ -10,11 +10,12 @@ module.exports = (sequelize, DataTypes) => {
|
|||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: false
|
||||
},
|
||||
type: DataTypes.ENUM('mention', 'thread update', 'reply')
|
||||
type: DataTypes.ENUM('mention', 'thread update', 'reply', 'friend request', 'friend accept')
|
||||
})
|
||||
Notification.associate = function (models) {
|
||||
Notification.hasOne(models.PostNotification)
|
||||
Notification.belongsTo(models.User)
|
||||
Notification.hasOne(models.MessageNotification)
|
||||
}
|
||||
Notification.filterMentions = function (mentions) {
|
||||
//If mentions is not an array of strings
|
||||
|
@ -53,6 +54,24 @@ module.exports = (sequelize, DataTypes) => {
|
|||
|
||||
return reloadedNotification
|
||||
}
|
||||
Notification.createNotification = function (props) {
|
||||
let { MessageNotification, User, Post } = sequelize.models
|
||||
|
||||
let userTo = User.findOne({ where: { username: props.usernameTo.username } })
|
||||
if(!userTo) return null
|
||||
|
||||
let notification = Notification.create({ type: props.type, UserId: props.usernameTo.id })
|
||||
let message = MessageNotification.create({message: props.message, UserId: props.userFrom.id, NotificationId: notification.id})
|
||||
notification.setMessageNotification(message)
|
||||
let reloadedNotification = notification.toJSON({
|
||||
include: [{
|
||||
model: MessageNotification,
|
||||
include: [Post, { model: User, attributes: ['createdAt', 'username', 'color'] }]
|
||||
}]
|
||||
})
|
||||
|
||||
return reloadedNotification
|
||||
}
|
||||
Notification.prototype.emitNotificationMessage = function (ioUsers, io) {
|
||||
let User = sequelize.models.User
|
||||
let user = User.findByPk(this.UserId)
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
module.exports = (sequelize, DataTypes) => {
|
||||
let MessageNotification = sequelize.define('MessageNotification', {
|
||||
message: {
|
||||
type: DataTypes.TEXT,
|
||||
default: 'Unknown'
|
||||
}
|
||||
})
|
||||
MessageNotification.associate = function (models) {
|
||||
MessageNotification.belongsTo(models.User)
|
||||
MessageNotification.belongsTo(models.Notification)
|
||||
}
|
||||
return MessageNotification
|
||||
}
|
|
@ -1,11 +1,35 @@
|
|||
|
||||
let express = require('express')
|
||||
let router = express.Router()
|
||||
const auth = require('../lib/auth')
|
||||
let multer = require('multer')
|
||||
let cryptoRandomString = require("crypto-random-string");
|
||||
|
||||
const Errors = require('../lib/errors')
|
||||
let pagination = require('../lib/pagination')
|
||||
let { Ban, Item, Transaction, Inventory, ItemCategory, User, Ip, sequelize, Sequelize } = require('../models')
|
||||
let img2 = cryptoRandomString({length: 32})
|
||||
let img = img2
|
||||
const storage = multer.diskStorage({
|
||||
destination: (req, file, cb) => {
|
||||
cb(null, 'C:\\Users\\matth\\Documents\\GitHub\\website\\rendering\\global\\');
|
||||
},
|
||||
filename: (req, file, cb) => {
|
||||
cb(null, img)
|
||||
}
|
||||
});
|
||||
|
||||
var upload = multer({
|
||||
storage: storage,
|
||||
fileFilter: (req, file, cb) => {
|
||||
if (file.mimetype === "image/png") {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(null, false);
|
||||
return cb(new Error('Only .png is allowed'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/', async(req, res) => {
|
||||
try {
|
||||
|
@ -194,4 +218,38 @@ try {
|
|||
} catch (err) { next(err) }
|
||||
})
|
||||
|
||||
router.post('/upload/:id', auth, upload.single('image'), async (req, res, next) => {
|
||||
try {
|
||||
|
||||
let findCategory = await ItemCategory.findOne({
|
||||
where: {id: req.params.id}
|
||||
});
|
||||
let user = await User.findOne({
|
||||
where: {id: req.userData.UserId}
|
||||
});
|
||||
|
||||
if(findCategory.value === "HATS" && !req.userData.admin && !user.admin ) {
|
||||
throw Errors.marketplaceAdminOnly
|
||||
}
|
||||
if(findCategory.value === "FACES" && !req.userData.admin && !user.admin ) {
|
||||
throw Errors.marketplaceAdminOnly
|
||||
}
|
||||
if(req.body.limited && !req.userData.admin && !user.admin) {
|
||||
throw Errors.marketplaceAdminOnly
|
||||
}
|
||||
if(!req.body.image) {
|
||||
throw Errors.uploadFile
|
||||
}
|
||||
if(findCategory) {
|
||||
let marketplace = await Item.create({
|
||||
name: req.body.name, UserId: user.id, sourceFile: img, previewFile: img, limited: req.body.limited, salePrice: req.body.salePrice, saleEnabled: req.body.saleEnabled, price: req.body.price, quantityAllowed: req.body.quantityAllowed, approved: false, itemCategoryId: findCategory.id
|
||||
})
|
||||
|
||||
res.json(marketplace.toJSON())
|
||||
} else {
|
||||
throw Errors.marketplaceNotFound
|
||||
}
|
||||
} catch (e) { next(e) }
|
||||
})
|
||||
|
||||
module.exports = router
|
||||
|
|
|
@ -3,7 +3,7 @@ let router = express.Router()
|
|||
const auth = require('../lib/auth')
|
||||
|
||||
const Errors = require('../lib/errors')
|
||||
let { Notification, User, Post, PostNotification } = require('../models')
|
||||
let { Notification, User, Post, PostNotification, MessageNotification } = require('../models')
|
||||
|
||||
router.all('*', auth, (req, res, next) => {
|
||||
if(req.userData.loggedIn) {
|
||||
|
@ -26,6 +26,9 @@ router.get('/', auth, async(req, res, next) => {
|
|||
include: [{
|
||||
model: PostNotification,
|
||||
include: [Post, { model: User, attributes: ['createdAt', 'username', 'color'] }]
|
||||
}, {
|
||||
model: MessageNotification,
|
||||
include: [{model: User, attributes: ['createdAt', 'username', 'color']}]
|
||||
}]
|
||||
})
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ let express = require('express')
|
|||
let router = express.Router()
|
||||
const auth = require('../lib/auth')
|
||||
const Errors = require('../lib/errors')
|
||||
let { User, Ban, Relationship } = require('../models')
|
||||
let { User, Ban, Relationship, Notification } = require('../models')
|
||||
|
||||
router.post('/send', auth, async(req, res, next) => {
|
||||
try {
|
||||
|
@ -29,6 +29,12 @@ router.post('/send', auth, async(req, res, next) => {
|
|||
}
|
||||
Relationship.create({friend1Id: user.id, friend2Id: user2.id, type: 'pending'})
|
||||
Relationship.create({friend1Id: user2.id, friend2Id: user.id, type: 'pendingCanAccept'})
|
||||
Notification.createNotification({
|
||||
usernameTo: user2,
|
||||
userFrom: user,
|
||||
type: 'friend request',
|
||||
message: user.username + ' sent a friend request'
|
||||
})
|
||||
res.status(200)
|
||||
res.json({success: true})
|
||||
} else {
|
||||
|
@ -160,8 +166,8 @@ router.get('/get/:username', auth, async(req, res, next) => {
|
|||
throw Errors.accountDoesNotExist
|
||||
}
|
||||
let checkIfSent = await Relationship.findAll({
|
||||
where: {friend1Id: user.id},
|
||||
include: [{ model: User, as: 'friend2', attributes: ['username', 'createdAt', 'id', 'color', 'picture', 'locked', 'admin', 'booster', 'executive', 'bot'] } ]
|
||||
where: {friend1Id: user.id, type: 'accepted'},
|
||||
include: [{ model: User, as: 'friend2', attributes: ['username', 'description', 'picture', 'createdAt', 'id', 'color', 'picture', 'locked', 'admin', 'booster', 'executive', 'bot'] } ]
|
||||
})
|
||||
if (checkIfSent) {
|
||||
res.status(200)
|
||||
|
|
Loading…
Reference in New Issue