mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-11 23:54:43 +08:00
Add stock filters [SCI-6547] (#3938)
Co-authored-by: Anton <anton@scinote.net>
This commit is contained in:
parent
97c15eaac0
commit
004aeda601
8 changed files with 183 additions and 2 deletions
|
@ -173,11 +173,16 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.stock-filter-attributes {
|
||||
grid-template-columns: min-content auto 100px;
|
||||
}
|
||||
|
||||
.number-range-selector {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
gap: .5em;
|
||||
grid-auto-flow: column;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
.dropdown-selector-container {
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
import RepositoryStatusValue from 'vue/repository_filter/filters/repositoryStatusValue.vue'
|
||||
import RepositoryChecklistValue from 'vue/repository_filter/filters/repositoryChecklistValue.vue'
|
||||
import RepositoryUserValue from 'vue/repository_filter/filters/repositoryUserValue.vue'
|
||||
import RepositoryStockValue from 'vue/repository_filter/filters/repositoryStockValue.vue'
|
||||
import DropdownSelector from 'vue/shared/dropdown_selector.vue'
|
||||
|
||||
|
||||
|
@ -61,7 +62,8 @@
|
|||
RepositoryStatusValue,
|
||||
RepositoryChecklistValue,
|
||||
RepositoryListValue,
|
||||
RepositoryUserValue
|
||||
RepositoryUserValue,
|
||||
RepositoryStockValue
|
||||
},
|
||||
methods: {
|
||||
updateFilter(value) {
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<template>
|
||||
<div class="filter-attributes stock-filter-attributes">
|
||||
<div class="operator-selector">
|
||||
<DropdownSelector
|
||||
:disableSearch="true"
|
||||
:options="this.operators"
|
||||
:selectedValue="this.operator"
|
||||
:selectorId="`OperatorSelector${this.filter.id}`"
|
||||
@dropdown:changed="updateOperator"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="operator !== 'between'" class="sci-input-container">
|
||||
<input
|
||||
class="sci-input-field"
|
||||
type="text"
|
||||
name="value"
|
||||
v-model="value"
|
||||
:placeholder= "this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryStockValue.input_placeholder')"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="number-range-selector">
|
||||
<div class="sci-input-container">
|
||||
<input
|
||||
class="sci-input-field"
|
||||
type="text"
|
||||
name="from"
|
||||
v-model="from"
|
||||
:placeholder= "this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryStockValue.from_placeholder')"
|
||||
/>
|
||||
</div>
|
||||
<span class="between-delimiter">—</span>
|
||||
<div class="sci-input-container">
|
||||
<input
|
||||
class="sci-input-field"
|
||||
type="text"
|
||||
name="to"
|
||||
v-model="to"
|
||||
:placeholder= "this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryStockValue.to_placeholder')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stock-unit-filter-dropdown">
|
||||
<DropdownSelector
|
||||
:singleSelect="true"
|
||||
:closeOnSelect="true"
|
||||
:selectedValue="this.stock_unit"
|
||||
:options="this.prepareUnitOptions()"
|
||||
:selectorId="`StockUnitSelector${this.filter.id}`"
|
||||
@dropdown:changed="updateStockUnit"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/repository_filter/mixins/filter.js'
|
||||
import DropdownSelector from 'vue/shared/dropdown_selector.vue'
|
||||
export default {
|
||||
name: 'RepositoryStockValue',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
operators: [
|
||||
{ value: 'equal_to', label: this.i18n.t('repositories.show.repository_filter.filters.operators.equal_to')},
|
||||
{ value: 'unequal_to', label: this.i18n.t('repositories.show.repository_filter.filters.operators.unequal_to') },
|
||||
{ value: 'greater_than', label: this.i18n.t('repositories.show.repository_filter.filters.operators.greater_than') },
|
||||
{ value: 'greater_than_or_equal_to', label: this.i18n.t('repositories.show.repository_filter.filters.operators.greater_than_or_equal_to') },
|
||||
{ value: 'less_than', label: this.i18n.t('repositories.show.repository_filter.filters.operators.less_than') },
|
||||
{ value: 'less_than_or_equal_to', label: this.i18n.t('repositories.show.repository_filter.filters.operators.less_than_or_equal_to') },
|
||||
{ value: 'between', label: this.i18n.t('repositories.show.repository_filter.filters.operators.between') }
|
||||
],
|
||||
operator: 'equal_to',
|
||||
value: '',
|
||||
from: '',
|
||||
to: '',
|
||||
stock_unit: 'all'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
DropdownSelector
|
||||
},
|
||||
methods: {
|
||||
validateNumber(number) {
|
||||
return number.replace(/[^0-9.]/g, '').match(/^\d*(\.\d{0,10})?/)[0]
|
||||
},
|
||||
|
||||
prepareUnitOptions() {
|
||||
return [
|
||||
{ label: this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryStockValue.all_units'), value: 'all'},
|
||||
{ label: this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryStockValue.no_unit'), value: 'none'}
|
||||
].concat(this.filter.column.items);
|
||||
},
|
||||
|
||||
updateStockUnit(value) {
|
||||
this.stock_unit = value
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
stock_unit() {
|
||||
this.parameters.stock_unit = this.stock_unit
|
||||
this.updateFilter();
|
||||
},
|
||||
value() {
|
||||
this.value = this.validateNumber(this.value)
|
||||
this.parameters = { value: this.value, stock_unit: this.stock_unit }
|
||||
this.updateFilter();
|
||||
},
|
||||
to() {
|
||||
this.to = this.validateNumber(this.to)
|
||||
this.parameters = {from: this.from, to: this.to, stock_unit: this.stock_unit}
|
||||
this.updateFilter();
|
||||
},
|
||||
from() {
|
||||
this.from = this.validateNumber(this.from)
|
||||
this.parameters = {from: this.from, to: this.to, stock_unit: this.stock_unit}
|
||||
this.updateFilter();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isBlank(){
|
||||
return (!this.value && this.operator != 'between') ||
|
||||
((!this.to || !this.from) && this.operator == 'between');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -123,6 +123,7 @@ class RepositoryColumn < ApplicationRecord
|
|||
|
||||
def items
|
||||
items_method_name = "#{data_type.chomp('Value').underscore}_items"
|
||||
items_method_name = 'repository_stock_unit_items' if data_type == 'RepositoryStockValue'
|
||||
__send__(items_method_name) if respond_to?(items_method_name, true)
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ class RepositoryStockUnitItem < ApplicationRecord
|
|||
validates :data, presence: true,
|
||||
uniqueness: { scope: :repository_column_id },
|
||||
length: { maximum: Constants::NAME_MAX_LENGTH }
|
||||
|
||||
private
|
||||
|
||||
def validate_per_column_limit
|
||||
|
|
|
@ -24,6 +24,44 @@ class RepositoryStockValue < ApplicationRecord
|
|||
amount <= low_stock_threshold
|
||||
end
|
||||
|
||||
def self.add_filter_condition(repository_rows, join_alias, filter_element)
|
||||
parameters = filter_element.parameters
|
||||
if filter_element.operator == 'between'
|
||||
return repository_rows if parameters['from'].blank? || parameters['to'].blank?
|
||||
elsif parameters['value'].blank?
|
||||
return repository_rows
|
||||
end
|
||||
|
||||
repository_rows = case parameters['stock_unit']
|
||||
when 'all'
|
||||
repository_rows.where("#{join_alias}.repository_stock_unit_item_id IS NOT NULL")
|
||||
when 'none'
|
||||
repository_rows.where("#{join_alias}.repository_stock_unit_item_id IS NULL")
|
||||
else
|
||||
repository_rows.where("#{join_alias}.repository_stock_unit_item_id = ?", parameters['stock_unit'])
|
||||
end
|
||||
|
||||
case filter_element.operator
|
||||
when 'equal_to'
|
||||
repository_rows.where("#{join_alias}.amount = ?", parameters['value'].to_d)
|
||||
when 'unequal_to'
|
||||
repository_rows.where.not("#{join_alias}.amount = ?", parameters['value'].to_d)
|
||||
when 'greater_than'
|
||||
repository_rows.where("#{join_alias}.amount > ?", parameters['value'].to_d)
|
||||
when 'greater_than_or_equal_to'
|
||||
repository_rows.where("#{join_alias}.amount >= ?", parameters['value'].to_d)
|
||||
when 'less_than'
|
||||
repository_rows.where("#{join_alias}.amount < ?", parameters['value'].to_d)
|
||||
when 'less_than_or_equal_to'
|
||||
repository_rows.where("#{join_alias}.amount <= ?", parameters['value'].to_d)
|
||||
when 'between'
|
||||
repository_rows
|
||||
.where("#{join_alias}.amount > ? AND #{join_alias}.amount < ?", parameters['from'].to_d, parameters['to'].to_d)
|
||||
else
|
||||
raise ArgumentError, 'Wrong operator for RepositoryStockValue!'
|
||||
end
|
||||
end
|
||||
|
||||
def data_changed?(new_data)
|
||||
BigDecimal(new_data.to_s) != data
|
||||
end
|
||||
|
|
|
@ -117,6 +117,8 @@ class Extends
|
|||
table_name: :repository_date_time_values
|
||||
}, RepositoryTimeRangeValue: {
|
||||
table_name: :repository_date_time_range_values
|
||||
}, RepositoryStockValue: {
|
||||
table_name: :repository_stock_values
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,6 +141,7 @@ class Extends
|
|||
RepositoryDateRangeValue
|
||||
RepositoryTimeValue
|
||||
RepositoryTimeRangeValue
|
||||
RepositoryStockValue
|
||||
)
|
||||
|
||||
# Array of preload relations used in search query for repository rows
|
||||
|
|
|
@ -1504,6 +1504,12 @@ en:
|
|||
select_placeholder: "Select user"
|
||||
multiple_selected: "users selected"
|
||||
all_selected: "All users selected"
|
||||
RepositoryStockValue:
|
||||
input_placeholder: "Enter numeric value"
|
||||
to_placeholder: "To"
|
||||
from_placeholder: "From"
|
||||
all_units: "All units"
|
||||
no_unit: "No unit"
|
||||
bmt_search:
|
||||
bmt_filter: "Biomolecule filter"
|
||||
save_filters: "Save filters"
|
||||
|
|
Loading…
Add table
Reference in a new issue