Merge branch 'akaunting:master' into master

This commit is contained in:
Burak Civan 2022-07-26 14:04:44 +03:00 committed by GitHub
commit fb3f94066a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 368 additions and 16 deletions

View File

@ -27,6 +27,9 @@ abstract class Form extends Component
/** @var string */ /** @var string */
public $placeholder; public $placeholder;
/** @var string */
public $searchText;
/** @var array */ /** @var array */
public $options; public $options;
@ -39,6 +42,9 @@ abstract class Form extends Component
/** @var string */ /** @var string */
public $optionValue; public $optionValue;
/** @var array */
public $fullOptions;
/** @var string */ /** @var string */
public $checked; public $checked;
@ -66,6 +72,9 @@ abstract class Form extends Component
/** @var bool */ /** @var bool */
public $group; public $group;
/** @var bool */
public $searchable;
/** @var bool */ /** @var bool */
public $disabled; public $disabled;
@ -99,10 +108,10 @@ abstract class Form extends Component
* @return void * @return void
*/ */
public function __construct( public function __construct(
string $name = '', string $type = 'text', string $label = '', string $id = null, $value = '', $valueKey = null, string $placeholder = '', string $name = '', string $type = 'text', string $label = '', string $id = null, $value = '', $valueKey = null, string $placeholder = '', string $searchText = '',
$options = [], $option = [], string $optionKey = 'id', string $optionValue = 'name', $checked = null, $checkedKey = null, $selected = null, $selectedKey = null, $rows = '3', $options = [], $option = [], string $optionKey = 'id', string $optionValue = 'name', $fullOptions = [], $checked = null, $checkedKey = null, $selected = null, $selectedKey = null, $rows = '3',
$remote = false, $multiple = false, $addNew = false, $group = false, $remote = false, $multiple = false, $addNew = false, $group = false,
bool $disabled = false, bool $readonly = false, bool $required = true, bool $notRequired = false, bool $searchable = false, bool $disabled = false, bool $readonly = false, bool $required = true, bool $notRequired = false,
string $formGroupClass = '', string $inputGroupClass = '', string $formGroupClass = '', string $inputGroupClass = '',
$dynamicAttributes = '', $dynamicAttributes = '',
bool $hideCurrency = false bool $hideCurrency = false
@ -113,6 +122,7 @@ abstract class Form extends Component
$this->id = $id ?? $name; $this->id = $id ?? $name;
$this->value = $this->getValue($value, $valueKey); $this->value = $this->getValue($value, $valueKey);
$this->placeholder = $this->getPlaceholder($placeholder); $this->placeholder = $this->getPlaceholder($placeholder);
$this->searchText = $this->getSearchText($searchText);
$this->rows = $rows; $this->rows = $rows;
$this->remote = $remote; $this->remote = $remote;
@ -120,6 +130,7 @@ abstract class Form extends Component
$this->addNew = $addNew; $this->addNew = $addNew;
$this->group = $group; $this->group = $group;
$this->searchable = $searchable;
$this->disabled = $disabled; $this->disabled = $disabled;
$this->readonly = $readonly; $this->readonly = $readonly;
$this->required = $this->getRequired($required, $notRequired); $this->required = $this->getRequired($required, $notRequired);
@ -128,6 +139,7 @@ abstract class Form extends Component
$this->option = $option; $this->option = $option;
$this->optionKey = $optionKey; $this->optionKey = $optionKey;
$this->optionValue = $optionValue; $this->optionValue = $optionValue;
$this->fullOptions = $this->getFullOptions($fullOptions, $options, $searchable);
$this->checked = $this->getChecked($checked, $checkedKey); $this->checked = $this->getChecked($checked, $checkedKey);
$this->selected = $this->getSelected($selected, $selectedKey); $this->selected = $this->getSelected($selected, $selectedKey);
@ -222,6 +234,15 @@ abstract class Form extends Component
return trans('general.form.enter', ['field' => $label]); return trans('general.form.enter', ['field' => $label]);
} }
protected function getSearchText($searchText)
{
if (! empty($searchText)) {
return $searchText;
}
return trans('general.search_placeholder');
}
protected function getOptions($options) protected function getOptions($options)
{ {
if (! empty($options)) { if (! empty($options)) {
@ -248,6 +269,21 @@ abstract class Form extends Component
return []; return [];
} }
protected function getFullOptions($fullOptions, $options, $searchable)
{
if (! empty($fullOptions)) {
return $fullOptions;
}
if ($searchable && empty($fullOptions)) {
$this->options = $this->options->take(setting('default.select_limit'));
return $options;
}
return [];
}
protected function getChecked($checked, $checkedKey) protected function getChecked($checked, $checkedKey)
{ {
return $this->getValue($checked, $checkedKey); return $this->getValue($checked, $checkedKey);

View File

@ -10,8 +10,10 @@
]" ]"
:error="formError"> :error="formError">
<el-select v-model="selected" :placeholder="placeholder" filterable <el-select v-model="selected" :placeholder="dynamicPlaceholder" filterable
@change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus" @change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus"
:remote="remote"
:remote-method="serchableMethod"
:clearable="clearable" :clearable="clearable"
:disabled="disabled" :disabled="disabled"
:multiple="multiple" :multiple="multiple"
@ -66,7 +68,7 @@
</template> </template>
<el-option v-if="!group" v-for="(option, index) in sortedOptions" <el-option v-if="!group" v-for="(option, index) in sortedOptions"
:key="index" :key="option.key"
:disabled="disabledOptions.includes(option.key)" :disabled="disabledOptions.includes(option.key)"
:label="option.value" :label="option.value"
:value="option.key"> :value="option.key">
@ -81,7 +83,7 @@
:label="group_options.key"> :label="group_options.key">
<el-option <el-option
v-for="(option, option_index) in group_options.value" v-for="(option, option_index) in group_options.value"
:key="option_index" :key="option.key"
:disabled="disabledOptions.includes(option.key)" :disabled="disabledOptions.includes(option.key)"
:label="option.value" :label="option.value"
:value="option.key"> :value="option.key">
@ -189,6 +191,8 @@ export default {
dynamicOptions: null, dynamicOptions: null,
fullOptions: null,
disabledOptions: { disabledOptions: {
type: Array, type: Array,
default: function () { default: function () {
@ -283,10 +287,23 @@ export default {
default: 'No Matchign Data', default: 'No Matchign Data',
description: "Selectbox search option not found item message" description: "Selectbox search option not found item message"
}, },
searchable: {
type: Boolean,
default: false,
description: "Selectbox searchable"
},
searchText: {
type: String,
default: '',
description: "Selectbox input search placeholder text"
},
}, },
data() { data() {
return { return {
dynamicPlaceholder: this.placeholder,
add_new: { add_new: {
text: this.addNew.text, text: this.addNew.text,
show: false, show: false,
@ -301,18 +318,26 @@ export default {
form: {}, form: {},
sorted_options: [], sorted_options: [],
full_options:[],
new_options: {}, new_options: {},
loading: false, loading: false,
remote: false,
} }
}, },
created() { created() {
this.setSortedOptions(); this.setSortedOptions();
if (this.searchable) {
this.remote = true;
this.setFullOptions();
}
}, },
computed: { computed: {
sortedOptions() { sortedOptions() {
if (!this.sortOptions) { if (! this.sortOptions) {
return this.sorted_options return this.sorted_options
} }
@ -344,7 +369,6 @@ export default {
} catch (e) { } catch (e) {
this.selected = this.model; this.selected = this.model;
} }
} }
if (this.multiple && !this.selected.length) { if (this.multiple && !this.selected.length) {
@ -453,6 +477,82 @@ export default {
} }
}, },
setFullOptions() {
// Reset full_options
this.full_options = [];
let created_options = (this.dynamicOptions) ? this.dynamicOptions : this.fullOptions;
if (this.group) {
// Option set sort_option data
if (!Array.isArray(created_options)) {
for (const [index, options] of Object.entries(created_options)) {
let values = [];
for (const [key, value] of Object.entries(options)) {
values.push({
key: key,
value: value,
level: 0
});
}
this.full_options.push({
key: index,
value: values
});
}
} else {
created_options.forEach(function (option, index) {
if (typeof(option) == 'string') {
this.full_options.push({
index: index,
key: index.toString(),
value: option,
level: 0
});
} else {
this.full_options.push({
index: index,
key: option.id.toString(),
value: (option.title) ? option.title : (option.display_name) ? option.display_name : option.name,
level: (option.level) ? option.level : 0
});
}
}, this);
}
} else {
// Option set sort_option data
if (!Array.isArray(created_options)) {
for (const [key, value] of Object.entries(created_options)) {
this.full_options.push({
key: key,
value: value,
level: 0
});
}
} else {
created_options.forEach(function (option, index) {
if (typeof(option) == 'string') {
this.full_options.push({
index: index,
key: index.toString(),
value: option,
level: 0
});
} else {
this.full_options.push({
index: index,
key: option.id.toString(),
value: (option.title) ? option.title : (option.display_name) ? option.display_name : option.name,
level: (option.level) ? option.level : 0
});
}
}, this);
}
}
},
change() { change() {
// This controll added add new changed.. // This controll added add new changed..
if (typeof(this.selected) === 'object' && typeof(this.selected.type) !== 'undefined') { if (typeof(this.selected) === 'object' && typeof(this.selected.type) !== 'undefined') {
@ -531,6 +631,30 @@ export default {
visibleChange(event) { visibleChange(event) {
this.$emit('visible-change', event); this.$emit('visible-change', event);
this.dynamicPlaceholder = this.placeholder;
if (event && this.searchText) {
this.dynamicPlaceholder = this.searchText;
}
if (this.searchable) {
let selected = this.selected;
this.sorted_options = [];
this.setSortedOptions();
for (const [key, value] of Object.entries(this.full_options)) {
if (selected == value.key) {
this.sorted_options.push({
index: value.index,
key: value.key,
value: value.value,
level: value.level
});
}
}
}
}, },
removeTag(event) { removeTag(event) {
@ -724,6 +848,23 @@ export default {
addModal() { addModal() {
}, },
serchableMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
this.sorted_options = this.full_options.filter(item => {
return item.value.toLowerCase()
.indexOf(query.toLowerCase()) > -1;
});
}, 200);
} else {
this.setSortedOptions();
}
},
}, },
watch: { watch: {

View File

@ -11,7 +11,7 @@
]" ]"
:error="formError"> :error="formError">
<el-select v-model="selected" :placeholder="placeholder" filterable remote reserve-keyword <el-select v-model="selected" :placeholder="dynamicPlaceholder" filterable remote reserve-keyword
@change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus" @change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus"
:clearable="clearable" :clearable="clearable"
:disabled="disabled" :disabled="disabled"
@ -111,7 +111,7 @@
</base-input> </base-input>
<span v-else> <span v-else>
<el-select v-model="selected" :placeholder="placeholder" filterable remote reserve-keyword <el-select v-model="selected" :placeholder="dynamicPlaceholder" filterable remote reserve-keyword
@change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus" @change="change" @visible-change="visibleChange" @remove-tag="removeTag" @clear="clear" @blur="blur" @focus="focus"
:clearable="clearable" :clearable="clearable"
:disabled="disabled" :disabled="disabled"
@ -288,6 +288,8 @@ export default {
dynamicOptions: null, dynamicOptions: null,
fullOptions: null,
disabledOptions: { disabledOptions: {
type: Array, type: Array,
default: function () { default: function () {
@ -389,11 +391,24 @@ export default {
description: "Selectbox search option not found item message" description: "Selectbox search option not found item message"
}, },
searchable: {
type: Boolean,
default: false,
description: "Selectbox searchable"
},
searchText: {
type: String,
default: '',
description: "Selectbox input search placeholder text"
},
remoteAction: { remoteAction: {
type: String, type: String,
default: null, default: null,
description: "Selectbox remote action path" description: "Selectbox remote action path"
}, },
currencyCode: { currencyCode: {
type: String, type: String,
default: 'USD', default: 'USD',
@ -403,6 +418,7 @@ export default {
data() { data() {
return { return {
dynamicPlaceholder: this.placeholder,
add_new: { add_new: {
text: this.addNew.text, text: this.addNew.text,
show: false, show: false,
@ -417,6 +433,7 @@ export default {
form: {}, form: {},
sorted_options: [], sorted_options: [],
full_options:[],
new_options: {}, new_options: {},
loading: false, loading: false,
} }
@ -424,11 +441,15 @@ export default {
created() { created() {
this.setSortedOptions(); this.setSortedOptions();
if (this.searchable) {
this.setFullOptions();
}
}, },
computed: { computed: {
sortedOptions() { sortedOptions() {
if (!this.sortOptions) { if (! this.sortOptions) {
return this.sorted_options; return this.sorted_options;
} }
@ -460,7 +481,6 @@ export default {
} catch (e) { } catch (e) {
this.selected = this.model; this.selected = this.model;
} }
} }
if (this.multiple && !this.selected.length) { if (this.multiple && !this.selected.length) {
@ -569,6 +589,82 @@ export default {
} }
}, },
setFullOptions() {
// Reset full_options
this.full_options = [];
let created_options = (this.dynamicOptions) ? this.dynamicOptions : this.fullOptions;
if (this.group) {
// Option set sort_option data
if (!Array.isArray(created_options)) {
for (const [index, options] of Object.entries(created_options)) {
let values = [];
for (const [key, value] of Object.entries(options)) {
values.push({
key: key,
value: value,
level: 0
});
}
this.full_options.push({
key: index,
value: values
});
}
} else {
created_options.forEach(function (option, index) {
if (typeof(option) == 'string') {
this.full_options.push({
index: index,
key: index.toString(),
value: option,
level: 0
});
} else {
this.full_options.push({
index: index,
key: option.id.toString(),
value: (option.title) ? option.title : (option.display_name) ? option.display_name : option.name,
level: (option.level) ? option.level : 0
});
}
}, this);
}
} else {
// Option set sort_option data
if (!Array.isArray(created_options)) {
for (const [key, value] of Object.entries(created_options)) {
this.full_options.push({
key: key,
value: value,
level: 0
});
}
} else {
created_options.forEach(function (option, index) {
if (typeof(option) == 'string') {
this.full_options.push({
index: index,
key: index.toString(),
value: option,
level: 0
});
} else {
this.full_options.push({
index: index,
key: option.id.toString(),
value: (option.title) ? option.title : (option.display_name) ? option.display_name : option.name,
level: (option.level) ? option.level : 0
});
}
}, this);
}
}
},
change() { change() {
// This controll added add new changed.. // This controll added add new changed..
if (typeof(this.selected) === 'object' && typeof(this.selected.type) !== 'undefined') { if (typeof(this.selected) === 'object' && typeof(this.selected.type) !== 'undefined') {
@ -647,6 +743,30 @@ export default {
visibleChange(event) { visibleChange(event) {
this.$emit('visible-change', event); this.$emit('visible-change', event);
this.dynamicPlaceholder = this.placeholder;
if (event && this.searchText) {
this.dynamicPlaceholder = this.searchText;
}
if (this.searchable) {
let selected = this.selected;
this.sorted_options = [];
this.setSortedOptions();
for (const [key, value] of Object.entries(this.full_options)) {
if (selected == value.key) {
this.sorted_options.push({
index: value.index,
key: value.key,
value: value.value,
level: value.level
});
}
}
}
}, },
removeTag(event) { removeTag(event) {
@ -670,6 +790,10 @@ export default {
document.getElementById('form-select-' + this.name).getElementsByTagName("input")[0].readOnly = false; document.getElementById('form-select-' + this.name).getElementsByTagName("input")[0].readOnly = false;
} }
if (this.searchable) {
return this.serchableMethod(query);
}
if (query !== '') { if (query !== '') {
this.loading = true; this.loading = true;
@ -742,6 +866,23 @@ export default {
} }
}, },
serchableMethod(query) {
if (query !== '') {
this.loading = true;
setTimeout(() => {
this.loading = false;
this.sorted_options = this.full_options.filter(item => {
return item.value.toLowerCase()
.indexOf(query.toLowerCase()) > -1;
});
}, 200);
} else {
this.setSortedOptions();
}
},
async onAddItem() { async onAddItem() {
// Get Select Input value // Get Select Input value
if (this.multiple) { if (this.multiple) {

View File

@ -6,7 +6,6 @@
add-new add-new
path="{{ $path }}" path="{{ $path }}"
add-new
name="{{ $name }}" name="{{ $name }}"
label="{!! $label !!}" label="{!! $label !!}"
:options="$contacts" :options="$contacts"
@ -26,7 +25,6 @@
add-new add-new
path="{{ $path }}" path="{{ $path }}"
add-new
name="{{ $name }}" name="{{ $name }}"
label="{!! $label !!}" label="{!! $label !!}"
:options="$contacts" :options="$contacts"

View File

@ -47,6 +47,24 @@
:dynamic-options="{{ $attributes['dynamicOptions'] }}" :dynamic-options="{{ $attributes['dynamicOptions'] }}"
@endif @endif
@if (! empty($attributes['searchable']))
searchable
@elseif (! empty($searchable))
searchable
@endif
@if (isset($attributes['fullOptions']) || isset($attributes['full-options']))
:full-options="{{ json_encode(! empty($attributes['fullOptions']) ? $attributes['fullOptions'] : $attributes['full-options']) }}"
@else
:full-options="{{ json_encode($fullOptions) }}"
@endif
@if (isset($attributes['searchText']) || isset($attributes['search-text']))
search-text="{{ ! empty($attributes['searchText']) ? $attributes['searchText'] : $attributes['search-text'] }}"
@else
search-text="{{ $searchText }}"
@endif
@if (empty($multiple)) @if (empty($multiple))
@if (isset($selected) || old($name)) @if (isset($selected) || old($name))
value="{{ old($name, $selected) }}" value="{{ old($name, $selected) }}"

View File

@ -47,6 +47,24 @@
:dynamic-options="{{ $attributes['dynamicOptions'] }}" :dynamic-options="{{ $attributes['dynamicOptions'] }}"
@endif @endif
@if (! empty($attributes['searchable']))
searchable
@elseif (! empty($searchable))
searchable
@endif
@if (isset($attributes['fullOptions']) || isset($attributes['full-options']))
:full-options="{{ json_encode(! empty($attributes['fullOptions']) ? $attributes['fullOptions'] : $attributes['full-options']) }}"
@else
:full-options="{{ json_encode($fullOptions) }}"
@endif
@if (isset($attributes['searchText']) || isset($attributes['search-text']))
search-text="{{ ! empty($attributes['searchText']) ? $attributes['searchText'] : $attributes['search-text'] }}"
@else
search-text="{{ $searchText }}"
@endif
@if (empty($multiple)) @if (empty($multiple))
@if (isset($selected) || old($name)) @if (isset($selected) || old($name))
value="{{ old($name, $selected) }}" value="{{ old($name, $selected) }}"

View File

@ -20,7 +20,7 @@
<x-slot name="body"> <x-slot name="body">
<x-form.group.text name="name" label="{{ trans('general.name') }}" /> <x-form.group.text name="name" label="{{ trans('general.name') }}" />
<x-form.group.select name="code" label="{{ trans('currencies.code') }}" :options="$codes" change="onChangeCode" /> <x-form.group.select name="code" label="{{ trans('currencies.code') }}" :options="$codes" searchable change="onChangeCode" />
<x-form.group.text name="rate" label="{{ trans('currencies.rate') }}" @input="onChangeRate" /> <x-form.group.text name="rate" label="{{ trans('currencies.rate') }}" @input="onChangeRate" />

View File

@ -14,7 +14,7 @@
<x-slot name="body"> <x-slot name="body">
<x-form.group.text name="name" label="{{ trans('general.name') }}" /> <x-form.group.text name="name" label="{{ trans('general.name') }}" />
<x-form.group.select name="code" label="{{ trans('currencies.code') }}" :options="$codes" change="onChangeCode" /> <x-form.group.select name="code" label="{{ trans('currencies.code') }}" :options="$codes" searchable change="onChangeCode" />
<x-form.group.text name="rate" label="{{ trans('currencies.rate') }}" @input="onChangeRate" /> <x-form.group.text name="rate" label="{{ trans('currencies.rate') }}" @input="onChangeRate" />