mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-11 15:45:34 +08:00
Implement filters and JSON building [SCI-5956]
This commit is contained in:
parent
0b74f34de7
commit
9a87bad740
14 changed files with 410 additions and 24 deletions
|
@ -1,12 +1,36 @@
|
|||
#bmtFilterContainer {
|
||||
min-width: 300px;
|
||||
min-width: 422px;
|
||||
z-index: 100;
|
||||
|
||||
label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
.form-control,
|
||||
.form-select {
|
||||
margin-bottom: 21px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
|
||||
.filter-list-notice {
|
||||
color: $color-silver-chalice;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.header {
|
||||
align-items: center;
|
||||
border-bottom: $border-tertiary;
|
||||
display: flex;
|
||||
padding: .5em 1em;
|
||||
padding: 0 1em;
|
||||
|
||||
.title {
|
||||
@include font-h2;
|
||||
|
@ -16,19 +40,37 @@
|
|||
|
||||
.filter-element {
|
||||
align-items: center;
|
||||
border-bottom: $border-tertiary;
|
||||
display: flex;
|
||||
padding: 15px 52px 15px 15px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.filter-remove {
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 16px;
|
||||
|
||||
.btn {
|
||||
height: 16px;
|
||||
padding: 0;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: $color-white;
|
||||
}
|
||||
}
|
||||
|
||||
.filters-list {
|
||||
border-top: $border-tertiary;
|
||||
padding: .5em 1em;
|
||||
}
|
||||
|
||||
.footer {
|
||||
align-items: center;
|
||||
border-top: $border-tertiary;
|
||||
display: flex;
|
||||
padding: .5em 1em;
|
||||
|
||||
.add-filter {
|
||||
margin-right: auto;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"jsx": true
|
||||
}
|
||||
},
|
||||
"ignorePatterns": ["*.vue", "**/mixins/*.js"],
|
||||
"rules": {
|
||||
"import/extensions": "off",
|
||||
"import/no-unresolved": "off",
|
||||
|
|
|
@ -3,7 +3,7 @@ import Vue from 'vue/dist/vue.esm';
|
|||
import FilterContainer from '../../vue/bmt_filter/container.vue';
|
||||
|
||||
Vue.use(TurbolinksAdapter);
|
||||
|
||||
Vue.prototype.i18n = window.I18n;
|
||||
|
||||
window.initBMTFilter = () => {
|
||||
const app = new Vue({
|
||||
|
@ -13,8 +13,5 @@ window.initBMTFilter = () => {
|
|||
}
|
||||
});
|
||||
|
||||
$('#bmtFilterContainer').on('click', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
$('#bmtFilterContainer').on('click', (e) => e.stopPropagation());
|
||||
};
|
||||
|
|
|
@ -10,7 +10,16 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="filters-list">
|
||||
<FilterElement v-for="(filter, index) in filters" :key="filter.id" :filter.sync="filters[index]" @delete:filter="filters.splice(index, 1)"></FilterElement>
|
||||
<div v-if="filters.length == 0" class="filter-list-notice">
|
||||
<p class="text-muted"><em>{{ i18n.t('repositories.show.bmt_search.no_filters') }}</em></p>
|
||||
</div>
|
||||
<FilterElement
|
||||
v-for="(filter, index) in filters"
|
||||
:key="filter.id"
|
||||
:filter.sync="filters[index]"
|
||||
@filter:delete="filters.splice(index, 1)"
|
||||
@filter:update="updateFilter"
|
||||
/>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<button class="btn btn-light add-filter" @click="addFilter">
|
||||
|
@ -31,30 +40,44 @@
|
|||
name: 'FilterContainer',
|
||||
data() {
|
||||
return {
|
||||
filters: [],
|
||||
i18n: I18n
|
||||
filters: []
|
||||
}
|
||||
},
|
||||
props: {
|
||||
container: Object
|
||||
},
|
||||
components: { FilterElement },
|
||||
computed: {
|
||||
searchJSON() {
|
||||
return this.filters.map((f) => f.data);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
addFilter: function() {
|
||||
var id;
|
||||
|
||||
addFilter() {
|
||||
let id;
|
||||
if (this.filters.length > 0) {
|
||||
id = this.filters[this.filters.length - 1].id + 1
|
||||
} else {
|
||||
id = 1
|
||||
};
|
||||
|
||||
this.filters.push({
|
||||
id: id
|
||||
});
|
||||
this.filters.push({ id: id, data: { type: "fullSequenceFilter" } });
|
||||
},
|
||||
clearAllFilters: function() {
|
||||
this.filters = []
|
||||
updateFilter(filter) {
|
||||
this.filters.find((f) => f.id === filter.id).data = filter.data;
|
||||
},
|
||||
clearAllFilters() {
|
||||
this.filters = [];
|
||||
},
|
||||
loadFilters(filters) {
|
||||
this.clearAllFilters();
|
||||
filters.forEach((filter, index) => {
|
||||
this.filters.push(
|
||||
{
|
||||
id: index,
|
||||
data: filter
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,72 @@
|
|||
<template>
|
||||
<div class="filter-element">
|
||||
<div class="filter-action">
|
||||
Filter {{ filter.id }}
|
||||
<div class="form-group filter-action">
|
||||
<div class="form-select">
|
||||
<select @change="updateFilter({ type: $event.target.value })" v-model="type">
|
||||
<option
|
||||
v-for="type in types"
|
||||
:key="type.name" :value="type">
|
||||
{{ i18n.t('repositories.show.bmt_search.filters.types.' + type + '.name') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<component :is="type" @filter:updateData="updateFilter" :currentData="filter.data" />
|
||||
</div>
|
||||
<div class="filter-remove">
|
||||
<button class="btn btn-light icon-btn" @click="$emit('delete:filter')">
|
||||
<button class="btn btn-light icon-btn" @click="$emit('filter:delete')">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
</button>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import additionalDataFilter from 'vue/bmt_filter/filters/additionalDataFilter.vue'
|
||||
import entityTypeFilter from 'vue/bmt_filter/filters/entityTypeFilter.vue'
|
||||
import monomerTypeFilter from 'vue/bmt_filter/filters/monomerTypeFilter.vue'
|
||||
import subsequenceFilter from 'vue/bmt_filter/filters/subsequenceFilter.vue'
|
||||
import variantSequenceFilter from 'vue/bmt_filter/filters/variantSequenceFilter.vue'
|
||||
import fullSequenceFilter from 'vue/bmt_filter/filters/fullSequenceFilter.vue'
|
||||
import monomerSubstructureSearchFilter from 'vue/bmt_filter/filters/monomerSubstructureSearchFilter.vue'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
filter: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: this.filter.data.type,
|
||||
types: [
|
||||
'additionalDataFilter',
|
||||
'entityTypeFilter',
|
||||
'monomerTypeFilter',
|
||||
'subsequenceFilter',
|
||||
'variantSequenceFilter',
|
||||
'fullSequenceFilter',
|
||||
'monomerSubstructureSearchFilter'
|
||||
]
|
||||
}
|
||||
},
|
||||
components: {
|
||||
additionalDataFilter,
|
||||
entityTypeFilter,
|
||||
monomerTypeFilter,
|
||||
subsequenceFilter,
|
||||
variantSequenceFilter,
|
||||
fullSequenceFilter,
|
||||
monomerSubstructureSearchFilter
|
||||
},
|
||||
methods: {
|
||||
updateFilter(data) {
|
||||
this.$emit(
|
||||
'filter:update',
|
||||
{
|
||||
id: this.filter.id,
|
||||
data: data
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<template>
|
||||
<h1>TODO: additionalData</h1>
|
||||
</template>
|
25
app/javascript/vue/bmt_filter/filters/entityTypeFilter.vue
Normal file
25
app/javascript/vue/bmt_filter/filters/entityTypeFilter.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="entityType"
|
||||
v-model="entityType"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.entityTypeFilter.placeholder')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'entityTypeFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
entityType: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
42
app/javascript/vue/bmt_filter/filters/fullSequenceFilter.vue
Normal file
42
app/javascript/vue/bmt_filter/filters/fullSequenceFilter.vue
Normal file
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="sequence"
|
||||
v-model="sequence"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.fullSequenceFilter.placeholder')"
|
||||
/>
|
||||
<div>
|
||||
<label>
|
||||
<div class="sci-checkbox-container">
|
||||
<input
|
||||
@change="updateFilterData"
|
||||
class="sci-checkbox"
|
||||
type="checkbox"
|
||||
v-model="derivativesIncluded"
|
||||
/>
|
||||
<label class="sci-checkbox-label"></label>
|
||||
</div>
|
||||
<span class="checkbox-label">
|
||||
{{ i18n.t('repositories.show.bmt_search.filters.types.fullSequenceFilter.derivatives_included') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'fullSequenceFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
sequence: "",
|
||||
derivativesIncluded: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="structure"
|
||||
v-model="structure"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.monomerSubstructureSearchFilter.placeholder')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'monomerSubstructureSearchFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
structure: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
25
app/javascript/vue/bmt_filter/filters/monomerTypeFilter.vue
Normal file
25
app/javascript/vue/bmt_filter/filters/monomerTypeFilter.vue
Normal file
|
@ -0,0 +1,25 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="monomerType"
|
||||
v-model="monomerType"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.monomerTypeFilter.placeholder')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'monomerTypeFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
monomerType: ""
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
42
app/javascript/vue/bmt_filter/filters/subsequenceFilter.vue
Normal file
42
app/javascript/vue/bmt_filter/filters/subsequenceFilter.vue
Normal file
|
@ -0,0 +1,42 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="sequence"
|
||||
v-model="sequence"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.subsequenceFilter.placeholder')"
|
||||
/>
|
||||
<div>
|
||||
<label>
|
||||
<div class="sci-checkbox-container">
|
||||
<input
|
||||
@change="updateFilterData"
|
||||
class="sci-checkbox"
|
||||
type="checkbox"
|
||||
v-model="derivativesIncluded"
|
||||
/>
|
||||
<label class="sci-checkbox-label"></label>
|
||||
</div>
|
||||
<span class="checkbox-label">
|
||||
{{ i18n.t('repositories.show.bmt_search.filters.types.subsequenceFilter.derivatives_included') }}
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'subsequenceFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
sequence: "",
|
||||
derivativesIncluded: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,59 @@
|
|||
<template>
|
||||
<div class="filter-form">
|
||||
<input
|
||||
@input="updateFilterData"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="sequence"
|
||||
v-model="sequence"
|
||||
:placeholder="i18n.t('repositories.show.bmt_search.filters.types.variantSequenceFilter.placeholder')"
|
||||
/>
|
||||
<div>
|
||||
<label>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label for="distance">{{ i18n.t('repositories.show.bmt_search.filters.types.variantSequenceFilter.distance') }}</label>
|
||||
<input class="form-control" @input="updateFilterData" type="text" v-model="distance" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label>
|
||||
<input
|
||||
@change="updateFilterData"
|
||||
type="radio"
|
||||
v-model="distanceType"
|
||||
value="EXACT"
|
||||
/>
|
||||
<span>{{ i18n.t('repositories.show.bmt_search.filters.types.variantSequenceFilter.exact') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label>
|
||||
<input
|
||||
@change="updateFilterData"
|
||||
type="radio"
|
||||
v-model="distanceType"
|
||||
value="MAX"
|
||||
/>
|
||||
<span>{{ i18n.t('repositories.show.bmt_search.filters.types.variantSequenceFilter.maximum') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
|
||||
export default {
|
||||
name: 'variantSequenceFilter',
|
||||
mixins: [FilterMixin],
|
||||
data() {
|
||||
return {
|
||||
sequence: "",
|
||||
distance: null,
|
||||
distanceType: "EXACT"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
19
app/javascript/vue/bmt_filter/mixins/filter.js
Normal file
19
app/javascript/vue/bmt_filter/mixins/filter.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
export default {
|
||||
props: {
|
||||
currentData: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: this.$options.name
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// load existing filter data
|
||||
Object.keys(this.currentData).forEach((key) => { this[key] = this.currentData[key] });
|
||||
},
|
||||
methods: {
|
||||
updateFilterData() {
|
||||
this.$emit('filter:updateData', this.$data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1369,6 +1369,37 @@ en:
|
|||
clear_all: "Clear all"
|
||||
add_filter: "Add filter"
|
||||
apply: "Apply"
|
||||
filter: "Filter"
|
||||
no_filters: "Filter through Chemaxon's database. No active filters are applied at the moment."
|
||||
filters:
|
||||
types:
|
||||
additionalDataFilter:
|
||||
name: "Additional data"
|
||||
entityTypeFilter:
|
||||
name: "Entity type"
|
||||
placeholder: "Enter entity type"
|
||||
monomerTypeFilter:
|
||||
name: "Monomer type"
|
||||
placeholder: "Enter monomer type"
|
||||
subsequenceFilter:
|
||||
name: "Subsequence"
|
||||
placeholder: "Enter subsequence"
|
||||
derivatives_included: "Derivatives included"
|
||||
variantSequenceFilter:
|
||||
name: "Variant sequence"
|
||||
placeholder: "Enter variant sequence"
|
||||
derivatives_included: "Derivatives included"
|
||||
distance: "Distance"
|
||||
distance_type: "Distance type"
|
||||
exact: "Exact"
|
||||
maximum: "Maximum"
|
||||
fullSequenceFilter:
|
||||
name: "Full sequence"
|
||||
placeholder: "Enter full sequence"
|
||||
derivatives_included: "Derivatives included"
|
||||
monomerSubstructureSearchFilter:
|
||||
name: "Monomer substructure"
|
||||
placeholder: "Enter substructure"
|
||||
table:
|
||||
id: 'ID'
|
||||
external_id: 'External ID'
|
||||
|
|
Loading…
Add table
Reference in a new issue