Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Admin/User.vue
Show First 20 Lines • Show All 80 Lines • ▼ Show 20 Lines | <div class="container"> | ||||
</btn> | </btn> | ||||
<btn v-if="user.isSuspended" id="button-unsuspend" class="btn-warning" @click="unsuspendUser"> | <btn v-if="user.isSuspended" id="button-unsuspend" class="btn-warning" @click="unsuspendUser"> | ||||
{{ $t('btn.unsuspend') }} | {{ $t('btn.unsuspend') }} | ||||
</btn> | </btn> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<ul class="nav nav-tabs mt-3" role="tablist"> | <tabs class="mt-3" :tabs="tabs" ref="tabs"></tabs> | ||||
<li class="nav-item"> | |||||
<a class="nav-link active" id="tab-finances" href="#user-finances" role="tab" aria-controls="user-finances" aria-selected="true"> | |||||
{{ $t('user.finances') }} | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-aliases" href="#user-aliases" role="tab" aria-controls="user-aliases" aria-selected="false"> | |||||
{{ $t('user.aliases') }} ({{ user.aliases.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-subscriptions" href="#user-subscriptions" role="tab" aria-controls="user-subscriptions" aria-selected="false"> | |||||
{{ $t('user.subscriptions') }} ({{ skus.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-domains" href="#user-domains" role="tab" aria-controls="user-domains" aria-selected="false"> | |||||
{{ $t('user.domains') }} ({{ domains.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-users" href="#user-users" role="tab" aria-controls="user-users" aria-selected="false"> | |||||
{{ $t('user.users') }} ({{ users.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-distlists" href="#user-distlists" role="tab" aria-controls="user-distlists" aria-selected="false"> | |||||
{{ $t('user.distlists') }} ({{ distlists.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-resources" href="#user-resources" role="tab" aria-controls="user-resources" aria-selected="false"> | |||||
{{ $t('user.resources') }} ({{ resources.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-shared-folders" href="#user-shared-folders" role="tab" aria-controls="user-shared-folders" aria-selected="false"> | |||||
{{ $t('dashboard.shared-folders') }} ({{ folders.length }}) | |||||
</a> | |||||
</li> | |||||
<li class="nav-item"> | |||||
<a class="nav-link" id="tab-settings" href="#user-settings" role="tab" aria-controls="user-settings" aria-selected="false"> | |||||
{{ $t('form.settings') }} | |||||
</a> | |||||
</li> | |||||
</ul> | |||||
<div class="tab-content"> | <div class="tab-content"> | ||||
<div class="tab-pane show active" id="user-finances" role="tabpanel" aria-labelledby="tab-finances"> | <div class="tab-pane show active" id="finances" role="tabpanel" aria-labelledby="tab-finances"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<h2 class="card-title"> | <h2 class="card-title"> | ||||
{{ $t('wallet.title') }} | {{ $t('wallet.title') }} | ||||
<span :class="wallet.balance < 0 ? 'text-danger' : 'text-success'"><strong>{{ $root.price(wallet.balance, wallet.currency) }}</strong></span> | <span :class="wallet.balance < 0 ? 'text-danger' : 'text-success'"><strong>{{ $root.price(wallet.balance, wallet.currency) }}</strong></span> | ||||
</h2> | </h2> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<form class="read-only short"> | <form class="read-only short"> | ||||
<div class="row"> | <div class="row"> | ||||
Show All 30 Lines | <div class="container"> | ||||
<btn id="button-award" class="btn-success" @click="awardDialog">{{ $t('user.add-bonus') }}</btn> | <btn id="button-award" class="btn-success" @click="awardDialog">{{ $t('user.add-bonus') }}</btn> | ||||
<btn id="button-penalty" class="btn-danger" @click="penalizeDialog">{{ $t('user.add-penalty') }}</btn> | <btn id="button-penalty" class="btn-danger" @click="penalizeDialog">{{ $t('user.add-penalty') }}</btn> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<h2 class="card-title mt-4">{{ $t('wallet.transactions') }}</h2> | <h2 class="card-title mt-4">{{ $t('wallet.transactions') }}</h2> | ||||
<transaction-log v-if="wallet.id && !walletReload" class="card-text" :wallet-id="wallet.id" :is-admin="true"></transaction-log> | <transaction-log v-if="wallet.id && !walletReload" class="card-text" :wallet-id="wallet.id" :is-admin="true"></transaction-log> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-aliases" role="tabpanel" aria-labelledby="tab-aliases"> | <div class="tab-pane" id="aliases" role="tabpanel" aria-labelledby="tab-aliases"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<list-table :list="user.aliases" :setup="aliasesListSetup" class="mb-0"></list-table> | <list-table :list="user.aliases" :setup="aliasesListSetup" class="mb-0"></list-table> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-subscriptions" role="tabpanel" aria-labelledby="tab-subscriptions"> | <div class="tab-pane" id="subscriptions" role="tabpanel" aria-labelledby="tab-subscriptions"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<list-table :list="skus" :setup="skusListSetup" class="mb-0"></list-table> | <list-table :list="skus" :setup="skusListSetup" class="mb-0"></list-table> | ||||
<small v-if="discount > 0" class="hint"> | <small v-if="discount > 0" class="hint"> | ||||
<hr class="m-0"> | <hr class="m-0"> | ||||
¹ {{ $t('user.discount-hint') }}: {{ discount }}% - {{ discount_description }} | ¹ {{ $t('user.discount-hint') }}: {{ discount }}% - {{ discount_description }} | ||||
</small> | </small> | ||||
<div class="mt-2 buttons"> | <div class="mt-2 buttons"> | ||||
<btn class="btn-danger" id="reset2fa" v-if="has2FA" @click="$refs.reset2faDialog.show()">{{ $t('user.reset-2fa') }}</btn> | <btn class="btn-danger" id="reset2fa" v-if="has2FA" @click="$refs.reset2faDialog.show()">{{ $t('user.reset-2fa') }}</btn> | ||||
<btn class="btn-secondary" id="addbetasku" v-if="!hasBeta" @click="addBetaSku">{{ $t('user.add-beta') }}</btn> | <btn class="btn-secondary" id="addbetasku" v-if="!hasBeta" @click="addBetaSku">{{ $t('user.add-beta') }}</btn> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-domains" role="tabpanel" aria-labelledby="tab-domains"> | <div class="tab-pane" id="domains" role="tabpanel" aria-labelledby="tab-domains"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<domain-list :list="domains" class="mb-0"></domain-list> | <domain-list :list="domains" class="mb-0"></domain-list> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-users" role="tabpanel" aria-labelledby="tab-users"> | <div class="tab-pane" id="users" role="tabpanel" aria-labelledby="tab-users"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<user-list :list="users" :current="user" class="mb-0"></user-list> | <user-list :list="users" :current="user" class="mb-0"></user-list> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-distlists" role="tabpanel" aria-labelledby="tab-distlists"> | <div class="tab-pane" id="distlists" role="tabpanel" aria-labelledby="tab-distlists"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<distlist-list :list="distlists" class="mb-0"></distlist-list> | <distlist-list :list="distlists" class="mb-0"></distlist-list> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-resources" role="tabpanel" aria-labelledby="tab-resources"> | <div class="tab-pane" id="resources" role="tabpanel" aria-labelledby="tab-resources"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<resource-list :list="resources" class="mb-0"></resource-list> | <resource-list :list="resources" class="mb-0"></resource-list> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-shared-folders" role="tabpanel" aria-labelledby="tab-shared-folders"> | <div class="tab-pane" id="folders" role="tabpanel" aria-labelledby="tab-folders"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<shared-folder-list :list="folders" :with-email="true" class="mb-0"></shared-folder-list> | <shared-folder-list :list="folders" :with-email="true" class="mb-0"></shared-folder-list> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-settings" role="tabpanel" aria-labelledby="tab-settings"> | <div class="tab-pane" id="settings" role="tabpanel" aria-labelledby="tab-settings"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<form class="read-only short"> | <form class="read-only short"> | ||||
<div class="row plaintext"> | <div class="row plaintext"> | ||||
<label for="greylist_enabled" class="col-sm-4 col-form-label">{{ $t('user.greylisting') }}</label> | <label for="greylist_enabled" class="col-sm-4 col-form-label">{{ $t('user.greylisting') }}</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<span class="form-control-plaintext" id="greylist_enabled"> | <span class="form-control-plaintext" id="greylist_enabled"> | ||||
<span v-if="user.config.greylist_enabled" class="text-success">{{ $t('form.enabled') }}</span> | <span v-if="user.config.greylist_enabled" class="text-success">{{ $t('form.enabled') }}</span> | ||||
▲ Show 20 Lines • Show All 124 Lines • ▼ Show 20 Lines | export default { | ||||
prop: 'price', | prop: 'price', | ||||
className: 'price', | className: 'price', | ||||
label: 'user.price' | label: 'user.price' | ||||
} | } | ||||
], | ], | ||||
footLabel: 'user.subscriptions-none', | footLabel: 'user.subscriptions-none', | ||||
model: 'sku' | model: 'sku' | ||||
}, | }, | ||||
tabs: [ | |||||
{ label: 'user.finances' }, | |||||
{ label: 'user.aliases', count: 0 }, | |||||
{ label: 'user.subscriptions', count: 0 }, | |||||
{ label: 'user.domains', count: 0 }, | |||||
{ label: 'user.users', count: 0 }, | |||||
{ label: 'user.distlists', count: 0 }, | |||||
{ label: 'user.resources', count: 0 }, | |||||
{ label: 'dashboard.shared-folders', count: 0 }, | |||||
{ label: 'form.settings' } | |||||
], | |||||
users: [], | users: [], | ||||
user: { | user: { | ||||
aliases: [], | aliases: [], | ||||
config: {}, | config: {}, | ||||
wallet: {}, | wallet: {}, | ||||
skus: {}, | skus: {}, | ||||
} | } | ||||
} | } | ||||
}, | }, | ||||
created() { | created() { | ||||
const user_id = this.$route.params.user | const user_id = this.$route.params.user | ||||
axios.get('/api/v4/users/' + user_id, { loader: true }) | axios.get('/api/v4/users/' + user_id, { loader: true }) | ||||
.then(response => { | .then(response => { | ||||
this.user = response.data | this.user = response.data | ||||
const loader = '#user-finances' | const loader = '#finances' | ||||
const keys = ['first_name', 'last_name', 'external_email', 'billing_address', 'phone', 'organization'] | const keys = ['first_name', 'last_name', 'external_email', 'billing_address', 'phone', 'organization'] | ||||
let country = this.user.settings.country | let country = this.user.settings.country | ||||
if (country && country in window.config.countries) { | if (country && country in window.config.countries) { | ||||
country = window.config.countries[country][1] | country = window.config.countries[country][1] | ||||
} | } | ||||
this.user.country = country | this.user.country = country | ||||
keys.forEach(key => { this.user[key] = this.user.settings[key] }) | keys.forEach(key => { this.user[key] = this.user.settings[key] }) | ||||
this.discount = this.user.wallet.discount | this.discount = this.user.wallet.discount | ||||
this.discount_description = this.user.wallet.discount_description | this.discount_description = this.user.wallet.discount_description | ||||
this.$refs.tabs.updateCounter('aliases', this.user.aliases.length) | |||||
// TODO: currencies, multi-wallets, accounts | // TODO: currencies, multi-wallets, accounts | ||||
// Get more info about the wallet (e.g. payment provider related) | // Get more info about the wallet (e.g. payment provider related) | ||||
axios.get('/api/v4/wallets/' + this.user.wallets[0].id, { loader }) | axios.get('/api/v4/wallets/' + this.user.wallets[0].id, { loader }) | ||||
.then(response => { | .then(response => { | ||||
this.wallet = response.data | this.wallet = response.data | ||||
this.setMandateState() | this.setMandateState() | ||||
}) | }) | ||||
Show All 21 Lines | export default { | ||||
if (sku.handler == 'Auth2F') { | if (sku.handler == 'Auth2F') { | ||||
this.has2FA = true | this.has2FA = true | ||||
this.sku2FA = sku.id | this.sku2FA = sku.id | ||||
} else if (sku.handler == 'Beta') { | } else if (sku.handler == 'Beta') { | ||||
this.hasBeta = true | this.hasBeta = true | ||||
} | } | ||||
} | } | ||||
}) | }) | ||||
this.$refs.tabs.updateCounter('subscriptions', this.skus.length) | |||||
}) | }) | ||||
// Fetch users | // Fetch users | ||||
// TODO: Multiple wallets | // TODO: Multiple wallets | ||||
axios.get('/api/v4/users?owner=' + user_id) | axios.get('/api/v4/users?owner=' + user_id) | ||||
.then(response => { | .then(response => { | ||||
this.users = response.data.list; | this.users = response.data.list; | ||||
this.$refs.tabs.updateCounter('users', this.users.length) | |||||
}) | }) | ||||
// Fetch domains | // Fetch domains | ||||
axios.get('/api/v4/domains?owner=' + user_id) | axios.get('/api/v4/domains?owner=' + user_id) | ||||
.then(response => { | .then(response => { | ||||
this.domains = response.data.list | this.domains = response.data.list | ||||
this.$refs.tabs.updateCounter('domains', this.domains.length) | |||||
}) | }) | ||||
// Fetch distribution lists | // Fetch distribution lists | ||||
axios.get('/api/v4/groups?owner=' + user_id) | axios.get('/api/v4/groups?owner=' + user_id) | ||||
.then(response => { | .then(response => { | ||||
this.distlists = response.data.list | this.distlists = response.data.list | ||||
this.$refs.tabs.updateCounter('distlists', this.distlists.length) | |||||
}) | }) | ||||
// Fetch resources lists | // Fetch resources lists | ||||
axios.get('/api/v4/resources?owner=' + user_id) | axios.get('/api/v4/resources?owner=' + user_id) | ||||
.then(response => { | .then(response => { | ||||
this.resources = response.data.list | this.resources = response.data.list | ||||
this.$refs.tabs.updateCounter('resources', this.resources.length) | |||||
}) | }) | ||||
// Fetch shared folders lists | // Fetch shared folders lists | ||||
axios.get('/api/v4/shared-folders?owner=' + user_id) | axios.get('/api/v4/shared-folders?owner=' + user_id) | ||||
.then(response => { | .then(response => { | ||||
this.folders = response.data.list | this.folders = response.data.list | ||||
this.$refs.tabs.updateCounter('folders', this.folders.length) | |||||
}) | }) | ||||
}) | }) | ||||
.catch(this.$root.errorHandler) | .catch(this.$root.errorHandler) | ||||
}, | }, | ||||
mounted() { | mounted() { | ||||
$(this.$el).find('ul.nav-tabs a').on('click', this.$root.tab) | |||||
this.$refs.discountDialog.events({ | this.$refs.discountDialog.events({ | ||||
shown: () => { | shown: () => { | ||||
// Note: Vue v-model is strict, convert null to a string | // Note: Vue v-model is strict, convert null to a string | ||||
this.wallet.discount_id = this.wallet.discount_id || '' | this.wallet.discount_id = this.wallet.discount_id || '' | ||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
methods: { | methods: { | ||||
addBetaSku() { | addBetaSku() { | ||||
axios.post('/api/v4/users/' + this.user.id + '/skus/beta') | axios.post('/api/v4/users/' + this.user.id + '/skus/beta') | ||||
.then(response => { | .then(response => { | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
this.hasBeta = true | this.hasBeta = true | ||||
const sku = response.data.sku | const sku = response.data.sku | ||||
this.skus.push({ | this.skus.push({ | ||||
id: sku.id, | id: sku.id, | ||||
name: sku.name, | name: sku.name, | ||||
cost: sku.cost, | cost: sku.cost, | ||||
price: this.$root.priceLabel(sku.cost, this.discount) | price: this.$root.priceLabel(sku.cost, this.discount) | ||||
}) | }) | ||||
this.$refs.tabs.updateCounter('subscriptions', this.skus.length) | |||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
capitalize(str) { | capitalize(str) { | ||||
return str.charAt(0).toUpperCase() + str.slice(1) | return str.charAt(0).toUpperCase() + str.slice(1) | ||||
}, | }, | ||||
awardDialog() { | awardDialog() { | ||||
this.oneOffDialog(false) | this.oneOffDialog(false) | ||||
Show All 39 Lines | export default { | ||||
reset2FA() { | reset2FA() { | ||||
this.$refs.reset2faDialog.hide() | this.$refs.reset2faDialog.hide() | ||||
axios.post('/api/v4/users/' + this.user.id + '/reset2FA') | axios.post('/api/v4/users/' + this.user.id + '/reset2FA') | ||||
.then(response => { | .then(response => { | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
this.skus = this.skus.filter(sku => sku.id != this.sku2FA) | this.skus = this.skus.filter(sku => sku.id != this.sku2FA) | ||||
this.has2FA = false | this.has2FA = false | ||||
this.$refs.tabs.updateCounter('subscriptions', this.skus.length) | |||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
submitDiscount() { | submitDiscount() { | ||||
this.$refs.discountDialog.hide() | this.$refs.discountDialog.hide() | ||||
axios.put('/api/v4/wallets/' + this.user.wallets[0].id, { discount: this.wallet.discount_id }) | axios.put('/api/v4/wallets/' + this.user.wallets[0].id, { discount: this.wallet.discount_id }) | ||||
.then(response => { | .then(response => { | ||||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |