New client tour (#8921)

* Linted tour. Added intro tour

* Added initial tours

* Fixed page number for intro

* Lint fix

* Updated shrinkwrap

* Removed bootstrap tour

* Lint fix
This commit is contained in:
Keith Holliday
2017-08-02 20:15:00 -06:00
committed by GitHub
parent 026014b8d6
commit e61884ed08
8 changed files with 376 additions and 333 deletions

5
npm-shrinkwrap.json generated
View File

@@ -5189,6 +5189,11 @@
"from": "intersect@>=0.0.3 <0.1.0", "from": "intersect@>=0.0.3 <0.1.0",
"resolved": "https://registry.npmjs.org/intersect/-/intersect-0.0.3.tgz" "resolved": "https://registry.npmjs.org/intersect/-/intersect-0.0.3.tgz"
}, },
"intro.js": {
"version": "2.6.0",
"from": "intro.js@latest",
"resolved": "http://registry.npmjs.org/intro.js/-/intro.js-2.6.0.tgz"
},
"invariant": { "invariant": {
"version": "2.2.2", "version": "2.2.2",
"from": "invariant@>=2.2.0 <3.0.0", "from": "invariant@>=2.2.0 <3.0.0",

View File

@@ -73,6 +73,7 @@
"html-webpack-plugin": "^2.8.1", "html-webpack-plugin": "^2.8.1",
"image-size": "~0.3.2", "image-size": "~0.3.2",
"in-app-purchase": "^1.1.6", "in-app-purchase": "^1.1.6",
"intro.js": "^2.6.0",
"jade": "~1.11.0", "jade": "~1.11.0",
"jquery": "^3.1.1", "jquery": "^3.1.1",
"js2xmlparser": "~1.0.0", "js2xmlparser": "~1.0.0",

View File

@@ -63,6 +63,7 @@ export default {
}; };
</script> </script>
<style src="intro.js/minified/introjs.min.css"></style>
<style src="bootstrap/scss/bootstrap.scss" lang="scss"></style> <style src="bootstrap/scss/bootstrap.scss" lang="scss"></style>
<style src="assets/scss/index.scss" lang="scss"></style> <style src="assets/scss/index.scss" lang="scss"></style>
<style src="assets/css/index.css"></style> <style src="assets/css/index.css"></style>

View File

@@ -84,10 +84,10 @@
v-for="group in itemsGroups", v-for="group in itemsGroups",
v-if="viewOptions[group.key].selected", v-if="viewOptions[group.key].selected",
:key="group.key", :key="group.key",
:class='group.key',
) )
h2 h2
| {{ group.label }} | {{ group.label }}
|
span.badge.badge-pill.badge-default {{items[group.key].length}} span.badge.badge-pill.badge-default {{items[group.key].length}}
.items .items

View File

@@ -105,11 +105,9 @@
div.potion-icon(:class="'Pet_HatchingPotion_'+currentDraggingPotion.key") div.potion-icon(:class="'Pet_HatchingPotion_'+currentDraggingPotion.key")
div.popover div.popover
div.popover-content {{ $t('clickOnEggToHatch', {potionName: currentDraggingPotion.text() }) }} div.popover-content {{ $t('clickOnEggToHatch', {potionName: currentDraggingPotion.text() }) }}
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.hatchingPotionInfo { .hatchingPotionInfo {
position: absolute; position: absolute;
left: -500px; left: -500px;

View File

@@ -25,6 +25,7 @@ div
import { mapState } from 'client/libs/store'; import { mapState } from 'client/libs/store';
import notifications from 'client/mixins/notifications'; import notifications from 'client/mixins/notifications';
import guide from 'client/mixins/guide';
import welcomeModal from './achievements/welcome'; import welcomeModal from './achievements/welcome';
import newStuff from './achievements/newStuff'; import newStuff from './achievements/newStuff';
@@ -49,7 +50,7 @@ import ultimateGear from './achievements/ultimateGear';
import wonChallenge from './achievements/wonChallenge'; import wonChallenge from './achievements/wonChallenge';
export default { export default {
mixins: [notifications], mixins: [notifications, guide],
components: { components: {
wonChallenge, wonChallenge,
ultimateGear, ultimateGear,
@@ -132,8 +133,8 @@ export default {
invitedToQuest () { invitedToQuest () {
return this.user.party.quest.RSVPNeeded && !this.user.party.quest.completed; return this.user.party.quest.RSVPNeeded && !this.user.party.quest.completed;
}, },
userDailies () { userTasks () {
return this.$store.state.tasks.data.dailys; return this.$store.state.tasks.data;
}, },
}, },
watch: { watch: {
@@ -223,7 +224,8 @@ export default {
if (after !== true) return; if (after !== true) return;
this.$root.$emit('show::modal', 'quest-invitation'); this.$root.$emit('show::modal', 'quest-invitation');
}, },
userDailies () { userTasks () {
// @TODO: Is this the best way to check for loaded?
this.runYesterDailies(); this.runYesterDailies();
}, },
}, },
@@ -231,6 +233,12 @@ export default {
if (!this.user.flags.welcomed) { if (!this.user.flags.welcomed) {
this.$root.$emit('show::modal', 'welcome'); this.$root.$emit('show::modal', 'welcome');
} }
window.setTimeout(() => {
this.initTour();
if (this.user.flags.tour.intro === this.TOUR_END) return;
this.goto('intro', 0);
}, 2000);
}, },
methods: { methods: {
playSound () { playSound () {

View File

@@ -1,5 +1,5 @@
<template lang="pug"> <template lang="pug">
.tasks-column .tasks-column(:class='type')
b-modal(ref="editTaskModal") b-modal(ref="editTaskModal")
span Hello From My Modal! span Hello From My Modal!
.d-flex .d-flex

View File

@@ -1,278 +1,302 @@
// var chapters = { // import each from 'lodash/each';
// intro: [ // import flattenDeep from 'lodash/flattenDeep';
// [ import times from 'lodash/times';
// { import Intro from 'intro.js/';
export default {
data () {
return {
TOUR_END: -2,
tour: {},
chapters: {},
loaded: false,
};
},
watch: {
$route () {
this.routeChange();
},
},
methods: {
load () {
// @TODO: this should be called after app is loaded
// Init and show the welcome tour (only after user is pulled from server & wrapped).
if (window.env.IS_MOBILE) return; // Don't show tour immediately on mobile devices
// let alreadyShown = (before, after) => {
// return Boolean(!before && after === true);
// };
// $rootScope.$watch('user.flags.dropsEnabled', _.flow(alreadyShown, function(already) { //FIXME requires lodash@~3.2.0
},
initTour () {
if (this.loaded) return;
this.chapters = {
intro: [
[
{
// state: 'options.profile.avatar', // state: 'options.profile.avatar',
// element: '.tab-content.ng-scope', element: '.member-details',
// content: this.$t('tourAvatar'), intro: this.$t('tourAvatar'),
// placement: 'top', // placement: 'top',
// proceed: this.$t('tourAvatarProceed'), // proceed: this.$t('tourAvatarProceed'),
// backdrop: false, // backdrop: false,
// orphan: true, // orphan: true,
// gold: 4, // gold: 4,
// experience: 29 // experience: 29,
// }, },
// { {
// state: 'tasks', // state: 'tasks',
// element: '.task-column.todos', element: '.todo',
// content: this.$t('tourToDosBrief'), intro: this.$t('tourToDosBrief'),
// placement: 'top', placement: 'top',
// proceed: this.$t('tourOkay'), // proceed: this.$t('tourOkay'),
// gold: 4, // gold: 4,
// experience: 29 // experience: 29,
// }, },
// { {
// state: 'tasks', // state: 'tasks',
// element: '.task-column.dailys', element: '.daily',
// content: this.$t('tourDailiesBrief'), intro: this.$t('tourDailiesBrief'),
// placement: 'top', placement: 'top',
// proceed: this.$t('tourDailiesProceed'), // proceed: this.$t('tourDailiesProceed'),
// gold: 4, // gold: 4,
// experience: 29 // experience: 29,
// }, },
// { {
// state: 'tasks', // state: 'tasks',
// element: '.task-column.habits', element: '.habit',
// content: this.$t('tourHabitsBrief'), intro: this.$t('tourHabitsBrief'),
// placement: 'top', placement: 'top',
// proceed: this.$t('tourHabitsProceed'), // proceed: this.$t('tourHabitsProceed'),
// gold: 4, // gold: 4,
// experience: 29 // experience: 29,
// }, },
// { {
// state: 'tasks', // state: 'tasks',
// element: 'h2.task-column_title.reward-title', element: '.reward',
// content: User.user.flags.armoireEnabled ? this.$t('tourRewardsArmoire') : this.$t('tourRewardsBrief'), intro: this.user.flags.armoireEnabled ? this.$t('tourRewardsArmoire') : this.$t('tourRewardsBrief'),
// placement: 'left', placement: 'left',
// proceed: this.$t('tourRewardsProceed'), // proceed: this.$t('tourRewardsProceed'),
// gold: 4, // gold: 4,
// experience: 29, // experience: 29,
// final: true
// }
// ]
// ],
// classes: [
// [
// {
// orphan: true,
// content: this.$t('classGearText'),
// final: true, // final: true,
// state: 'options.inventory.equipment', },
// element: '.equipment-tab', ],
// title: this.$t('classGear'), ],
// hideNavigation: true classes: [
// } [
// /*, { {
// state: 'options.profile.stats', orphan: true,
// element: '.allocate-stats', intro: this.$t('classGearText'),
// title: this.$t('stats'), final: true,
// content: this.$t('classStats') state: 'options.inventory.equipment',
// }, { element: '.weapon',
// state: 'options.profile.stats', title: this.$t('classGear'),
// element: '.auto-allocate', hideNavigation: true,
// title: this.$t('autoAllocate'), },
// placement: 'left', ],
// content: this.$t('autoAllocateText') ],
// }, { stats: [[
// element: '.meter.mana', {
// title: this.$t('spells'), orphan: true,
// content: this.$t('spellsText') intro: this.$t('tourStatsPage'),
// }, { final: true,
proceed: this.$t('tourOkay'),
hideNavigation: true,
},
]],
tavern: [[
{
orphan: true,
intro: this.$t('tourTavernPage'),
final: true,
proceed: this.$t('tourAwesome'),
hideNavigation: true,
},
]],
party: [[
{
orphan: true,
intro: this.$t('tourPartyPage'),
final: true,
proceed: this.$t('tourSplendid'),
hideNavigation: true,
},
]],
guilds: [[
{
// orphan: true, // orphan: true,
// title: this.$t('readMore'), intro: this.$t('tourGuildsPage'),
// content: this.$t('moreClass'),
// final: true
// }*/
// ]
// ],
// stats: [[
// {
// orphan: true,
// content: this.$t('tourStatsPage'),
// final: true,
// proceed: this.$t('tourOkay'),
// hideNavigation: true
// }
// ]],
// tavern: [[
// {
// orphan: true,
// content: this.$t('tourTavernPage'),
// final: true,
// proceed: this.$t('tourAwesome'),
// hideNavigation: true
// }
// ]],
// party: [[
// {
// orphan: true,
// content: this.$t('tourPartyPage'),
// final: true,
// proceed: this.$t('tourSplendid'),
// hideNavigation: true
// }
// ]],
// guilds: [[
// {
// orphan: true,
// content: this.$t('tourGuildsPage'),
// final: true, // final: true,
// proceed: this.$t('tourNifty'), // proceed: this.$t('tourNifty'),
// hideNavigation: true // hideNavigation: true,
// } },
// ]], ]],
// challenges: [[ challenges: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourChallengesPage'), intro: this.$t('tourChallengesPage'),
// final: true, final: true,
// proceed: this.$t('tourOkay'), proceed: this.$t('tourOkay'),
// hideNavigation: true hideNavigation: true,
// } },
// ]], ]],
// market: [[ market: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourMarketPage'), intro: this.$t('tourMarketPage'),
// final: true, final: true,
// proceed: this.$t('tourAwesome'), proceed: this.$t('tourAwesome'),
// hideNavigation: true hideNavigation: true,
// } },
// ]], ]],
// hall: [[ hall: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourHallPage'), intro: this.$t('tourHallPage'),
// final: true, final: true,
// proceed: this.$t('tourSplendid'), proceed: this.$t('tourSplendid'),
// hideNavigation: true hideNavigation: true,
// } },
// ]], ]],
// pets: [[ pets: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourPetsPage'), intro: this.$t('tourPetsPage'),
// final: true, final: true,
// proceed: this.$t('tourNifty'), proceed: this.$t('tourNifty'),
// hideNavigation: true hideNavigation: true,
// } },
// ]], ]],
// mounts: [[ mounts: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourMountsPage'), intro: this.$t('tourMountsPage'),
// final: true, final: true,
// proceed: this.$t('tourOkay'), proceed: this.$t('tourOkay'),
// hideNavigation: true hideNavigation: true,
// } },
// ]], ]],
// equipment: [[ equipment: [[
// { {
// orphan: true, orphan: true,
// content: this.$t('tourEquipmentPage'), intro: this.$t('tourEquipmentPage'),
// final: true, final: true,
// proceed: this.$t('tourAwesome'), proceed: this.$t('tourAwesome'),
// hideNavigation: true hideNavigation: true,
// } },
// ]] ]],
// } };
// let chapters = this.chapters;
// each(chapters, (chapter, k) => {
// flattenDeep(chapter).forEach((step, i) => {
// // @TODO: (env.worldDmg.guide ? 'npc_justin_broken' : 'npc_justin')
// step.content = `<div><div class='npc_justin float-left'></div>${step.content}</div>`;
// // @TODO: $(step.element).popover('destroy'); // destroy existing hover popovers so we can add our own
// //
// _.each(chapters, function(chapter, k){ // step.onShow = () => {
// _(chapter).flattenDeep().forEach(function(step, i) { // // @TODO: Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'tutorial','eventLabel':k+'-web','eventValue':i+1,'complete':false});
// step.content = '<div><div class='' + (env.worldDmg.guide ? 'npc_justin_broken' : 'npc_justin') + ' float-left'></div>' + step.content + '</div>'; // // @TODO: Add Router if (!step.state || $state.is(step.state)) return;
// $(step.element).popover('destroy'); // destroy existing hover popovers so we can add our own // // @TODO: Add Router $state.go(step.state);
// step.onShow = function(){ // // @TODO: Do we need this? return $timeout(() => {});
// Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'tutorial','eventLabel':k+'-web','eventValue':i+1,'complete':false});
// if (step.state && !$state.is(step.state)) {
// $state.go(step.state);
// return $timeout(function(){});
// }
// }; // };
// step.onHide = function(){
// var ups = {};
// var lastKnownStep = User.user.flags.tour[k];
//
// // Return early if user has already completed this tutorial
// if (lastKnownStep === -2) {
// return;
// }
//
// if (i > lastKnownStep) {
// if (step.gold) ups['stats.gp'] = User.user.stats.gp + step.gold;
// if (step.experience) ups['stats.exp'] = User.user.stats.exp + step.experience;
// ups['flags.tour.'+k] = i;
// }
//
// if (step.final) { // -2 indicates complete
// if (k === 'intro') {
// // Manually show bunny scroll reward
// var rewardData = {
// reward: [Shared.content.quests.dustbunnies],
// rewardKey: ['inventory_quest_scroll_dustbunnies'],
// rewardText: Shared.content.quests.dustbunnies.text(),
// message: this.$t('checkinEarned'),
// nextRewardAt: 1,
// };
// Notification.showLoginIncentive(User.user, rewardData, Social.loadWidgets);
// }
// //Mark tour complete
// ups['flags.tour.'+k] = -2;
// Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'tutorial','eventLabel':k+'-web','eventValue':i+1,'complete':true})
// }
//
// User.set(ups);
// // User.set() doesn't include a check for level changes, so manually check here.
// if (step.experience) {
// User.user.fns.updateStats(User.user.stats);
// }
// }
// }); // });
// }); // });
//
// var tour = {}; // let tour = this.tour;
// _.each(chapters, function(v,k){ // each(chapters, (v, k) => {
// tour[k] = new Tour({ // tour[k] = new Tour({
// name: k, // name: k,
// backdrop: true, // backdrop: true,
// template: function(i,step){ // template: (i, step) => {
// var showFinish = step.final || k == 'classes'; // let showFinish = step.final || k === 'classes';
// var showCounter = k=='intro' && !step.final; // let showCounter = k === 'intro' && !step.final;
// // TODO: we can probably create a component for all this
// //
// return '<div class='popover' role='tooltip'>' + // let counterSpan = '';
// '<div class='arrow'></div>' + // if (showCounter) counterSpan = `<span style="float:right;">${i + 1} of ${flattenDeep(chapters[k]).length}</span>`;
// '<h3 class='popover-title'></h3>' + //
// '<div class='popover-content'></div>' + // let prevButton = '';
// '<div class='popover-navigation'> ' + // if (!step.hideNavigation) prevButton = '<button class="btn btn-sm btn-default" data-role="prev">&laquo; Previous</button>';
// (showCounter ? '<span style='float:right;'>'+ (i+1 +' of '+ _.flattenDeep(chapters[k]).length) +'</span>' : '')+ // counter //
// '<div class='btn-group'>' + // let nextButton = '';
// (step.hideNavigation ? '' : '<button class='btn btn-sm btn-default' data-role='prev'>&laquo; Previous</button>') + // let stepProceedText = 'Next';
// (showFinish ? ('<button class='btn btn-sm btn-primary' data-role='end' style='float:none;'>' + (step.proceed ? step.proceed : 'Finish Tour') + '</button>') : // if (step.proceed) stepProceedText = step.proceed;
// (step.hideNavigation ? '' : ('<button class='btn btn-sm btn-primary' data-role='next'>' + (step.proceed ? step.proceed : 'Next') + ' &raquo;</button>'))) + // if (!step.hideNavigation) nextButton = `<button class="btn btn-sm btn-primary" data-role="next">${stepProceedText} &raquo;</button>`;
// '<button class='btn btn-sm btn-default' data-role='pause-resume' data-pause-text='Pause' data-resume-text='Resume'>Pause</button>' + // let stepFinishText = 'Finish Tour';
// '</div>' + // if (step.proceed) stepFinishText = step.proceed;
// '</div>' + // if (showFinish) nextButton = `<button class="btn btn-sm btn-primary" data-role="end" style="float:none;">${stepFinishText}</button>`;
// '</div>'; //
// return `<div class="popover" role="tooltip"> \
// <div class="arrow"></div> \
// <h3 class="popover-title"></h3> \
// <div class="popover-content"></div> \
// <div class="popover-navigation"> \
// ${counterSpan} \
// <div class="btn-group"> \
// ${prevButton} \
// ${nextButton} \
// <button class="btn btn-sm btn-default" \
// data-role="pause-resume" data-pause-text="Pause" data-resume-text="Resume">Pause</button> \
// </div> \
// </div> \
// </div>`;
// }, // },
// storage: false // storage: false,
// }); // });
// }); // });
// this.loaded = true;
// var goto = function(chapter, page, force) { },
// if (chapter == 'intro' && User.user.flags.welcomed != true) User.set({'flags.welcomed': true}); routeChange () {
// if (chapter == 'classes' && User.user.flags.tour.classes === -2) return; this.initTour();
// if (page === -1) page = 0; switch (this.$route.name) {
// var curr = User.user.flags.tour[chapter]; // case 'options.profile.avatar': return goto('intro', 5);
// if (page != curr+1 && !force) return; case 'stats': return this.goto('stats', 0);
// var chap = tour[chapter], opts = chap._options; case 'tavern': return this.goto('tavern', 0);
// opts.steps = []; case 'party': return this.goto('party', 0);
// _.times(page, function(p){ case 'guildsDiscovery': return this.goto('guilds', 0);
// opts.steps = opts.steps.concat(chapters[chapter][p]); case 'challenges': return this.goto('challenges', 0);
// }) case 'patrons': return this.goto('hall', 0);
// case 'items': return this.goto('market', 0);
// var end = opts.steps.length; case 'stable': return this.goto('pets', 0);
// opts.steps = opts.steps.concat(chapters[chapter][page]); // @TODO: same page now case 'stable': return this.goto('mounts', 0);
case 'equipment': return this.goto('equipment', 0);
}
},
hoyo (user) {
// @TODO: What is was the timeout for?
window.amplitude.setUserId(user._id);
window.ga('set', {userId: user._id});
},
goto (chapter, page, force) {
if (chapter === 'intro' && this.user.flags.welcomed !== true) {
// @TODO: Add dispatch User.set({'flags.welcomed': true});
}
if (chapter === 'classes' && this.user.flags.tour.classes === -2) return;
if (page === -1) page = 0;
let curr = this.user.flags.tour[chapter];
if (page !== curr + 1 && !force) return;
let chap = this.tour[chapter];
if (!chap) return;
let opts = chap._options;
opts.steps = [];
page += 1;
times(page, (p) => {
opts.steps = opts.steps.concat(this.chapters[chapter][p]);
});
// let end = opts.steps.length;
// opts.steps = opts.steps.concat(this.chapters[chapter][page]);
// chap._removeState('end'); // chap._removeState('end');
// // @TODO: Do we always need to initialize here?
let intro = Intro.introJs();
intro.setOptions({steps: opts.steps});
intro.start();
intro.oncomplete(() => {
this.markTourComplete(chapter);
});
// if (chap._inited) { // if (chap._inited) {
// chap.goTo(end); // chap.goTo(end);
// } else { // } else {
@@ -284,42 +308,48 @@
// chap.start(); // chap.start();
// } // }
// } // }
},
markTourComplete (chapter) {
// @TODO: this is suppose to keep track of wher ethe left off. Do that later
let ups = {};
let lastKnownStep = this.user.flags.tour[chapter];
// Return early if user has already completed this tutorial
if (lastKnownStep === -2) {
return;
}
// if (i > lastKnownStep) {
// if (step.gold) ups['stats.gp'] = this.user.stats.gp + step.gold;
// if (step.experience) ups['stats.exp'] = this.user.stats.exp + step.experience;
// ups[`flags.tour.${k}`] = i;
// } // }
//
// //Init and show the welcome tour (only after user is pulled from server & wrapped). // step.final
// var watcher = $rootScope.$watch('User.user._wrapped', function(wrapped){ // if (true) { // -2 indicates complete
// if (!wrapped) return; // only run after user has been wrapped // if (chapter === 'intro') {
// watcher(); // deregister watcher // // Manually show bunny scroll reward
// if (window.env.IS_MOBILE) return; // Don't show tour immediately on mobile devices // // let rewardData = {
// if (User.user.flags.welcomed == false) { // // reward: [Shared.content.quests.dustbunnies],
// $rootScope.openModal('welcome', {size: 'lg', backdrop: 'static', keyboard: false}); // // rewardKey: ['inventory_quest_scroll_dustbunnies'],
// // rewardText: Shared.content.quests.dustbunnies.text(),
// // message: this.$t('checkinEarned'),
// // nextRewardAt: 1,
// // };
// // @TODO: Notification.showLoginIncentive(this.user, rewardData, Social.loadWidgets);
// } // }
//
// var alreadyShown = function(before, after) { return !(!before && after === true) }; // Mark tour complete
// //$rootScope.$watch('user.flags.dropsEnabled', _.flow(alreadyShown, function(already) { //FIXME requires lodash@~3.2.0 ups[`flags.tour.${chapter}`] = -2; // @TODO: Move magic numbers to enum
// $rootScope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){ // @TODO: Analytics.track({'hitType':'event','eventCategory':'behavior','eventAction':'tutorial','eventLabel':k+'-web','eventValue':i+1,'complete':true})
// switch (toState.name) {
// // case 'options.profile.avatar': return goto('intro', 5);
// case 'options.profile.stats': return goto('stats', 0);
// case 'options.social.tavern': return goto('tavern', 0);
// case 'options.social.party': return goto('party', 0);
// case 'options.social.guilds.public': return goto('guilds', 0);
// case 'options.social.challenges': return goto('challenges', 0);
// case 'options.social.hall.heroes': return goto('hall', 0);
// case 'options.inventory.drops': return goto('market', 0);
// case 'options.inventory.pets': return goto('pets', 0);
// case 'options.inventory.mounts': return goto('mounts', 0);
// case 'options.inventory.equipment': return goto('equipment', 0);
// } // }
// });
// }); this.$store.dispatch('user:set', ups);
// // User.set() doesn't include a check for level changes, so manually check here.
// export default { // @TODO:
// methods: { // if (step.experience) {
// hoyo (user) { // this.user.fns.updateStats(this.user.stats);
// // @TODO: What is was the timeout for? // }
// window.amplitude.setUserId(user._id); },
// window.ga('set', {userId: user._id}); },
// }, };
// },
// };