mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-01-27 10:08:11 +08:00
Merge branch 'features/global-activities' of github.com:biosistemika/scinote-web into ml-sci-3021
This commit is contained in:
commit
4f9814b884
26 changed files with 349 additions and 198 deletions
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ module Activities
|
|||
def call
|
||||
enrich_message_items
|
||||
@activity.save!
|
||||
@activity.generate_breadcrumbs
|
||||
self
|
||||
end
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %>
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue