mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Implement user notifications settings
This commit is contained in:
parent
bd10149e05
commit
7ae5593f82
@ -70,6 +70,7 @@ Factory.define('basicUser')
|
||||
termsAndConditionsAgreedAt: '2019-08-01T10:47:19.212Z',
|
||||
allowEmbedIframes: false,
|
||||
showShoutsPublicly: false,
|
||||
sendNotificationEmails: true,
|
||||
locale: 'en',
|
||||
})
|
||||
.attr('slug', ['slug', 'name'], (slug, name) => {
|
||||
|
||||
@ -5,12 +5,7 @@ import { htmlToText } from 'nodemailer-html-to-text'
|
||||
const hasEmailConfig = CONFIG.SMTP_HOST && CONFIG.SMTP_PORT
|
||||
const hasAuthData = CONFIG.SMTP_USERNAME && CONFIG.SMTP_PASSWORD
|
||||
|
||||
// Wolle
|
||||
// let sendMailCallback = async () => {}
|
||||
// Wolle
|
||||
let sendMailCallback = async (templateArgs) => {
|
||||
// console.log('templateArgs: ', templateArgs)
|
||||
}
|
||||
let sendMailCallback = async () => {}
|
||||
if (!hasEmailConfig) {
|
||||
if (!CONFIG.TEST) {
|
||||
// eslint-disable-next-line no-console
|
||||
@ -18,8 +13,6 @@ if (!hasEmailConfig) {
|
||||
}
|
||||
} else {
|
||||
sendMailCallback = async (templateArgs) => {
|
||||
// Wolle
|
||||
// console.log('templateArgs: ', templateArgs)
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: CONFIG.SMTP_HOST,
|
||||
port: CONFIG.SMTP_PORT,
|
||||
|
||||
@ -35,26 +35,22 @@ const queryNotificationsEmails = async (context, notificationUserIds) => {
|
||||
const publishNotifications = async (context, promises) => {
|
||||
let notifications = await Promise.all(promises)
|
||||
notifications = notifications.flat()
|
||||
// Wolle
|
||||
// console.log('notifications: ', notifications)
|
||||
const notificationsEmailAddresses = await queryNotificationsEmails(
|
||||
context,
|
||||
notifications.map((notification) => notification.to.id),
|
||||
)
|
||||
// Wolle
|
||||
// console.log('notificationsEmailAddresses: ', notificationsEmailAddresses)
|
||||
notifications.forEach((notificationAdded, index) => {
|
||||
pubsub.publish(NOTIFICATION_ADDED, { notificationAdded })
|
||||
// Wolle await
|
||||
sendMail(
|
||||
notificationTemplate({
|
||||
email: notificationsEmailAddresses[index].email,
|
||||
notification: notificationAdded,
|
||||
}),
|
||||
)
|
||||
if (notificationAdded.to.sendNotificationEmails) {
|
||||
// Wolle await
|
||||
sendMail(
|
||||
notificationTemplate({
|
||||
email: notificationsEmailAddresses[index].email,
|
||||
notification: notificationAdded,
|
||||
}),
|
||||
)
|
||||
}
|
||||
})
|
||||
// Wolle
|
||||
// return XXX successful?
|
||||
}
|
||||
|
||||
const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
|
||||
|
||||
@ -153,6 +153,10 @@ export default {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
sendNotificationEmails: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
},
|
||||
locale: {
|
||||
type: 'string',
|
||||
allow: [null],
|
||||
|
||||
@ -93,6 +93,7 @@ const signupCypher = (inviteCode) => {
|
||||
SET user.updatedAt = toString(datetime())
|
||||
SET user.allowEmbedIframes = FALSE
|
||||
SET user.showShoutsPublicly = FALSE
|
||||
SET user.sendNotificationEmails = TRUE
|
||||
SET email.verifiedAt = toString(datetime())
|
||||
RETURN user {.*}
|
||||
`
|
||||
|
||||
@ -290,6 +290,7 @@ export default {
|
||||
'termsAndConditionsAgreedAt',
|
||||
'allowEmbedIframes',
|
||||
'showShoutsPublicly',
|
||||
'sendNotificationEmails',
|
||||
'locale',
|
||||
],
|
||||
boolean: {
|
||||
|
||||
@ -46,6 +46,7 @@ type User {
|
||||
|
||||
allowEmbedIframes: Boolean
|
||||
showShoutsPublicly: Boolean
|
||||
sendNotificationEmails: Boolean
|
||||
locale: String
|
||||
friends: [User]! @relation(name: "FRIENDS", direction: "BOTH")
|
||||
friendsCount: Int! @cypher(statement: "MATCH (this)<-[:FRIENDS]->(r:User) RETURN COUNT(DISTINCT r)")
|
||||
@ -207,6 +208,7 @@ type Mutation {
|
||||
termsAndConditionsAgreedAt: String
|
||||
allowEmbedIframes: Boolean
|
||||
showShoutsPublicly: Boolean
|
||||
sendNotificationEmails: Boolean
|
||||
locale: String
|
||||
): User
|
||||
|
||||
|
||||
@ -41,6 +41,7 @@ export default (i18n) => {
|
||||
url
|
||||
}
|
||||
showShoutsPublicly
|
||||
sendNotificationEmails
|
||||
}
|
||||
}
|
||||
`
|
||||
@ -224,6 +225,7 @@ export const updateUserMutation = () => {
|
||||
$about: String
|
||||
$allowEmbedIframes: Boolean
|
||||
$showShoutsPublicly: Boolean
|
||||
$sendNotificationEmails: Boolean
|
||||
$termsAndConditionsAgreedVersion: String
|
||||
$avatar: ImageInput
|
||||
) {
|
||||
@ -235,6 +237,7 @@ export const updateUserMutation = () => {
|
||||
about: $about
|
||||
allowEmbedIframes: $allowEmbedIframes
|
||||
showShoutsPublicly: $showShoutsPublicly
|
||||
sendNotificationEmails: $sendNotificationEmails
|
||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||
avatar: $avatar
|
||||
) {
|
||||
@ -245,6 +248,7 @@ export const updateUserMutation = () => {
|
||||
about
|
||||
allowEmbedIframes
|
||||
showShoutsPublicly
|
||||
sendNotificationEmails
|
||||
locale
|
||||
termsAndConditionsAgreedVersion
|
||||
avatar {
|
||||
@ -275,6 +279,7 @@ export const currentUserQuery = gql`
|
||||
locale
|
||||
allowEmbedIframes
|
||||
showShoutsPublicly
|
||||
sendNotificationEmails
|
||||
termsAndConditionsAgreedVersion
|
||||
socialMedia {
|
||||
id
|
||||
|
||||
@ -739,13 +739,18 @@
|
||||
"unmuted": "{name} ist nicht mehr stummgeschaltet"
|
||||
},
|
||||
"name": "Einstellungen",
|
||||
"notifications": {
|
||||
"send-email-notifications": "Sende E-Mail-Benachrichtigungen",
|
||||
"name": "Benachrichtigungen",
|
||||
"success-update": "Benachrichtigungs-Einstellungen gespeichert!"
|
||||
},
|
||||
"organizations": {
|
||||
"name": "Meine Organisationen"
|
||||
},
|
||||
"privacy": {
|
||||
"make-shouts-public": "Teile von mir empfohlene Artikel öffentlich auf meinem Profil",
|
||||
"name": "Privatsphäre",
|
||||
"success-update": "Privatsphäre-Einstellungen gespeichert"
|
||||
"success-update": "Privatsphäre-Einstellungen gespeichert!"
|
||||
},
|
||||
"security": {
|
||||
"change-password": {
|
||||
|
||||
@ -739,13 +739,18 @@
|
||||
"unmuted": "{name} is unmuted again"
|
||||
},
|
||||
"name": "Settings",
|
||||
"notifications": {
|
||||
"send-email-notifications": "Send e-mail notifications",
|
||||
"name": "Notifications",
|
||||
"success-update": "Notifications settings saved!"
|
||||
},
|
||||
"organizations": {
|
||||
"name": "My Organizations"
|
||||
},
|
||||
"privacy": {
|
||||
"make-shouts-public": "Share articles I have shouted on my public profile",
|
||||
"name": "Privacy",
|
||||
"success-update": "Privacy settings saved"
|
||||
"success-update": "Privacy settings saved!"
|
||||
},
|
||||
"security": {
|
||||
"change-password": {
|
||||
|
||||
@ -51,6 +51,10 @@ export default {
|
||||
name: this.$t('settings.embeds.name'),
|
||||
path: `/settings/embeds`,
|
||||
},
|
||||
{
|
||||
name: this.$t('settings.notifications.name'),
|
||||
path: '/settings/notifications',
|
||||
},
|
||||
{
|
||||
name: this.$t('settings.download.name'),
|
||||
path: `/settings/data-download`,
|
||||
|
||||
70
webapp/pages/settings/notifications.spec.js
Normal file
70
webapp/pages/settings/notifications.spec.js
Normal file
@ -0,0 +1,70 @@
|
||||
import Vuex from 'vuex'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Notifications from './notifications.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
describe('notifications.vue', () => {
|
||||
let wrapper
|
||||
let mocks
|
||||
let store
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = {
|
||||
$t: jest.fn(),
|
||||
$apollo: {
|
||||
mutate: jest.fn(),
|
||||
},
|
||||
$toast: {
|
||||
success: jest.fn(),
|
||||
error: jest.fn(),
|
||||
},
|
||||
}
|
||||
store = new Vuex.Store({
|
||||
getters: {
|
||||
'auth/user': () => {
|
||||
return {
|
||||
id: 'u343',
|
||||
name: 'MyAccount',
|
||||
sendNotificationEmails: true,
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('mount', () => {
|
||||
const Wrapper = () => {
|
||||
return mount(Notifications, {
|
||||
store,
|
||||
mocks,
|
||||
localVue,
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.is('.base-card')).toBe(true)
|
||||
})
|
||||
|
||||
it('clicking on submit changes notifyByEmail to false', async () => {
|
||||
wrapper.find('#send-email').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
wrapper.find('.base-button').trigger('click')
|
||||
expect(wrapper.vm.notifyByEmail).toBe(false)
|
||||
})
|
||||
|
||||
it('clicking on submit with a server error shows a toast and notifyByEmail is still true', async () => {
|
||||
mocks.$apollo.mutate = jest.fn().mockRejectedValue({ message: 'Ouch!' })
|
||||
wrapper.find('#send-email').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
await wrapper.find('.base-button').trigger('click')
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(mocks.$toast.error).toHaveBeenCalledWith('Ouch!')
|
||||
expect(wrapper.vm.notifyByEmail).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
61
webapp/pages/settings/notifications.vue
Normal file
61
webapp/pages/settings/notifications.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<base-card>
|
||||
<h2 class="title">{{ $t('settings.notifications.name') }}</h2>
|
||||
<ds-space margin-bottom="small">
|
||||
<input id="send-email" type="checkbox" v-model="notifyByEmail" />
|
||||
<label for="send-email">{{ $t('settings.notifications.send-email-notifications') }}</label>
|
||||
</ds-space>
|
||||
<base-button filled @click="submit" :disabled="disabled">{{ $t('actions.save') }}</base-button>
|
||||
</base-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { updateUserMutation } from '~/graphql/User'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
notifyByEmail: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
disabled() {
|
||||
return this.notifyByEmail === this.currentUser.sendNotificationEmails
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.notifyByEmail = this.currentUser.sendNotificationEmails || false
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
setCurrentUser: 'auth/SET_USER',
|
||||
}),
|
||||
async submit() {
|
||||
try {
|
||||
await this.$apollo.mutate({
|
||||
mutation: updateUserMutation(),
|
||||
variables: {
|
||||
id: this.currentUser.id,
|
||||
sendNotificationEmails: this.notifyByEmail,
|
||||
},
|
||||
update: (_, { data: { UpdateUser } }) => {
|
||||
const { sendNotificationEmails } = UpdateUser
|
||||
this.setCurrentUser({
|
||||
...this.currentUser,
|
||||
sendNotificationEmails,
|
||||
})
|
||||
this.$toast.success(this.$t('settings.notifications.success-update'))
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
this.notifyByEmail = !this.notifyByEmail
|
||||
this.$toast.error(error.message)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
Loading…
x
Reference in New Issue
Block a user