mirror of
https://github.com/crater-invoice/crater.git
synced 2026-02-09 20:32:40 -05:00
Merge branch 'master' of https://gitlab.com/mohit.panjvani/crater-web into sweetalert-on-action
This commit is contained in:
@@ -96,6 +96,7 @@
|
||||
<line-chart
|
||||
v-if="isLoaded"
|
||||
:format-money="$utils.formatMoney"
|
||||
:format-graph-money="$utils.formatGraphMoney"
|
||||
:invoices="getChartInvoices"
|
||||
:expenses="getChartExpenses"
|
||||
:receipts="getReceiptTotals"
|
||||
|
||||
@@ -688,7 +688,7 @@ export default {
|
||||
isValid = false
|
||||
}
|
||||
})
|
||||
if (this.$v.newEstimate.$invalid === false && isValid === true) {
|
||||
if (!this.$v.selectedCustomer.$invalid && this.$v.newEstimate.$invalid === false && isValid === true) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
@select="onSelectItem"
|
||||
@deselect="deselectItem"
|
||||
@onDesriptionInput="$v.item.description.$touch()"
|
||||
@onSelectItem="isSelected = true"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
@@ -193,13 +194,17 @@ export default {
|
||||
prefix: '$ ',
|
||||
precision: 2,
|
||||
masked: false
|
||||
}
|
||||
},
|
||||
isSelected: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('item', [
|
||||
'items'
|
||||
]),
|
||||
...mapGetters('modal', [
|
||||
'modalActive'
|
||||
]),
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrencyForInput'
|
||||
]),
|
||||
@@ -284,6 +289,11 @@ export default {
|
||||
if (this.item.discount_type === 'percentage') {
|
||||
this.item.discount_val = (this.item.discount * newValue) / 100
|
||||
}
|
||||
},
|
||||
modalActive (val) {
|
||||
if (!val) {
|
||||
this.isSelected = false
|
||||
}
|
||||
}
|
||||
},
|
||||
validations () {
|
||||
@@ -313,7 +323,11 @@ export default {
|
||||
},
|
||||
created () {
|
||||
window.hub.$on('checkItems', this.validateItem)
|
||||
window.hub.$on('newItem', this.onSelectItem)
|
||||
window.hub.$on('newItem', (val) => {
|
||||
if (!this.item.item_id && this.modalActive && this.isSelected) {
|
||||
this.onSelectItem(val)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
updateTax (data) {
|
||||
|
||||
@@ -126,6 +126,7 @@ export default {
|
||||
this.$emit('search', val)
|
||||
},
|
||||
openItemModal () {
|
||||
this.$emit('onSelectItem')
|
||||
this.openModal({
|
||||
'title': 'Add Item',
|
||||
'componentName': 'ItemModal'
|
||||
|
||||
@@ -92,13 +92,14 @@
|
||||
<money
|
||||
v-model="amount"
|
||||
v-bind="defaultCurrencyForInput"
|
||||
:class="{'invalid' : $v.formData.amount.$error}"
|
||||
class="input-field"
|
||||
@input="$v.formData.amount.$touch()"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="$v.formData.amount.$error">
|
||||
<span v-if="!$v.formData.amount.required" class="text-danger">{{ $t('validation.required') }}</span>
|
||||
<span v-if="!$v.formData.amount.maxLength" class="text-danger">{{ $t('validation.amount_maxlength') }}</span>
|
||||
<span v-if="!$v.formData.amount.maxValue" class="text-danger">{{ $t('validation.amount_minvalue') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-sm-6">
|
||||
|
||||
@@ -519,14 +519,6 @@ export default {
|
||||
...mapActions('item', [
|
||||
'fetchItems'
|
||||
]),
|
||||
isEmpty (obj) {
|
||||
for (let key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
selectFixed () {
|
||||
if (this.newInvoice.discount_type === 'fixed') {
|
||||
return
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
@select="onSelectItem"
|
||||
@deselect="deselectItem"
|
||||
@onDesriptionInput="$v.item.description.$touch()"
|
||||
@onSelectItem="isSelected = true"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
@@ -194,13 +195,17 @@ export default {
|
||||
prefix: '$ ',
|
||||
precision: 2,
|
||||
masked: false
|
||||
}
|
||||
},
|
||||
isSelected: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters('item', [
|
||||
'items'
|
||||
]),
|
||||
...mapGetters('modal', [
|
||||
'modalActive'
|
||||
]),
|
||||
...mapGetters('currency', [
|
||||
'defaultCurrencyForInput'
|
||||
]),
|
||||
@@ -285,6 +290,11 @@ export default {
|
||||
if (this.item.discount_type === 'percentage') {
|
||||
this.item.discount_val = (this.item.discount * newValue) / 100
|
||||
}
|
||||
},
|
||||
modalActive (val) {
|
||||
if (!val) {
|
||||
this.isSelected = false
|
||||
}
|
||||
}
|
||||
},
|
||||
validations () {
|
||||
@@ -314,7 +324,11 @@ export default {
|
||||
},
|
||||
created () {
|
||||
window.hub.$on('checkItems', this.validateItem)
|
||||
window.hub.$on('newItem', this.onSelectItem)
|
||||
window.hub.$on('newItem', (val) => {
|
||||
if (!this.item.item_id && this.modalActive && this.isSelected) {
|
||||
this.onSelectItem(val)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
updateTax (data) {
|
||||
|
||||
@@ -115,6 +115,7 @@ export default {
|
||||
this.$emit('search', val)
|
||||
},
|
||||
openItemModal () {
|
||||
this.$emit('onSelectItem')
|
||||
this.openModal({
|
||||
'title': 'Add Item',
|
||||
'componentName': 'ItemModal'
|
||||
|
||||
@@ -34,16 +34,16 @@
|
||||
<label>{{ $t('items.price') }}</label><span class="text-danger"> *</span>
|
||||
<div class="base-input">
|
||||
<money
|
||||
:invalid="$v.formData.price.$error"
|
||||
:class="{'invalid' : $v.formData.price.$error}"
|
||||
v-model="price"
|
||||
v-bind="defaultCurrencyForInput"
|
||||
class="input-field"
|
||||
@input="$v.formData.price.$touch()"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="$v.formData.price.$error">
|
||||
<span v-if="!$v.formData.price.required" class="text-danger">{{ $t('validation.required') }} </span>
|
||||
<span v-if="!$v.formData.price.maxLength" class="text-danger">{{ $t('validation.price_maxlength') }}</span>
|
||||
<span v-if="!$v.formData.price.minValue" class="text-danger">{{ $t('validation.price_minvalue') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -92,7 +92,8 @@
|
||||
<script>
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import { mapActions, mapGetters } from 'vuex'
|
||||
const { required, minLength, numeric, alpha, minValue, maxLength} = require('vuelidate/lib/validators')
|
||||
const { required, minLength, numeric, alpha, minValue, maxLength } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
mixins: {
|
||||
validationMixin
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</div>
|
||||
<div class="col-sm-8 reports-tab-container">
|
||||
<iframe :src="getReportUrl" class="reports-frame-style"/>
|
||||
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank">
|
||||
<a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
|
||||
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -179,6 +179,11 @@ export default {
|
||||
setRangeToCustom () {
|
||||
this.selectedRange = 'Custom'
|
||||
},
|
||||
async viewReportsPDF () {
|
||||
let data = await this.getReports()
|
||||
window.open(this.getReportUrl, '_blank')
|
||||
return data
|
||||
},
|
||||
async getReports (isDownload = false) {
|
||||
this.$v.range.$touch()
|
||||
this.$v.formData.$touch()
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</div>
|
||||
<div class="col-sm-8 reports-tab-container">
|
||||
<iframe :src="getReportUrl" class="reports-frame-style"/>
|
||||
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank">
|
||||
<a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
|
||||
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -184,6 +184,11 @@ export default {
|
||||
setRangeToCustom () {
|
||||
this.selectedRange = 'Custom'
|
||||
},
|
||||
async viewReportsPDF () {
|
||||
let data = await this.getReports()
|
||||
window.open(this.getReportUrl, '_blank')
|
||||
return data
|
||||
},
|
||||
async getReports (isDownload = false) {
|
||||
this.$v.range.$touch()
|
||||
this.$v.formData.$touch()
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
<div class="col-sm-8 reports-tab-container">
|
||||
<iframe :src="getReportUrl" class="reports-frame-style"/>
|
||||
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank">
|
||||
<a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
|
||||
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -217,6 +217,11 @@ export default {
|
||||
this.url = `${this.itemsSiteURL}?from_date=${moment(this.formData.from_date).format('DD/MM/YYYY')}&to_date=${moment(this.formData.to_date).format('DD/MM/YYYY')}`
|
||||
return true
|
||||
},
|
||||
async viewReportsPDF () {
|
||||
let data = await this.getReports()
|
||||
window.open(this.getReportUrl, '_blank')
|
||||
return data
|
||||
},
|
||||
async getReports (isDownload = false) {
|
||||
this.$v.range.$touch()
|
||||
this.$v.formData.$touch()
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</div>
|
||||
<div class="col-sm-8 reports-tab-container">
|
||||
<iframe :src="getReportUrl" class="reports-frame-style"/>
|
||||
<a :href="getReportUrl" class="base-button btn btn-primary btn-lg report-view-button" target="_blank">
|
||||
<a class="base-button btn btn-primary btn-lg report-view-button" @click="viewReportsPDF">
|
||||
<font-awesome-icon icon="file-pdf" class="vue-icon icon-left svg-inline--fa fa-download fa-w-16 mr-2" /> <span>{{ $t('reports.view_pdf') }}</span>
|
||||
</a>
|
||||
</div>
|
||||
@@ -179,6 +179,11 @@ export default {
|
||||
setRangeToCustom () {
|
||||
this.selectedRange = 'Custom'
|
||||
},
|
||||
async viewReportsPDF () {
|
||||
let data = await this.getReports()
|
||||
window.open(this.getReportUrl, '_blank')
|
||||
return data
|
||||
},
|
||||
async getReports (isDownload = false) {
|
||||
this.$v.range.$touch()
|
||||
this.$v.formData.$touch()
|
||||
|
||||
213
resources/assets/js/views/settings/MailConfig.vue
Normal file
213
resources/assets/js/views/settings/MailConfig.vue
Normal file
@@ -0,0 +1,213 @@
|
||||
<template>
|
||||
<div class="setting-main-container">
|
||||
<div class="card setting-card">
|
||||
<div class="page-header">
|
||||
<h3 class="page-title">{{ $t('settings.mail.mail_config') }}</h3>
|
||||
<p class="page-sub-title">
|
||||
{{ $t('settings.mail.mail_config_desc') }}
|
||||
</p>
|
||||
</div>
|
||||
<form action="" @submit.prevent="saveEmailConfig()">
|
||||
<div class="row my-2 mt-5">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.driver') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-select
|
||||
v-model="mailConfigData.mail_driver"
|
||||
:invalid="$v.mailConfigData.mail_driver.$error"
|
||||
:options="mail_drivers"
|
||||
:searchable="true"
|
||||
:show-labels="false"
|
||||
@change="$v.mailConfigData.mail_driver.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_driver.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_driver.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.host') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_host.$error"
|
||||
v-model.trim="mailConfigData.mail_host"
|
||||
type="text"
|
||||
name="mail_host"
|
||||
@input="$v.mailConfigData.mail_host.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_host.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_host.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.username') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_username.$error"
|
||||
v-model.trim="mailConfigData.mail_username"
|
||||
type="text"
|
||||
name="db_name"
|
||||
@input="$v.mailConfigData.mail_username.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_username.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_username.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.password') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_password.$error"
|
||||
v-model.trim="mailConfigData.mail_password"
|
||||
type="mail_password"
|
||||
name="name"
|
||||
@input="$v.mailConfigData.mail_password.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_password.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_password.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.port') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_port.$error"
|
||||
v-model.trim="mailConfigData.mail_port"
|
||||
type="text"
|
||||
name="mail_port"
|
||||
@input="$v.mailConfigData.mail_port.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_port.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_port.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
<span v-if="!$v.mailConfigData.mail_port.numeric" class="text-danger">
|
||||
{{ $tc('validation.numbers_only') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 my-2">
|
||||
<label class="form-label">{{ $t('settings.mail.encryption') }}</label>
|
||||
<span class="text-danger"> *</span>
|
||||
<base-input
|
||||
:invalid="$v.mailConfigData.mail_encryption.$error"
|
||||
v-model.trim="mailConfigData.mail_encryption"
|
||||
type="text"
|
||||
name="name"
|
||||
@input="$v.mailConfigData.mail_encryption.$touch()"
|
||||
/>
|
||||
<div v-if="$v.mailConfigData.mail_encryption.$error">
|
||||
<span v-if="!$v.mailConfigData.mail_encryption.required" class="text-danger">
|
||||
{{ $tc('validation.required') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-5"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import MultiSelect from 'vue-multiselect'
|
||||
import { validationMixin } from 'vuelidate'
|
||||
import Ls from '../../services/ls'
|
||||
const { required, email, numeric } = require('vuelidate/lib/validators')
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MultiSelect
|
||||
},
|
||||
mixins: [validationMixin],
|
||||
data () {
|
||||
return {
|
||||
mailConfigData: {
|
||||
mail_driver: 'smtp',
|
||||
mail_host: 'mailtrap.io',
|
||||
mail_port: 2525,
|
||||
mail_username: 'cc3c64516febd4',
|
||||
mail_password: 'e6a0176301f587',
|
||||
mail_encryption: 'tls'
|
||||
},
|
||||
loading: false,
|
||||
mail_drivers: []
|
||||
}
|
||||
},
|
||||
validations: {
|
||||
mailConfigData: {
|
||||
mail_driver: {
|
||||
required
|
||||
},
|
||||
mail_host: {
|
||||
required
|
||||
},
|
||||
mail_port: {
|
||||
required,
|
||||
numeric
|
||||
},
|
||||
mail_username: {
|
||||
required
|
||||
},
|
||||
mail_password: {
|
||||
required
|
||||
},
|
||||
mail_encryption: {
|
||||
required
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// this.getMailDrivers()
|
||||
},
|
||||
methods: {
|
||||
async getMailDrivers () {
|
||||
this.loading = true
|
||||
|
||||
let response = await window.axios.get('/api/admin/onboarding/environment/mail')
|
||||
|
||||
if (response.data) {
|
||||
this.mail_drivers = response.data
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async saveEmailConfig () {
|
||||
this.$v.mailConfigData.$touch()
|
||||
if (this.$v.mailConfigData.$invalid) {
|
||||
return true
|
||||
}
|
||||
this.loading = true
|
||||
try {
|
||||
let response = await window.axios.post('/api/admin/onboarding/environment/mail', this.mailConfigData)
|
||||
if (response.data.success) {
|
||||
window.toastr['success'](this.$t('wizard.success.' + response.data.success))
|
||||
} else {
|
||||
window.toastr['error'](this.$t('wizard.errors.' + response.data.error))
|
||||
}
|
||||
this.loading = false
|
||||
return true
|
||||
} catch (e) {
|
||||
window.toastr['error']('Something went wrong')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -113,7 +113,11 @@
|
||||
<h3 class="page-title">{{ $t('settings.preferences.discount_setting') }}</h3>
|
||||
<div class="flex-box">
|
||||
<div class="left">
|
||||
<base-switch v-model="discount_per_item" class="btn-switch" @change="setDiscount" />
|
||||
<base-switch
|
||||
v-model="discount_per_item"
|
||||
class="btn-switch"
|
||||
@change="setDiscount"
|
||||
/>
|
||||
</div>
|
||||
<div class="right ml-15">
|
||||
<p class="box-title"> {{ $t('settings.preferences.discount_per_item') }} </p>
|
||||
|
||||
@@ -63,6 +63,12 @@ export default {
|
||||
icon: 'list-alt',
|
||||
iconType: 'far'
|
||||
},
|
||||
{
|
||||
link: '/admin/settings/mail-configuration',
|
||||
title: 'settings.mail.mail_config',
|
||||
icon: 'envelope',
|
||||
iconType: 'fa'
|
||||
},
|
||||
{
|
||||
link: '/admin/settings/notifications',
|
||||
title: 'settings.menu_title.notifications',
|
||||
|
||||
@@ -109,15 +109,26 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right mt-5"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
<div class="row mt-5">
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right"
|
||||
icon="save"
|
||||
color="theme"
|
||||
type="submit"
|
||||
>
|
||||
{{ $t('wizard.save_cont') }}
|
||||
</base-button>
|
||||
<base-button
|
||||
:loading="loading"
|
||||
class="pull-right ml-4"
|
||||
outline
|
||||
color="theme"
|
||||
@click="$emit('next')"
|
||||
>
|
||||
{{ $t('wizard.skip') }}
|
||||
</base-button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
@@ -137,10 +148,10 @@ export default {
|
||||
mailConfigData: {
|
||||
mail_driver: 'smtp',
|
||||
mail_host: 'mailtrap.io',
|
||||
mail_port: 2525,
|
||||
mail_username: 'cc3c64516febd4',
|
||||
mail_password: 'e6a0176301f587',
|
||||
mail_encryption: 'tls'
|
||||
mail_port: null,
|
||||
mail_username: null,
|
||||
mail_password: null,
|
||||
mail_encryption: null
|
||||
},
|
||||
loading: false,
|
||||
mail_drivers: []
|
||||
|
||||
Reference in New Issue
Block a user