Merge branch 'master' of github.com:akaunting/akaunting into 2.1-dev

# Conflicts:
#	app/Http/Controllers/Common/Items.php
#	resources/views/modules/item/documentation.blade.php
#	resources/views/modules/item/show.blade.php
#	resources/views/partials/admin/header.blade.php
#	resources/views/purchases/bills/show.blade.php
#	resources/views/purchases/vendors/show.blade.php
#	resources/views/sales/customers/show.blade.php
#	resources/views/sales/invoices/show.blade.php
#	resources/views/wizard/companies/edit.blade.php
#	resources/views/wizard/currencies/index.blade.php
#	resources/views/wizard/finish/index.blade.php
#	resources/views/wizard/taxes/index.blade.php
This commit is contained in:
Cüneyt Şentürk
2020-08-28 19:24:26 +03:00
824 changed files with 14086 additions and 5612 deletions

View File

@ -19,9 +19,12 @@
<el-carousel-item v-for="(screenshot, index) in screenshots" :key="index">
<img class="d-block w-100 carousel-frame" height="365px" :src="screenshot.path_string" :alt="screenshot.alt_attribute">
<div class="carousel-description py-2">
<div class="carousel-description py-2" v-if="screenshot.description">
{{ screenshot.description }}
</div>
<div class="carousel-description py-2" v-else>
{{ name }}
</div>
</el-carousel-item>
</el-carousel>
</div>

View File

@ -0,0 +1,201 @@
<template>
<div class="countdown">
<section class="flex text-6xl justify-center content-center">
<div class="days mr-2 relative">
{{ displayDays}}
<div class="label text-sm absolut bottom-0"> {{ textDays }} </div>
</div>
<span class="leading-snug">:</span>
<div class="hours mx-2 relative">
{{ displayHours }}
<div class="label text-sm absolut bottom-0">{{ textHours }} </div>
</div>
<span class="leading-snug">:</span>
<div class="minutes mx-2 relative">
{{ displayMinutes }}
<div class="label text-sm absolut bottom-0"> {{ textMinutes }} </div>
</div>
<span class="leading-snug">:</span>
<div class="seconds ml-2 relative">
{{ displaySeconds }}
<div class="label text-sm absolut bottom-0"> {{ textSeconds }} </div>
</div>
</section>
</div>
</template>
<script>
export default {
name: 'akaunting-countdown',
props: {
textDays: {
type: String,
default: 'days',
description: "Modal header title"
},
textHours: {
type: String,
default: 'hours',
description: "Modal header title"
},
textMinutes: {
type: String,
default: 'minutes',
description: "Modal header title"
},
textSeconds: {
type: String,
default: 'seconds',
description: "Modal header title"
},
year: {
type: Number,
default: 0,
description: "Modal header title"
},
month: {
type: Number,
default: 0,
description: "Modal header title"
},
date: {
type: Number,
default: 0,
description: "Input readonly status"
},
hour: {
type: Number,
default: 0,
description: "Input disabled status"
},
minute: {
type: Number,
default: 0,
description: "Input value defalut"
},
second: {
type: Number,
default: 0,
description: "Input model defalut"
},
millisecond: {
type: Number,
default: 0,
description: "Prepend icon (left)"
}
},
data:() => ({
displayDays: 0,
displayHours: 0,
displayMinutes: 0,
displaySeconds: 0,
loaded: false,
expired: false
}),
computed: {
_seconds: () => 1000,
_minutes() {
return this._seconds * 60;
},
_hours() {
return this._minutes * 60;
},
_days() {
return this._hours * 24;
},
end() {
return new Date(
this.year,
this.month,
this.date,
this.hour,
this.minute,
this.second,
this.millisecond
);
}
},
mounted() {
this.showRemainig();
},
methods: {
formatNum: num =>(num < 10 ? '0' + num : num),
showRemainig() {
const timer = setInterval(() => {
const now = new Date();
const distance = this.end.getTime() - now.getTime();
if (distance < 0) {
clearInterval(timer);
this.expired = true;
return;
}
const days = Math.floor(distance / this._days);
const hours = Math.floor((distance % this._days) / this._hours);
const minutes = Math.floor((distance % this._hours) / this._minutes);
const seconds = Math.floor((distance % this._minutes) / this._seconds);
this.displayMinutes = this.formatNum(minutes);
this.displaySeconds = this.formatNum(seconds);
this.displayHours = this.formatNum(hours);
this.displayDays = this.formatNum(days);
this.loaded = true;
}, 1000);
}
}
}
</script>
<style scoped>
.countdown {
text-align: justify;
}
.relative {
position: relative;
}
.flex {
display: flex;
}
.justify-center {
justify-content: center;
}
.content-center {
align-content: center;
}
.seconds {
max-width: 60px;
}
.leading-snug {
line-height: 1.375;
}
.days, .hours, .minutes, .seconds {
text-align: center;
}
</style>

