Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/Admin/User.vue
Show First 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | <div class="container"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row" v-if="wallet.providerLink"> | <div class="form-group row" v-if="wallet.providerLink"> | ||||
<label class="col-sm-4 col-form-label">{{ capitalize(wallet.provider) }} ID</label> | <label class="col-sm-4 col-form-label">{{ capitalize(wallet.provider) }} ID</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<span class="form-control-plaintext" v-html="wallet.providerLink"></span> | <span class="form-control-plaintext" v-html="wallet.providerLink"></span> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<button id="button-award" class="btn btn-success" type="button" @click="awardDialog">Award</button> | |||||
bohlender: I'd label the buttons "add bonus" / "add penalty" | |||||
<button id="button-penalty" class="btn btn-danger" type="button" @click="penalizeDialog">Penalize</button> | |||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="user-aliases" role="tabpanel" aria-labelledby="tab-aliases"> | <div class="tab-pane" id="user-aliases" role="tabpanel" aria-labelledby="tab-aliases"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<table class="table table-sm table-hover"> | <table class="table table-sm table-hover"> | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | <div class="container"> | ||||
<button type="button" class="btn btn-secondary modal-cancel" data-dismiss="modal">Cancel</button> | <button type="button" class="btn btn-secondary modal-cancel" data-dismiss="modal">Cancel</button> | ||||
<button type="button" class="btn btn-primary modal-action" @click="submitEmail()"> | <button type="button" class="btn btn-primary modal-action" @click="submitEmail()"> | ||||
<svg-icon icon="check"></svg-icon> Submit | <svg-icon icon="check"></svg-icon> Submit | ||||
</button> | </button> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div id="oneoff-dialog" class="modal" tabindex="-1" role="dialog"> | |||||
<div class="modal-dialog" role="document"> | |||||
<div class="modal-content"> | |||||
<div class="modal-header"> | |||||
<h5 class="modal-title">{{ oneoff_negative ? 'Add a penalty to the wallet' : 'Add a bonus to the wallet' }}</h5> | |||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> | |||||
<span aria-hidden="true">×</span> | |||||
</button> | |||||
</div> | |||||
<div class="modal-body"> | |||||
<form data-validation-prefix="oneoff_"> | |||||
<div class="form-group"> | |||||
<label for="oneoff_amount">Amount</label> | |||||
<div class="input-group"> | |||||
<input type="text" class="form-control" id="oneoff_amount" v-model="oneoff_amount" required> | |||||
<span class="input-group-append"> | |||||
<span class="input-group-text">{{ oneoff_currency }}</span> | |||||
</span> | |||||
</div> | |||||
</div> | |||||
<div class="form-group"> | |||||
<label for="oneoff_description">Description</label> | |||||
<input class="form-control" id="oneoff_description" v-model="oneoff_description" required> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
<div class="modal-footer"> | |||||
<button type="button" class="btn btn-secondary modal-cancel" data-dismiss="modal">Cancel</button> | |||||
<button type="button" class="btn btn-primary modal-action" @click="submitOneOff()"> | |||||
<svg-icon icon="check"></svg-icon> Submit | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
Not Done Inline ActionsWe seem make more use of modals lately. I wonder if going with changing the user interface inline might provide a better user experience. bohlender: We seem make more use of modals lately. I wonder if going with changing the user interface… | |||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
export default { | export default { | ||||
beforeRouteUpdate (to, from, next) { | beforeRouteUpdate (to, from, next) { | ||||
// An event called when the route that renders this component has changed, | // An event called when the route that renders this component has changed, | ||||
// but this component is reused in the new route. | // but this component is reused in the new route. | ||||
// Required to handle links from /user/XXX to /user/YYY | // Required to handle links from /user/XXX to /user/YYY | ||||
next() | next() | ||||
this.$parent.routerReload() | this.$parent.routerReload() | ||||
}, | }, | ||||
data() { | data() { | ||||
return { | return { | ||||
oneoff_amount: '', | |||||
oneoff_currency: 'CHF', | |||||
oneoff_description: '', | |||||
oneoff_negative: false, | |||||
balance: 0, | |||||
discount: 0, | discount: 0, | ||||
discount_description: '', | discount_description: '', | ||||
discounts: [], | discounts: [], | ||||
external_email: '', | external_email: '', | ||||
wallet: {}, | wallet: {}, | ||||
domains: [], | domains: [], | ||||
skus: [], | skus: [], | ||||
users: [], | users: [], | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | export default { | ||||
e.preventDefault() | e.preventDefault() | ||||
$(e.target).tab('show') | $(e.target).tab('show') | ||||
}) | }) | ||||
}, | }, | ||||
methods: { | methods: { | ||||
capitalize(str) { | capitalize(str) { | ||||
return str.charAt(0).toUpperCase() + str.slice(1) | return str.charAt(0).toUpperCase() + str.slice(1) | ||||
}, | }, | ||||
awardDialog() { | |||||
this.oneOffDialog(false) | |||||
}, | |||||
discountEdit() { | discountEdit() { | ||||
$('#discount-dialog') | $('#discount-dialog') | ||||
.on('shown.bs.modal', e => { | .on('shown.bs.modal', e => { | ||||
$(e.target).find('select').focus() | $(e.target).find('select').focus() | ||||
// 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 || '' | ||||
}) | }) | ||||
.modal() | .modal() | ||||
Show All 11 Lines | export default { | ||||
this.$root.clearFormValidation($('#email-dialog')) | this.$root.clearFormValidation($('#email-dialog')) | ||||
$('#email-dialog') | $('#email-dialog') | ||||
.on('shown.bs.modal', e => { | .on('shown.bs.modal', e => { | ||||
$(e.target).find('input').focus() | $(e.target).find('input').focus() | ||||
}) | }) | ||||
.modal() | .modal() | ||||
}, | }, | ||||
oneOffDialog(negative) { | |||||
this.oneoff_negative = negative | |||||
this.dialog = $('#oneoff-dialog').on('shown.bs.modal', event => { | |||||
this.$root.clearFormValidation(event.target) | |||||
$(event.target).find('#oneoff_amount').focus() | |||||
}).modal() | |||||
}, | |||||
penalizeDialog() { | |||||
this.oneOffDialog(true) | |||||
}, | |||||
submitDiscount() { | submitDiscount() { | ||||
$('#discount-dialog').modal('hide') | $('#discount-dialog').modal('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 => { | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
this.wallet = Object.assign({}, this.wallet, response.data) | this.wallet = Object.assign({}, this.wallet, response.data) | ||||
Show All 16 Lines | export default { | ||||
if (response.data.status == 'success') { | if (response.data.status == 'success') { | ||||
$('#email-dialog').modal('hide') | $('#email-dialog').modal('hide') | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
this.user.external_email = this.external_email | this.user.external_email = this.external_email | ||||
this.external_email = null // required because of Vue | this.external_email = null // required because of Vue | ||||
} | } | ||||
}) | }) | ||||
}, | }, | ||||
submitOneOff() { | |||||
let wallet_id = this.user.wallets[0].id | |||||
let post = { | |||||
amount: this.oneoff_amount, | |||||
description: this.oneoff_description | |||||
} | |||||
if (this.oneoff_negative && /^\d+(\.?\d+)?$/.test(post.amount)) { | |||||
post.amount *= -1 | |||||
} | |||||
// TODO: We maybe should use system currency not wallet currency, | |||||
// or have a selector so the operator does not have to calculate | |||||
// exchange rates | |||||
this.$root.clearFormValidation(this.dialog) | |||||
axios.post('/api/v4/wallets/' + wallet_id + '/one-off', post) | |||||
.then(response => { | |||||
if (response.data.status == 'success') { | |||||
this.dialog.modal('hide') | |||||
this.$toast.success(response.data.message) | |||||
this.balance = response.data.balance | |||||
this.oneoff_amount = '' | |||||
this.oneoff_description = '' | |||||
} | |||||
}) | |||||
}, | |||||
suspendUser() { | suspendUser() { | ||||
axios.post('/api/v4/users/' + this.user.id + '/suspend', {}) | axios.post('/api/v4/users/' + this.user.id + '/suspend', {}) | ||||
.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.user = Object.assign({}, this.user, { isSuspended: true }) | this.user = Object.assign({}, this.user, { isSuspended: true }) | ||||
} | } | ||||
}) | }) | ||||
Show All 13 Lines |
I'd label the buttons "add bonus" / "add penalty"