@ordergroove/offers 2.26.2 → 2.26.3-alpha-PR-593-11.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/build.js +3 -1
  2. package/dist/bundle-report.html +174 -103
  3. package/dist/offers.js +63 -74
  4. package/dist/offers.js.map +3 -3
  5. package/examples/cart.js +105 -0
  6. package/examples/index.html +2 -2
  7. package/examples/products/cheap-watch.js +183 -0
  8. package/examples/shopify-cart.html +26 -0
  9. package/examples/shopify-pdp.html +34 -0
  10. package/karma.conf.js +2 -1
  11. package/package.json +4 -4
  12. package/src/__tests__/offers.spec.js +32 -2
  13. package/src/components/FrequencyStatus.js +14 -11
  14. package/src/components/Offer.js +11 -7
  15. package/src/components/OptinButton.js +1 -1
  16. package/src/components/OptinSelect.js +2 -2
  17. package/src/components/OptinToggle.js +2 -2
  18. package/src/components/OptoutButton.js +1 -1
  19. package/src/components/Price.js +3 -3
  20. package/src/components/Select.js +3 -13
  21. package/src/components/SelectFrequency.js +23 -5
  22. package/src/components/__tests__/OG.fspec.js +24 -0
  23. package/src/components/__tests__/Offer.spec.js +4 -4
  24. package/src/components/__tests__/OptinButton.spec.js +2 -2
  25. package/src/components/__tests__/OptinToggle.spec.js +2 -2
  26. package/src/components/__tests__/OptoutButton.spec.js +1 -1
  27. package/src/components/__tests__/SelectFrequency.fspec.js +1 -0
  28. package/src/components/__tests__/SelectFrequency.spec.js +1 -1
  29. package/src/components/__tests__/TestWizard.spec.js +2 -2
  30. package/src/core/__tests__/actions.spec.js +6 -6
  31. package/src/core/actions.js +10 -10
  32. package/src/core/constants.js +2 -0
  33. package/src/core/reducer.js +15 -14
  34. package/src/core/resolveProperties.js +2 -7
  35. package/src/core/selectors.js +1 -1
  36. package/src/core/store.js +6 -5
  37. package/src/index.js +44 -206
  38. package/src/make-api.js +187 -0
  39. package/src/shopify/__tests__/shopifyReducer.spec.js +477 -0
  40. package/src/shopify/getProduct.ts +6 -0
  41. package/src/shopify/guessProductHandle.ts +26 -0
  42. package/src/shopify/shopifyMiddleware.ts +137 -0
  43. package/src/shopify/shopifyReducer.js +199 -0
  44. package/tsconfig.json +35 -0
  45. package/examples/5starnutrition-main.js +0 -3
  46. package/examples/single-offer.html +0 -9
  47. package/src/init-test.js +0 -3
