Add assigned tasks filters [SCI-6221] (#3726)

* Add endpoint for repository tasks [SCI-6221]

* Add assigned tasks filter [SCI-6221]

Co-authored-by: Anton <anton@scinote.net>
This commit is contained in:
aignatov-bio 2021-12-07 15:28:20 +01:00 committed by GitHub
parent e4606abf3e
commit 00f30b8d6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 146 additions and 18 deletions

View file

@ -33,8 +33,7 @@
padding: .5em; padding: .5em;
.apply-button { .apply-button {
flex-grow: 1; margin-left: auto !important;
margin-left: .5em !important;
} }
.column-filters-element { .column-filters-element {

View file

@ -7,6 +7,7 @@ class RepositoriesController < ApplicationController
include IconsHelper include IconsHelper
include TeamsHelper include TeamsHelper
include RepositoriesDatatableHelper include RepositoriesDatatableHelper
include MyModulesHelper
before_action :switch_team_with_param, only: :show before_action :switch_team_with_param, only: :show
before_action :load_repository, except: %i(index create create_modal sidebar archive restore) before_action :load_repository, except: %i(index create create_modal sidebar archive restore)
@ -360,6 +361,18 @@ class RepositoriesController < ApplicationController
end end
end end
def assigned_my_modules
my_modules = MyModule.joins(:repository_rows).where(repository_rows: { repository: @repository })
.readable_by_user(current_user).distinct
render json: grouped_by_prj_exp(my_modules).map { |g|
{
label: "#{g[:project_name]} / #{g[:experiment_name]}", options: g[:tasks].map do |t|
{ label: t.name, value: t.id }
end
}
}
end
private private
def repostiory_import_actions def repostiory_import_actions

View file

@ -11,7 +11,8 @@ window.initRepositoryFilter = () => {
data: () => { data: () => {
return { return {
filters: [], filters: [],
columns: [] columns: [],
my_modules: []
}; };
}, },
created() { created() {
@ -27,6 +28,10 @@ window.initRepositoryFilter = () => {
} }
}); });
$.get($('#filterContainer').data('my-modules-url'), function(data) {
repositoryFilterContainer.my_modules = data;
});
// Replace with remote endpoint // Replace with remote endpoint
repositoryFilterContainer.columns = [ repositoryFilterContainer.columns = [
{ id: 'assigned', name: 'Assigned to task', data_type: 'RepositoryMyModuleValue' }, { id: 'assigned', name: 'Assigned to task', data_type: 'RepositoryMyModuleValue' },

View file

@ -16,6 +16,7 @@
v-for="(filter, index) in filters" v-for="(filter, index) in filters"
:key="filter.id" :key="filter.id"
:filter.sync="filters[index]" :filter.sync="filters[index]"
:my_modules.sync= "my_modules"
@filter:update="updateFilter" @filter:update="updateFilter"
@filter:delete="filters.splice(index, 1)" @filter:delete="filters.splice(index, 1)"
/> />
@ -55,6 +56,7 @@
} }
}, },
props: { props: {
my_modules: Array,
container: Object, container: Object,
savedFilters: Array, savedFilters: Array,
columns: Array columns: Array

View file

@ -6,6 +6,7 @@
<component <component
:is="filter.column.data_type" :is="filter.column.data_type"
:filter="filter" :filter="filter"
:my_modules='my_modules'
@filter:update="updateFilter" /> @filter:update="updateFilter" />
</div> </div>
<div class="filter-remove"> <div class="filter-remove">
@ -23,6 +24,7 @@
import RepositoryAssetValue from 'vue/repository_filter/filters/repositoryAssetValue.vue' import RepositoryAssetValue from 'vue/repository_filter/filters/repositoryAssetValue.vue'
import RepositoryTextValue from 'vue/repository_filter/filters/repositoryTextValue.vue' import RepositoryTextValue from 'vue/repository_filter/filters/repositoryTextValue.vue'
import RepositoryNumberValue from 'vue/repository_filter/filters/repositoryNumberValue.vue' import RepositoryNumberValue from 'vue/repository_filter/filters/repositoryNumberValue.vue'
import RepositoryMyModuleValue from 'vue/repository_filter/filters/repositoryMyModuleValue.vue'
import DropdownSelector from 'vue/shared/dropdown_selector.vue' import DropdownSelector from 'vue/shared/dropdown_selector.vue'
@ -30,16 +32,17 @@
name: "FilterElement", name: "FilterElement",
props: { props: {
filter: Object, filter: Object,
my_modules: Array
}, },
components: { components: {
DropdownSelector, DropdownSelector,
RepositoryAssetValue, RepositoryAssetValue,
RepositoryTextValue, RepositoryTextValue,
RepositoryNumberValue RepositoryNumberValue,
RepositoryMyModuleValue
}, },
methods: { methods: {
updateFilter(value) { updateFilter(value) {
console.log(value);
this.$emit('filter:update', value) this.$emit('filter:update', value)
} }
} }

View file

@ -0,0 +1,57 @@
<template>
<div class="filter-attributes">
<DropdownSelector
:disableSearch="true"
:options="this.operators"
:selectorId="`OperatorSelector${this.filter.id}`"
@dropdown:changed="updateOperator"
/>
<DropdownSelector
:optionClass="'checkbox-icon'"
:dataCombineTags="true"
:noEmptyOption="false"
:singleSelect="false"
:groupSelector="true"
:options="this.my_modules"
:dataSelectMultipleName="this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.multiple_selected')"
:dataSelectMultipleAllSelected="this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.all_selected')"
:selectorId="`MyModulesSelector${this.filter.id}`"
:placeholder="this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.select_placeholder')"
@dropdown:changed="updateValue"
/>
</div>
</template>
<script>
import FilterMixin from 'vue/repository_filter/mixins/filter.js'
import DropdownSelector from 'vue/shared/dropdown_selector.vue'
export default {
name: 'RepositoryMyModuleValue',
mixins: [FilterMixin],
data() {
return {
operators: [
{ value: 'any_of', label: this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.operators.any_of') },
{ value: 'all_of', label: this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.operators.all_of') },
{ value: 'none_of', label: this.i18n.t('repositories.show.repository_filter.filters.types.RepositoryMyModuleValue.operators.none_of') }
],
operator: 'any_of',
value: ''
}
},
components: {
DropdownSelector
},
methods: {
updateValue(value) {
this.value = value
this.updateFilter();
}
},
computed: {
isBlank(){
return this.operator == 'any_of' && !this.value;
}
}
}
</script>

View file

@ -1,6 +1,7 @@
export default { export default {
props: { props: {
filter: Object filter: Object,
my_modules: Array
}, },
created() { created() {
this.operator = this.operator || this.filter.data.operator; this.operator = this.operator || this.filter.data.operator;

View file

@ -1,7 +1,18 @@
<template> <template>
<div class="dropdown-selector"> <div class="dropdown-selector">
<select :id="this.selectorId"> <select :id="this.selectorId"
<option :data-select-by-group="groupSelector"
:data-combine-tags="dataCombineTags"
:data-select-multiple-all-selected="dataSelectMultipleAllSelected"
:data-select-multiple-name="dataSelectMultipleName"
:data-placeholder="placeholder"
>
<optgroup v-if="groupSelector" v-for="group in this.options" :label="group.label">
<option v-for="option in group.options" :key="option.label" :value="option.value">
{{ option.label }}
</option>
</optgroup>
<option v-if="!groupSelector"
v-for="option in this.options" v-for="option in this.options"
:key="option.label" :value="option.value"> :key="option.label" :value="option.value">
{{ option.label }} {{ option.label }}
@ -16,10 +27,18 @@
props: { props: {
options: Array, options: Array,
selectorId: String, selectorId: String,
groupSelector: {
type: Boolean,
default: false
},
noEmptyOption: { noEmptyOption: {
type: Boolean, type: Boolean,
default: true default: true
}, },
placeholder: {
type: String,
default: ''
},
singleSelect: { singleSelect: {
type: Boolean, type: Boolean,
default: true default: true
@ -36,11 +55,28 @@
type: Boolean, type: Boolean,
default: false default: false
}, },
optionClass: {
type: String,
default: ''
},
dataCombineTags: {
type: Boolean,
default: false
},
dataSelectMultipleAllSelected: {
type: String,
default: ''
},
dataSelectMultipleName: {
type: String,
default: ''
},
onChange: Function onChange: Function
}, },
mounted: function() { mounted: function() {
dropdownSelector.init(`#${this.selectorId}`, { dropdownSelector.init(`#${this.selectorId}`, {
optionClass: this.optionClass,
noEmptyOption: this.noEmptyOption, noEmptyOption: this.noEmptyOption,
singleSelect: this.singleSelect, singleSelect: this.singleSelect,
closeOnSelect: this.closeOnSelect, closeOnSelect: this.closeOnSelect,

View file

@ -11,10 +11,12 @@
<div <div
class="dropdown-menu dropdown-menu-right" class="dropdown-menu dropdown-menu-right"
id="filterContainer" id="filterContainer"
data-my-modules-url="<%= assigned_my_modules_repository_path(@repository) %>"
data-datatable-id="#repository-table-<%= @repository.id %>" data-datatable-id="#repository-table-<%= @repository.id %>"
> >
<filter-container <filter-container
:columns.sync="columns" :columns.sync="columns"
:my_modules.sync="my_modules"
/> />
</div> </div>
</div> </div>

View file

@ -1394,7 +1394,7 @@ en:
title: "Filters" title: "Filters"
clear: "Clear" clear: "Clear"
add_filter: "Add filter" add_filter: "Add filter"
apply: "Apply" apply: "Show results"
repository_filter: repository_filter:
enter_value: "Enter text" enter_value: "Enter text"
filters: filters:
@ -1419,6 +1419,15 @@ en:
less: "Less than" less: "Less than"
less_equal: "Less than or equal to" less_equal: "Less than or equal to"
between: "Between" between: "Between"
RepositoryMyModuleValue:
select_placeholder: "Select task"
multiple_selected: "tasks selected"
all_selected: "All tasks selected"
operators:
any_of: "Any of"
all_of: "All of"
none_of: "None of"
bmt_search: bmt_search:
bmt_filter: "Biomolecule filter" bmt_filter: "Biomolecule filter"
save_filters: "Save filters" save_filters: "Save filters"

View file

@ -548,6 +548,7 @@ Rails.application.routes.draw do
as: 'table_index', as: 'table_index',
defaults: { format: 'json' } defaults: { format: 'json' }
member do member do
get :assigned_my_modules
get :load_table get :load_table
end end
# Save repository table state # Save repository table state