mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-06 11:57:16 +08:00
Merge pull request #1070 from okriuchykhin/ok_SCI_2223
Refactor smart annotations modal [SCI-2223]
This commit is contained in:
commit
6d68c5b9f4
8 changed files with 151 additions and 68 deletions
|
@ -39,16 +39,18 @@ var SmartAnnotation = (function() {
|
||||||
dataUrl: $(document.body).attr('data-atwho-project-url')},
|
dataUrl: $(document.body).attr('data-atwho-project-url')},
|
||||||
EXPERIMENT: {tag: "exp",
|
EXPERIMENT: {tag: "exp",
|
||||||
dataUrl: $(document.body).attr('data-atwho-experiment-url')},
|
dataUrl: $(document.body).attr('data-atwho-experiment-url')},
|
||||||
SAMPLE: {tag: "sam",
|
REPOSITORY: {tag: "rep",
|
||||||
dataUrl: $(document.body).attr('data-atwho-sample-url')},
|
dataUrl: $(document.body).attr('data-atwho-rep-items-url')},
|
||||||
MENU: {tag: "menu",
|
MENU: {tag: "menu",
|
||||||
dataUrl: $(document.body).attr('data-atwho-menu-items')}
|
dataUrl: $(document.body).attr('data-atwho-menu-items')}
|
||||||
});
|
});
|
||||||
var prevAt,
|
var prevAt,
|
||||||
// Default selected filter when using '#'
|
// Default selected filter when using '#'
|
||||||
DEFAULT_SEARCH_FILTER = FilterTypeEnum.SAMPLE,
|
DEFAULT_SEARCH_FILTER = FilterTypeEnum.REPOSITORY,
|
||||||
atWhoUpdating = false;
|
atWhoUpdating = false;
|
||||||
|
|
||||||
|
var defaultRepId;
|
||||||
|
|
||||||
// helper methods for AtWho callback
|
// helper methods for AtWho callback
|
||||||
function _templateEval(_tpl, map) {
|
function _templateEval(_tpl, map) {
|
||||||
var res;
|
var res;
|
||||||
|
@ -109,7 +111,7 @@ var SmartAnnotation = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize or update dropdown header buttons
|
// Initialize or update dropdown header buttons
|
||||||
function updateHeaderButtons(query, filterTypeTag) {
|
function updateHeaderButtons(query, filterType) {
|
||||||
var $currentAtWho = $('.atwho-view[style]');
|
var $currentAtWho = $('.atwho-view[style]');
|
||||||
initDismissButton($currentAtWho);
|
initDismissButton($currentAtWho);
|
||||||
|
|
||||||
|
@ -117,15 +119,25 @@ var SmartAnnotation = (function() {
|
||||||
$currentAtWho.find('[data-filter]')
|
$currentAtWho.find('[data-filter]')
|
||||||
.removeClass('btn-primary')
|
.removeClass('btn-primary')
|
||||||
.addClass('btn-default');
|
.addClass('btn-default');
|
||||||
$currentAtWho.find('[data-filter="' + filterTypeTag + '"]')
|
if(filterType.tag === 'rep') {
|
||||||
.removeClass('btn-default')
|
$currentAtWho.find('[data-rep-id="' + filterType.repository_id + '"]')
|
||||||
.addClass('btn-primary');
|
.removeClass('btn-default')
|
||||||
|
.addClass('btn-primary');
|
||||||
|
} else {
|
||||||
|
$currentAtWho.find('[data-filter="' + filterType.tag + '"]')
|
||||||
|
.removeClass('btn-default')
|
||||||
|
.addClass('btn-primary');
|
||||||
|
}
|
||||||
|
|
||||||
// Update the selected filter button when clicking on one of them
|
// Update the selected filter button when clicking on one of them
|
||||||
$currentAtWho.find('[data-filter]').off()
|
$currentAtWho.find('[data-filter]').off()
|
||||||
.on('click', function(e) {
|
.on('click', function(e) {
|
||||||
|
if($(this).hasClass('btn-primary')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var $selectedBtn = $(this);
|
var $selectedBtn = $(this);
|
||||||
var $prevBtn = $selectedBtn.closest('.title').children('.btn-primary');
|
var $prevBtn = $selectedBtn.closest('.atwho-header-res')
|
||||||
|
.children('.btn-primary');
|
||||||
$selectedBtn.removeClass('btn-default').addClass('btn-primary');
|
$selectedBtn.removeClass('btn-default').addClass('btn-primary');
|
||||||
$prevBtn.removeClass('btn-primary').addClass('btn-default');
|
$prevBtn.removeClass('btn-primary').addClass('btn-default');
|
||||||
|
|
||||||
|
@ -136,16 +148,31 @@ var SmartAnnotation = (function() {
|
||||||
|
|
||||||
// Generates suggestion dropdown filter
|
// Generates suggestion dropdown filter
|
||||||
function generateFilterMenu(active, res_data) {
|
function generateFilterMenu(active, res_data) {
|
||||||
|
var rep_buttons = '';
|
||||||
|
$.ajax({
|
||||||
|
async: false,
|
||||||
|
dataType: 'json',
|
||||||
|
url: $(document.body).attr('data-atwho-repositories-url'),
|
||||||
|
success: function(data) {
|
||||||
|
$.each(data['repositories'], function(id, name) {
|
||||||
|
if(defaultRepId === undefined){
|
||||||
|
defaultRepId = id;
|
||||||
|
}
|
||||||
|
rep_buttons += '<button data-filter="rep" data-rep-id="' + id +
|
||||||
|
'" class="btn btn-xs btn-primary">' + name + '</button>';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
var header = '<div class="atwho-header-res">' +
|
var header = '<div class="atwho-header-res">' +
|
||||||
'<div class="title">' +
|
'<button data-filter="prj" class="btn btn-xs btn-primary' +
|
||||||
'<button data-filter="prj" class="btn btn-xs ' +
|
'">Projects</button>' +
|
||||||
(active === 'prj' ? 'btn-primary' : 'btn-default') + '">project#</button>' +
|
'<button data-filter="exp" class="btn btn-xs btn-primary' +
|
||||||
'<button data-filter="exp" class="btn btn-xs ' +
|
'">Experiments</button>' +
|
||||||
(active === 'exp' ? 'btn-primary' : 'btn-default') + '">experiment#</button>' +
|
'<button data-filter="tsk" class="btn btn-xs btn-primary' +
|
||||||
'<button data-filter="tsk" class="btn btn-xs ' +
|
'">Tasks</button>' +
|
||||||
(active === 'tsk' ? 'btn-primary' : 'btn-default') + '">task#</button>' +
|
rep_buttons +
|
||||||
'<button data-filter="sam" class="btn btn-xs ' +
|
'<div class="dismiss">' +
|
||||||
(active === 'sam' ? 'btn-primary' : 'btn-default') + '">sample#</button>' +
|
'<span class="glyphicon glyphicon-remove"></span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="help">' +
|
'<div class="help">' +
|
||||||
'<div>' +
|
'<div>' +
|
||||||
|
@ -159,9 +186,6 @@ var SmartAnnotation = (function() {
|
||||||
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
||||||
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="dismiss">' +
|
|
||||||
'<span class="glyphicon glyphicon-remove"></span>' +
|
|
||||||
'</div>' +
|
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
|
|
||||||
|
@ -193,8 +217,9 @@ var SmartAnnotation = (function() {
|
||||||
case 'exp':
|
case 'exp':
|
||||||
res += '<span data-type class="res-type">' + map.type + '</span>';
|
res += '<span data-type class="res-type">' + map.type + '</span>';
|
||||||
break;
|
break;
|
||||||
case 'sam':
|
case 'rep_item':
|
||||||
res += '<span class="glyphicon glyphicon-tint"></span>';
|
res += '<span data-type class="res-type">' +
|
||||||
|
map.repository_tag + '</span>';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,9 +312,21 @@ var SmartAnnotation = (function() {
|
||||||
$currentAtWho.removeAttr("style");
|
$currentAtWho.removeAttr("style");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var params = { query: query };
|
||||||
|
|
||||||
|
if(filterType.tag === 'rep') {
|
||||||
|
params.repository_id = $currentAtWho
|
||||||
|
.find('.btn-primary')
|
||||||
|
.data('rep-id');
|
||||||
|
if(params.repository_id === undefined) {
|
||||||
|
params.repository_id = defaultRepId;
|
||||||
|
}
|
||||||
|
filterType.repository_id = params.repository_id;
|
||||||
|
}
|
||||||
|
|
||||||
$.getJSON(
|
$.getJSON(
|
||||||
filterType.dataUrl,
|
filterType.dataUrl,
|
||||||
{query: query},
|
params,
|
||||||
function(data) {
|
function(data) {
|
||||||
// Updates dropdown
|
// Updates dropdown
|
||||||
if (data.res.length < 1) {
|
if (data.res.length < 1) {
|
||||||
|
@ -298,7 +335,7 @@ var SmartAnnotation = (function() {
|
||||||
callback(data.res);
|
callback(data.res);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHeaderButtons(query, filterType.tag);
|
updateHeaderButtons(query, filterType);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -389,7 +426,7 @@ var SmartAnnotation = (function() {
|
||||||
},
|
},
|
||||||
headerTpl:
|
headerTpl:
|
||||||
'<div class="atwho-header-res">' +
|
'<div class="atwho-header-res">' +
|
||||||
'<div class="title title-user"><%= I18n.t("atwho.users.title") %></div>' +
|
'<div class="title-user"><%= I18n.t("atwho.users.title") %></div>' +
|
||||||
'<div class="help">' +
|
'<div class="help">' +
|
||||||
'<div>' +
|
'<div>' +
|
||||||
'<strong><%= I18n.t("atwho.users.navigate_1") %></strong> ' +
|
'<strong><%= I18n.t("atwho.users.navigate_1") %></strong> ' +
|
||||||
|
@ -403,21 +440,21 @@ var SmartAnnotation = (function() {
|
||||||
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
'<strong><%= I18n.t("atwho.users.dismiss_1") %></strong> ' +
|
||||||
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
'<%= I18n.t("atwho.users.dismiss_2") %>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
'<div class="dismiss">' +
|
'<div class="dismiss">' +
|
||||||
'<span class="glyphicon glyphicon-remove"></span>' +
|
'<span class="glyphicon glyphicon-remove"></span>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>' +
|
|
||||||
'</div>',
|
'</div>',
|
||||||
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
limit: <%= Constants::ATWHO_SEARCH_LIMIT %>,
|
||||||
startsWithSpace: true,
|
startsWithSpace: true,
|
||||||
acceptSpaceBar: true,
|
acceptSpaceBar: true,
|
||||||
displayTimeout: 120000
|
displayTimeout: 120000
|
||||||
})
|
})
|
||||||
.atwho(atWhoSettings('#', DEFAULT_SEARCH_FILTER));
|
.atwho(atWhoSettings('#', DEFAULT_SEARCH_FILTER))
|
||||||
// .atwho(atWhoSettings('task#', FilterTypeEnum.TASK)) Waiting for better times
|
// .atwho(atWhoSettings('task#', FilterTypeEnum.TASK)) Waiting for better times
|
||||||
// .atwho(atWhoSettings('project#', FilterTypeEnum.PROJECT))
|
// .atwho(atWhoSettings('project#', FilterTypeEnum.PROJECT))
|
||||||
// .atwho(atWhoSettings('experiment#', FilterTypeEnum.EXPERIMENT))
|
// .atwho(atWhoSettings('experiment#', FilterTypeEnum.EXPERIMENT))
|
||||||
// .atwho(atWhoSettings('sample#', FilterTypeEnum.SAMPLE));
|
// .atwho(atWhoSettings('sample#', FilterTypeEnum.REPOSITORY));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1549,8 +1549,8 @@ th.custom-field .modal-tooltiptext {
|
||||||
border: 1px solid $color-emperor;
|
border: 1px solid $color-emperor;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-shadow: 0 0 5px $color-gainsboro;
|
box-shadow: 0 0 5px $color-gainsboro;
|
||||||
min-width: 520px;
|
max-width: 800px;
|
||||||
max-height: 200px;
|
min-width: 700px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
z-index: 11110 !important;
|
z-index: 11110 !important;
|
||||||
|
|
||||||
|
@ -1594,33 +1594,20 @@ th.custom-field .modal-tooltiptext {
|
||||||
// <End of overrides>
|
// <End of overrides>
|
||||||
|
|
||||||
.atwho-header-res {
|
.atwho-header-res {
|
||||||
padding-top: 3px;
|
|
||||||
padding-bottom: 7px;
|
|
||||||
height: 34px;
|
|
||||||
background-color: $color-concrete;
|
background-color: $color-concrete;
|
||||||
border-bottom: 1px solid $color-emperor;
|
border-bottom: 1px solid $color-emperor;
|
||||||
clear: both;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 3px 5px;
|
||||||
|
|
||||||
> div {
|
.btn {
|
||||||
display: inline;
|
border-radius: 4px;
|
||||||
|
margin: 5px;
|
||||||
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.btn-default {
|
||||||
float: left;
|
background-color: transparent;
|
||||||
margin-left: 15px;
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
margin-right: 5px;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:last-child {
|
|
||||||
margin-right: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-default {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.title-user {
|
.title-user {
|
||||||
|
@ -1628,27 +1615,33 @@ th.custom-field .modal-tooltiptext {
|
||||||
}
|
}
|
||||||
|
|
||||||
.help {
|
.help {
|
||||||
float: right;
|
margin-left: auto;
|
||||||
padding-top: 4px;
|
margin-right: 15px;
|
||||||
|
order: 99;
|
||||||
|
padding: 4px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
div {
|
div {
|
||||||
display: inline;
|
display: inline;
|
||||||
margin-right: 15px;
|
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
|
margin-left: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div strong {
|
strong {
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dismiss {
|
.dismiss {
|
||||||
color: $color-emperor;
|
color: $color-emperor;
|
||||||
}
|
position: absolute;
|
||||||
|
right: 5px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.dismiss:hover {
|
.dismiss:hover {
|
||||||
color: $color-black;
|
color: $color-black;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,28 @@ class AtWhoController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def samples
|
def rep_items
|
||||||
res = SmartAnnotation.new(current_user, current_team, @query)
|
res = SmartAnnotation.new(current_user, current_team, @query)
|
||||||
|
repository = Repository.find_by_id(params[:repository_id])
|
||||||
|
render_403 && return unless repository && can_read_team?(repository.team)
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
render json: {
|
render json: {
|
||||||
res: res.samples,
|
res: res.repository_rows(repository),
|
||||||
|
status: :ok
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def repositories
|
||||||
|
repositories = @team.repositories.limit(Constants::REPOSITORIES_LIMIT)
|
||||||
|
respond_to do |format|
|
||||||
|
format.json do
|
||||||
|
render json: {
|
||||||
|
repositories: repositories.map do |r|
|
||||||
|
[r.id, r.name.truncate(Constants::ATWHO_REP_NAME_LIMIT)]
|
||||||
|
end.to_h,
|
||||||
status: :ok
|
status: :ok
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,4 +97,36 @@ class SmartAnnotation
|
||||||
end
|
end
|
||||||
samples_list
|
samples_list
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def repository_rows(repository)
|
||||||
|
res = RepositoryRow
|
||||||
|
.where(repository: repository)
|
||||||
|
.where_attributes_like('name', @query)
|
||||||
|
.limit(Constants::ATWHO_SEARCH_LIMIT)
|
||||||
|
rep_items_list = []
|
||||||
|
splitted_name = repository.name.gsub(/[^0-9a-z ]/i, '').split
|
||||||
|
repository_tag =
|
||||||
|
case splitted_name.length
|
||||||
|
when 1
|
||||||
|
splitted_name[0][0..2]
|
||||||
|
when 2
|
||||||
|
if splitted_name[0].length == 1
|
||||||
|
splitted_name[0][0] + splitted_name[1][0..1]
|
||||||
|
else
|
||||||
|
splitted_name[0][0..1] + splitted_name[1][0]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
splitted_name[0][0] + splitted_name[1][0] + splitted_name[2][0]
|
||||||
|
end
|
||||||
|
repository_tag.downcase!
|
||||||
|
res.each do |rep_row|
|
||||||
|
rep_item = {}
|
||||||
|
rep_item['id'] = rep_row.id.base62_encode
|
||||||
|
rep_item['name'] = sanitize(rep_row.name)
|
||||||
|
rep_item['repository_tag'] = repository_tag
|
||||||
|
rep_item['type'] = 'rep_item'
|
||||||
|
rep_items_list << rep_item
|
||||||
|
end
|
||||||
|
rep_items_list
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
data-atwho-task-url="<%= atwho_my_modules_team_path(current_team) %>"
|
data-atwho-task-url="<%= atwho_my_modules_team_path(current_team) %>"
|
||||||
data-atwho-project-url="<%= atwho_projects_team_path(current_team) %>"
|
data-atwho-project-url="<%= atwho_projects_team_path(current_team) %>"
|
||||||
data-atwho-experiment-url="<%= atwho_experiments_team_path(current_team) %>"
|
data-atwho-experiment-url="<%= atwho_experiments_team_path(current_team) %>"
|
||||||
data-atwho-sample-url="<%= atwho_samples_team_path(current_team) %>"
|
data-atwho-repositories-url="<%= atwho_repositories_team_path(current_team) %>"
|
||||||
|
data-atwho-rep-items-url="<%= atwho_rep_items_team_path(current_team) %>"
|
||||||
data-atwho-menu-items="<%= atwho_menu_items_team_path(current_team) %>"
|
data-atwho-menu-items="<%= atwho_menu_items_team_path(current_team) %>"
|
||||||
<% end %>
|
<% end %>
|
||||||
>
|
>
|
||||||
|
|
|
@ -51,6 +51,9 @@ class Constants
|
||||||
# Maximum nr. of search results for atwho (smart annotations)
|
# Maximum nr. of search results for atwho (smart annotations)
|
||||||
ATWHO_SEARCH_LIMIT = 5
|
ATWHO_SEARCH_LIMIT = 5
|
||||||
|
|
||||||
|
# Max characters for repository name in Atwho modal
|
||||||
|
ATWHO_REP_NAME_LIMIT = 16
|
||||||
|
|
||||||
# Maximum number of repositories per team allowed
|
# Maximum number of repositories per team allowed
|
||||||
REPOSITORIES_LIMIT = 5
|
REPOSITORIES_LIMIT = 5
|
||||||
|
|
||||||
|
|
|
@ -181,7 +181,8 @@ Rails.application.routes.draw do
|
||||||
post 'export_repository', to: 'repositories#export_repository'
|
post 'export_repository', to: 'repositories#export_repository'
|
||||||
# Used for atwho (smart annotations)
|
# Used for atwho (smart annotations)
|
||||||
get 'atwho_users', to: 'at_who#users'
|
get 'atwho_users', to: 'at_who#users'
|
||||||
get 'atwho_samples', to: 'at_who#samples'
|
get 'atwho_repositories', to: 'at_who#repositories'
|
||||||
|
get 'atwho_rep_items', to: 'at_who#rep_items'
|
||||||
get 'atwho_projects', to: 'at_who#projects'
|
get 'atwho_projects', to: 'at_who#projects'
|
||||||
get 'atwho_experiments', to: 'at_who#experiments'
|
get 'atwho_experiments', to: 'at_who#experiments'
|
||||||
get 'atwho_my_modules', to: 'at_who#my_modules'
|
get 'atwho_my_modules', to: 'at_who#my_modules'
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue