From f128f3d3cdcd76da2b58fcf194e960c153636bb9 Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Fri, 22 Sep 2017 13:29:08 +0200 Subject: [PATCH] Client Fixes (#9064) * fix loading of payments scripts * improve loading times --- website/client/app.vue | 7 ++++ .../components/payments/amazonModal.vue | 21 ++++++---- website/client/index.html | 3 -- website/client/libs/analytics.js | 40 +++++++++---------- website/client/libs/payments.js | 32 +++++++++++++++ website/client/main.js | 9 +++-- website/client/store/index.js | 5 ++- 7 files changed, 80 insertions(+), 37 deletions(-) create mode 100644 website/client/libs/payments.js diff --git a/website/client/app.vue b/website/client/app.vue index a4299b6639..75da88904c 100644 --- a/website/client/app.vue +++ b/website/client/app.vue @@ -75,6 +75,7 @@ import * as Analytics from 'client/libs/analytics'; import BuyModal from './components/shops/buyModal.vue'; import SelectMembersModal from 'client/components/selectMembersModal.vue'; import notifications from 'client/mixins/notifications'; +import { setup as setupPayments } from 'client/libs/payments'; export default { mixins: [notifications], @@ -205,6 +206,12 @@ export default { 'preferences.timezoneOffset': this.browserTimezoneOffset, }); } + + this.$nextTick(() => { + // Load external scripts after the app has been rendered + setupPayments(); + Analytics.load(); + }); }).catch((err) => { console.error('Impossible to fetch user. Clean up localStorage and refresh.', err); // eslint-disable-line no-console }); diff --git a/website/client/components/payments/amazonModal.vue b/website/client/components/payments/amazonModal.vue index d7eea171d4..58814b7554 100644 --- a/website/client/components/payments/amazonModal.vue +++ b/website/client/components/payments/amazonModal.vue @@ -19,7 +19,6 @@ - - - diff --git a/website/client/libs/analytics.js b/website/client/libs/analytics.js index b42673f7fe..4862d86899 100644 --- a/website/client/libs/analytics.js +++ b/website/client/libs/analytics.js @@ -5,6 +5,10 @@ import includes from 'lodash/includes'; import getStore from 'client/store'; import Vue from 'vue'; +const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env +const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env +const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env + let REQUIRED_FIELDS = ['hitType', 'eventCategory', 'eventAction']; let ALLOWED_HIT_TYPES = [ 'pageview', @@ -93,12 +97,7 @@ export function updateUser (properties) { }); } - export function setup () { - const IS_PRODUCTION = process.env.NODE_ENV === 'production'; // eslint-disable-line no-process-env - const AMPLITUDE_KEY = process.env.AMPLITUDE_KEY; // eslint-disable-line no-process-env - const GA_ID = process.env.GA_ID; // eslint-disable-line no-process-env - // Setup queues until the real scripts are loaded /* eslint-disable */ @@ -119,25 +118,24 @@ export function setup () { }, window['ga'].l = 1 * new Date(); ga('create', GA_ID); /* eslint-enable */ +} +export function load () { // Load real scripts - if (!IS_PRODUCTION) return; - Vue.nextTick(() => { - // Amplitude - const amplitudeScript = document.createElement('script'); - let firstScript = document.getElementsByTagName('script')[0]; - amplitudeScript.type = 'text/javascript'; - amplitudeScript.async = true; - amplitudeScript.src = 'https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.2.0-min.gz.js'; - firstScript.parentNode.insertBefore(amplitudeScript, firstScript); + // Amplitude + const amplitudeScript = document.createElement('script'); + let firstScript = document.getElementsByTagName('script')[0]; + amplitudeScript.type = 'text/javascript'; + amplitudeScript.async = true; + amplitudeScript.src = 'https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.2.0-min.gz.js'; + firstScript.parentNode.insertBefore(amplitudeScript, firstScript); - // Google Analytics - const gaScript = document.createElement('script'); - firstScript = document.getElementsByTagName('script')[0]; - gaScript.async = 1; - gaScript.src = '//www.google-analytics.com/analytics.js'; - firstScript.parentNode.insertBefore(gaScript, firstScript); - }); + // Google Analytics + const gaScript = document.createElement('script'); + firstScript = document.getElementsByTagName('script')[0]; + gaScript.async = 1; + gaScript.src = '//www.google-analytics.com/analytics.js'; + firstScript.parentNode.insertBefore(gaScript, firstScript); } \ No newline at end of file diff --git a/website/client/libs/payments.js b/website/client/libs/payments.js new file mode 100644 index 0000000000..1ebfe8cdaa --- /dev/null +++ b/website/client/libs/payments.js @@ -0,0 +1,32 @@ +import getStore from 'client/store'; + +const AMAZON_PAYMENTS = process.env.AMAZON_PAYMENTS; // eslint-disable-line +const NODE_ENV = process.env.NODE_ENV; // eslint-disable-line + +export function setup () { + const store = getStore(); + + // Set Amazon Payments as ready in the store, + // Added here to make sure the listener is registered before the script can be executed + window.onAmazonLoginReady = () => { + store.state.isAmazonReady = true; + window.amazon.Login.setClientId(AMAZON_PAYMENTS.CLIENT_ID); + }; + + // Load the scripts + + // Amazon Payments + const amazonScript = document.createElement('script'); + let firstScript = document.getElementsByTagName('script')[0]; + amazonScript.type = 'text/javascript'; + amazonScript.async = true; + amazonScript.src = `https://static-na.payments-amazon.com/OffAmazonPayments/us/${(NODE_ENV === 'production' ? '' : 'sandbox/')}js/Widgets.js`; + firstScript.parentNode.insertBefore(amazonScript, firstScript); + + // Stripe + const stripeScript = document.createElement('script'); + firstScript = document.getElementsByTagName('script')[0]; + stripeScript.async = true; + stripeScript.src = '//checkout.stripe.com/v2/checkout.js'; + firstScript.parentNode.insertBefore(stripeScript, firstScript); +} \ No newline at end of file diff --git a/website/client/main.js b/website/client/main.js index ef40655bc2..ad9b6e5790 100644 --- a/website/client/main.js +++ b/website/client/main.js @@ -4,7 +4,9 @@ require('babel-polyfill'); import Vue from 'vue'; import AppComponent from './app'; -import { setup as setupAnalytics } from 'client/libs/analytics'; +import { + setup as setupAnalytics, +} from 'client/libs/analytics'; import router from './router'; import getStore from './store'; import StoreModule from './libs/store'; @@ -27,11 +29,12 @@ Vue.config.productionTip = IS_PRODUCTION; Vue.use(i18n, {i18nData: window && window['habitica-i18n']}); Vue.use(StoreModule); -setupAnalytics(); +setupAnalytics(); // just create queues for analytics, no scripts loaded at this time +const store = getStore(); export default new Vue({ el: '#app', router, - store: getStore(), + store, render: h => h(AppComponent), }); diff --git a/website/client/store/index.js b/website/client/store/index.js index ca3c07154e..ba56c21112 100644 --- a/website/client/store/index.js +++ b/website/client/store/index.js @@ -55,6 +55,7 @@ export default function () { title: 'Habitica', isUserLoggedIn, isUserLoaded: false, // Means the user and the user's tasks are ready + isAmazonReady: false, // Whether the Amazon Payments lib can be used user: asyncResourceFactory(), credentials: AUTH_SETTINGS ? { API_ID: AUTH_SETTINGS.auth.apiId, @@ -95,9 +96,9 @@ export default function () { cloning: false, tasksToClone: {}, }, - editingGroup: {}, // TODO move to local state + editingGroup: {}, // @TODO move to local state // content data, frozen to prevent Vue from modifying it since it's static and never changes - // TODO apply freezing to the entire codebase (the server) and not only to the client side? + // @TODO apply freezing to the entire codebase (the server) and not only to the client side? // NOTE this takes about 10-15ms on a fast computer content: deepFreeze(content), constants: deepFreeze({...commonConstants, DAY_MAPPING}),