diff options
| author | Zephyrrus <[email protected]> | 2020-07-02 23:42:02 +0300 |
|---|---|---|
| committer | Zephyrrus <[email protected]> | 2020-07-02 23:42:02 +0300 |
| commit | c2dbbe6396540ee9d76991a00f5028b49d221d0c (patch) | |
| tree | 0ac9bb8a45c6837e31692e913ba50c5107e2af65 | |
| parent | feat: return APIKey when fetching user (diff) | |
| download | host.fuwn.me-c2dbbe6396540ee9d76991a00f5028b49d221d0c.tar.xz host.fuwn.me-c2dbbe6396540ee9d76991a00f5028b49d221d0c.zip | |
feat: refactor account to use vuex, fix small presentational components
| -rw-r--r-- | src/site/components/footer/Footer.vue | 12 | ||||
| -rw-r--r-- | src/site/components/grid/Grid.vue | 8 | ||||
| -rw-r--r-- | src/site/components/loading/BulmaLoading.vue | 33 | ||||
| -rw-r--r-- | src/site/components/navbar/Navbar.vue | 4 | ||||
| -rw-r--r-- | src/site/components/sidebar/Sidebar.vue | 15 | ||||
| -rw-r--r-- | src/site/pages/dashboard/account.vue | 74 | ||||
| -rw-r--r-- | src/site/pages/dashboard/index.vue | 2 | ||||
| -rw-r--r-- | src/site/pages/login.vue | 2 | ||||
| -rw-r--r-- | src/site/store/auth.js | 39 | ||||
| -rw-r--r-- | src/site/store/images.js | 4 |
10 files changed, 139 insertions, 54 deletions
diff --git a/src/site/components/footer/Footer.vue b/src/site/components/footer/Footer.vue index 49f622c..44e34f4 100644 --- a/src/site/components/footer/Footer.vue +++ b/src/site/components/footer/Footer.vue @@ -49,15 +49,15 @@ </footer> </template> <script> +import { mapState, mapGetters } from 'vuex'; import { saveAs } from 'file-saver'; + export default { computed: { - loggedIn() { - return this.$store.state.loggedIn; - }, - version() { - return this.$store.state.config.version; - } + ...mapGetters({ loggedIn: 'auth/isLoggedIn' }), + ...mapState({ + version: state => state.config.version + }) }, methods: { createShareXThing() { diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue index 279472c..a06eabf 100644 --- a/src/site/components/grid/Grid.vue +++ b/src/site/components/grid/Grid.vue @@ -198,6 +198,8 @@ </template> <script> +import { mapState } from 'vuex'; + import Waterfall from './waterfall/Waterfall.vue'; import WaterfallItem from './waterfall/WaterfallItem.vue'; @@ -246,9 +248,9 @@ export default { }; }, computed: { - user() { - return this.$store.state.user; - }, + ...mapState({ + user: state => state.auth.user + }), blank() { return require('@/assets/images/blank.png'); }, diff --git a/src/site/components/loading/BulmaLoading.vue b/src/site/components/loading/BulmaLoading.vue new file mode 100644 index 0000000..37cc5a5 --- /dev/null +++ b/src/site/components/loading/BulmaLoading.vue @@ -0,0 +1,33 @@ +<template> + <div class="loader-wrapper"> + <div class="loader is-loading" /> + </div> +</template> + +<style lang="scss" scoped> + .loader-wrapper { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; + background: #fff; + opacity: 0; + z-index: -1; + transition: opacity .3s; + display: flex; + justify-content: center; + align-items: center; + border-radius: 6px; + + .loader { + height: 80px; + width: 80px; + } + + &.is-active { + opacity: 1; + z-index: 1; + } + } +</style> diff --git a/src/site/components/navbar/Navbar.vue b/src/site/components/navbar/Navbar.vue index aa4a672..7fb2f22 100644 --- a/src/site/components/navbar/Navbar.vue +++ b/src/site/components/navbar/Navbar.vue @@ -82,8 +82,8 @@ export default { ...mapState(['config']) }, methods: { - logOut() { - this.$store.dispatch('logout'); + async logOut() { + await this.$store.dispatch('auth/logout'); this.$router.replace('/login'); } } diff --git a/src/site/components/sidebar/Sidebar.vue b/src/site/components/sidebar/Sidebar.vue index a2ad3f4..3cb8b43 100644 --- a/src/site/components/sidebar/Sidebar.vue +++ b/src/site/components/sidebar/Sidebar.vue @@ -6,13 +6,11 @@ <router-link to="/dashboard/albums"> <i class="icon-interface-window" />Albums </router-link> - <!-- <router-link to="/dashboard/tags"> <i class="icon-ecommerce-tag-c" />Tags </router-link> - --> <router-link to="/dashboard/account"> - <i class="icon-ecommerce-tag-c" />Account + <i class="icon-user-alt" />Account </router-link> <template v-if="user && user.isAdmin"> <router-link to="/dashboard/admin/users"> @@ -28,13 +26,14 @@ </div> </template> <script> +import { mapState } from 'vuex'; + export default { - computed: { - user() { - return this.$store.state.user; - } - } + computed: mapState({ + user: state => state.auth.user + }) }; + </script> <style lang="scss" scoped> @import '~/assets/styles/_colors.scss'; diff --git a/src/site/pages/dashboard/account.vue b/src/site/pages/dashboard/account.vue index 121b2b3..1c335e8 100644 --- a/src/site/pages/dashboard/account.vue +++ b/src/site/pages/dashboard/account.vue @@ -12,7 +12,7 @@ <b-field label="Username" message="Nothing to do here" horizontal> - <b-input v-model="user.username" + <b-input :value="user.username" expanded disabled /> </b-field> @@ -20,7 +20,7 @@ <b-field label="Current password" message="If you want to change your password input the current one here" horizontal> - <b-input v-model="user.password" + <b-input v-model="password" type="password" expanded /> </b-field> @@ -28,7 +28,7 @@ <b-field label="New password" message="Your new password" horizontal> - <b-input v-model="user.newPassword" + <b-input v-model="newPassword" type="password" expanded /> </b-field> @@ -36,7 +36,7 @@ <b-field label="New password again" message="Your new password once again" horizontal> - <b-input v-model="user.reNewPassword" + <b-input v-model="reNewPassword" type="password" expanded /> </b-field> @@ -46,12 +46,17 @@ @click="changePassword">Change password</button> </div> - <b-field label="Api key" + <b-field label="API key" message="This API key lets you use the service from other apps" horizontal> - <b-input v-model="user.apiKey" - expanded - disabled /> + <b-field expanded> + <b-input :value="apiKey" + expanded + disabled /> + <p class="control"> + <button class="button is-primary">Copy</button> + </p> + </b-field> </b-field> <div class="mb2 mt2 text-center"> @@ -65,51 +70,62 @@ </template> <script> +import { mapState, mapActions, mapGetters } from 'vuex'; import Sidebar from '~/components/sidebar/Sidebar.vue'; export default { components: { Sidebar }, - middleware: 'auth', + middleware: ['auth', ({ store }) => { + store.dispatch('auth/fetchCurrentUser'); + }], data() { return { - user: {} + password: '', + newPassword: '', + reNewPassword: '' }; + }, + computed: { + ...mapGetters({ 'apiKey': 'auth/getApiKey' }), + ...mapState({ + user: state => state.auth.user + }) }, metaInfo() { return { title: 'Account' }; }, - mounted() { - this.getUserSetttings(); - }, methods: { - async getUserSetttings() { - const response = await this.$axios.$get(`users/me`); - this.user = response.user; - }, + ...mapActions({ + getUserSetttings: 'auth/fetchCurrentUser' + }), async changePassword() { - if (!this.user.password || !this.user.newPassword || !this.user.reNewPassword) { - this.$store.dispatch('alert', { + const { password, newPassword, reNewPassword } = this; + + if (!password || !newPassword || !reNewPassword) { + this.$store.dispatch('alert/set', { text: 'One or more fields are missing', error: true }); return; } - if (this.user.newPassword !== this.user.reNewPassword) { - this.$store.dispatch('alert', { + if (newPassword !== reNewPassword) { + this.$store.dispatch('alert/set', { text: 'Passwords don\'t match', error: true }); return; } - const response = await this.$axios.$post(`user/password/change`, - { - password: this.user.password, - newPassword: this.user.newPassword - }); - this.$buefy.toast.open(response.message); + const response = await this.$store.dispatch('auth/changePassword', { + password, + newPassword + }); + + if (response) { + this.$buefy.toast.open(response.message); + } }, promptNewAPIKey() { this.$buefy.dialog.confirm({ @@ -119,9 +135,7 @@ export default { }); }, async requestNewAPIKey() { - const response = await this.$axios.$post(`user/apikey/change`); - this.user.apiKey = response.apiKey; - this.$forceUpdate(); + const response = await this.$store.dispatch('auth/requestAPIKey'); this.$buefy.toast.open(response.message); } } diff --git a/src/site/pages/dashboard/index.vue b/src/site/pages/dashboard/index.vue index 6c1b99b..89f0fac 100644 --- a/src/site/pages/dashboard/index.vue +++ b/src/site/pages/dashboard/index.vue @@ -99,7 +99,7 @@ export default { fetch: 'images/fetch' }), fetchPaginate() { - this.fetch(this.current) + this.fetch(this.current); } } }; diff --git a/src/site/pages/login.vue b/src/site/pages/login.vue index 3c43755..cef0868 100644 --- a/src/site/pages/login.vue +++ b/src/site/pages/login.vue @@ -99,6 +99,7 @@ export default { } await this.$store.dispatch('auth/login', { username, password }); + if (this.auth.loggedIn) { this.redirect(); } @@ -119,7 +120,6 @@ export default { }); },*/ redirect() { - console.log('redirect'); if (typeof this.$route.query.redirect !== 'undefined') { this.$router.push(this.$route.query.redirect); return; diff --git a/src/site/store/auth.js b/src/site/store/auth.js index a62a6ec..73976d6 100644 --- a/src/site/store/auth.js +++ b/src/site/store/auth.js @@ -10,7 +10,8 @@ const getDefaultState = () => ({ export const state = getDefaultState; export const getters = { - isLoggedIn: state => state.loggedIn + isLoggedIn: state => state.loggedIn, + getApiKey: state => state.user?.apiKey }; export const actions = { @@ -35,6 +36,36 @@ export const actions = { dispatch('alert/set', { text: e.message, error: true }, { root: true }); } }, + async fetchCurrentUser({ commit, dispatch }) { + try { + const data = await this.$axios.$get(`users/me`); + commit('setUser', data.user); + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async changePassword({ dispatch }, { password, newPassword }) { + try { + const response = await this.$axios.$post(`user/password/change`, { + password, + newPassword + }); + + return response; + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, + async requestAPIKey({ commit, dispatch }) { + try { + const response = await this.$axios.$post(`user/apikey/change`); + commit('setApiKey', response.apiKey); + + return response; + } catch (e) { + dispatch('alert/set', { text: e.message, error: true }, { root: true }); + } + }, logout({ commit }) { commit('logout'); } @@ -44,6 +75,12 @@ export const mutations = { setToken(state, token) { state.token = token; }, + setApiKey(state, apiKey) { + state.user.apiKey = apiKey; + }, + setUser(state, user) { + state.user = user; + }, loginRequest(state) { state.isLoading = true; }, diff --git a/src/site/store/images.js b/src/site/store/images.js index e87dac1..f6dae1b 100644 --- a/src/site/store/images.js +++ b/src/site/store/images.js @@ -10,8 +10,8 @@ export const state = () => ({ }); export const getters = { - getTotalFiles: state => state.pagination.totalFiles, - getFetchedCount: state => state.files.length, + getTotalFiles: ({ pagination }) => pagination.totalFiles, + getFetchedCount: ({ files }) => files.length, shouldPaginate: ({ pagination }) => pagination.totalFiles > pagination.limit, getLimit: ({ pagination }) => pagination.limit }; |