Changeset View
Changeset View
Standalone View
Standalone View
src/resources/vue/User/Info.vue
<template> | <template> | ||||
<div class="container"> | <div class="container"> | ||||
<status-component v-if="user_id !== 'new'" :status="status" @status-update="statusUpdate"></status-component> | <status-component v-if="user_id !== 'new'" :status="status" @status-update="statusUpdate"></status-component> | ||||
<div class="card" id="user-info"> | <div class="card" id="user-info"> | ||||
<div class="card-body"> | <div class="card-body"> | ||||
<div class="card-title" v-if="user_id !== 'new'">User account</div> | <div class="card-title" v-if="user_id !== 'new'">User account</div> | ||||
<div class="card-title" v-if="user_id === 'new'">New user account</div> | <div class="card-title" v-if="user_id === 'new'">New user account</div> | ||||
<div class="card-text"> | <div class="card-text"> | ||||
<ul class="nav nav-tabs mt-3" role="tablist"> | |||||
<li class="nav-item"> | |||||
<a class="nav-link active" id="tab-general" href="#general" role="tab" aria-controls="general" aria-selected="true" @click="$root.tab"> | |||||
General | |||||
</a> | |||||
</li> | |||||
<li v-if="user_id !== 'new'" class="nav-item"> | |||||
<a class="nav-link" id="tab-settings" href="#settings" role="tab" aria-controls="settings" aria-selected="false" @click="$root.tab"> | |||||
Settings | |||||
</a> | |||||
</li> | |||||
</ul> | |||||
<div class="tab-content"> | |||||
<div class="tab-pane show active" id="general" role="tabpanel" aria-labelledby="tab-general"> | |||||
<div class="card-body"> | |||||
<form @submit.prevent="submit"> | <form @submit.prevent="submit"> | ||||
<div v-if="user_id !== 'new'" class="form-group row plaintext"> | <div v-if="user_id !== 'new'" class="form-group row plaintext"> | ||||
<label for="first_name" class="col-sm-4 col-form-label">Status</label> | <label for="first_name" class="col-sm-4 col-form-label">Status</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<span :class="$root.userStatusClass(user) + ' form-control-plaintext'" id="status">{{ $root.userStatusText(user) }}</span> | <span :class="$root.userStatusClass(user) + ' form-control-plaintext'" id="status">{{ $root.userStatusText(user) }}</span> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="first_name" class="col-sm-4 col-form-label">First name</label> | <label for="first_name" class="col-sm-4 col-form-label">First name</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="text" class="form-control" id="first_name" v-model="user.first_name"> | <input type="text" class="form-control" id="first_name" v-model="user.first_name"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="last_name" class="col-sm-4 col-form-label">Last name</label> | <label for="last_name" class="col-sm-4 col-form-label">Last name</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="text" class="form-control" id="last_name" v-model="user.last_name"> | <input type="text" class="form-control" id="last_name" v-model="user.last_name"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="organization" class="col-sm-4 col-form-label">Organization</label> | <label for="organization" class="col-sm-4 col-form-label">Organization</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="text" class="form-control" id="organization" v-model="user.organization"> | <input type="text" class="form-control" id="organization" v-model="user.organization"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="email" class="col-sm-4 col-form-label">Email</label> | <label for="email" class="col-sm-4 col-form-label">Email</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="text" class="form-control" id="email" :disabled="user_id !== 'new'" required v-model="user.email"> | <input type="text" class="form-control" id="email" :disabled="user_id !== 'new'" required v-model="user.email"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="aliases-input" class="col-sm-4 col-form-label">Email aliases</label> | <label for="aliases-input" class="col-sm-4 col-form-label">Email aliases</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<list-input id="aliases" :list="user.aliases"></list-input> | <list-input id="aliases" :list="user.aliases"></list-input> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="password" class="col-sm-4 col-form-label">Password</label> | <label for="password" class="col-sm-4 col-form-label">Password</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="password" class="form-control" id="password" v-model="user.password" :required="user_id === 'new'"> | <input type="password" class="form-control" id="password" v-model="user.password" :required="user_id === 'new'"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="form-group row"> | <div class="form-group row"> | ||||
<label for="password_confirmaton" class="col-sm-4 col-form-label">Confirm password</label> | <label for="password_confirmaton" class="col-sm-4 col-form-label">Confirm password</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<input type="password" class="form-control" id="password_confirmation" v-model="user.password_confirmation" :required="user_id === 'new'"> | <input type="password" class="form-control" id="password_confirmation" v-model="user.password_confirmation" :required="user_id === 'new'"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div v-if="user_id === 'new'" id="user-packages" class="form-group row"> | <div v-if="user_id === 'new'" id="user-packages" class="form-group row"> | ||||
<label class="col-sm-4 col-form-label">Package</label> | <label class="col-sm-4 col-form-label">Package</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<table class="table table-sm form-list"> | <table class="table table-sm form-list"> | ||||
<thead class="thead-light sr-only"> | <thead class="thead-light sr-only"> | ||||
<tr> | <tr> | ||||
<th scope="col"></th> | <th scope="col"></th> | ||||
<th scope="col">Package</th> | <th scope="col">Package</th> | ||||
<th scope="col">Price</th> | <th scope="col">Price</th> | ||||
<th scope="col"></th> | <th scope="col"></th> | ||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
<tr v-for="pkg in packages" :id="'p' + pkg.id" :key="pkg.id"> | <tr v-for="pkg in packages" :id="'p' + pkg.id" :key="pkg.id"> | ||||
<td class="selection"> | <td class="selection"> | ||||
<input type="checkbox" @click="selectPackage" | <input type="checkbox" @click="selectPackage" | ||||
:value="pkg.id" | :value="pkg.id" | ||||
:checked="pkg.id == package_id" | :checked="pkg.id == package_id" | ||||
:id="'pkg-input-' + pkg.id" | :id="'pkg-input-' + pkg.id" | ||||
> | > | ||||
</td> | </td> | ||||
<td class="name"> | <td class="name"> | ||||
<label :for="'pkg-input-' + pkg.id">{{ pkg.name }}</label> | <label :for="'pkg-input-' + pkg.id">{{ pkg.name }}</label> | ||||
</td> | </td> | ||||
<td class="price text-nowrap"> | <td class="price text-nowrap"> | ||||
{{ $root.priceLabel(pkg.cost, 1, discount) }} | {{ $root.priceLabel(pkg.cost, 1, discount) }} | ||||
</td> | </td> | ||||
<td class="buttons"> | <td class="buttons"> | ||||
<button v-if="pkg.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip.click="pkg.description"> | <button v-if="pkg.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip.click="pkg.description"> | ||||
<svg-icon icon="info-circle"></svg-icon> | <svg-icon icon="info-circle"></svg-icon> | ||||
<span class="sr-only">More information</span> | <span class="sr-only">More information</span> | ||||
</button> | </button> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<small v-if="discount > 0" class="hint"> | <small v-if="discount > 0" class="hint"> | ||||
<hr class="m-0"> | <hr class="m-0"> | ||||
¹ applied discount: {{ discount }}% - {{ discount_description }} | ¹ applied discount: {{ discount }}% - {{ discount_description }} | ||||
</small> | </small> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div v-if="user_id !== 'new'" id="user-skus" class="form-group row"> | <div v-if="user_id !== 'new'" id="user-skus" class="form-group row"> | ||||
<label class="col-sm-4 col-form-label">Subscriptions</label> | <label class="col-sm-4 col-form-label">Subscriptions</label> | ||||
<div class="col-sm-8"> | <div class="col-sm-8"> | ||||
<table class="table table-sm form-list"> | <table class="table table-sm form-list"> | ||||
<thead class="thead-light sr-only"> | <thead class="thead-light sr-only"> | ||||
<tr> | <tr> | ||||
<th scope="col"></th> | <th scope="col"></th> | ||||
<th scope="col">Subscription</th> | <th scope="col">Subscription</th> | ||||
<th scope="col">Price</th> | <th scope="col">Price</th> | ||||
<th scope="col"></th> | <th scope="col"></th> | ||||
</tr> | </tr> | ||||
</thead> | </thead> | ||||
<tbody> | <tbody> | ||||
<tr v-for="sku in skus" :id="'s' + sku.id" :key="sku.id"> | <tr v-for="sku in skus" :id="'s' + sku.id" :key="sku.id"> | ||||
<td class="selection"> | <td class="selection"> | ||||
<input type="checkbox" @input="onInputSku" | <input type="checkbox" @input="onInputSku" | ||||
:value="sku.id" | :value="sku.id" | ||||
:disabled="sku.readonly" | :disabled="sku.readonly" | ||||
:checked="sku.enabled" | :checked="sku.enabled" | ||||
:id="'sku-input-' + sku.title" | :id="'sku-input-' + sku.title" | ||||
> | > | ||||
</td> | </td> | ||||
<td class="name"> | <td class="name"> | ||||
<label :for="'sku-input-' + sku.title">{{ sku.name }}</label> | <label :for="'sku-input-' + sku.title">{{ sku.name }}</label> | ||||
<div v-if="sku.range" class="range-input"> | <div v-if="sku.range" class="range-input"> | ||||
<label class="text-nowrap">{{ sku.range.min }} {{ sku.range.unit }}</label> | <label class="text-nowrap">{{ sku.range.min }} {{ sku.range.unit }}</label> | ||||
<input | <input | ||||
type="range" class="custom-range" @input="rangeUpdate" | type="range" class="custom-range" @input="rangeUpdate" | ||||
:value="sku.value || sku.range.min" | :value="sku.value || sku.range.min" | ||||
:min="sku.range.min" | :min="sku.range.min" | ||||
:max="sku.range.max" | :max="sku.range.max" | ||||
> | > | ||||
</div> | </div> | ||||
</td> | </td> | ||||
<td class="price text-nowrap"> | <td class="price text-nowrap"> | ||||
{{ $root.priceLabel(sku.cost, 1, discount) }} | {{ $root.priceLabel(sku.cost, 1, discount) }} | ||||
</td> | </td> | ||||
<td class="buttons"> | <td class="buttons"> | ||||
<button v-if="sku.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip.click="sku.description"> | <button v-if="sku.description" type="button" class="btn btn-link btn-lg p-0" v-tooltip.click="sku.description"> | ||||
<svg-icon icon="info-circle"></svg-icon> | <svg-icon icon="info-circle"></svg-icon> | ||||
<span class="sr-only">More information</span> | <span class="sr-only">More information</span> | ||||
</button> | </button> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
<small v-if="discount > 0" class="hint"> | <small v-if="discount > 0" class="hint"> | ||||
<hr class="m-0"> | <hr class="m-0"> | ||||
¹ applied discount: {{ discount }}% - {{ discount_description }} | ¹ applied discount: {{ discount }}% - {{ discount_description }} | ||||
</small> | </small> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<button class="btn btn-primary" type="submit"><svg-icon icon="check"></svg-icon> Submit</button> | <button class="btn btn-primary" type="submit"><svg-icon icon="check"></svg-icon> Submit</button> | ||||
</form> | </form> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="tab-pane" id="settings" role="tabpanel" aria-labelledby="tab-settings"> | |||||
<div class="card-body"> | |||||
<form @submit.prevent="submitSettings"> | |||||
<div class="form-group row checkbox"> | |||||
<label for="greylisting" class="col-sm-4 col-form-label">Greylisting</label> | |||||
<div class="col-sm-8 pt-2"> | |||||
<input type="checkbox" id="greylisting" name="greylisting" value="1" :checked="user.config.greylisting"> | |||||
<small id="greylisting-hint" class="form-text text-muted"> | |||||
Greylisting is a method of defending users against spam. Any incoming mail from an unrecognized sender | |||||
is temporarily rejected. The originating server should try again after a delay. | |||||
This time the email will be accepted. Spammers usually do not reattempt mail delivery. | |||||
</small> | |||||
</div> | |||||
</div> | |||||
<button class="btn btn-primary" type="submit"><svg-icon icon="check"></svg-icon> Submit</button> | |||||
</form> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
<script> | <script> | ||||
import ListInput from '../Widgets/ListInput' | import ListInput from '../Widgets/ListInput' | ||||
import StatusComponent from '../Widgets/Status' | import StatusComponent from '../Widgets/Status' | ||||
export default { | export default { | ||||
components: { | components: { | ||||
ListInput, | ListInput, | ||||
StatusComponent | StatusComponent | ||||
}, | }, | ||||
data() { | data() { | ||||
return { | return { | ||||
discount: 0, | discount: 0, | ||||
discount_description: '', | discount_description: '', | ||||
user_id: null, | user_id: null, | ||||
user: { aliases: [] }, | user: { aliases: [], config: [] }, | ||||
packages: [], | packages: [], | ||||
package_id: null, | package_id: null, | ||||
skus: [], | skus: [], | ||||
status: {} | status: {} | ||||
} | } | ||||
}, | }, | ||||
created() { | created() { | ||||
this.user_id = this.$route.params.user | this.user_id = this.$route.params.user | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | export default { | ||||
if (response.data.statusInfo) { | if (response.data.statusInfo) { | ||||
this.$store.state.authInfo.statusInfo = response.data.statusInfo | this.$store.state.authInfo.statusInfo = response.data.statusInfo | ||||
} | } | ||||
this.$toast.success(response.data.message) | this.$toast.success(response.data.message) | ||||
this.$router.push({ name: 'users' }) | this.$router.push({ name: 'users' }) | ||||
}) | }) | ||||
}, | }, | ||||
submitSettings() { | |||||
this.$root.clearFormValidation($('#settings form')) | |||||
let post = { greylisting: $('#greylisting').prop('checked') ? 1 : 0 } | |||||
axios.post('/api/v4/users/' + this.user_id + '/config', post) | |||||
.then(response => { | |||||
this.$toast.success(response.data.message) | |||||
}) | |||||
}, | |||||
onInputSku(e) { | onInputSku(e) { | ||||
let input = e.target | let input = e.target | ||||
let sku = this.findSku(input.value) | let sku = this.findSku(input.value) | ||||
let required = [] | let required = [] | ||||
// We use 'readonly', not 'disabled', because we might want to handle | // We use 'readonly', not 'disabled', because we might want to handle | ||||
// input events. For example to display an error when someone clicks | // input events. For example to display an error when someone clicks | ||||
// the locked input | // the locked input | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |