mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
Vuex Structure (#8054)
* wip: vuex structure * add missing files * client: do not fail dev build on eslint error * eslint does not block compilation, mount app when data is ready * eslintrc.js -> eslintrc
This commit is contained in:
@@ -13,8 +13,8 @@
|
|||||||
"async": "^1.5.0",
|
"async": "^1.5.0",
|
||||||
"autoprefixer": "^6.4.0",
|
"autoprefixer": "^6.4.0",
|
||||||
"aws-sdk": "^2.0.25",
|
"aws-sdk": "^2.0.25",
|
||||||
"babel-loader": "^6.0.0",
|
|
||||||
"babel-core": "^6.0.0",
|
"babel-core": "^6.0.0",
|
||||||
|
"babel-loader": "^6.0.0",
|
||||||
"babel-plugin-transform-async-to-module-method": "^6.8.0",
|
"babel-plugin-transform-async-to-module-method": "^6.8.0",
|
||||||
"babel-polyfill": "^6.6.1",
|
"babel-polyfill": "^6.6.1",
|
||||||
"babel-preset-es2015": "^6.6.0",
|
"babel-preset-es2015": "^6.6.0",
|
||||||
@@ -108,6 +108,7 @@
|
|||||||
"vue": "^2.0.0-rc.6",
|
"vue": "^2.0.0-rc.6",
|
||||||
"vue-hot-reload-api": "^1.2.0",
|
"vue-hot-reload-api": "^1.2.0",
|
||||||
"vue-loader": "^9.4.0",
|
"vue-loader": "^9.4.0",
|
||||||
|
"vue-resource": "^1.0.2",
|
||||||
"vue-router": "^2.0.0-rc.5",
|
"vue-router": "^2.0.0-rc.5",
|
||||||
"vuex": "^2.0.0-rc.5",
|
"vuex": "^2.0.0-rc.5",
|
||||||
"vuex-router-sync": "^3.0.0",
|
"vuex-router-sync": "^3.0.0",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
require('eventsource-polyfill')
|
require('eventsource-polyfill')
|
||||||
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
|
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true&overlay=false')
|
||||||
|
|
||||||
hotClient.subscribe(function (event) {
|
hotClient.subscribe(function (event) {
|
||||||
if (event.action === 'reload') {
|
if (event.action === 'reload') {
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ var baseConfig = {
|
|||||||
if (!IS_PROD) {
|
if (!IS_PROD) {
|
||||||
baseConfig.eslint = {
|
baseConfig.eslint = {
|
||||||
formatter: require('eslint-friendly-formatter'),
|
formatter: require('eslint-friendly-formatter'),
|
||||||
|
emitWarning: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
module.exports = baseConfig;
|
module.exports = baseConfig;
|
||||||
@@ -23,7 +23,6 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
||||||
new webpack.optimize.OccurenceOrderPlugin(),
|
new webpack.optimize.OccurenceOrderPlugin(),
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
new webpack.HotModuleReplacementPlugin(),
|
||||||
new webpack.NoErrorsPlugin(),
|
|
||||||
// https://github.com/ampedandwired/html-webpack-plugin
|
// https://github.com/ampedandwired/html-webpack-plugin
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: 'index.html',
|
filename: 'index.html',
|
||||||
|
|||||||
@@ -6,5 +6,4 @@
|
|||||||
"plugins": [
|
"plugins": [
|
||||||
"html"
|
"html"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
#app
|
#app
|
||||||
site-header
|
site-header
|
||||||
|
p Welcome back {{user.profile.name}}
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
router-link(to='/') Home
|
router-link(to='/') Home
|
||||||
@@ -11,15 +12,35 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SiteHeader from './siteHeader';
|
import SiteHeader from './siteHeader';
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SiteHeader,
|
SiteHeader,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: mapState(['user']),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading-screen { /* outside Vue because can't wait for rendering to finish */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
z-index: 10001;
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
#app
|
#app
|
||||||
site-header
|
site-header
|
||||||
|
p Welcome back {{user.profile.name}}
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
router-link(to='/') Home
|
router-link(to='/') Home
|
||||||
@@ -11,15 +12,35 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import SiteHeader from './siteHeader';
|
import SiteHeader from './siteHeader';
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
SiteHeader,
|
SiteHeader,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: mapState(['user']),
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loading-screen { /* outside Vue because can't wait for rendering to finish */
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #fff;
|
||||||
|
z-index: 10001;
|
||||||
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
<title>Habitica</title>
|
<title>Habitica</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<!-- #loading-screen needs to be rendered before vue, will be deleted once app is loaded -->
|
||||||
|
<div id="loading-screen">Loading...</div>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -4,16 +4,37 @@ require('babel-polyfill');
|
|||||||
|
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VuexRouterSync from 'vuex-router-sync';
|
import VuexRouterSync from 'vuex-router-sync';
|
||||||
import App from './components/app';
|
import VueResource from 'vue-resource';
|
||||||
|
import AppComponent from './components/app';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import store from './vuex/store';
|
import store from './vuex/store';
|
||||||
|
|
||||||
|
Vue.use(VueResource);
|
||||||
|
Vue.http.headers.common['x-api-user'] = '';
|
||||||
|
Vue.http.headers.common['x-api-key'] = '';
|
||||||
|
|
||||||
// Sync Vuex and Router
|
// Sync Vuex and Router
|
||||||
VuexRouterSync.sync(store, router);
|
VuexRouterSync.sync(store, router);
|
||||||
|
|
||||||
new Vue({ // eslint-disable-line no-new
|
const app = new Vue({ // eslint-disable-line no-new
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
el: '#app',
|
render: h => h(AppComponent),
|
||||||
render: h => h(App),
|
mounted () { // Remove the loading screen when the app is mounted
|
||||||
});
|
let loadingScreen = document.getElementById('loading-screen');
|
||||||
|
if (loadingScreen) document.body.removeChild(loadingScreen);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup listener for title that is outside Vue's scope
|
||||||
|
store.watch(state => state.title, (title) => {
|
||||||
|
document.title = title;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mount the app when the user is loaded
|
||||||
|
let userWatcher = store.watch(state => state.user, (user) => {
|
||||||
|
if (user && user._id) {
|
||||||
|
userWatcher(); // remove the watcher
|
||||||
|
app.$mount('#app');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
15
website/client/vuex/actions.js
Normal file
15
website/client/vuex/actions.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export function setTitle (store, title) {
|
||||||
|
store.commit('SET_TITLE', title);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function fetchUser (store) {
|
||||||
|
let promise = Vue.http.get('/api/v3/user');
|
||||||
|
|
||||||
|
promise.then(response => {
|
||||||
|
store.commit('SET_USER', response.body.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
7
website/client/vuex/mutations.js
Normal file
7
website/client/vuex/mutations.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export function SET_TITLE (state, title) {
|
||||||
|
state.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SET_USER (state, userJson) {
|
||||||
|
state.user = userJson;
|
||||||
|
}
|
||||||
@@ -1,12 +1,17 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
import * as mutations from './mutations';
|
||||||
|
import * as actions from './actions';
|
||||||
|
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
title: 'Habitica',
|
title: 'Habitica',
|
||||||
|
user: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state,
|
state,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
});
|
});
|
||||||
Reference in New Issue
Block a user