introduce vuex
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
weeman 2021-09-19 17:30:37 +02:00
parent 94d2a98b96
commit a408cae686
Signed by: weeman
GPG Key ID: 34F0524D4DA694A1
10 changed files with 129 additions and 46 deletions

24
package-lock.json generated
View File

@ -21,7 +21,8 @@
"sass": "^1.37.5", "sass": "^1.37.5",
"sass-loader": "^10.2.0", "sass-loader": "^10.2.0",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-router": "^4.0.0-0" "vue-router": "^4.0.0-0",
"vuex": "^4.0.2"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -13335,6 +13336,18 @@
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
"dev": true "dev": true
}, },
"node_modules/vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"dev": true,
"dependencies": {
"@vue/devtools-api": "^6.0.0-beta.11"
},
"peerDependencies": {
"vue": "^3.0.2"
}
},
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "1.7.5", "version": "1.7.5",
"resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437900992&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz", "resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437900992&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz",
@ -25940,6 +25953,15 @@
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
"dev": true "dev": true
}, },
"vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"dev": true,
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
},
"watchpack": { "watchpack": {
"version": "1.7.5", "version": "1.7.5",
"resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437900992&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz", "resolved": "https://registry.nlark.com/watchpack/download/watchpack-1.7.5.tgz?cache=0&sync_timestamp=1621437900992&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fwatchpack%2Fdownload%2Fwatchpack-1.7.5.tgz",

View File

@ -20,6 +20,7 @@
"sass": "^1.37.5", "sass": "^1.37.5",
"sass-loader": "^10.2.0", "sass-loader": "^10.2.0",
"vue": "^3.0.0", "vue": "^3.0.0",
"vue-router": "^4.0.0-0" "vue-router": "^4.0.0-0",
"vuex": "^4.0.2"
} }
} }

View File

@ -8,7 +8,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
<header v-if="this.$route.path.includes('/s/')"> <header v-if="this.$route.path.includes('/s/')">
<Navbar /> <Navbar />
</header> </header>
<router-view /> <router-view :key="$route.fullPath" />
<Footer /> <Footer />
</template> </template>
<script> <script>
@ -16,21 +16,10 @@ import Footer from '@/components/Footer.vue'
import Navbar from '@/components/Navbar.vue' import Navbar from '@/components/Navbar.vue'
export default { export default {
name: "App", name: 'App',
components: { components: {
Footer, Footer,
Navbar, Navbar,
}, }
data() {
return {
memberId: null,
};
},
created() {
this.memberId = localStorage.getItem("user_id");
},
updated() {
this.memberId = localStorage.getItem("user_id");
},
}; };
</script> </script>

View File

