From a5cb59a7cefc789d39825469f62f58ded19a3524 Mon Sep 17 00:00:00 2001 From: Michiel De Smet Date: Thu, 18 Apr 2019 00:47:41 +0200 Subject: [PATCH 1/7] newsletter module --- .gitignore | 1 + config/default.json | 2 +- .../blocks/MyAccount/MyNewsletter.js | 34 +--------- .../newsletter/components/Newsletter.ts | 8 +++ .../modules/newsletter}/index.ts | 6 +- .../modules/newsletter/mixins}/Subscribe.ts | 15 ++--- .../newsletter/mixins/SubscriptionStatus.ts | 63 +++++++++++++++++++ core/modules/newsletter/mixins/Unsubscribe.ts | 28 +++++++++ .../modules/newsletter}/store/index.ts | 38 +++++++++-- .../newsletter}/store/mutation-types.ts | 0 .../newsletter/types/newsletterState.ts | 4 +- core/scripts/installer.js | 2 +- core/store/index.ts | 3 +- core/types/RootState.ts | 1 + src/modules/index.ts | 4 +- .../mailchimp/components/Unsubscribe.ts | 17 ----- .../components/core/NewsletterPopup.vue | 7 ++- .../core/blocks/Footer/Newsletter.vue | 10 ++- .../core/blocks/MyAccount/MyNewsletter.vue | 8 +++ 19 files changed, 167 insertions(+), 84 deletions(-) create mode 100644 core/modules/newsletter/components/Newsletter.ts rename {src/modules/mailchimp => core/modules/newsletter}/index.ts (79%) rename {src/modules/mailchimp/components => core/modules/newsletter/mixins}/Subscribe.ts (76%) create mode 100644 core/modules/newsletter/mixins/SubscriptionStatus.ts create mode 100644 core/modules/newsletter/mixins/Unsubscribe.ts rename {src/modules/mailchimp => core/modules/newsletter}/store/index.ts (57%) rename {src/modules/mailchimp => core/modules/newsletter}/store/mutation-types.ts (100%) rename src/modules/mailchimp/types/mailchimpState.ts => core/modules/newsletter/types/newsletterState.ts (59%) delete mode 100644 src/modules/mailchimp/components/Unsubscribe.ts diff --git a/.gitignore b/.gitignore index 8e800e47fc..9069dc6d6c 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/config/default.json b/config/default.json index 3ebbf6e54c..48d70ccad4 100644 --- a/config/default.json +++ b/config/default.json @@ -385,7 +385,7 @@ "fullLanguageName": "English", "bundleAllStoreviewLanguages": true }, - "mailchimp": { + "newsletter": { "endpoint": "http://localhost:8080/api/ext/mailchimp-subscribe/subscribe" }, "mailer": { diff --git a/core/compatibility/components/blocks/MyAccount/MyNewsletter.js b/core/compatibility/components/blocks/MyAccount/MyNewsletter.js index 98c7f2e180..dd2f415edb 100644 --- a/core/compatibility/components/blocks/MyAccount/MyNewsletter.js +++ b/core/compatibility/components/blocks/MyAccount/MyNewsletter.js @@ -1,35 +1,7 @@ +import { Newsletter } from '@vue-storefront/core/modules/newsletter/components/Newsletter' + // this component is deprecated and is now in Newsletter module export default { name: 'MyNewsletter', - data () { - return { - user: { - isSubscribed: false - } - } - }, - methods: { - unsubscribe () { - this.$store.dispatch('mailchimp/unsubscribe', this.$store.state.user.current.email).then(() => { - this.user.isSubscribed = false - }).catch(err => - this.$emit('unsubscription-error', err) - ) - }, - subscribe () { - this.$store.dispatch('mailchimp/subscribe', this.$store.state.user.current.email).then(() => { - this.user.isSubscribed = true - }).catch(err => - this.$emit('subscription-error', err) - ) - }, - updateNewsletter () { - if (this.user.isSubscribed) { - this.subscribe() - } else { - this.unsubscribe() - } - this.exitSection() - } - } + mixins: [Newsletter] } diff --git a/core/modules/newsletter/components/Newsletter.ts b/core/modules/newsletter/components/Newsletter.ts new file mode 100644 index 0000000000..c481644085 --- /dev/null +++ b/core/modules/newsletter/components/Newsletter.ts @@ -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] +} diff --git a/src/modules/mailchimp/index.ts b/core/modules/newsletter/index.ts similarity index 79% rename from src/modules/mailchimp/index.ts rename to core/modules/newsletter/index.ts index d507a71961..9cd941e019 100644 --- a/src/modules/mailchimp/index.ts +++ b/core/modules/newsletter/index.ts @@ -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) \ No newline at end of file +export const Newsletter = new VueStorefrontModule(moduleConfig) diff --git a/src/modules/mailchimp/components/Subscribe.ts b/core/modules/newsletter/mixins/Subscribe.ts similarity index 76% rename from src/modules/mailchimp/components/Subscribe.ts rename to core/modules/newsletter/mixins/Subscribe.ts index e584b6f255..c84dfbe963 100644 --- a/src/modules/mailchimp/components/Subscribe.ts +++ b/core/modules/newsletter/mixins/Subscribe.ts @@ -13,8 +13,8 @@ import { required, email } from 'vuelidate/lib/validators' * - `submit(success?: Function, failure?: Function)` dispatches `newsletter-mailchimp/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 const Subscribe = { - name: 'MailchimpSubscribe', +export default { + name: 'NewsletterSubscribe', data () { return { email: '' @@ -27,20 +27,15 @@ export const Subscribe = { } }, methods: { - submit (success?: Function, failure?: Function) { + subscribe (success?: Function, failure?: Function) { // argument omitted for validation purposes if (!this.$v.$invalid) { - this.$store.dispatch('mailchimp/subscribe', this.email).then(res => { + this.$store.dispatch('newsletter/subscribe', this.email).then(res => { if (success) success(res) }).catch(err => { if (failure) failure(err) } )} } - }, - computed: { - isSubscribed (): boolean { - return this.$store.state.mailchimp.subscribed - } - }, + } } diff --git a/core/modules/newsletter/mixins/SubscriptionStatus.ts b/core/modules/newsletter/mixins/SubscriptionStatus.ts new file mode 100644 index 0000000000..847600e0d9 --- /dev/null +++ b/core/modules/newsletter/mixins/SubscriptionStatus.ts @@ -0,0 +1,63 @@ +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 + * - `submit(success?: Function, failure?: Function)` dispatches `newsletter-mailchimp/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: '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) { + 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 + 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'] + } + } +} diff --git a/core/modules/newsletter/mixins/Unsubscribe.ts b/core/modules/newsletter/mixins/Unsubscribe.ts new file mode 100644 index 0000000000..a2bf943257 --- /dev/null +++ b/core/modules/newsletter/mixins/Unsubscribe.ts @@ -0,0 +1,28 @@ +import { required, email } from 'vuelidate/lib/validators' + +export default { + name: 'NewsletterUnsubscribe', + data () { + return { + email: '' + } + }, + validations: { + email: { + required, + email + } + }, + methods: { + unsubscribe () { + // argument omitted for validation purposes + if (!this.$v.$invalid) { + this.$store.dispatch('newsletter/unsubscribe', this.email).then(res => { + this.$emit('unsubscribed', res) + }).catch(err => + this.$emit('unsubscription-error', err) + ) + } + } + } +} diff --git a/src/modules/mailchimp/store/index.ts b/core/modules/newsletter/store/index.ts similarity index 57% rename from src/modules/mailchimp/store/index.ts rename to core/modules/newsletter/store/index.ts index 1c86b01881..1b4061993e 100644 --- a/src/modules/mailchimp/store/index.ts +++ b/core/modules/newsletter/store/index.ts @@ -1,15 +1,21 @@ import * as types from './mutation-types' import config from 'config' import { Module } from 'vuex' -import { mailchimpState } from '../types/mailchimpState' +import { newsletterState } from '../types/newsletterState' import { cacheStorage } from '../' +import CmsBlockState from "core/modules/cms/types/CmsBlockState"; +import RootState from "core/types/RootState"; -export const module: Module ={ +export const module: Module ={ namespaced: true, state: { - isSubscribed: null, + isSubscribed: false, email: null, }, + getters: { + isSubscribed: state => state.isSubscribed, + email: state => state.email + }, mutations: { [types.NEWSLETTER_SUBSCRIBE] (state) { state.isSubscribed = true @@ -22,10 +28,30 @@ export const module: Module ={ } }, actions: { + status ({ commit, state }, email): Promise { + 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 { 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', @@ -42,9 +68,9 @@ export const module: Module ={ } }, unsubscribe ({ commit, state }, email): Promise { - 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', diff --git a/src/modules/mailchimp/store/mutation-types.ts b/core/modules/newsletter/store/mutation-types.ts similarity index 100% rename from src/modules/mailchimp/store/mutation-types.ts rename to core/modules/newsletter/store/mutation-types.ts diff --git a/src/modules/mailchimp/types/mailchimpState.ts b/core/modules/newsletter/types/newsletterState.ts similarity index 59% rename from src/modules/mailchimp/types/mailchimpState.ts rename to core/modules/newsletter/types/newsletterState.ts index cb846e20f2..cfb28cdf47 100644 --- a/src/modules/mailchimp/types/mailchimpState.ts +++ b/core/modules/newsletter/types/newsletterState.ts @@ -1,4 +1,4 @@ -export interface mailchimpState { +export interface newsletterState { isSubscribed: boolean | null, email: string | null -} \ No newline at end of file +} diff --git a/core/scripts/installer.js b/core/scripts/installer.js index 186b73df94..72b55ebef8 100644 --- a/core/scripts/installer.js +++ b/core/scripts/installer.js @@ -450,7 +450,7 @@ class Storefront extends Abstract { config.cart.applycoupon_endpoint = `${backendPath}/api/cart/apply-coupon?token={{token}}&cartId={{cartId}}&coupon={{coupon}}` config.reviews.create_endpoint = `${backendPath}/api/review/create?token={{token}}` - config.mailchimp.endpoint = `${backendPath}/api/ext/mailchimp-subscribe/subscribe` + config.newsletter.endpoint = `${backendPath}/api/ext/mailchimp-subscribe/subscribe` config.mailer.endpoint.send = `${backendPath}/api/ext/mail-service/send-email` config.mailer.endpoint.token = `${backendPath}/api/ext/mail-service/get-token` config.images.baseUrl = this.answers.images_endpoint diff --git a/core/store/index.ts b/core/store/index.ts index d85aba7935..4968b1a4dd 100644 --- a/core/store/index.ts +++ b/core/store/index.ts @@ -19,6 +19,7 @@ const state = { shipping: {}, user: {}, ui: {}, + newsletter: {}, wishlist: {}, attribute: '', category: { @@ -47,4 +48,4 @@ let rootStore = new Vuex.Store({ state }) -export default rootStore \ No newline at end of file +export default rootStore diff --git a/core/types/RootState.ts b/core/types/RootState.ts index 515d3fc781..be459a8b0a 100644 --- a/core/types/RootState.ts +++ b/core/types/RootState.ts @@ -12,6 +12,7 @@ export default interface RootState { wishlist: any, attribute: string, ui: any, + newsletter: any, category: { current_path: string, current_product_query: any, diff --git a/src/modules/index.ts b/src/modules/index.ts index 2746a6d0ed..51d22fda1a 100644 --- a/src/modules/index.ts +++ b/src/modules/index.ts @@ -7,7 +7,7 @@ import { Compare } from '@vue-storefront/core/modules/compare' import { Review } from '@vue-storefront/core/modules/review' import { Mailer } from '@vue-storefront/core/modules/mailer' import { Wishlist } from '@vue-storefront/core/modules/wishlist' -import { Mailchimp } from '../modules/mailchimp' +import { Newsletter } from '@vue-storefront/core/modules/newsletter' import { Notification } from '@vue-storefront/core/modules/notification' import { RecentlyViewed } from '@vue-storefront/core/modules/recently-viewed' import { Url } from '@vue-storefront/core/modules/url' @@ -60,7 +60,7 @@ export const registerModules: VueStorefrontModule[] = [ Review, Mailer, Wishlist, - Mailchimp, + Newsletter, Notification, Ui, RecentlyViewed, diff --git a/src/modules/mailchimp/components/Unsubscribe.ts b/src/modules/mailchimp/components/Unsubscribe.ts deleted file mode 100644 index 3b64c05896..0000000000 --- a/src/modules/mailchimp/components/Unsubscribe.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const Unsubscribe = { - name: 'MailchimpUnsubscribe', - methods: { - unsubscribe () { - this.$store.dispatch('mailchimp/unsubscribe', this.email).then(res => { - this.$emit('unsubscribed', res) - }).catch(err => - this.$emit('unsubscription-error', err) - ) - } - }, - computed: { - isSubscribed () { - return this.$store.state.mailchimp.isSubscribed - } - } -} diff --git a/src/themes/default/components/core/NewsletterPopup.vue b/src/themes/default/components/core/NewsletterPopup.vue index 5a64ae1f21..0e545480dc 100644 --- a/src/themes/default/components/core/NewsletterPopup.vue +++ b/src/themes/default/components/core/NewsletterPopup.vue @@ -4,7 +4,7 @@ {{ $t('Newsletter') }}

-
+

{{ $t('Sign up to our newsletter and receive a coupon for 10% off!') }} @@ -41,7 +41,8 @@ diff --git a/src/themes/default/components/core/blocks/Footer/Newsletter.vue b/src/themes/default/components/core/blocks/Footer/Newsletter.vue index bd26b55e4c..a0b18a66e2 100644 --- a/src/themes/default/components/core/blocks/Footer/Newsletter.vue +++ b/src/themes/default/components/core/blocks/Footer/Newsletter.vue @@ -1,5 +1,5 @@