package/src/index.js CHANGED
@@ -1,206 +1,44 @@
1
- import { offersLiveEditor } from '@ordergroove/offers-live-editor';
2
- import { setStore } from './core/connect';
3
- import { getStore } from './core/store';
4
- import { listenLocalStorageChanges } from './core/localStorage';
5
- import * as adapters from './core/adapters';
6
- import * as actions from './core/actions';
7
- import { ConnectedWhen } from './components/When';
8
- import { ConnectedOptinButton } from './components/OptinButton';
9
- import { ConnectedOptoutButton } from './components/OptoutButton';
10
- import { ConnectedOptinSelect } from './components/OptinSelect';
11
- import { ConnectedUpsellButton } from './components/UpsellButton';
12
- import { ConnectedUpsellModal } from './components/UpsellModal';
13
- import { ConnectedOptinToggle } from './components/OptinToggle';
14
- import { ConnectedOptinStatus } from './components/OptinStatus';
15
- import { ConnectedText } from './components/Text';
16
- import { ConnectedIncentiveText } from './components/IncentiveText';
17
- import { ConnectedSelectFrequency } from './components/SelectFrequency';
18
- import { ConnectedNextUpcomingOrder } from './components/NextUpcomingOrder';
19
- import { ConnectedOffer } from './components/Offer';
20
- import { Modal } from './components/Modal';
21
- import { Select } from './components/Select';
22
- import { Tooltip } from './components/Tooltip';
23
- import { ConnectedFrequencyStatus } from './components/FrequencyStatus';
24
- import * as testMode from './test-mode';
25
- import { api } from './core/api';
26
- import { environment, offer } from './core/reducer';
27
- import { RECEIVE_PRODUCT_PLANS } from './core/constants';
28
- import ConnectedPrice from './components/Price';
29
-
30
- testMode.enable();
31
- let store;
32
-
33
- export const offers = {};
34
-
35
- export function setEnvironment(e) {
36
- store.dispatch(actions.setEnvironment(e));
37
- return offers;
38
- }
39
- export function setMerchantId(m) {
40
- store.dispatch(actions.setMerchantId(m));
41
- return offers;
42
- }
43
- export function setAuthUrl(authUrl) {
44
- store.dispatch(actions.setAuthUrl(authUrl));
45
- return offers;
46
- }
47
- export function getProductsForPurchasePost(productIds = []) {
48
- return adapters.getProductsForPurchasePost(store.getState(), productIds);
49
- }
50
- export function getOptins(productIds = []) {
51
- return adapters.getProductsForPurchasePost(store.getState(), productIds);
52
- }
53
- export function clear() {
54
- store.dispatch(actions.checkout());
55
- }
56
- export function addOptinChangedCallback(fn) {
57
- if (typeof fn === 'function') document.addEventListener('optin-changed', e => fn(e.detail));
58
- }
59
- export function disableOptinChangedCallbacks() {
60
- document.addEventListener('optin-changed', e => e.stopPropagation(), true);
61
- }
62
- export function register() {
63
- try {
64
- customElements.define('og-when', ConnectedWhen);
65
- customElements.define('og-text', ConnectedText);
66
- customElements.define('og-incentive-text', ConnectedIncentiveText);
67
- customElements.define('og-offer', ConnectedOffer);
68
- customElements.define('og-select-frequency', ConnectedSelectFrequency);
69
- customElements.define('og-optout-button', ConnectedOptoutButton);
70
- customElements.define('og-optin-toggle', ConnectedOptinToggle);
71
- customElements.define('og-optin-status', ConnectedOptinStatus);
72
- customElements.define('og-optin-button', ConnectedOptinButton);
73
- customElements.define('og-optin-select', ConnectedOptinSelect);
74
- customElements.define('og-upsell-button', ConnectedUpsellButton);
75
- customElements.define('og-frequency-status', ConnectedFrequencyStatus);
76
- customElements.define('og-modal', Modal);
77
- customElements.define('og-select', Select);
78
- customElements.define('og-tooltip', Tooltip);
79
- customElements.define('og-upsell-modal', ConnectedUpsellModal);
80
- customElements.define('og-next-upcoming-order', ConnectedNextUpcomingOrder);
81
- customElements.define('og-price', ConnectedPrice);
82
- } catch (err) {
83
- // eslint-disable-next-line no-console
84
- console.warn(err);
85
- }
86
- offers.register = () => 0;
87
- }
88
- export function previewMode(set) {
89
- window.og = window.og || {};
90
- if (set === false) {
91
- delete window.og;
92
- } else {
93
- window.og.previewMode = true;
94
- }
95
- return this;
96
- }
97
- export function config(configuration) {
98
- store.dispatch(actions.setConfig(configuration));
99
- return offers;
100
- }
101
- export function setLocale(locale) {
102
- store.dispatch(actions.setLocale(locale));
103
- return offers;
104
- }
105
- export function addTemplate(tagName, content, configOption) {
106
- store.dispatch(actions.addTemplate(tagName, content, configOption));
107
- return offers;
108
- }
109
- /**
110
- * templates object where keys are selectors and values are content
111
- */
112
- export function setTemplates(templates) {
113
- store.dispatch(actions.setTemplates(templates));
114
- return offers;
115
- }
116
- export function setPublicPath(publicPath) {
117
- return offers;
118
- }
119
- export function resolveSettings(merchantId, env, settings, storeInstance = store) {
120
- if (merchantId && env && settings) {
121
- let products = [];
122
- if (settings.product) {
123
- products.push(settings.product);
124
- } else if (settings.cart && Array.isArray(settings.cart.products)) {
125
- products = products.concat(settings.cart.products);
126
- }
127
- const { apiUrl } = environment({}, actions.setEnvironment(env));
128
- const { sessionId } = storeInstance.getState();
129
- if (sessionId) {
130
- products.forEach(product => {
131
- api.fetchOffer(apiUrl, merchantId, sessionId, `${product}`, 'pdp');
132
- });
133
- }
134
-
135
- if (settings.product_discounts && typeof settings.product_discounts === 'object') {
136
- storeInstance.dispatch({ type: RECEIVE_PRODUCT_PLANS, payload: settings.product_discounts });
137
- }
138
- }
139
- }
140
-
141
- /**
142
- * Initialize OG object
143
- * @param {*} merchantId
144
- * @param {*} env
145
- * @param {*} authUrl
146
- */
147
- export function initialize(merchantId, env, authUrl) {
148
- if (offers.isReady) {
149
- console.warn('og.offers has been initialized already. Skipping.');
150
- return offers;
151
- }
152
-
153
- store = getStore();
154
-
155
- offers.store = store;
156
- offers.resolveSettings(merchantId, env, window.og_settings, store);
157
-
158
- setStore(store);
159
-
160
- if (merchantId) offers.setMerchantId(merchantId);
161
- if (env) offers.setEnvironment(env);
162
- if (authUrl) offers.setAuthUrl(authUrl);
163
-
164
- window.addEventListener('storage', listenLocalStorageChanges(store));
165
-
166
- if (merchantId && env) {
167
- store.dispatch(actions.requestSessionId());
168
- store.dispatch(actions.fetchAuth());
169
- offers.register();
170
- }
171
-
172
- offers.isReady = true;
173
-
174
- return offers;
175
- }
176
-
177
- export default initialize;
178
-
179
- Object.assign(offers, {
180
- setEnvironment,
181
- setMerchantId,
182
- setAuthUrl,
183
- getProductsForPurchasePost,
184
- getOptins,
185
- clear,
186
- addOptinChangedCallback,
187
- disableOptinChangedCallbacks,
188
- register,
189
- previewMode,
190
- config,
191
- setLocale,
192
- addTemplate,
193
- setTemplates,
194
- setPublicPath,
195
- resolveSettings,
196
- initialize
197
- });
198
-
199
- window.OG = window.OG || {};
200
- Object.assign(window.OG, offers);
201
- Object.assign(offers.initialize, offers);
202
-
203
- offersLiveEditor();
204
-
205
- // // use this syntax to allow es6 module be called as default function og.offers(...)
206
- // module.exports = offers.initialize;
1
+ import { makeStore } from './core/store';
2
+ import makeApi from './make-api';
3
+ import defaultReducer from './core/reducer';
4
+ import shopifyReducer from './shopify/shopifyReducer';
5
+ import shopifyMiddleware from './shopify/shopifyMiddleware';
6
+
7
+ // detect the
8
+ export const platform = {
9
+ shopify: !!window.Shopify
10
+ };
11
+
12
+ export const flags = {
13
+ // detect in the frontend if we should use shopify selling plans or not
14
+ selling_plans: !!window.Shopify
15
+ };
16
+
17
+ export const store = makeStore(
18
+ ...(platform.shopify && flags.selling_plans ? [shopifyReducer, shopifyMiddleware] : [defaultReducer])
19
+ );
20
+
21
+ export const offers = makeApi(store);
22
+
23
+ export const addOptinChangedCallback = offers.addOptinChangedCallback;
24
+ export const addTemplate = offers.addTemplate;
25
+ export const clear = offers.clear;
26
+ export const config = offers.config;
27
+ export const disableOptinChangedCallbacks = offers.disableOptinChangedCallbacks;
28
+ export const getOptins = offers.getOptins;
29
+ export const getProductsForPurchasePost = offers.getProductsForPurchasePost;
30
+ export const initialize = offers.initialize;
31
+ export const previewMode = offers.previewMode;
32
+ export const register = offers.register;
33
+ export const resolveSettings = offers.resolveSettings;
34
+ export const setAuthUrl = offers.setAuthUrl;
35
+ export const setEnvironment = offers.setEnvironment;
36
+ export const setLocale = offers.setLocale;
37
+ export const setMerchantId = offers.setMerchantId;
38
+ export const setPublicPath = offers.setPublicPath;
39
+ export const setTemplates = offers.setTemplates;
40
+ export const setupCart = offers.setupCart;
41
+ export const setupProduct = offers.setupProduct;
42
+ export const setupProducts = offers.setupProducts;
43
+
44
+ export default offers.initialize;
@@ -0,0 +1,187 @@
1
+ import { offersLiveEditor } from '@ordergroove/offers-live-editor';
2
+ import { setStore } from './core/connect';
3
+ import { listenLocalStorageChanges } from './core/localStorage';
4
+ import * as adapters from './core/adapters';
5
+ import * as actions from './core/actions';
6
+ import { ConnectedWhen } from './components/When';
7
+ import { ConnectedOptinButton } from './components/OptinButton';
8
+ import { ConnectedOptoutButton } from './components/OptoutButton';
9
+ import { ConnectedOptinSelect } from './components/OptinSelect';
10
+ import { ConnectedUpsellButton } from './components/UpsellButton';
11
+ import { ConnectedUpsellModal } from './components/UpsellModal';
12
+ import { ConnectedOptinToggle } from './components/OptinToggle';
13
+ import { ConnectedOptinStatus } from './components/OptinStatus';
14
+ import { ConnectedText } from './components/Text';
15
+ import { ConnectedIncentiveText } from './components/IncentiveText';
16
+ import { ConnectedSelectFrequency } from './components/SelectFrequency';
17
+ import { ConnectedNextUpcomingOrder } from './components/NextUpcomingOrder';
18
+ import { ConnectedOffer } from './components/Offer';
19
+ import { Modal } from './components/Modal';
20
+ import { Select } from './components/Select';
21
+ import { Tooltip } from './components/Tooltip';
22
+ import { ConnectedFrequencyStatus } from './components/FrequencyStatus';
23
+ import * as testMode from './test-mode';
24
+ import { api } from './core/api';
25
+ import { environment, offer } from './core/reducer';
26
+ import { RECEIVE_PRODUCT_PLANS, SETUP_CART, SETUP_PRODUCT } from './core/constants';
27
+ import ConnectedPrice from './components/Price';
28
+
29
+ export default function makeApi(store) {
30
+ testMode.enable();
31
+
32
+ setStore(store);
33
+
34
+ // // use this syntax to allow es6 module be called as default function og.offers(...)
35
+ // module.exports = offers.initialize;
36
+
37
+ const offers = {
38
+ store,
39
+ setEnvironment(e) {
40
+ store.dispatch(actions.setEnvironment(e));
41
+ return this;
42
+ },
43
+ setMerchantId(m) {
44
+ store.dispatch(actions.setMerchantId(m));
45
+ return this;
46
+ },
47
+ setAuthUrl(authUrl) {
48
+ store.dispatch(actions.setAuthUrl(authUrl));
49
+ return this;
50
+ },
51
+ getProductsForPurchasePost(productIds = []) {
52
+ return adapters.getProductsForPurchasePost(store.getState(), productIds);
53
+ },
54
+ getOptins(productIds = []) {
55
+ return adapters.getProductsForPurchasePost(store.getState(), productIds);
56
+ },
57
+ clear() {
58
+ store.dispatch(actions.checkout());
59
+ },
60
+ addOptinChangedCallback(fn) {
61
+ if (typeof fn === 'function') document.addEventListener('optin-changed', e => fn(e.detail));
62
+ },
63
+ disableOptinChangedCallbacks() {
64
+ document.addEventListener('optin-changed', e => e.stopPropagation(), true);
65
+ },
66
+
67
+ register() {
68
+ /* noop */
69
+ },
70
+ previewMode(set) {
71
+ window.og = window.og || {};
72
+ if (set === false) {
73
+ delete window.og;
74
+ } else {
75
+ window.og.previewMode = true;
76
+ }
77
+ return this;
78
+ },
79
+ config(configuration) {
80
+ store.dispatch(actions.setConfig(configuration));
81
+ return this;
82
+ },
83
+ setLocale(locale) {
84
+ store.dispatch(actions.setLocale(locale));
85
+ return this;
86
+ },
87
+ addTemplate(tagName, content, configOption) {
88
+ store.dispatch(actions.addTemplate(tagName, content, configOption));
89
+ return this;
90
+ },
91
+ /**
92
+ * templates object where keys are selectors and values are content
93
+ */
94
+ setTemplates(templates) {
95
+ store.dispatch(actions.setTemplates(templates));
96
+ return this;
97
+ },
98
+
99
+ setPublicPath(publicPath) {
100
+ return this;
101
+ },
102
+
103
+ resolveSettings(merchantId, env, settings, storeInstance = store) {
104
+ if (merchantId && env && settings) {
105
+ let products = [];
106
+ if (settings.product) {
107
+ products.push(settings.product);
108
+ } else if (settings.cart && Array.isArray(settings.cart.products)) {
109
+ products = products.concat(settings.cart.products);
110
+ }
111
+ const { apiUrl } = environment({}, actions.setEnvironment(env));
112
+ const { sessionId } = storeInstance.getState();
113
+ if (sessionId) {
114
+ products.forEach(product => {
115
+ api.fetchOffer(apiUrl, merchantId, sessionId, `${product}`, 'pdp');
116
+ });
117
+ }
118
+
119
+ if (settings.product_discounts && typeof settings.product_discounts === 'object') {
120
+ storeInstance.dispatch({ type: RECEIVE_PRODUCT_PLANS, payload: settings.product_discounts });
121
+ }
122
+ }
123
+ },
124
+
125
+ /**
126
+ * Initialize OG object
127
+ * @param {*} merchantId
128
+ * @param {*} env
129
+ * @param {*} authUrl
130
+ */
131
+ initialize(merchantId, env, authUrl) {
132
+ if (offers.isReady) {
133
+ console.warn('og.offers has been initialized already. Skipping.');
134
+ return this;
135
+ }
136
+
137
+ try {
138
+ customElements.define('og-when', ConnectedWhen);
139
+ customElements.define('og-text', ConnectedText);
140
+ customElements.define('og-incentive-text', ConnectedIncentiveText);
141
+ customElements.define('og-offer', ConnectedOffer);
142
+ customElements.define('og-select-frequency', ConnectedSelectFrequency);
143
+ customElements.define('og-optout-button', ConnectedOptoutButton);
144
+ customElements.define('og-optin-toggle', ConnectedOptinToggle);
145
+ customElements.define('og-optin-status', ConnectedOptinStatus);
146
+ customElements.define('og-optin-button', ConnectedOptinButton);
147
+ customElements.define('og-optin-select', ConnectedOptinSelect);
148
+ customElements.define('og-upsell-button', ConnectedUpsellButton);
149
+ customElements.define('og-frequency-status', ConnectedFrequencyStatus);
150
+ customElements.define('og-modal', Modal);
151
+ customElements.define('og-select', Select);
152
+ customElements.define('og-tooltip', Tooltip);
153
+ customElements.define('og-upsell-modal', ConnectedUpsellModal);
154
+ customElements.define('og-next-upcoming-order', ConnectedNextUpcomingOrder);
155
+ customElements.define('og-price', ConnectedPrice);
156
+ } catch (err) {
157
+ console.info('OG WebComponents already registered, skipping.');
158
+ }
159
+
160
+ offers.store = store;
161
+ offers.resolveSettings(merchantId, env, window.og_settings, store);
162
+
163
+ if (merchantId) offers.setMerchantId(merchantId);
164
+ if (env) offers.setEnvironment(env);
165
+ if (authUrl) offers.setAuthUrl(authUrl);
166
+
167
+ window.addEventListener('storage', listenLocalStorageChanges(store));
168
+
169
+ if (merchantId && env) {
170
+ store.dispatch(actions.requestSessionId());
171
+ store.dispatch(actions.fetchAuth());
172
+ }
173
+
174
+ offers.isReady = true;
175
+
176
+ return this;
177
+ }
178
+ };
179
+
180
+ window.OG = window.OG || {};
181
+ Object.assign(window.OG, offers);
182
+ Object.assign(offers.initialize, offers);
183
+
184
+ offersLiveEditor();
185
+
186
+ return offers;
187
+ }