@ -58,8 +58,9 @@ SPDX-License-Identifier: AGPL-3.0-or-later
</div> </div>
</template> </template>
<script> <script>
import RequestMixin from "@/mixins/request.mixin" import { mapState } from 'vuex'
import RequestMixin from "@/mixins/request.mixin"
import ProfileList from "@/components/ProfileList"; import ProfileList from "@/components/ProfileList";
export default { export default {
@ -87,6 +88,9 @@ export default {
showErrorMessage: false, showErrorMessage: false,
}; };
}, },
computed: {
...mapState(['currentUserId'])
},
methods: { methods: {
addResult(result = false) { addResult(result = false) {
if (!result) result = this.searchResults[0]; if (!result) result = this.searchResults[0];
@ -98,7 +102,7 @@ export default {
let changeValues = Object.assign(this.values); let changeValues = Object.assign(this.values);
let newValue = { let newValue = {
profile_id: localStorage.getItem("user_id"), profile_id: this.currentUserId,
}; };
if (this.type != "contacttype") { if (this.type != "contacttype") {
newValue.level = 1; newValue.level = 1;

View File

@ -16,7 +16,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
<span class="d-sm-none">KI</span> <span class="d-sm-none">KI</span>
</router-link> </router-link>
<button <button
@click="showMobileNavbar = !showMobileNavbar" @click="toggleMobileNav"
class="navbar-toggler" class="navbar-toggler"
type="button" type="button"
aria-controls="navbarSupportedContent" aria-controls="navbarSupportedContent"
@ -27,7 +27,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
</button> </button>
<div <div
class="collapse navbar-collapse" class="collapse navbar-collapse"
:class="{ show: showMobileNavbar }" :class="{ show: showMobileNav }"
id="navbarSupportedContent" id="navbarSupportedContent"
> >
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> <ul class="navbar-nav me-auto mb-2 mb-lg-0">
@ -42,7 +42,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
<li class="nav-item"> <li class="nav-item">
<router-link <router-link
class="nav-link" class="nav-link"
:to="{ path: `/s/profile/${$root.memberId}` }" :to="{ path: `/s/profile/${currentUserId}` }"
active-class="active" active-class="active"
>Mein Profil</router-link >Mein Profil</router-link
> >
@ -86,21 +86,29 @@ SPDX-License-Identifier: AGPL-3.0-or-later
<script> <script>
import RequestMixin from "@/mixins/request.mixin" import { mapState } from 'vuex'
import RequestMixin from '@/mixins/request.mixin'
export default { export default {
name: "Navbar", name: 'Navbar',
mixins: [RequestMixin], mixins: [RequestMixin],
data() { data() {
return { return {
showMobileNavbar: false, searchText: '',
searchText: '' showMobileNav: false
} }
}, },
computed: {
...mapState(['currentUserId'])
},
methods: { methods: {
toggleMobileNav() {
this.showMobileNav = !this.showMobileNav
},
logout() { logout() {
localStorage.clear(); this.$store.dispatch('clear')
this.$router.push({ path: "/" }); this.$router.push({ path: '/' });
}, },
searchRedirect() { searchRedirect() {
this.$router.push({ path: `/s/search?text`, query: { query: this.searchText } } ); this.$router.push({ path: `/s/search?text`, query: { query: this.searchText } } );

View File

@ -5,12 +5,14 @@
import { createApp } from 'vue/dist/vue.esm-bundler' import { createApp } from 'vue/dist/vue.esm-bundler'
import App from './App.vue' import App from './App.vue'
import router from './router' import router from './router'
import store from '@/store'
import './assets/global.scss' import './assets/global.scss'
const app = createApp(App) const app = createApp(App)
app.use(router) app.use(router)
app.use(store)
app.config.globalProperties.apiUrl = window.ki.apiUrl app.config.globalProperties.apiUrl = window.ki.apiUrl

View File

@ -2,6 +2,8 @@
// //
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
import store from '@/store'
export default { export default {
methods: { methods: {
async submitLogin() { async submitLogin() {
@ -26,8 +28,8 @@ export default {
} }
const responseData = await response.json() const responseData = await response.json()
localStorage.setItem('token', responseData.token); store.commit('setCurrentUserId', parseInt(responseData.user_id, 10))
localStorage.setItem('user_id', responseData.user_id); store.commit('setToken', responseData.token)
this.$router.push({ path: '/s/search' }); this.$router.push({ path: '/s/search' });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -38,7 +40,7 @@ export default {
try { try {
const response = await fetch(`${this.apiUrl}/${this.type}s?search=${this.searchText}`, { const response = await fetch(`${this.apiUrl}/${this.type}s?search=${this.searchText}`, {
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`, Authorization: `Bearer ${store.state.token}`,
}, },
} }
); );
@ -65,13 +67,13 @@ export default {
} }
}, },
async initEditPage() { async initEditPage() {
const userId = localStorage.getItem('user_id') const userId = store.state.currentUserId
const url = `${this.apiUrl}/users/${userId}/profile` const url = `${this.apiUrl}/users/${userId}/profile`
try { try {
const response = await fetch(url, { const response = await fetch(url, {
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}` Authorization: `Bearer ${store.state.token}`
}, },
} }
); );
@ -94,11 +96,11 @@ export default {
try { try {
const body = JSON.stringify(this.profile) const body = JSON.stringify(this.profile)
const response = await fetch( const response = await fetch(
`${this.apiUrl}/users/${localStorage.getItem("user_id")}/profile`, `${this.apiUrl}/users/${store.currentUserId}/profile`,
{ {
method: 'POST', method: 'POST',
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`, Authorization: `Bearer ${store.state.token}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body body
@ -119,7 +121,7 @@ export default {
async initViewPage() { async initViewPage() {
try { try {
const response = await fetch(`${this.apiUrl}/users/${this.$route.params.memberId}/profile`, { const response = await fetch(`${this.apiUrl}/users/${this.$route.params.memberId}/profile`, {
headers: { Authorization: `Bearer ${localStorage.getItem("token")}` }, headers: { Authorization: `Bearer ${store.state.token}` },
} }
); );
@ -128,7 +130,7 @@ export default {
} }
const responseData = await response.json() const responseData = await response.json()
this.profile = responseData.profile; store.commit('setCurrentProfile', responseData.profile)
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
@ -145,7 +147,7 @@ export default {
const response = await fetch(url, { const response = await fetch(url, {
headers: { headers: {
Authorization: `Bearer ${localStorage.getItem("token")}`, Authorization: `Bearer ${store.state.token}`,
}, },
}); });

View File

@ -3,6 +3,9 @@
// SPDX-License-Identifier: AGPL-3.0-or-later // SPDX-License-Identifier: AGPL-3.0-or-later
import { createRouter, createWebHistory } from 'vue-router' import { createRouter, createWebHistory } from 'vue-router'
import store from '@/store'
import Index from '@/views/Index.vue' import Index from '@/views/Index.vue'
import Search from '@/views/Search.vue' import Search from '@/views/Search.vue'
import Edit from '@/views/profile/Edit.vue' import Edit from '@/views/profile/Edit.vue'
@ -16,7 +19,7 @@ const routes = [
template: "<router-view/>", template: "<router-view/>",
}, },
beforeEnter: (to, from, next) => { beforeEnter: (to, from, next) => {
if(localStorage.getItem('token') !== null){ if (store.state.token){
next() next()
} else { } else {
next({path: '/', query: {url: to.fullPath, access: false}}) next({path: '/', query: {url: to.fullPath, access: false}})

50
src/store.js Normal file
View File

@ -0,0 +1,50 @@
// SPDX-FileCopyrightText: WTF Kooperative eG <https://wtf-eg.de/>
//
// SPDX-License-Identifier: AGPL-3.0-or-later
import { createStore } from 'vuex'
const localStorageKeys = {
currentUserId: 'ki_current_user_id',
token: 'ki_token',
}
export default createStore({
state() {
return {
currentUserId: JSON.parse(localStorage.getItem(localStorageKeys.currentUserId)),
token: JSON.parse(localStorage.getItem(localStorageKeys.token)),
currentProfile: null
}
},
mutations: {
clearCurrentUserId(state) {
state.currentUserId = null
localStorage.removeItem(localStorageKeys.currentUserId)
},
setCurrentUserId(state, currentUserId) {
state.currentUserId = currentUserId
localStorage.setItem(
localStorageKeys.currentUserId,
JSON.stringify(currentUserId)
)
},
clearToken(state) {
state.token = null
localStorage.removeItem(localStorageKeys.token)
},
setToken(state, token) {
state.token = token
localStorage.setItem(localStorageKeys.token, JSON.stringify(token))
},
setCurrentProfile(state, profile) {
state.currentProfile = profile
}
},
actions: {
clear(context) {
context.commit('clearCurrentUserId')
context.commit('clearToken')
}
}
})

View File

@ -40,9 +40,11 @@ SPDX-License-Identifier: AGPL-3.0-or-later
</div> </div>
</template> </template>
<script> <script>
import RequestMixin from "@/mixins/request.mixin" import { mapState } from 'vuex'
import ProfileList from "@/components/ProfileList"; import RequestMixin from '@/mixins/request.mixin'
import ProfileList from '@/components/ProfileList';
export default { export default {
name: "profileView", name: "profileView",
@ -50,10 +52,10 @@ export default {
components: { components: {
ProfileList, ProfileList,
}, },
data() { computed: {
return { ...mapState({
profile: null profile: 'currentProfile'
}; })
}, },
async created() { async created() {
await this.initViewPage(); await this.initViewPage();