@@ -14,6 +14,7 @@ import PolicyPage from '../account/profile/PolicyPage' | |||||
import DevicesPage from '../account/DevicesPage' | import DevicesPage from '../account/DevicesPage' | ||||
import AppsPage from '../account/AppsPage' | import AppsPage from '../account/AppsPage' | ||||
import AppPage from '../account/AppPage' | import AppPage from '../account/AppPage' | ||||
import BillsPage from '../account/payment/BillsPage' | |||||
import AppSitePage from '../account/AppSitePage' | import AppSitePage from '../account/AppSitePage' | ||||
import AppDataViewPage from '../account/AppDataViewPage' | import AppDataViewPage from '../account/AppDataViewPage' | ||||
import AppConfigPage from '../account/AppConfigPage' | import AppConfigPage from '../account/AppConfigPage' | ||||
@@ -65,6 +66,7 @@ export const router = new Router({ | |||||
{ path: '/me/changePassword', component: ChangePasswordPage }, | { path: '/me/changePassword', component: ChangePasswordPage }, | ||||
{ path: '/me/setPassword/:code', component: SetPasswordPage }, | { path: '/me/setPassword/:code', component: SetPasswordPage }, | ||||
{ path: '/me/keys', component: SshKeysPage }, | { path: '/me/keys', component: SshKeysPage }, | ||||
{ path: '/me/bills', component: BillsPage }, | |||||
{ path: '/devices', component: DevicesPage }, | { path: '/devices', component: DevicesPage }, | ||||
{ path: '/apps', component: AppsPage }, | { path: '/apps', component: AppsPage }, | ||||
{ path: '/app/:app', component: AppPage }, | { path: '/app/:app', component: AppPage }, | ||||
@@ -0,0 +1,15 @@ | |||||
import config from 'config'; | |||||
import { util } from '../_helpers'; | |||||
export const billService = { | |||||
getAllBillsByAccount, | |||||
getBillByAccountAndId | |||||
}; | |||||
function getAllBillsByAccount(userId, messages, errors) { | |||||
return fetch(`${config.apiUrl}/users/${userId}/bills`, util.getWithAuth()).then(util.handleCrudResponse(messages, errors)); | |||||
} | |||||
function getBillByAccountAndId(userId, billId, messages, errors) { | |||||
return fetch(`${config.apiUrl}/users/${userId}/bills/${billId}`, util.getWithAuth()).then(util.handleCrudResponse(messages, errors)); | |||||
} |
@@ -8,3 +8,4 @@ export * from './accountPlan.service'; | |||||
export * from './network.service'; | export * from './network.service'; | ||||
export * from './device.service'; | export * from './device.service'; | ||||
export * from './app.service'; | export * from './app.service'; | ||||
export * from './bill.service'; |
@@ -0,0 +1,67 @@ | |||||
import { billService } from '../_services'; | |||||
import { util } from '../_helpers'; | |||||
const state = { | |||||
loading: { | |||||
bills: false, bill: false | |||||
}, | |||||
error: null, | |||||
bills: null, | |||||
bill: null | |||||
}; | |||||
const actions = { | |||||
getAllBillsByAccount({ commit }, {userId, messages, errors}) { | |||||
commit('getAllBillsByAccountRequest'); | |||||
billService.getAllBillsByAccount(userId, messages, errors) | |||||
.then( | |||||
bills => commit('getAllBillsByAccountSuccess', bills), | |||||
error => commit('getAllBillsByAccountFailure', error) | |||||
); | |||||
}, | |||||
getBillByAccountAndId({ commit }, {userId, billId, messages, errors}) { | |||||
commit('getBillByAccountAndIdRequest'); | |||||
billService.getBillByAccountAndId(userId, billId, messages, errors) | |||||
.then( | |||||
bill => commit('getBillByAccountAndIdSuccess', bill), | |||||
error => commit('getBillByAccountAndIdFailure', error) | |||||
); | |||||
} | |||||
}; | |||||
const mutations = { | |||||
getAllBillsByAccountRequest(state) { | |||||
state.loading.bills = true; | |||||
}, | |||||
getAllBillsByAccountSuccess(state, bills) { | |||||
state.loading.bills = false; | |||||
state.bills = bills; | |||||
}, | |||||
getAllBillsByAccountFailure(state, error) { | |||||
state.loading.bills = false; | |||||
state.error = { error }; | |||||
}, | |||||
getBillByAccountAndIdRequest(state) { | |||||
state.loading.bill = true; | |||||
}, | |||||
getBillByAccountAndIdSuccess(state, bill) { | |||||
state.loading.bill = false; | |||||
state.bill = bill; | |||||
}, | |||||
getBillByAccountAndIdFailure(state, error) { | |||||
state.loading.bill = false; | |||||
state.error = { error }; | |||||
} | |||||
}; | |||||
const getters = { | |||||
loading: util.checkLoading(state.loading) | |||||
}; | |||||
export const bills = { | |||||
namespaced: true, | |||||
state, | |||||
actions, | |||||
mutations, | |||||
getters | |||||
}; |
@@ -13,6 +13,7 @@ import { accountPlans } from './accountPlans.module'; | |||||
import { networks } from './networks.module'; | import { networks } from './networks.module'; | ||||
import { devices } from './devices.module'; | import { devices } from './devices.module'; | ||||
import { apps } from './apps.module'; | import { apps } from './apps.module'; | ||||
import { bills } from './bills.module'; | |||||
Vue.use(Vuex); | Vue.use(Vuex); | ||||
@@ -29,7 +30,8 @@ export const store = new Vuex.Store({ | |||||
accountPlans, | accountPlans, | ||||
networks, | networks, | ||||
devices, | devices, | ||||
apps | |||||
apps, | |||||
bills | |||||
} | } | ||||
}); | }); | ||||
@@ -0,0 +1,94 @@ | |||||
<template> | |||||
<div> | |||||
<h4>{{messages.title_bills}}<span v-if="this.me === false"> - {{this.userId}}</span></h4> | |||||
<table border="1"> | |||||
<thead> | |||||
<tr> | |||||
<td>{{messages.label_bill_period}}</td> | |||||
<td>{{messages.label_bill_plan}}</td> | |||||
<td>{{messages.label_bill_status}}</td> | |||||
<td>{{messages.label_bill_total}}</td> | |||||
</tr> | |||||
</thead> | |||||
<tbody v-if="billObjects"> | |||||
<tr v-for="bill in billObjects"> | |||||
<td>{{bill.periodStart}} - {{bill.periodEnd}} ({{bill.periodLabel}})</td> | |||||
<td>{{messages['plan_name_'+bill.planObject.name]}}</td> | |||||
<td>{{messages['bill_status_'+bill.status]}}</td> | |||||
<td> | |||||
{{messages.label_bill_total_format.parseExpression({messages: messages, ...bill})}} | |||||
</td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
</template> | |||||
<script> | |||||
import { mapState, mapActions, mapGetters } from 'vuex'; | |||||
import { util } from '../../_helpers'; | |||||
import { Settings } from 'luxon'; | |||||
export default { | |||||
data() { | |||||
return { | |||||
me: null, | |||||
userId: null, | |||||
linkPrefix: null, | |||||
currentUser: util.currentUser(), | |||||
billObjects: null | |||||
}; | |||||
}, | |||||
computed: { | |||||
...mapState('system', ['messages']), | |||||
...mapState('bills', ['bills']) | |||||
}, | |||||
methods: { | |||||
...mapActions('bills', ['getAllBillsByAccount']), | |||||
...mapGetters('bills', ['loading']) | |||||
}, | |||||
watch: { | |||||
bills (b) { | |||||
if (b && b.length && b.length > 0) { | |||||
const billObjects = []; | |||||
for (let i=0; i<b.length; i++) { | |||||
const bill = b[i]; | |||||
bill['totalMajorUnits'] = bill.total / 100; | |||||
bill['totalMinorUnits'] = bill.total % 100; | |||||
billObjects.push(bill); | |||||
} | |||||
this.billObjects = billObjects; | |||||
} | |||||
} | |||||
}, | |||||
created () { | |||||
this.me = this.$route.path.startsWith('/me/'); | |||||
if (this.me) { | |||||
this.linkPrefix = '/me'; | |||||
if (this.currentUser === null) { | |||||
console.warn('BillsPage.created: /me requested but no currentUser, sending to home page'); | |||||
this.$router.push('/'); | |||||
return; | |||||
} else { | |||||
this.userId = this.currentUser.uuid; | |||||
} | |||||
} else if (this.currentUser.admin !== true) { | |||||
console.warn('BillsPage.created: not admin and path not /me, sending to /me ...'); | |||||
this.$router.push('/me'); | |||||
return; | |||||
} else if (typeof this.$route.params.id === 'undefined' || this.$route.params.id === null) { | |||||
console.warn('BillsPage.created: no id param found, sending to accounts page'); | |||||
this.$router.push('/admin/accounts'); | |||||
return; | |||||
} else { | |||||
this.userId = this.$route.params.id; | |||||
this.linkPrefix = '/admin/accounts/' + this.userId; | |||||
} | |||||
this.getAllBillsByAccount({userId: this.userId, messages: this.messages, errors: this.errors}); | |||||
} | |||||
}; | |||||
</script> |
@@ -151,13 +151,11 @@ | |||||
if (this.me) { | if (this.me) { | ||||
this.linkPrefix = '/me'; | this.linkPrefix = '/me'; | ||||
if (this.currentUser === null) { | if (this.currentUser === null) { | ||||
this.admin = false; | |||||
console.warn('SshKeysPage.created: /me requested but no currentUser, sending to home page'); | console.warn('SshKeysPage.created: /me requested but no currentUser, sending to home page'); | ||||
this.$router.push('/'); | this.$router.push('/'); | ||||
return; | return; | ||||
} else { | } else { | ||||
this.admin = this.currentUser.admin === true; | |||||
this.userId = this.currentUser.uuid; | this.userId = this.currentUser.uuid; | ||||
} | } | ||||
@@ -175,15 +173,6 @@ | |||||
this.userId = this.$route.params.id; | this.userId = this.$route.params.id; | ||||
this.linkPrefix = '/admin/accounts/' + this.userId; | this.linkPrefix = '/admin/accounts/' + this.userId; | ||||
} | } | ||||
// const user = util.currentUser(); | |||||
// if (util.userHasLocale(user)) { | |||||
// Settings.defaultLocale = util.jsLocale(this.user, null); | |||||
// } else if (this.detectedLocale === null) { | |||||
// this.detectLocale(); | |||||
// } else { | |||||
// Settings.defaultLocale = util.jsLocale(null, this.detectedLocale); | |||||
// } | |||||
this.listSshKeysByUserId({userId: this.userId, messages: this.messages, errors: this.errors}); | this.listSshKeysByUserId({userId: this.userId, messages: this.messages, errors: this.errors}); | ||||
} | } | ||||
}; | }; |