View File

@ -6,7 +6,7 @@
{'disabled': disabled},
formClasses
]"
:error="formError"
:footer-error="formError"
:prependIcon="icon"
:readonly="readonly"
:disabled="disabled"

View File

@ -49,45 +49,64 @@
let editorRef = this.$refs.editor;
let node = editorRef.children[0];
this.editor.on('text-change', () => {
let html = node.innerHTML
let html = node.innerHTML;
if (html === '<p><br></p>') {
html = '';
}
this.content = html
this.content = html;
this.$emit('input', this.content);
})
},
pasteHTML () {
if (!this.editor) {
return
}
this.editor.pasteHTML(this.value)
this.editor.pasteHTML(this.value);
},
randomString() {
let text = "";
let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (let i = 0; i < 5; i++)
for (let i = 0; i < 5; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
},
async mounted () {
let Quill = await import('quill')
Quill = Quill.default || Quill
this.content = this.value;
let Quill = await import('quill');
Quill = Quill.default || Quill;
this.editorId = this.randomString();
this.toolbarId = this.randomString();
this.$nextTick(() => {
this.initialize(Quill)
});
},
watch: {
value (newVal) {
if (newVal !== this.content) {
this.pasteHTML(newVal);
}
},
content (newVal) {
this.$emit('input', newVal);
}
}
}

View File

@ -22,6 +22,7 @@
</div>
<div class="modal-body pb-0" v-else>
<form id="form-create" method="POST" action="#"/>
<component v-bind:is="component"></component>
</div>
</slot>
@ -33,7 +34,11 @@
{{ buttons.cancel.text }}
</button>
<button :disabled="form.loading" type="button" class="btn button-submit" :class="buttons.confirm.class" @click="onSubmit">
<a v-if="buttons.payment" :href="buttons.payment.url" class="btn btn-white" :class="buttons.payment.class">
{{ buttons.payment.text }}
</a>
<button :disabled="form.loading" type="button" class="btn button-submit" :class="buttons.confirm.class" @click="onSubmit">
<div class="aka-loader"></div><span>{{ buttons.confirm.text }}</span>
</button>
</div>
@ -139,10 +144,12 @@ export default {
},
mounted() {
let form_prefix = this._uid;
if (this.is_component) {
this.component = Vue.component('add-new-component', (resolve, reject) => {
resolve({
template : '<div id="modal-add-new-form">' + this.message + '</div>',
template : '<div id="modal-add-new-form-' + form_prefix + '">' + this.message + '</div>',
components: {
AkauntingRadioGroup,
@ -159,7 +166,7 @@ export default {
},
mounted() {
let form_id = document.getElementById('modal-add-new-form').children[0].id;
let form_id = document.getElementById('modal-add-new-form-' + form_prefix).children[0].id;
this.form = new Form(form_id);
},
@ -217,7 +224,24 @@ export default {
})
.catch(error => {
});
}
},
// Change bank account get money and currency rate
async onChangePaymentAccount(account_id) {
let payment_account = Promise.resolve(window.axios.get(url + '/banking/accounts/currency', {
params: {
account_id: account_id
}
}));
payment_account.then(response => {
this.form.currency = response.data.currency_name;
this.form.currency_code = response.data.currency_code;
this.form.currency_rate = response.data.currency_rate;
})
.catch(error => {
});
},
}
})
});

View File

@ -10,7 +10,7 @@
</span>
</div>
<money :name="name" @input="input" :placeholder="placeholder" v-bind="money" :value="value" :disabled="disabled" :masked="masked" class="form-control"></money>
<money :name="name" @input="input" :placeholder="placeholder" v-bind="money" :value="model" :disabled="disabled" :masked="masked" class="form-control"></money>
</div>
<div class="invalid-feedback d-block" v-if="error" v-html="error"></div>
@ -126,6 +126,8 @@ export default {
},
mounted() {
//this.model = this.value;
this.$emit('interface', this.model);
},
@ -133,10 +135,15 @@ export default {
change() {
//this.$emit('change', this.model);
//this.$emit('interface', this.model);
this.$emit('input', this.model);
},
input(event) {
this.model = event;
this.$emit('input', event);
//this.$emit('change', this.model);
//this.$emit('interface', this.model);
}
@ -144,6 +151,10 @@ export default {
watch: {
dynamicCurrency: function (currency) {
if (!currency) {
return;
}
this.money = {
decimal: currency.decimal_mark,
thousands: currency.thousands_separator,
@ -153,9 +164,11 @@ export default {
masked: this.masked
};
},
value: function (value) {
this.model = value;
},
model: function (model) {
this.$emit('change', this.model);
this.$emit('interface', this.model);

View File

@ -763,7 +763,7 @@
<span slot="infoBlock" class="badge badge-success badge-resize float-right" v-if="new_options[real_model]">{{ new_text }}</span>
<select :name="name" v-model="real_model" class="d-none">
<select :name="name" :id="name" v-model="real_model" class="d-none">
<option v-for="(label, value) in selectOptions" :key="value" :value="value">{{ label }}</option>
</select>
</span>
@ -923,6 +923,7 @@ export default {
add_new_html: '',
form: {},
new_options: false,
couunt: 1,
}
},
@ -989,6 +990,24 @@ export default {
this.$emit('interface', this.real_model);
this.$emit('change', this.real_model);
//this.$children[0].$children[0].$emit('keydown.native.tab');
//this.$children[0].$children[0].handleMenuEnter();
this.$children[0].$children[0].visible = false;
/*
this.$children[0].$children[0].setSoftFocus();
if (this.$children[0].$children[0].visible) return;
let option = {};
option.value = this.real_model;
this.$children[0].$children[0].$nextTick(() => {
this.$children[0].$children[0].scrollToOption(option);
});
*/
},
async onAddItem() {
@ -1180,7 +1199,17 @@ export default {
return;
}
this.change();
if (this.real_model != value) {
this.change();
}
let e = $.Event('keyup');
e.keyCode= 9; // tab
$('#' + this.name).trigger(e);
let event = new window.KeyboardEvent('keydown', { keyCode: 9 }); // Tab key
window.dispatchEvent(event);
},
value: function (value) {
@ -1246,4 +1275,4 @@ export default {
margin-right: 35px;
position: relative;
}
</style>
</style>

View File

@ -12,7 +12,11 @@
]"
:error="formError">
<el-select v-model="real_model" @input="change" disabled filterable v-if="disabled"
:placeholder="placeholder">
remote
reserve-keyword
:placeholder="placeholder"
:remote-method="remoteMethod"
:loading="loading">
<div v-if="addNew.status && options.length != 0" class="el-select-dropdown__wrap" slot="empty">
<p class="el-select-dropdown__empty">
{{ noMatchingDataText }}
@ -85,7 +89,11 @@
</el-select>
<el-select v-model="real_model" @input="change" filterable v-if="!disabled && !multiple"
:placeholder="placeholder">
remote
reserve-keyword
:placeholder="placeholder"
:remote-method="remoteMethod"
:loading="loading">
<div v-if="addNew.status && options.length != 0" class="el-select-dropdown__wrap" slot="empty">
<p class="el-select-dropdown__empty">
{{ noMatchingDataText }}
@ -158,7 +166,11 @@
</el-select>
<el-select v-model="real_model" @input="change" filterable v-if="!disabled && multiple && !collapse" multiple
:placeholder="placeholder">
remote
reserve-keyword
:placeholder="placeholder"
:remote-method="remoteMethod"
:loading="loading">
<div v-if="addNew.status && options.length != 0" class="el-select-dropdown__wrap" slot="empty">
<p class="el-select-dropdown__empty">
{{ noMatchingDataText }}
@ -231,7 +243,11 @@
</el-select>
<el-select v-model="real_model" @input="change" filterable v-if="!disabled && multiple && collapse" multiple collapse-tags
:placeholder="placeholder">
remote
reserve-keyword
:placeholder="placeholder"
:remote-method="remoteMethod"
:loading="loading">
<div v-if="addNew.status && options.length != 0" class="el-select-dropdown__wrap" slot="empty">
<p class="el-select-dropdown__empty">
{{ noMatchingDataText }}
@ -464,14 +480,14 @@ export default {
},
value: {
type: [String, Number, Array],
default: null,
default: '',
description: "Selectbox selected value"
},
options: null,
model: {
type: [String, Number],
default: '',
default: null,
description: "Selectbox selected model"
},
@ -582,10 +598,21 @@ export default {
},
mounted() {
this.real_model = this.value;
if (this.multiple) {
if (!this.value.length) {
this.real_model = [];
} else {
let pre_value = [];
if (this.multiple && !this.real_model.length) {
this.real_model = [];
this.value.forEach(item => {
pre_value.push(item.toString());
});
this.real_model = pre_value;
}
} else {
this.real_model = this.value;
}
this.$emit('interface', this.real_model);
@ -593,6 +620,10 @@ export default {
methods: {
remoteMethod(query) {
if (document.getElementById('form-select-' + this.name)) {
document.getElementById('form-select-' + this.name).getElementsByTagName("input")[0].readOnly = false;
}
if (query !== '') {
this.loading = true;
@ -634,21 +665,27 @@ export default {
},
change() {
if (typeof(this.real_model) === 'object') {
if (typeof(this.real_model) === 'object' && !Array.isArray(this.real_model)) {
return false;
}
if (Array.isArray(this.real_model) && !this.real_model.length) {
return false;
}
this.$emit('interface', this.real_model);
this.$emit('change', this.real_model);
this.selectOptions.forEach(item => {
if (item.id == this.real_model) {
this.$emit('label', item.name);
this.$emit('option', item);
if (Array.isArray(this.selectOptions)) {
this.selectOptions.forEach(item => {
if (item.id == this.real_model) {
this.$emit('label', item.name);
this.$emit('option', item);
return true;
}
});
return true;
}
});
}
},
onPressEnter() {
@ -871,9 +908,37 @@ export default {
}
},
real_model: function (value) {
if (this.multiple) {
return;
}
if (this.real_model != value) {
this.change();
}
let e = $.Event('keyup');
e.keyCode= 9; // tab
$('#' + this.name).trigger(e);
let event = new window.KeyboardEvent('keydown', { keyCode: 9 }); // Tab key
window.dispatchEvent(event);
},
value: function (value) {
if (this.multiple) {
this.real_model = value;
if (Array.isArray(this.real_model) && !this.real_model.length) {
this.real_model = value;
} else {
let pre_value = [];
value.forEach(item => {
pre_value.push(item.toString());
});
this.real_model = pre_value;
}
} else {
//this.real_model = value.toString();
this.real_model = value;

View File

@ -52,6 +52,11 @@
</div>
</slot>
</div>
<slot name="error">
<div v-if="footerError" class="invalid-feedback d-block"
v-html="footerError">
</div>
</slot>
</div>
</template>
<script>
@ -84,6 +89,10 @@
type: String,
description: "Input error (below input)"
},
footerError: {
type: String,
description: "Input error (below input)"
},
successMessage: {
type: String,
description: "Input success message",