Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

newsletter module #2754

Merged
merged 15 commits into from
May 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ core/resource/i18n/nl-NL.json
core/resource/i18n/pl-PL.json
core/resource/i18n/pt-BR.json
core/resource/i18n/ru-RU.json
*.iml

#unit testing
/test/unit/coverage
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Global config api path under `api.url` - @BartoszLiburski (#2622)
- Google Tag Manager integration - @talalus (#841)
- Portuguese (pt-PT) translation - @xlcnd (#2695)
- Module Mailchimp is removed in favor of more generic Newsletter - @mdesmet (#2558)
- Added `syncTasks` cleanup, `elasticCacheQuota` lowered to 3096KB - @pkarw (#2729)
- Added back-button on orde detail page [#2819]
- Added Elastic Search Suggestions in the Search Response - @jpetar (#2853)
Expand Down
2 changes: 1 addition & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@
"fullLanguageName": "English",
"bundleAllStoreviewLanguages": true
},
"mailchimp": {
"newsletter": {
"endpoint": "http://localhost:8080/api/ext/mailchimp-subscribe/subscribe"
},
"mailer": {
Expand Down
44 changes: 0 additions & 44 deletions core/compatibility/components/blocks/MyAccount/MyNewsletter.js

This file was deleted.

8 changes: 8 additions & 0 deletions core/modules/newsletter/components/Newsletter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import SubscriptionStatus from '@vue-storefront/core/modules/newsletter/mixins/SubscriptionStatus'
import Subscribe from '@vue-storefront/core/modules/newsletter/mixins/Subscribe'
import Unsubscribe from '@vue-storefront/core/modules/newsletter/mixins/Unsubscribe'

export const Newsletter = {
name: 'Newsletter',
mixins: [SubscriptionStatus, Subscribe, Unsubscribe]
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import { module } from './store'
import { VueStorefrontModule, VueStorefrontModuleConfig } from '@vue-storefront/core/lib/module'
import { initCacheStorage } from '@vue-storefront/core/helpers/initCacheStorage'

export const KEY = 'mailchimp'
export const KEY = 'newsletter'
export const cacheStorage = initCacheStorage(KEY)

const moduleConfig: VueStorefrontModuleConfig = {
key: KEY,
store: { modules: [{ key: KEY, module }] },
}

export const Mailchimp = new VueStorefrontModule(moduleConfig)
export const Newsletter = new VueStorefrontModule(moduleConfig)
39 changes: 39 additions & 0 deletions core/modules/newsletter/mixins/Subscribe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { required, email } from 'vuelidate/lib/validators'

/**
* Newsletter subscription form component.
*
* #### Data
* - `email: String` - email that will be used for subscription, validated with vuelidate (email, required)
*
* #### Methods
* - `subscribe(success?: Function, failure?: Function)` dispatches `newsletter/subscribe` with `email` data property. `success(res)` and `failure(err)` are callback functions called depending on subscription result and contain response info or error.
*
*/
export default {
name: 'NewsletterSubscribe',
data () {
return {
email: ''
}
},
validations: {
email: {
required,
email
}
},
methods: {
subscribe (success?: Function, failure?: Function) {
// argument omitted for validation purposes
if (!this.$v.$invalid) {
return this.$store.dispatch('newsletter/subscribe', this.email).then(res => {
if (success) success(res)
}).catch(err => {
if (failure) failure(err)
}
)
}
}
}
}
64 changes: 64 additions & 0 deletions core/modules/newsletter/mixins/SubscriptionStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { required, email } from 'vuelidate/lib/validators'

/**
* Newsletter subscription form component.
*
* #### Data
* - `email: String` - email that will be used for subscription, validated with vuelidate (email, required)
*
* ### Computed
* - `isSubscribed: boolean` - returns true if user subscribed to the newsletter in this session
*
* #### Methods
* - `checkStatus(success?: Function, failure?: Function)` dispatches `newsletter/status` with `email` data property. `success(res)` and `failure(err)` are callback functions called depending on subscription result and contain response info or error.
*
*/
export default {
name: 'SubscriptionStatus',
data () {
return {
email: '',
user: {
isSubscribed: false
}
}
},
validations: {
email: {
required,
email
}
},
methods: {
onLoggedIn () {
this.email = this.$store.state.user.current.email
this.checkStatus(response => {
this.user.isSubscribed = response.result === 'subscribed'
})
},
checkStatus (success?: Function, failure?: Function) {
// argument omitted for validation purposes
if (!this.$v.$invalid) {
return this.$store.dispatch('newsletter/status', this.email).then(res => {
if (success) success(res)
}).catch(err => {
if (failure) failure(err)
}
)
}
}
},
beforeMount () {
// the user might already be logged in, so check the subscription status
if (this.$store.state.user.current) this.onLoggedIn()
this.$bus.$on('user-after-loggedin', this.onLoggedIn)
},
beforeDestroy () {
this.$bus.$off('user-after-loggedin', this.onLoggedIn)
},
computed: {
isSubscribed () : Boolean {
return this.$store.getters['newsletter/isSubscribed']
}
}
}
38 changes: 38 additions & 0 deletions core/modules/newsletter/mixins/Unsubscribe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { required, email } from 'vuelidate/lib/validators'

/**
* Newsletter subscription form component.
*
* #### Data
* - `email: String` - email that will be used for subscription, validated with vuelidate (email, required)
*
* #### Methods
* - `unsubscribe(success?: Function, failure?: Function)` dispatches `newsletter/unsubscribe` with `email` data property. `success(res)` and `failure(err)` are callback functions called depending on subscription result and contain response info or error.
*
*/
export default {
name: 'NewsletterUnsubscribe',
data () {
return {
email: ''
}
},
validations: {
email: {
required,
email
}
},
methods: {
unsubscribe () {
// argument omitted for validation purposes
if (!this.$v.$invalid) {
return this.$store.dispatch('newsletter/unsubscribe', this.email).then(res => {
this.$emit('unsubscribed', res)
}).catch(err =>
this.$emit('unsubscription-error', err)
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import * as types from './mutation-types'
import { Module } from 'vuex'
import { mailchimpState } from '../types/mailchimpState'
import { newsletterState } from '../types/newsletterState'
import { cacheStorage } from '../'
import config from 'config'

export const module: Module<mailchimpState, any> ={
export const module: Module<newsletterState, any> ={
namespaced: true,
state: {
isSubscribed: null,
email: null,
},
getters: {
isSubscribed: state => state.isSubscribed,
email: state => state.email
},
mutations: {
[types.NEWSLETTER_SUBSCRIBE] (state) {
state.isSubscribed = true
Expand All @@ -22,11 +26,32 @@ export const module: Module<mailchimpState, any> ={
}
},
actions: {
status ({ commit, state }, email): Promise<Response> {

return new Promise((resolve, reject) => {
fetch(config.newsletter.endpoint + '?email=' + encodeURIComponent(email), {
method: 'GET',
headers: { 'Content-Type': 'application/json' },
mode: 'cors'
}).then(res => res.json())
.then(res => {
if(res.result === 'subscribed') {
commit(types.SET_EMAIL, email)
commit(types.NEWSLETTER_SUBSCRIBE)
} else {
commit(types.NEWSLETTER_UNSUBSCRIBE)
}
resolve(res)
}).catch(err => {
reject(err)
})
})
},
subscribe ({ commit, state }, email): Promise<Response> {

if (!state.isSubscribed) {
return new Promise((resolve, reject) => {
fetch(config.mailchimp.endpoint, {
fetch(config.newsletter.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
Expand All @@ -43,10 +68,10 @@ export const module: Module<mailchimpState, any> ={
}
},
unsubscribe ({ commit, state }, email): Promise<Response> {
if (!state.isSubscribed) {

if (state.isSubscribed) {
return new Promise((resolve, reject) => {
fetch(config.mailchimp.endpoint, {
fetch(config.newsletter.endpoint, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
mode: 'cors',
Expand Down
19 changes: 19 additions & 0 deletions core/modules/newsletter/test/unit/components/Newsletter.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { mountMixinWithStore } from '@vue-storefront/unit-tests/utils'

import { Newsletter } from '../../../components/Newsletter'

jest.mock('@vue-storefront/core/modules/newsletter/mixins/SubscriptionStatus', () => ({}))
jest.mock('@vue-storefront/core/modules/newsletter/mixins/Subscribe', () => ({}))
jest.mock('@vue-storefront/core/modules/newsletter/mixins/Unsubscribe', () => ({}))

describe('Newsletter', () => {
beforeEach(() => {
jest.clearAllMocks()
})

it('can be initialized', () => {
const wrapper = mountMixinWithStore(Newsletter)

expect(wrapper.isVueInstance()).toBe(true)
})
})
Loading