mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge pull request #1658 from Human-Connection/1637-notifications-self-update
🍰 Notifications self update and refactoring
This commit is contained in:
commit
1fed79a674
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -9,4 +9,4 @@
|
||||
],
|
||||
"editor.formatOnSave": false,
|
||||
"eslint.autoFixOnSave": true
|
||||
}
|
||||
}
|
||||
|
||||
@ -351,10 +351,12 @@ When("I log in with the following credentials:", table => {
|
||||
});
|
||||
|
||||
When("open the notification menu and click on the first item", () => {
|
||||
cy.get(".notifications-menu").click();
|
||||
cy.get(".notifications-menu").invoke('show').click(); // "invoke('show')" because of the delay for show the menu
|
||||
cy.get(".notification-mention-post")
|
||||
.first()
|
||||
.click();
|
||||
.click({
|
||||
force: true
|
||||
});
|
||||
});
|
||||
|
||||
Then("see {int} unread notifications in the top menu", count => {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
Feature: Notifications for a mentions
|
||||
Feature: Notification for a mention
|
||||
As a user
|
||||
I want to be notified if sb. mentions me in a post or comment
|
||||
In order join conversations about or related to me
|
||||
|
||||
@ -69,16 +69,16 @@ describe('Notification', () => {
|
||||
it('renders reason', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('.reason-text-for-test').text()).toEqual(
|
||||
'notifications.menu.commented_on_post',
|
||||
'notifications.reason.commented_on_post',
|
||||
)
|
||||
})
|
||||
it('renders title', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.text()).toContain("It's a post title")
|
||||
})
|
||||
it('renders the "Comment:"', () => {
|
||||
it('renders the identifier "notifications.comment"', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.text()).toContain('Comment:')
|
||||
expect(wrapper.text()).toContain('notifications.comment')
|
||||
})
|
||||
it('renders the contentExcerpt', () => {
|
||||
wrapper = Wrapper()
|
||||
@ -119,7 +119,7 @@ describe('Notification', () => {
|
||||
it('renders reason', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('.reason-text-for-test').text()).toEqual(
|
||||
'notifications.menu.mentioned_in_post',
|
||||
'notifications.reason.mentioned_in_post',
|
||||
)
|
||||
})
|
||||
it('renders title', () => {
|
||||
@ -169,7 +169,7 @@ describe('Notification', () => {
|
||||
it('renders reason', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('.reason-text-for-test').text()).toEqual(
|
||||
'notifications.menu.mentioned_in_comment',
|
||||
'notifications.reason.mentioned_in_comment',
|
||||
)
|
||||
})
|
||||
it('renders title', () => {
|
||||
@ -177,9 +177,9 @@ describe('Notification', () => {
|
||||
expect(wrapper.text()).toContain("It's a post title")
|
||||
})
|
||||
|
||||
it('renders the "Comment:"', () => {
|
||||
it('renders the identifier "notifications.comment"', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.text()).toContain('Comment:')
|
||||
expect(wrapper.text()).toContain('notifications.comment')
|
||||
})
|
||||
|
||||
it('renders the contentExcerpt', () => {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<hc-user :user="from.author" :date-time="from.createdAt" :trunc="35" />
|
||||
</ds-space>
|
||||
<ds-text class="reason-text-for-test" color="soft">
|
||||
{{ $t(`notifications.menu.${notification.reason}`) }}
|
||||
{{ $t(`notifications.reason.${notification.reason}`) }}
|
||||
</ds-text>
|
||||
</client-only>
|
||||
<ds-space margin-bottom="x-small" />
|
||||
@ -23,7 +23,9 @@
|
||||
>
|
||||
<ds-space margin-bottom="x-small" />
|
||||
<div>
|
||||
<span v-if="isComment" class="comment-notification-header">Comment:</span>
|
||||
<span v-if="isComment" class="comment-notification-header">
|
||||
{{ $t(`notifications.comment`) }}:
|
||||
</span>
|
||||
{{ from.contentExcerpt | removeHtml }}
|
||||
</div>
|
||||
</ds-card>
|
||||
|
||||
@ -46,11 +46,46 @@ describe('NotificationMenu.vue', () => {
|
||||
expect(wrapper.contains('.dropdown')).toBe(false)
|
||||
})
|
||||
|
||||
describe('given only unread notifications', () => {
|
||||
beforeEach(() => {
|
||||
data = () => {
|
||||
return {
|
||||
displayedNotifications: [
|
||||
{
|
||||
id: 'notification-41',
|
||||
read: true,
|
||||
post: {
|
||||
id: 'post-1',
|
||||
title: 'some post title',
|
||||
contentExcerpt: 'this is a post content',
|
||||
author: {
|
||||
id: 'john-1',
|
||||
slug: 'john-doe',
|
||||
name: 'John Doe',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('counter displays 0', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('ds-button-stub').text()).toEqual('0')
|
||||
})
|
||||
|
||||
it('button is not primary', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('ds-button-stub').props('primary')).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('given some notifications', () => {
|
||||
beforeEach(() => {
|
||||
data = () => {
|
||||
return {
|
||||
notifications: [
|
||||
displayedNotifications: [
|
||||
{
|
||||
id: 'notification-41',
|
||||
read: false,
|
||||
@ -79,15 +114,34 @@ describe('NotificationMenu.vue', () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'notification-43',
|
||||
read: true,
|
||||
post: {
|
||||
id: 'post-3',
|
||||
title: 'read post title',
|
||||
contentExcerpt: 'this is yet another post content',
|
||||
author: {
|
||||
id: 'john-1',
|
||||
slug: 'john-doe',
|
||||
name: 'John Doe',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('displays the total number of notifications', () => {
|
||||
it('displays the number of unread notifications', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('ds-button-stub').text()).toEqual('2')
|
||||
})
|
||||
|
||||
it('renders primary button', () => {
|
||||
wrapper = Wrapper()
|
||||
expect(wrapper.find('ds-button-stub').props('primary')).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
<template>
|
||||
<ds-button v-if="totalNotifications <= 0" class="notifications-menu" disabled icon="bell">
|
||||
{{ totalNotifications }}
|
||||
<ds-button v-if="!notificationsCount" class="notifications-menu" disabled icon="bell">
|
||||
{{ unreadNotificationsCount }}
|
||||
</ds-button>
|
||||
<dropdown v-else class="notifications-menu" :placement="placement">
|
||||
<template slot="default" slot-scope="{ toggleMenu }">
|
||||
<ds-button primary icon="bell" @click.prevent="toggleMenu">
|
||||
{{ totalNotifications }}
|
||||
<ds-button :primary="!!unreadNotificationsCount" icon="bell" @click.prevent="toggleMenu">
|
||||
{{ unreadNotificationsCount }}
|
||||
</ds-button>
|
||||
</template>
|
||||
<template slot="popover">
|
||||
<div class="notifications-menu-popover">
|
||||
<notification-list :notifications="notifications" @markAsRead="markAsRead" />
|
||||
<notification-list :notifications="displayedNotifications" @markAsRead="markAsRead" />
|
||||
</div>
|
||||
</template>
|
||||
</dropdown>
|
||||
@ -18,6 +18,7 @@
|
||||
|
||||
<script>
|
||||
import Dropdown from '~/components/Dropdown'
|
||||
import { NOTIFICATIONS_POLL_INTERVAL } from '~/constants/notifications'
|
||||
import { notificationQuery, markAsReadMutation } from '~/graphql/User'
|
||||
import NotificationList from '../NotificationList/NotificationList'
|
||||
|
||||
@ -29,6 +30,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
displayedNotifications: [],
|
||||
notifications: [],
|
||||
}
|
||||
},
|
||||
@ -46,17 +48,29 @@ export default {
|
||||
variables,
|
||||
})
|
||||
if (!(markAsRead && markAsRead.read === true)) return
|
||||
this.notifications = this.notifications.map(n => {
|
||||
return n.from.id === markAsRead.from.id ? markAsRead : n
|
||||
this.displayedNotifications = this.displayedNotifications.map(n => {
|
||||
return this.equalNotification(n, markAsRead) ? markAsRead : n
|
||||
})
|
||||
} catch (err) {
|
||||
throw new Error(err)
|
||||
this.$toast.error(err.message)
|
||||
}
|
||||
},
|
||||
equalNotification(a, b) {
|
||||
return a.from.id === b.from.id && a.createdAt === b.createdAt && a.reason === b.reason
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
totalNotifications() {
|
||||
return (this.notifications || []).length
|
||||
notificationsCount() {
|
||||
return (this.displayedNotifications || []).length
|
||||
},
|
||||
unreadNotificationsCount() {
|
||||
let countUnread = 0
|
||||
if (this.displayedNotifications) {
|
||||
this.displayedNotifications.forEach(notification => {
|
||||
if (!notification.read) countUnread++
|
||||
})
|
||||
}
|
||||
return countUnread
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
@ -64,6 +78,23 @@ export default {
|
||||
query() {
|
||||
return notificationQuery(this.$i18n)
|
||||
},
|
||||
pollInterval() {
|
||||
return NOTIFICATIONS_POLL_INTERVAL
|
||||
},
|
||||
update(data) {
|
||||
const newNotifications = data.notifications.filter(newN => {
|
||||
return !this.displayedNotifications.find(oldN => this.equalNotification(newN, oldN))
|
||||
})
|
||||
this.displayedNotifications = newNotifications
|
||||
.concat(this.displayedNotifications)
|
||||
.sort((a, b) => {
|
||||
return new Date(b.createdAt) - new Date(a.createdAt)
|
||||
})
|
||||
return data.notifications
|
||||
},
|
||||
error(error) {
|
||||
this.$toast.error(error)
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
1
webapp/constants/notifications.js
Normal file
1
webapp/constants/notifications.js
Normal file
@ -0,0 +1 @@
|
||||
export const NOTIFICATIONS_POLL_INTERVAL = 60000
|
||||
@ -135,11 +135,12 @@
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"menu": {
|
||||
"reason": {
|
||||
"mentioned_in_post": "Hat dich in einem Beitrag erwähnt …",
|
||||
"mentioned_in_comment": "Hat dich in einem Kommentar erwähnt …",
|
||||
"commented_on_post": "Hat deinen Beitrag kommentiert …"
|
||||
}
|
||||
},
|
||||
"comment": "Kommentar"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Suchen",
|
||||
|
||||
@ -136,11 +136,12 @@
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"menu": {
|
||||
"reason": {
|
||||
"mentioned_in_post": "Mentioned you in a post …",
|
||||
"mentioned_in_comment": "Mentioned you in a comment …",
|
||||
"commented_on_post": "Commented on your post …"
|
||||
}
|
||||
},
|
||||
"comment": "Comment"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "Search",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user