Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(subscriptions): add admin panel ✨
- Loading branch information
1 parent
838a29c
commit 8541fc6
Showing
9 changed files
with
418 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/** | ||
* Module dependencies. | ||
*/ | ||
import subscriptions from '../views/subscriptions.view.vue'; | ||
import subscription from '../views/subscription.view.vue'; | ||
|
||
/** | ||
* Router configuration | ||
*/ | ||
export default [ | ||
{ | ||
path: '/subscriptions', | ||
name: 'Subscriptions', | ||
component: subscriptions, | ||
meta: { | ||
icon: 'paper-plane', | ||
roles: ['admin'], // proteced, require one of this roles | ||
}, | ||
}, | ||
{ | ||
path: '/subscriptions/:id', | ||
name: 'subscription', | ||
component: subscription, | ||
meta: { | ||
display: false, // hide any time | ||
roles: ['admin'], // proteced, require one of this roles | ||
}, | ||
}, | ||
]; |
113 changes: 113 additions & 0 deletions
113
src/modules/subscriptions/stores/subscriptions.store.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/** | ||
* Module dependencies. | ||
*/ | ||
import Vue from 'vue'; | ||
import _ from 'lodash'; | ||
import config from '@/config'; | ||
import model from '@/lib/middlewares/model'; | ||
|
||
const api = `${config.api.protocol}://${config.api.host}:${config.api.port}/${config.api.base}`; | ||
const whitelists = ['firstName', 'lastName', 'bio', 'email', 'avatar', 'roles']; | ||
|
||
/** | ||
* Getters: get state | ||
*/ | ||
const getters = { | ||
subscriptions: (state) => state.subscriptions, | ||
subscription: (state) => state.subscription, | ||
}; | ||
|
||
/** | ||
* Actions | ||
*/ | ||
const actions = { | ||
getSubscriptions: async ({ commit }) => { | ||
try { | ||
const res = await Vue.prototype.axios.get(`${api}/${config.api.endPoints.subscriptions}/`); | ||
commit('subscriptions_set', res.data.data); | ||
} catch (err) { | ||
commit('subscription_error', err); | ||
} | ||
}, | ||
getSubscription: async ({ commit }, params) => { | ||
try { | ||
const res = await Vue.prototype.axios.get( | ||
`${api}/${config.api.endPoints.subscriptions}/${params}`, | ||
); | ||
commit('subscription_set', res.data.data); | ||
} catch (err) { | ||
commit('subscription_error', err); | ||
} | ||
}, | ||
updateSubscription: async ({ commit, state }, params) => { | ||
try { | ||
const obj = model.clean(_.merge(state.subscription, params), whitelists); | ||
const res = await Vue.prototype.axios.put( | ||
`${api}/${config.api.endPoints.subscriptions}/${params.id}`, | ||
obj, | ||
); | ||
commit('subscription_update', res.data.data); | ||
} catch (err) { | ||
commit('subscription_error', err); | ||
} | ||
}, | ||
deleteSubscription: async ({ commit }, params) => { | ||
try { | ||
await Vue.prototype.axios.delete(`${api}/${config.api.endPoints.subscriptions}/${params.id}`); | ||
commit('subscription_reset'); | ||
} catch (err) { | ||
commit('subscription_error', err); | ||
} | ||
}, | ||
}; | ||
|
||
/** | ||
* Mutation: change state in a Vuex store is by committing a mutation | ||
*/ | ||
const mutations = { | ||
// global | ||
subscription_error(state, err) { | ||
console.log('subscription_error', err); | ||
}, | ||
// scraps | ||
subscriptions_set(state, data) { | ||
state.subscriptions = data; | ||
}, | ||
// scrap | ||
subscription_set(state, data) { | ||
state.subscription = data; | ||
}, | ||
subscription_update(state, data) { | ||
_.merge(state.subscription, data); | ||
}, | ||
subscription_reset(state) { | ||
state.subscription = {}; | ||
}, | ||
}; | ||
|
||
/** | ||
* State | ||
*/ | ||
const state = { | ||
subscription: { | ||
firstName: '', | ||
lastName: '', | ||
bio: '', | ||
email: '', | ||
avatar: '', | ||
roles: [], | ||
updated: '', | ||
created: '', | ||
}, | ||
subscriptions: [], | ||
}; | ||
|
||
/** | ||
* Export default | ||
*/ | ||
export default { | ||
state, | ||
getters, | ||
actions, | ||
mutations, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
<template> | ||
<v-container fluid> | ||
<!-- Header --> | ||
<v-row class="mt-3 mx-3"> | ||
<v-subheader> | ||
<v-icon class="mr-5">fa-subscription</v-icon> | ||
<b>{{ firstName }} {{ lastName }}</b> | ||
</v-subheader> | ||
<div class="flex-grow-1"></div> | ||
<v-btn v-if="id" color="red lighten-3" @click.stop="removeConfirm = true" icon> | ||
<v-icon>fa-trash</v-icon> | ||
</v-btn> | ||
<v-dialog v-model="removeConfirm" max-width="290"> | ||
<v-card> | ||
<v-card-title class="headline">Delete this item ?</v-card-title> | ||
<v-card-text> | ||
Are you sure you want to delete this item ? we will not be able to recover it. | ||
</v-card-text> | ||
<v-card-actions> | ||
<v-spacer></v-spacer> | ||
<v-btn color="green darken-1" text @click="removeConfirm = false"> | ||
Close | ||
</v-btn> | ||
<v-btn color="red darken-1" text @click="remove"> | ||
Delete | ||
</v-btn> | ||
</v-card-actions> | ||
</v-card> | ||
</v-dialog> | ||
<v-btn v-if="id" class="mr-5" color="blue lighten-2" @click="update()" :disabled="!save" icon> | ||
<v-icon>fa-save</v-icon> | ||
</v-btn> | ||
</v-row> | ||
<!-- First Form --> | ||
<v-row class="mx-3"> | ||
<v-col cols="12" sm="12" md="12" lg="12" xl="12"> | ||
<v-row align="start" justify="center"> | ||
<v-card | ||
outlined | ||
tile | ||
width="100%" | ||
class="px-10 pa-6" | ||
:style="{ background: config.vuetify.theme.themes[theme].surface }" | ||
:flat="config.vuetify.theme.flat" | ||
> | ||
<v-form ref="form" v-model="valid"> | ||
<v-row> | ||
<v-col cols="12" xs="12" sm="12" md="9" lg="10" xl="11"> | ||
<v-text-field v-model="email" label="Email" required></v-text-field> | ||
<v-text-field v-model="news" label="News" required></v-text-field> | ||
</v-col> | ||
<v-col cols="12" xs="12" sm="12" md="3" lg="2" xl="1"> | ||
<center> | ||
<userArrayComponent | ||
:user="subscription" | ||
:width="'125px'" | ||
:height="'125px'" | ||
:radius="'50%'" | ||
:border="'0px'" | ||
:color="'#000'" | ||
/> | ||
</center> | ||
</v-col> | ||
</v-row> | ||
<v-row v-if="!id"> | ||
<v-btn :disabled="!valid" color="success" class="mr-4" @click="create" | ||
>Validate</v-btn | ||
> | ||
</v-row> | ||
</v-form> | ||
</v-card> | ||
</v-row> | ||
</v-col> | ||
</v-row> | ||
</v-container> | ||
</template> | ||
|
||
<script> | ||
/** | ||
* Module dependencies. | ||
*/ | ||
import { mapGetters } from 'vuex'; | ||
import userArrayComponent from '../../users/components/user.avatar.component.vue'; | ||
/** | ||
* Export default | ||
*/ | ||
export default { | ||
data() { | ||
return { | ||
// vue | ||
id: this.$route.params.id ? this.$route.params.id : null, | ||
save: false, | ||
valid: false, | ||
rules: { | ||
bio: [(v) => !v || (v && v.length <= 200) || 'Max 200 characters'], | ||
}, | ||
rolesItems: ['admin', 'subscription'], | ||
removeConfirm: false, | ||
}; | ||
}, | ||
components: { | ||
userArrayComponent, | ||
}, | ||
computed: { | ||
...mapGetters(['theme', 'subscription', 'result']), | ||
email: { | ||
get() { | ||
return this.subscription.email; | ||
}, | ||
set(email) { | ||
this.save = true; | ||
this.$store.commit('subscription_update', { email }); | ||
}, | ||
}, | ||
news: { | ||
get() { | ||
return this.subscription.news; | ||
}, | ||
set(news) { | ||
this.save = true; | ||
this.$store.commit('subscription_update', { news }); | ||
}, | ||
}, | ||
}, | ||
methods: { | ||
update() { | ||
if (this.$refs.form.validate()) { | ||
const { email } = this; | ||
const { news } = this; | ||
const data = { | ||
id: this.id, | ||
email, | ||
news, | ||
}; | ||
this.$store | ||
.dispatch('updateSubscription', data) | ||
.then(() => { | ||
this.save = false; | ||
}) | ||
.catch((err) => console.log(err)); | ||
} | ||
}, | ||
remove() { | ||
if (this.$refs.form.validate()) { | ||
this.$store | ||
.dispatch('deleteSubscription', { id: this.id }) | ||
.then(() => { | ||
this.$router.push('/subscriptions'); | ||
}) | ||
.catch((err) => console.log(err)); | ||
} | ||
}, | ||
}, | ||
created() { | ||
if (this.id) { | ||
this.$store.commit('subscription_reset'); | ||
this.$store.dispatch('getSubscription', this.id).catch((err) => console.log(err)); | ||
} else { | ||
this.$store.commit('subscription_reset'); | ||
} | ||
}, | ||
}; | ||
</script> |
Oops, something went wrong.