Implemented applying BMT filters [SCI-5980]

This commit is contained in:
Martin Artnik 2021-08-27 16:02:11 +02:00
parent b269f3f612
commit 896f0ce1e3
13 changed files with 133 additions and 29 deletions

View file

@ -407,6 +407,10 @@ var RepositoryDatatable = (function(global) {
url: $(TABLE_ID).data('source'),
data: function(d) {
d.archived = $('.repository-show').hasClass('archived');
if ($('[data-external-ids]').length) {
d.external_ids = $('[data-external-ids]').attr('data-external-ids').split(',');
}
},
global: false,
type: 'POST'

View file

@ -1,3 +1,19 @@
.bmt-filters-button.active-filters {
position: relative;
&::after {
background: $brand-accent;
border-radius: 50%;
content: "";
display: block;
height: 8px;
position: absolute;
right: .3em;
top: .3em;
width: 8px;
}
}
#bmtFilterContainer {
min-width: 422px;
z-index: 100;
@ -63,15 +79,37 @@
align-items: center;
border-top: $border-tertiary;
display: flex;
padding: 0 1em;
.add-filter {
margin-right: auto;
}
}
.savedFilterContainer {
.saved-filter-element {
display: flex;
.saved-filters-container {
.title {
cursor: pointer;
}
}
.saved-filters-list {
padding: 0 1em;
}
.saved-filters-element {
align-items: center;
cursor: pointer;
display: flex;
justify-content: space-between;
min-width: 200px;
i {
color: $color-silver-chalice;
}
}
.saved-filters-element:hover i {
color: $color-black;
}
}

View file

@ -66,8 +66,10 @@ class BioEddieAssetsController < ApplicationController
api_request['x-api-key'] = ENV['BIOMOLECULE_TOOLKIT_API_KEY'] if ENV['BIOMOLECULE_TOOLKIT_API_KEY']
api_request['Content-Type'] = 'application/json'
request_body = request.body.read
api_request.body = request_body if request_body.present?
api_response = http.request(api_request)
render body: api_response.body, content_type: api_response.content_type, status: api_response.code
end
end

View file

@ -8,7 +8,10 @@ class BmtFiltersController < ApplicationController
end
def create
filter = BmtFilter.new(filters_params)
filter = BmtFilter.new(
name: filters_params[:name],
filters: JSON.parse(filters_params[:filters])
)
filter.created_by = current_user
if filter.save
render json: filter, serializer: BmtFilterSerializer

View file

@ -10,10 +10,14 @@ window.initBMTFilter = () => {
el: '#bmtFilterContainer',
data: () => {
return {
bmtApiBaseUrl: $($('#bmtFilterContainer')).data('bmt-api-base-url'),
savedFilters: [],
filters: []
};
},
created() {
this.dataTableElement = $($('#bmtFilterContainer').data('datatable-id'));
},
components: {
'filter-container': FilterContainer
},
@ -23,22 +27,39 @@ window.initBMTFilter = () => {
},
getFilters() {
return this.filters;
},
updateExternalIds(ids) {
this.dataTableElement.attr('data-external-ids', ids.join(','));
this.closeFilters();
this.reloadDataTable();
},
clearFilters() {
this.dataTableElement.removeAttr('data-external-ids');
this.reloadDataTable();
},
closeFilters() {
$(this.$el).closest('.dropdown').removeClass('open');
},
reloadDataTable() {
this.dataTableElement.DataTable().ajax.reload();
}
}
});
// prevent closing of dropdown
$('#bmtFilterContainer').on('click', (e) => e.stopPropagation());
$("#saveBmtFilterForm" )
.off()
.on('ajax:before', function() {
$('#bmt_filter_filters').val(JSON.stringify(bmtFilterContainer.getFilters()));
$('#bmt_filter_filters').val(JSON.stringify(bmtFilterContainer.getFilters()));
})
.on('ajax:success', function(e, result) {
bmtFilterContainer.savedFilters.push(result.data);
$('#modalSaveBmtFilter').modal('hide');
});
$.get($('#bmtFilterContainer').data('url-saved-filters'), function(result) {
$.get($('#bmtFilterContainer').data('saved-filters-url'), function(result) {
bmtFilterContainer.savedFilters = result.data;
})
};

View file

@ -1,21 +1,22 @@
<template>
<div class="filter-container">
<div class="header">
<div class="dropdown savedFilterContainer">
<div class="title" @click="openSavedFilters()">
<div class="dropdown saved-filters-container">
<div class="title" @click="toggleSavedFilters">
{{ i18n.t('repositories.show.bmt_search.title') }}
<i class="fas fa-caret-down"></i>
<i v-if="savedFilters.length" class="fas fa-caret-down"></i>
</div>
<div class="dropdown-menu saved-filters-container">
<div v-if="savedFilters.length" class="dropdown-menu saved-filters-list">
<SavedFilterElement
v-for="(savedFilter, index) in savedFilters"
:key="savedFilter.id"
:savedFilter.sync="savedFilters[index]"
@savedFilter:load="loadFilters"
@savedFilter:delete="savedFilters.splice(index, 1)"
/>
</div>
</div>
<button class="btn btn-light" @click="clearAllFilters">
<button class="btn btn-light" @click="clearFilters">
<i class="fas fa-times-circle"></i>
{{ i18n.t('repositories.show.bmt_search.clear_all') }}
</button>
@ -37,7 +38,7 @@
<i class="fas fa-plus"></i>
{{ i18n.t('repositories.show.bmt_search.add_filter') }}
</button>
<button class="btn btn-primary">
<button @click="fetchCIDs" class="btn btn-primary">
{{ i18n.t('repositories.show.bmt_search.apply') }}
</button>
</div>
@ -52,7 +53,8 @@
name: 'FilterContainer',
props: {
container: Object,
savedFilters: Array
savedFilters: Array,
bmtApiBaseUrl: String
},
data() {
return {
@ -62,31 +64,50 @@
components: { FilterElement, SavedFilterElement },
computed: {
searchJSON() {
return this.filters.map((f) => f.data);
const filterData = this.filters.map(f => f.data)
return {
'filters': filterData,
'resultAttributeNames': ['Cid']
}
}
},
watch: {
filters() {
$('.open-save-bmt-modal').toggleClass('hidden', !this.filters.length)
$('.bmt-filters-button').toggleClass('active-filters', !!this.filters.length)
}
},
methods: {
addFilter() {
let id = this.filters.length ? this.filters[this.filters.length - 1].id + 1 : 1
const id = this.filters.length ? this.filters[this.filters.length - 1].id + 1 : 1
this.filters.push({ id: id, data: { type: "fullSequenceFilter" } });
},
updateFilter(filter) {
this.filters.find((f) => f.id === filter.id).data = filter.data;
this.$emit('filters:update', this.searchJSON);
this.$emit('filters:update', this.searchJSON.filters);
},
clearAllFilters() {
clearFilters() {
this.filters = [];
this.$emit('filters:clear');
},
openSavedFilters() {
$('.savedFilterContainer').toggleClass('open')
fetchCIDs() {
$.ajax({
type: 'POST',
url: this.bmtApiBaseUrl + '/macromolecule/search',
data: JSON.stringify(this.searchJSON),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: (data) => {
this.$emit('cids:update', data.map(i => i.Cid))
}
});
},
toggleSavedFilters() {
$('.saved-filters-container').toggleClass('open');
},
loadFilters(filters) {
this.clearAllFilters();
this.toggleSavedFilters();
this.clearFilters();
filters.forEach((filter, index) => {
this.filters.push(
{
@ -95,6 +116,7 @@
}
);
});
this.fetchCIDs();
}
}
}

View file

@ -30,7 +30,7 @@
<script>
import FilterMixin from 'vue/bmt_filter/mixins/filter.js'
export default {
name: 'fullSequenceFilter',
name: 'fullsequenceFilter',
mixins: [FilterMixin],
data() {
return {

View file

@ -1,6 +1,6 @@
<template>
<div class="saved-filter-element">
{{ savedFilter.attributes.name }}
<div class="saved-filters-element">
<span @click="loadFilters">{{ savedFilter.attributes.name }}</span>
<button class="btn btn-light icon-btn" @click="deleteFilter">
<i class="fas fa-trash"></i>
</button>
@ -14,6 +14,9 @@
savedFilter: Object
},
methods: {
loadFilters() {
this.$emit('savedFilter:load', this.savedFilter.attributes.filters)
},
deleteFilter() {
let filter = this
$.ajax({
@ -28,4 +31,3 @@
}
}
</script>
</script>

View file

@ -75,6 +75,8 @@ class RepositoryDatatableService
repository_rows.count
end
repository_rows = repository_rows.where(external_id: @params[:external_ids]) if @params[:external_ids]
if search_value.present?
if @repository.default_search_fileds.include?('users.full_name')
repository_rows = repository_rows.joins(:created_by)

View file

@ -88,7 +88,7 @@
<% if @repository.is_a?(BmtRepository) %>
<div class="dropdown">
<button id="bmtFiltersDropdown"
class="btn btn-secondary"
class="btn btn-secondary bmt-filters-button"
type="button"
data-toggle="dropdown"
aria-haspopup="true"
@ -96,9 +96,18 @@
<span class="fas fa-microscope"></span>
<%= t('repositories.show.bmt_search.bmt_filter') %>
</button>
<div class="dropdown-menu bmt-filters-container" id="bmtFilterContainer" data-url-saved-filters="<%= bmt_filters_path %>">
<div
class="dropdown-menu bmt-filters-container"
id="bmtFilterContainer"
data-datatable-id="#repository-table-<%= @repository.id %>"
data-saved-filters-url="<%= bmt_filters_url %>"
data-bmt-api-base-url="<%= bmt_request_url(path: 'api') %>"
>
<filter-container
@filters:update="updateFilters"
@filters:clear="clearFilters"
@cids:update="updateExternalIds"
:bmt-api-base-url="bmtApiBaseUrl"
:saved-filters.sync="savedFilters"
:filters.sync="filters" />
</div>

View file

@ -785,7 +785,8 @@ Rails.application.routes.draw do
match 'biomolecule_toolkit/*path', to: 'bio_eddie_assets#bmt_request',
via: %i(get post put delete),
defaults: { format: 'json' }
defaults: { format: 'json' },
as: 'bmt_request'
post 'global_activities', to: 'global_activities#index'

View file

@ -4,7 +4,7 @@ class CreateBmtFilters < ActiveRecord::Migration[6.1]
def change
create_table :bmt_filters do |t|
t.string :name, null: false
t.string :filters, null: false
t.json :filters, null: false
t.references :created_by, index: true, foreign_key: { to_table: :users }
t.timestamps
end

View file

@ -320,7 +320,7 @@ ALTER SEQUENCE public.assets_id_seq OWNED BY public.assets.id;
CREATE TABLE public.bmt_filters (
id bigint NOT NULL,
name character varying NOT NULL,
filters character varying NOT NULL,
filters json NOT NULL,
created_by_id bigint,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL