Merge branch 'features/global-activities' of github.com:biosistemika/scinote-web into ml-sci-3021

This commit is contained in:
Mojca Lorber 2019-03-20 11:03:00 +01:00
commit 4f9814b884
26 changed files with 349 additions and 198 deletions

View file

@ -2,7 +2,7 @@
'use strict';
(function() {
function globalActivitiesInit() {
function initExpandCollapseAllButtons() {
$('#global-activities-colapse-all').on('click', function() {
$('.activities-group').collapse('hide');
@ -13,40 +13,49 @@
}
function initExpandCollapseButton() {
$('.activities-group').on('hide.bs.collapse', function() {
$('.activities-group').on('hidden.bs.collapse', function() {
$(this.dataset.buttonLink)
.find('.fas').removeClass('fa-caret-down').addClass('fa-caret-right');
});
$('.activities-group').on('show.bs.collapse', function() {
$('.activities-group').on('shown.bs.collapse', function() {
$(this.dataset.buttonLink)
.find('.fas').removeClass('fa-caret-right').addClass('fa-caret-down');
});
}
function initShowMoreButton() {
var moreButton = $('.btn-more-activities');
moreButton.on('click', function(ev) {
var filters = GlobalActivitiesFilterPrepareArray();
ev.preventDefault();
animateSpinner(null, true);
filters.to_date = moreButton.data('next-date');
$.ajax({
url: $('.global-activities_activities-list').data('activities-url'),
data: { from_date: moreButton.data('next-date') },
url: $('.ga-activities-list').data('activities-url'),
data: filters,
dataType: 'json',
type: 'POST',
success: function(json) {
$('.global-activities_activities-list').html(json.activities_html);
$(json.activities_html).appendTo('.ga-activities-list');
if (json.more_activities === true) {
moreButton.data('next-date', json.next_date);
moreButton.data('next-date', json.from);
} else {
moreButton.addClass('hidden');
}
(new globalActivitiesInit()).updateCollapseButton();
animateSpinner(null, false);
}
});
});
}
if (this) {
this.updateCollapseButton = function() {
initExpandCollapseButton();
};
}
initExpandCollapseAllButtons();
initExpandCollapseButton();
initShowMoreButton();
}());
}
globalActivitiesInit();

View file

@ -64,6 +64,7 @@ function GlobalActivitiesUpdateTopPaneTags(event) {
}
$(function() {
var updateRunning = false;
var selectors = ['team', 'activity', 'user'];
// Ajax request for object search
var subjectAjaxQuery = {
@ -96,10 +97,46 @@ $(function() {
var subjectCustomDisplay = (state) => {
return state.label + ': ' + state.text;
};
// update_filter
var reloadActivities = function() {
var moreButton = $('.btn-more-activities');
if (updateRunning) return false;
updateRunning = true;
$('.ga-activities-list .activities-day').remove();
animateSpinner(null, true);
$.ajax({
url: $('.ga-activities-list').data('activities-url'),
data: GlobalActivitiesFilterPrepareArray(),
dataType: 'json',
type: 'POST',
success: function(json) {
$(json.activities_html).appendTo('.ga-activities-list');
if (json.more_activities === true) {
moreButton.removeClass('hidden');
moreButton.data('next-date', json.from);
} else {
moreButton.addClass('hidden');
}
(new globalActivitiesInit()).updateCollapseButton();
updateRunning = false;
animateSpinner(null, false);
},
error: function() {
updateRunning = false;
animateSpinner(null, false);
}
});
};
// Common selection intialize
$.each(selectors, (index, e) => {
$('.ga-side .' + e + '-selector select').select2Multiple({ singleDisplay: true })
.on('change', function() { GlobalActivitiesUpdateTopPaneTags(); });
.on('change', function() {
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
});
$('.ga-side .' + e + '-selector .clear').click(function() {
$('.ga-side .' + e + '-selector select').select2MultipleClearAll();
});
@ -110,14 +147,20 @@ $(function() {
customSelection: subjectCustomDisplay,
unlimitedSize: true
})
.on('change select2:select', function(e) { GlobalActivitiesUpdateTopPaneTags(e); });
.on('change select2:select', function(e) {
GlobalActivitiesUpdateTopPaneTags(e);
reloadActivities();
});
$('.ga-side .subject-selector .clear').click(function() {
$('.ga-side .subject-selector select').select2MultipleClearAll();
});
$('.ga-tags-container .clear-container span').click(function() {
updateRunning = true;
$.each(selectors, (index, e) => { $('.ga-side .' + e + '-selector select').select2MultipleClearAll(); });
$('.ga-side .subject-selector select').select2MultipleClearAll();
updateRunning = false;
reloadActivities();
});
$('#calendar-from-date').on('dp.change', function(e) {
@ -125,6 +168,7 @@ $(function() {
$('#calendar-to-date').data('DateTimePicker').minDate(e.date);
dateContainer[0].dataset.periodSelect = $('#calendar-from-date').val() + ' - ' + $('#calendar-to-date').val();
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
});
$('#calendar-to-date').on('dp.change', function(e) {
@ -132,44 +176,48 @@ $(function() {
$('#calendar-from-date').data('DateTimePicker').maxDate(e.date);
dateContainer[0].dataset.periodSelect = $('#calendar-from-date').val() + ' - ' + $('#calendar-to-date').val();
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
});
GlobalActivitiesUpdateTopPaneTags();
});
$('.date-selector .hot-button').click(function() {
var selectPeriod = this.dataset.period;
var dateContainer = $('.ga-side .date-selector.filter-block');
var fromDate = $('#calendar-from-date').data('DateTimePicker');
var toDate = $('#calendar-to-date').data('DateTimePicker');
var today = new Date();
var yesterday = new Date(new Date().setDate(today.getDate() - 1));
var weekDay = today.getDay();
var monday = new Date(new Date().setDate(today.getDate() - weekDay + (weekDay === 0 ? -6 : 1)));
var sunday = new Date(new Date().setDate(new Date(monday).getDate() + 6));
var lastWeek = new Date(new Date().setDate(today.getDate() - 6));
var firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
var lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
var lastMonth = new Date(new Date().setDate(today.getDate() - 30));
if (selectPeriod === 'today') {
toDate.date(today);
fromDate.date(today);
} else if (selectPeriod === 'yesterday') {
fromDate.date(yesterday);
toDate.date(yesterday);
} else if (selectPeriod === 'this_week') {
toDate.date(sunday);
fromDate.date(monday);
} else if (selectPeriod === 'last_week') {
toDate.date(today);
fromDate.date(lastWeek);
} else if (selectPeriod === 'this_month') {
toDate.date(lastDay);
fromDate.date(firstDay);
} else if (selectPeriod === 'last_month') {
toDate.date(today);
fromDate.date(lastMonth);
}
dateContainer[0].dataset.periodSelect = this.innerHTML;
GlobalActivitiesUpdateTopPaneTags();
});
$('.date-selector .hot-button').click(function() {
var selectPeriod = this.dataset.period;
var dateContainer = $('.ga-side .date-selector.filter-block');
var fromDate = $('#calendar-from-date').data('DateTimePicker');
var toDate = $('#calendar-to-date').data('DateTimePicker');
var today = new Date();
var yesterday = new Date(new Date().setDate(today.getDate() - 1));
var weekDay = today.getDay();
var monday = new Date(new Date().setDate(today.getDate() - weekDay + (weekDay === 0 ? -6 : 1)));
var sunday = new Date(new Date().setDate(new Date(monday).getDate() + 6));
var lastWeek = new Date(new Date().setDate(today.getDate() - 6));
var firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
var lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
var lastMonth = new Date(new Date().setDate(today.getDate() - 30));
updateRunning = true;
if (selectPeriod === 'today') {
toDate.date(today);
fromDate.date(today);
} else if (selectPeriod === 'yesterday') {
toDate.date(yesterday);
fromDate.date(yesterday);
} else if (selectPeriod === 'this_week') {
toDate.date(sunday);
fromDate.date(monday);
} else if (selectPeriod === 'last_week') {
toDate.date(today);
fromDate.date(lastWeek);
} else if (selectPeriod === 'this_month') {
toDate.date(lastDay);
fromDate.date(firstDay);
} else if (selectPeriod === 'last_month') {
toDate.date(today);
fromDate.date(lastMonth);
}
updateRunning = false;
dateContainer[0].dataset.periodSelect = this.innerHTML;
GlobalActivitiesUpdateTopPaneTags();
reloadActivities();
});
});

View file

@ -2,6 +2,7 @@
$.fn.extend({
select2Multiple: function(config = {}) {
// Adding ID to each block
if (this.next().find('.select2-selection').length > 0) return this;
var templateSelection = (state) => {
return $('<span class="select2-block-body" data-select-id="' + state.id + '">'
+ (config.customSelection !== undefined ? config.customSelection(state) : state.text)

View file

@ -7,10 +7,16 @@
padding: 1em;
.ga-main {
border-right: 1px solid $gray-lighter;
padding-top: 10px;
.ga-activities-list {
grid-area: activities;
min-height: 600px;
.activities-day {
margin-bottom: 10px;
}
}
.activities-counter-label {
@ -24,6 +30,15 @@
.activities-group-expand-button {
color: $color-emperor;
.fas {
display: inline-block;
width: 10px;
}
}
.activities-group{
margin-bottom: 0px;
}
.activity-card {
@ -51,7 +66,7 @@
}
.ga-side {
border-left: 1px solid $gray-lighter;
float: right;
.filter-block {

View file

@ -3,21 +3,24 @@
class GlobalActivitiesController < ApplicationController
def index
teams = activity_filters[:teams]
teams = current_user.teams if teams.blank?
@teams = teams
@teams = current_user.teams
teams = @teams.pluck(:id) if teams.blank?
@activity_types = Activity.activity_types_list
@user_list = User.where(id: UserTeam.where(team: current_user.teams).select(:user_id))
.distinct
.pluck(:full_name, :id)
@grouped_activities, more_activities =
@grouped_activities, @more_activities =
ActivitiesService.load_activities(current_user, teams, activity_filters)
last_day = @grouped_activities.keys.last
@next_date = (Date.parse(last_day) - 1.day).strftime('%Y-%m-%d') if last_day
respond_to do |format|
format.json do
render json: {
activities_html: @grouped_activities,
from: @grouped_activities.keys.first,
to: @grouped_activities.keys.last,
more_activities: more_activities
activities_html: render_to_string(
partial: 'activity_list.html.erb'
),
from: @next_date,
more_activities: @more_activities
}
end
format.html do
@ -47,6 +50,7 @@ class GlobalActivitiesController < ApplicationController
.limit(Constants::SEARCH_LIMIT)
.pluck(:id, :name)
next if matched.length.zero?
results[subject] = matched.map { |pr| { id: pr[0], name: pr[1] } }
end
respond_to do |format|
@ -59,8 +63,16 @@ class GlobalActivitiesController < ApplicationController
private
def activity_filters
begin
params[:types] = JSON.parse(params[:types])
params[:users] = JSON.parse(params[:users])
params[:teams] = JSON.parse(params[:teams])
params[:subjects] = JSON.parse(params[:subjects])
rescue StandardError
end
params.permit(
:from_date, :to_date, types: [], subjects: [], users: [], teams: []
:from_date, :to_date, types: [], subjects: {}, users: [], teams: []
)
end

View file

@ -7,68 +7,60 @@ module GlobalActivitiesHelper
def generate_activity_content(activity)
parameters = {}
activity.values[:parameters].each do |key, value|
activity.values[:message_items].each do |key, value|
parameters[key] =
if value.is_a? String
value
else
public_send("activity_#{value[:type].underscore}_link",
value[:id],
value[:name])
generate_link(value, activity)
end
end
I18n.t("activities.content.#{activity.type_of}_html", parameters)
I18n.t("global_activities.content.#{activity.type_of}_html",
parameters.symbolize_keys)
end
def team_link(id, name)
team = Team.find_by_id(id)
return name unless team
route_to_other_team projects_path(team: team), team, team.name
end
def generate_link(message_item, activity)
type = message_item[:type]
id = message_item[:id]
getter = message_item[:getter]
value = message_item[:value]
def activity_project_link(id, name)
project = Project.find_by_id(id)
return name unless project
link_to project.name, project_path(project)
end
obj = type.constantize.find_by_id id
return value unless obj
def activity_experiment_link(id, name)
experiment = Experiment.find_by_id(id)
return name unless experiment
link_to experiment.name, canvas_experiment_path(experiment)
end
current_value = obj.public_send(getter || 'name')
def activity_my_module_link(id, name)
task = MyModule.find_by_id(id)
return name unless task
link_to experiment.name, protocols_my_module_path(task)
end
def activity_protocol_link(id, name)
protocol = Protocol.find_by_id(id)
return name unless protocol
if protocol.in_repository?
route_to_other_team protocols_path, protocol.team, protocol.name
else
link_to protocol.name, protocols_my_module_path(protocol.my_module)
end
end
def activity_result_link(id, name)
result = Result.find_by_id(id)
return name unless result
link_to result.name, results_my_module_path(result.my_module)
end
def activity_inventory_link(id, name)
inventory = Repository.find_by_id(id)
return name unless inventory
link_to inventory.name, repository_path(inventory)
end
def activity_inventory_item_link(id, name)
item = RepositoryRow.find_by_id(id)
return name unless item
link_to item.name, repository_path(item.repository)
link = case obj
when User
popover_for_user_name(obj, activity.team, false, true)
when Tag
# Not link for now
current_value
when Team
route_to_other_team(projects_path(team: obj),
obj,
current_value)
when Project
link_to current_value, project_path(obj)
when Experiment
link_to current_value, canvas_experiment_path(obj)
when MyModule
link_to current_value, protocols_my_module_path(obj)
when Protocol
if obj.in_repository?
route_to_other_team protocols_path, obj.team, current_value
else
link_to current_value, protocols_my_module_path(obj.my_module)
end
when Repository
link_to current_value, repository_path(obj)
when RepositoryRow
link_to current_value, repository_path(obj.repository)
when RepositoryColumn
link_to current_value, repository_path(obj.repository)
when Result
link_to current_value, results_my_module_path(obj.my_module)
end
link
end
end

View file

@ -21,10 +21,11 @@ class Activity < ApplicationRecord
validates :subject_type, inclusion: { in: Extends::ACTIVITY_SUBJECT_TYPES,
allow_blank: true }
store_accessor :values, :message_items
store_accessor :values, :message_items, :breadcrumbs
default_values(
message_items: {}
message_items: {},
breadcrumbs: {}
)
def self.activity_types_list
@ -37,11 +38,45 @@ class Activity < ApplicationRecord
end
def old_activity?
subject.nil?
subject_id.nil?
end
def generate_breadcrumbs
generate_breadcrumb subject if subject
end
private
def generate_breadcrumb(subject)
case subject
when Protocol
breadcrumbs[:protocol] = subject.name
if subject.in_repository?
generate_breadcrumb(subject.team)
else
generate_breadcrumb(subject.my_module)
end
when MyModule
breadcrumbs[:my_module] = subject.name
generate_breadcrumb(subject.experiment)
when Experiment
breadcrumbs[:experiment] = subject.name
generate_breadcrumb(subject.project)
when Project
breadcrumbs[:project] = subject.name
generate_breadcrumb(subject.team)
when Repository
breadcrumbs[:repository] = subject.name
generate_breadcrumb(subject.team)
when Result
breadcrumbs[:result] = subject.name
generate_breadcrumb(subject.my_module)
when Team
breadcrumbs[:team] = subject.name
end
save!
end
def activity_version
if (experiment || my_module) && subject
errors.add(:activity, 'wrong combination of associations')

View file

@ -439,7 +439,7 @@ class Protocol < ApplicationRecord
team: team,
message_items: {
protocol: id,
action: I18n.t('activities.protocols.team_to_my_message')
storage: I18n.t('activities.protocols.team_to_my_message')
})
end
@ -466,7 +466,7 @@ class Protocol < ApplicationRecord
team: team,
message_items: {
protocol: id,
action: I18n.t('activities.protocols.my_to_team_message')
storage: I18n.t('activities.protocols.my_to_team_message')
})
end

View file

@ -26,6 +26,7 @@ module Activities
def call
enrich_message_items
@activity.save!
@activity.generate_breadcrumbs
self
end

View file

@ -4,14 +4,14 @@ class ActivitiesService
def self.load_activities(user, teams, filters = {})
# Create condition for view permissions checking first
visible_projects = Project.viewable_by_user(user, teams)
query = Activity.where('project_id IS NULL AND team_id IN (?)', teams.select(:id))
query = Activity.where('project_id IS NULL AND team_id IN (?)', teams)
.or(Activity.where(project: visible_projects))
if filters[:subjects].present?
query = query.where(
filters[:subjects].map { '(subject_type = ? AND subject_id IN(?))' }
.join(' OR '),
*filters[:subjects].flatten
filters[:subjects]
.to_h.map { '(subject_type = ? AND subject_id IN(?))' }.join(' OR '),
*filters[:subjects].to_h.flatten
)
end
@ -20,17 +20,21 @@ class ActivitiesService
if filters[:from_date] && filters[:to_date]
activities = query.where(
'created_at <= :from AND created_at >= :to',
'created_at >= :from AND created_at <= :to',
from: Time.zone.parse(filters[:from_date]).beginning_of_day.utc,
to: Time.zone.parse(filters[:to_date]).end_of_day.utc
)
elsif filters[:from_date] && !filters[:to_date]
activities = query.where(
'created_at <= :from',
'created_at >= :from',
from: Time.zone.parse(filters[:from_date]).beginning_of_day.utc
)
else
activities = query
activities = query.where(
'created_at >= :from AND created_at <= :to',
from: Time.now.beginning_of_day.utc,
to: Time.now.end_of_day.utc
)
end
activities = activities.order(created_at: :desc)
@ -44,12 +48,12 @@ class ActivitiesService
last_date = results.keys.last
activities = query.where(
'created_at <= :from AND created_at >= :to',
'created_at >= :from AND created_at <= :to',
from: Time.zone.parse(last_date).beginning_of_day.utc,
to: Time.zone.parse(last_date).end_of_day.utc
)
more_left = query.where(
'created_at < :from',
'created_at > :from',
from: Time.zone.parse(last_date).end_of_day.utc
).exists?
results[last_date] = activities.to_a

View file

@ -1,24 +1,23 @@
<div class="activity-card">
<div class="row">
<div class="col-xs-12">
<% if activity.owner.present? %>
<%= popover_for_user_name(activity.owner, activity.team, false, true) %>
<% if activity.old_activity? %>
<%= activity.message&.html_safe %>
<% else %>
<strong><%= activity.owner_id %></strong>
<%= activity.id %>
<%= generate_activity_content(activity).html_safe %>
<% end %>
<%= generate_activity_content(activity) %>
</div>
</div>
<div class="pull-left activity-timestamp">
<%= activity.created_at.strftime('%H:%M') %>
</div>
<div class="row navigational-breadcrumbs">
<% unless activity.old_activity? %>
<% if activity.subject_type.present? %>
<%= render partial: "global_activities/references/#{activity.subject_type.underscore}.html.erb",
locals: { subject: activity.subject, breadcrumbs: activity.values[:breadcrumbs] } %>
<% else %>
<%= render partial: "global_activities/references/result.html.erb",
locals: { subject: activity.subject, breadcrumbs: activity.values[:breadcrumbs] } %>
locals: { subject: activity.subject, breadcrumbs: activity.breadcrumbs } %>
<% end %>
<% end %>
</div>
</div>

View file

@ -1,8 +1,8 @@
<% @grouped_activities.each do |date, activities| %>
<div class="row">
<div class="row activities-day">
<div class="col-sm-4 col-md-2">
<a class="activities-group-expand-button"
href="#"
href="javascript:void(0);"
id="activities-group-<%= date %>-button"
data-toggle="collapse"
data-turbolinks="false"

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/project.html.erb",
locals: { subject: subject&.project } %>
locals: { subject: subject&.project, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<%= image_tag 'icon_small/experiment.svg' %>
<% if subject %>
<%= link_to experiment_path(subject), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:experiment] %>">
<%= breadcrumbs[:experiment].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:experiment]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/experiment.html.erb",
locals: { subject: subject&.experiment } %>
locals: { subject: subject&.experiment, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<%= image_tag 'icon_small/task.svg' %>
<% if subject %>
<%= link_to my_module_path(subject), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:my_module] %>">
<%= breadcrumbs[:my_module].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:my_module]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/team.html.erb",
locals: { subject: subject&.team } %>
locals: { subject: subject&.team, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<%= image_tag 'icon_small/project.svg' %>
<% if subject %>
<%= link_to project_path(subject), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:project] %>">
<%= breadcrumbs[:project].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:project]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,19 +1,20 @@
<%= render partial: "global_activities/references/my_module.html.erb",
locals: { subject: subject&.my_module } %>
locals: { subject: subject&.my_module, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<span class="fas fa-edit"></span>
<% if subject %>
<% if subject.in_repository %>
<% if subject.in_repository? %>
<%= route_to_other_team protocols_path(team: subject.team),
subject.team,
subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH),
subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH),
title: subject.name %>
<% else %>
<%= link_to truncated_name, protocols_my_module_path(subject.my_module), title: subject.name %>
<%= link_to subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH),
protocols_my_module_path(subject.my_module), title: subject.name %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:protocol] %>">
<%= breadcrumbs[:protocol].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:protocol]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/team.html.erb",
locals: { subject: subject&.team } %>
locals: { subject: subject&.team, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<%= image_tag 'icon_small/report.png' %>
<% if subject %>
<%= link_to reports_path(subject), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:report] %>">
<%= breadcrumbs[:report].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:report]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/team.html.erb",
locals: { subject: subject&.team } %>
locals: { subject: subject&.team, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<span class="fas fa-list-alt"></span>
<% if subject %>
<%= link_to repositories_path(subject), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:repository] %>">
<%= breadcrumbs[:repository].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:repository]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -1,14 +1,14 @@
<%= render partial: "global_activities/references/my_module.html.erb",
locals: { subject: subject&.my_module } %>
locals: { subject: subject&.my_module, breadcrumbs: breadcrumbs } %>
<div class="col-xs-2">
<%= image_tag 'icon_small/result.png' %>
<% if subject %>
<%= link_to results_my_module_path(subject.my_module), title: subject.name do %>
<%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<% end %>
<% else %>
<span title="<%= breadcrumbs[:result] %>">
<%= breadcrumbs[:result].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:result]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -3,11 +3,11 @@
<% if subject %>
<%= route_to_other_team projects_path(team: subject.id),
subject,
subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH),
subject.name&.truncate(Constants::NAME_TRUNCATION_LENGTH),
title: subject.name %>
<% else %>
<span title="<%= breadcrumbs[:team] %>">
<%= breadcrumbs[:team].truncate(Constants::NAME_TRUNCATION_LENGTH) %>
<%= breadcrumbs[:team]&.truncate(Constants::NAME_TRUNCATION_LENGTH) %>
</span>
<% end %>
</div>

View file

@ -56,7 +56,7 @@
</ul>
<ul class="nav nav-bottom">
<li class="<%= "active" if activities_are_selected? %>">
<%= link_to activities_path, id: "activities-link", title: t('left_menu_bar.activities') do %>
<%= link_to global_activities_path, id: "activities-link", title: t('left_menu_bar.activities') do %>
<span class="fas fa-list"></span>
<span><%= t('left_menu_bar.activities') %></span>
<% end %>

View file

@ -85,7 +85,7 @@ class Extends
FILE_FA_ICON_MAPPINGS = {}
ACTIVITY_SUBJECT_TYPES = %w(
Team Repository Project Experiment MyModule Result Protocol Step Report
Team Repository Project Experiment MyModule Result Protocol Report
).freeze
SEARCHABLE_ACTIVITY_SUBJECT_TYPES = %w(
@ -93,7 +93,7 @@ class Extends
).freeze
ACTIVITY_MESSAGE_ITEMS_TYPES =
ACTIVITY_SUBJECT_TYPES + %w(User Tag RepositoryColumn RepositoryRow)
ACTIVITY_SUBJECT_TYPES + %w(User Tag RepositoryColumn RepositoryRow Step)
.freeze
ACTIVITY_TYPES = {

View file

@ -1433,42 +1433,6 @@ en:
archive_experiment_html: "archived experiment %{experiment}."
start_edit_wopi_file_result_html: "edited Office online file %{file_name} on result %{result_name}: %{action}."
start_edit_wopi_file_step_html: "edited Office online file %{file_name} on step %{step_num} %{step_name}: %{action}."
restore_experiment_html: "restored experiment %{experiment}"
rename_task_html: "renamed task %{task}"
move_task_html: "moved task %{task} from experiment %{experiment_original} to experiment %{experiment_new}"
archive_task_html: "archived task %{task}"
set_task_due_date_html: "set due date %{date} on task %{task}"
change_task_due_date_html: "changed due date %{date} on task %{task}"
remove_task_due_date_html: "removed due date %{date} on task %{task}"
add_task_tag_html: "added tag %{tag} to task %{task}"
edit_task_tag_html: "edited tag %{tag} on task %{task}"
remove_task_tag_html: "removed tag %{tag} from task %{task}"
create_inventory_html: "created inventory %{inventory}"
rename_inventory_html: "renamed inventory %{inventory}"
delete_inventory_html: "deleted inventory %{inventory}"
create_item_inventory_html: "created inventory item %{item}"
edit_item_inventory_html: "edited inventory item %{item}"
delete_item_inventory_html: "deleted inventory item %{item}"
create_column_inventory_html: "created column %{column} in inventory %{inventory}"
edit_column_inventory_html: "edited column %{column} in inventory %{inventory}"
delete_column_inventory_html: "deleted column %{column} in inventory %{inventory}"
create_protocol_in_repository_html: "created protocol %{protocol} in Protocol repository"
add_step_to_protocol_repository_html: "created protocol %{protocol}'s step %{step} in Protocol repository"
edit_step_in_protocol_repository_html: "edited protocol %{protocol}'s step %{step} in Protocol repository"
delete_step_in_protocol_repository_html: "deleted protocol %{protocol}'s step %{step} in Protocol repository"
edit_description_in_protocol_repository_html: "edited protocol %{protocol}'s description in Protocol repository"
edit_keywords_in_protocol_repository_html: "edited protocol %{protocol}'s keywords in Protocol repository"
edit_authors_in_protocol_repository_html: "edited protocol %{protocol}'s authors in Protocol repository"
archive_protocol_in_repository_html: "archived protocol %{protocol} in Protocol repository"
restore_protocol_in_repository_html: "restored protocol %{protocol} from archive in Protocol repository"
move_protocol_in_repository_html: "moved protocol %{protocol} from %{protocol_storage}"
import_protocol_in_repository_html: "imported protocol %{protocol} to Protocol repository from file"
export_protocol_in_repository_html: "exported protocol %{protocol} from Protocol repository"
invite_user_to_team_html: "invited user %{user} to team %{team} with user role %{user_role}"
remove_user_from_team_html: "removed user %{user} from team %{team}"
change_users_role_on_team_html: "changed %{user}'s role in team %{team} to %{role}"
export_projects_html: "exported project(s) %{projects} to .zip"
export_inventory_items_html: "exported inventory item(s) from %{inventory}"
protocols:
my_to_team_message: 'My protocols to Team protocols'
team_to_my_message: 'Team protocols to My protocols'

View file

@ -20,3 +20,39 @@ en:
all_activities: All activities
l_activities: activities
clear_filters: Clear filters
content:
restore_experiment_html: "%{user} restored experiment %{experiment}"
rename_task_html: "%{user} renamed task %{my_module}"
move_task_html: "%{user} moved task %{my_module} from experiment %{experiment_original} to experiment %{experiment_new}"
archive_task_html: "%{user} archived task %{my_module}"
set_task_due_date_html: "%{user} set due date %{my_module_duedate} on task %{my_module}"
change_task_due_date_html: "%{user} changed due date %{my_module_duedate} on task %{my_module}"
remove_task_due_date_html: "%{user} removed due date %{my_module_duedate} on task %{my_module}"
add_task_tag_html: "%{user} added tag %{tag} to task %{my_module}"
remove_task_tag_html: "%{user} removed tag %{tag} from task %{my_module}"
create_inventory_html: "%{user} created inventory %{repository}"
rename_inventory_html: "%{user} renamed inventory %{repository}"
delete_inventory_html: "%{user} deleted inventory %{repository}"
create_item_inventory_html: "%{user} created inventory item %{repository_row}"
edit_item_inventory_html: "%{user} edited inventory item %{repository_row}"
delete_item_inventory_html: "%{user} deleted inventory item %{repository_row}"
create_column_inventory_html: "%{user} created column %{repository_column} in inventory %{repository}"
edit_column_inventory_html: "%{user} edited column %{repository_column} in inventory %{repository}"
delete_column_inventory_html: "%{user} deleted column %{repository_column} in inventory %{repository}"
create_protocol_in_repository_html: "%{user} created protocol %{protocol} in Protocol repository"
add_step_to_protocol_repository_html: "%{user} created protocol %{protocol}'s step %{step} in Protocol repository"
edit_step_in_protocol_repository_html: "%{user} edited protocol %{protocol}'s step %{step} in Protocol repository"
delete_step_in_protocol_repository_html: "%{user} deleted protocol %{protocol}'s step %{step} in Protocol repository"
edit_description_in_protocol_repository_html: "%{user} edited protocol %{protocol}'s description in Protocol repository"
edit_keywords_in_protocol_repository_html: "%{user} edited protocol %{protocol}'s keywords in Protocol repository"
edit_authors_in_protocol_repository_html: "%{user} edited protocol %{protocol}'s authors in Protocol repository"
archive_protocol_in_repository_html: "%{user} archived protocol %{protocol} in Protocol repository"
restore_protocol_in_repository_html: "%{user} restored protocol %{protocol} from archive in Protocol repository"
move_protocol_in_repository_html: "%{user} moved protocol %{protocol} from %{storage}"
import_protocol_in_repository_html: "%{user} imported protocol %{protocol} to Protocol repository from file"
export_protocol_in_repository_html: "%{user} exported protocol %{protocol} from Protocol repository"
invite_user_to_team_html: "%{user} invited user %{user_invited} to team %{team} with user role %{role}"
remove_user_from_team_html: "%{user} removed user %{user_removed} from team %{team}"
change_users_role_on_team_html: "%{user} changed %{user_changed}'s role in team %{team} to %{role}"
export_projects_html: "%{user} exported project(s) %{projects} to .zip"
export_inventory_items_html: "%{user} exported inventory item(s) from %{repository}"

View file

@ -10,7 +10,6 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190227110801) do
# These are extensions that must be enabled in order to support this database

View file

@ -63,4 +63,39 @@ describe Activity, type: :model do
expect(activity.message_items).to include(user: be_an(Hash))
end
end
describe '.generate_breadcrumbs' do
context 'when do not have subject' do
it 'does not add breadcrumbs to activity' do
expect { old_activity.generate_breadcrumbs }
.not_to(change { activity.values[:breadcrumbs] })
end
end
context 'when have subject' do
it 'adds breadcrumbs to activity' do
expect { activity.generate_breadcrumbs }
.to(change { activity.values[:breadcrumbs] })
end
context 'when subject is a my_module' do
let(:activity) { create :activity, subject: (create :my_module) }
it 'has keys my_module, experiment, project and team' do
activity.generate_breadcrumbs
expect(activity.breadcrumbs)
.to include(:my_module, :experiment, :project, :team)
end
end
context 'when subject is a team' do
let(:activity) { create :activity, subject: (create :team) }
it 'has key team' do
activity.generate_breadcrumbs
expect(activity.breadcrumbs).to include(:team)
end
end
end
end
end