diff --git a/app/assets/images/icon_small/experiment.svg b/app/assets/images/icon_small/experiment.svg new file mode 100644 index 000000000..74f7c3ad4 --- /dev/null +++ b/app/assets/images/icon_small/experiment.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/icon_small/project.svg b/app/assets/images/icon_small/project.svg new file mode 100644 index 000000000..27e54e76b --- /dev/null +++ b/app/assets/images/icon_small/project.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/images/icon_small/task.svg b/app/assets/images/icon_small/task.svg new file mode 100644 index 000000000..ed9f717eb --- /dev/null +++ b/app/assets/images/icon_small/task.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/javascripts/global_activities/index.js b/app/assets/javascripts/global_activities/index.js new file mode 100644 index 000000000..e8032eaeb --- /dev/null +++ b/app/assets/javascripts/global_activities/index.js @@ -0,0 +1,56 @@ +/* global animateSpinner */ + +'use strict'; + +(function() { + function initExpandCollapseAllButtons() { + $('#global-activities-colapse-all').on('click', function() { + $('.activities-group').collapse('hide'); + }); + $('#global-activities-expand-all').on('click', function() { + $('.activities-group').collapse('show'); + }); + } + + function initExpandCollapseButton() { + $('.activities-group').on('hide.bs.collapse', function() { + $('#' + $(this) + .attr('id') + '-button').find('.fas').removeClass('fa-caret-down'); + $('#' + $(this) + .attr('id') + '-button').find('.fas').addClass('fa-caret-right'); + }); + $('.activities-group').on('show.bs.collapse', function() { + $('#' + $(this) + .attr('id') + '-button').find('.fas').removeClass('fa-caret-right'); + $('#' + $(this) + .attr('id') + '-button').find('.fas').addClass('fa-caret-down'); + }); + } + + function initShowMoreButton() { + var moreButton = $('.btn-more-activities'); + moreButton.on('click', function(ev) { + ev.preventDefault(); + animateSpinner(null, true); + $.ajax({ + url: $('.global-activities_activities-list').data('activities-url'), + data: { from_date: moreButton.data('next-date') }, + dataType: 'json', + type: 'POST', + success: function(json) { + $('.global-activities_activities-list').html(json.activities_html); + if (json.more_activities === true) { + moreButton.data('next-date', json.next_date); + } else { + moreButton.addClass('hidden'); + } + animateSpinner(null, false); + } + }); + }); + } + + initExpandCollapseAllButtons(); + initExpandCollapseButton(); + initShowMoreButton(); +}()); diff --git a/app/assets/stylesheets/themes/global_activities.scss b/app/assets/stylesheets/themes/global_activities.scss index e0d6a8802..b9758f53e 100644 --- a/app/assets/stylesheets/themes/global_activities.scss +++ b/app/assets/stylesheets/themes/global_activities.scss @@ -34,10 +34,49 @@ grid-area: activities; overflow-y: scroll; min-height: 600px; + + .activities-counter-label { + margin-left: 10px; + } + + .activities-group { + list-style: none; + padding-left: 0; + } + + .activities-group-expand-button { + color: $color-emperor; + } + + .activity-card { + border-radius: 5px; + margin-right: 10px; + padding: 5px; + + &:hover { + background-color: $brand-primary-light; + } + + .atwho-user-popover { + padding-left: 0; + } + + .activity-timestamp { + color: $color-silver-chalice; + } + + .navigational-breadcrumbs { + color: $color-silver-chalice; + } + } } -.global-activities__top-actions{ +.global-activities__top-actions { grid-area: actions; + + a { + color: $color-emperor; + } } .global-activities__search-container{ diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 7270b7cf7..88f04d663 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -139,7 +139,10 @@ module ApplicationHelper end # Generate smart annotation link for one user object - def popover_for_user_name(user, team = nil, skip_user_status = false) + def popover_for_user_name(user, + team = nil, + skip_user_status = false, + skip_avatar = false) user_still_in_team = user.teams.include?(team) user_description = %(
@@ -166,10 +169,16 @@ module ApplicationHelper user_name = user.full_name + html = if skip_avatar + '' + else + raw("") + end + html = - raw("") + + raw(html) + raw(' +
+
+ <% if activity.owner.present? %> + <%= popover_for_user_name(activity.owner, activity.team, false, true) %> + <% else %> + <%= activity.owner_id %> + <% end %> + <%= generate_activity_content(activity) %> +
+
+
+ <%= activity.created_at.strftime('%H:%M') %> +
+ +
diff --git a/app/views/global_activities/_activity_list.html.erb b/app/views/global_activities/_activity_list.html.erb new file mode 100644 index 000000000..0e078dd1c --- /dev/null +++ b/app/views/global_activities/_activity_list.html.erb @@ -0,0 +1,28 @@ +<% @grouped_activities.each do |date, activities| %> +
+
+ + + <%= l(Time.parse(date), format: :full_date) %> + +
+
+
+ <%= activities.length %> + <%= t("activities.index.#{'activity'.pluralize(activities.length)}_counter_label") %> +
+ +
+
+<% end %> diff --git a/app/views/global_activities/index.html.erb b/app/views/global_activities/index.html.erb index b8dc746ae..c309019f6 100644 --- a/app/views/global_activities/index.html.erb +++ b/app/views/global_activities/index.html.erb @@ -1,3 +1,5 @@ +<% provide :head_title, t('nav.label.activities') %> +

@@ -6,9 +8,15 @@
@@ -18,10 +26,15 @@
-
-

list of activities

+
+ <%= render partial: "activity_list.html.erb" %> +
+ -
@@ -29,3 +42,5 @@
+ +<%= javascript_include_tag 'global_activities/index.js' %> diff --git a/app/views/global_activities/references/_experiment.html.erb b/app/views/global_activities/references/_experiment.html.erb new file mode 100644 index 000000000..3eb02e8a4 --- /dev/null +++ b/app/views/global_activities/references/_experiment.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/project.html.erb", + locals: { subject: subject&.project } %> +
+ <%= image_tag 'icon_small/experiment.svg' %> + <% if subject %> + <%= link_to experiment_path(subject), title: subject.name do %> + <%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %> + <% end %> + <% else %> + + <%= breadcrumbs[:experiment].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_my_module.html.erb b/app/views/global_activities/references/_my_module.html.erb new file mode 100644 index 000000000..8054737b4 --- /dev/null +++ b/app/views/global_activities/references/_my_module.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/experiment.html.erb", + locals: { subject: subject&.experiment } %> +
+ <%= 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) %> + <% end %> + <% else %> + + <%= breadcrumbs[:my_module].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_project.html.erb b/app/views/global_activities/references/_project.html.erb new file mode 100644 index 000000000..cb865a190 --- /dev/null +++ b/app/views/global_activities/references/_project.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/team.html.erb", + locals: { subject: subject&.team } %> +
+ <%= image_tag 'icon_small/project.svg' %> + <% if subject %> + <%= link_to project_path(subject), title: subject.name do %> + <%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %> + <% end %> + <% else %> + + <%= breadcrumbs[:project].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_protocol.html.erb b/app/views/global_activities/references/_protocol.html.erb new file mode 100644 index 000000000..c6dd37572 --- /dev/null +++ b/app/views/global_activities/references/_protocol.html.erb @@ -0,0 +1,19 @@ +<%= render partial: "global_activities/references/my_module.html.erb", + locals: { subject: subject&.my_module } %> +
+ + <% if subject %> + <% if subject.in_repository %> + <%= route_to_other_team protocols_path(team: subject.team), + subject.team, + 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 %> + <% end %> + <% else %> + + <%= breadcrumbs[:protocol].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_report.html.erb b/app/views/global_activities/references/_report.html.erb new file mode 100644 index 000000000..44c943d8c --- /dev/null +++ b/app/views/global_activities/references/_report.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/team.html.erb", + locals: { subject: subject&.team } %> +
+ <%= image_tag 'icon_small/report.png' %> + <% if subject %> + <%= link_to reports_path(subject), title: subject.name do %> + <%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %> + <% end %> + <% else %> + + <%= breadcrumbs[:report].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_repository.html.erb b/app/views/global_activities/references/_repository.html.erb new file mode 100644 index 000000000..c0d31f9d3 --- /dev/null +++ b/app/views/global_activities/references/_repository.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/team.html.erb", + locals: { subject: subject&.team } %> +
+ + <% if subject %> + <%= link_to repositories_path(subject), title: subject.name do %> + <%= subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH) %> + <% end %> + <% else %> + + <%= breadcrumbs[:repository].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_result.html.erb b/app/views/global_activities/references/_result.html.erb new file mode 100644 index 000000000..e77b7c341 --- /dev/null +++ b/app/views/global_activities/references/_result.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "global_activities/references/my_module.html.erb", + locals: { subject: subject&.my_module } %> +
+ <%= 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) %> + <% end %> + <% else %> + + <%= breadcrumbs[:result].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/app/views/global_activities/references/_team.html.erb b/app/views/global_activities/references/_team.html.erb new file mode 100644 index 000000000..0c0a8dcf5 --- /dev/null +++ b/app/views/global_activities/references/_team.html.erb @@ -0,0 +1,13 @@ +
+ + <% if subject %> + <%= route_to_other_team projects_path(team: subject.id), + subject, + subject.name.truncate(Constants::NAME_TRUNCATION_LENGTH), + title: subject.name %> + <% else %> + + <%= breadcrumbs[:team].truncate(Constants::NAME_TRUNCATION_LENGTH) %> + + <% end %> +
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 2ed794736..9784c8904 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -89,6 +89,7 @@ Rails.application.config.assets.precompile += Rails.application.config.assets.precompile += %w(repositories/my_module_repository.js) Rails.application.config.assets.precompile += %w(activities/index.js) +Rails.application.config.assets.precompile += %w(global_activities/index.js) Rails.application.config.assets.precompile += %w(repository_columns/index.js) Rails.application.config.assets.precompile += %w(repositories/show.js) Rails.application.config.assets.precompile += %w(sidebar_toggle.js) diff --git a/config/locales/en.yml b/config/locales/en.yml index abb63e567..3ba43495e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1304,8 +1304,12 @@ en: activities: index: today: "Today" - more_activities: "More Activities" + more_activities: "Show more activities" no_activities: "No activities!" + activity_counter_label: " activity" + activities_counter_label: " activities" + expand_all: "Expand all" + collapse_all: "Collapse all" modal: modal_title: "Activities" create_project: "%{user} created project %{project}." @@ -1372,6 +1376,98 @@ en: create_report: "%{user} created report %{report}." delete_report: "%{user} deleted report %{report}." edit_report: "%{user} edited report %{report}." + content: + create_project_html: "created project %{project}." + rename_project_html: "renamed project %{project}." + change_project_visibility_html: "changed project %{project}'s visibility to %{visibility}." + archive_project_html: "moved project %{project} to archive." + restore_project_html: "restored project %{project} from archive." + add_comment_to_project_html: "commented on project %{project}." + edit_project_comment_html: "edited comment on project %{project}." + delete_project_comment_html: "deleted comment on project %{project}." + create_report_html: "created report %{report}." + edit_report_html: "edited report %{report}." + delete_report_html: "deleted report %{report}." + add_result_html: "added %{result_type} result %{result} to task." + edit_result_html: "edited %{result_type} result %{result}." + add_comment_to_result_html: "commented on result %{result}." + edit_result_comment_html: "edited comment on result %{result}." + delete_result_comment_html: "deleted comment on result %{result}." + archive_result_html: "archived %{result_type] result %{result}." + destroy_result_html: "deleted %{result_type] result %{result}." + create_module_html: "created task %{task}." + clone_module_html: "copied task %{new_task} from task %{original_task} as template." + archive_module_html: "archived task %{task}." + restore_module_html: "restored task %{task} from archive." + add_comment_to_module_html: "commented on task %{task}." + edit_module_comment_html: "edited comment on task %{task}." + delete_module_comment_html: "deleted comment on task %{task}." + change_module_description_html: "edited task %{task]'s description." + create_step_html: "created protocol step %{step_num} %{step_name]." + edit_step_html: "edited protocol step %{step_num] %{step_name]." + destroy_step_html: "deleted protocol step %{step_num} %{step_name}." + load_protocol_from_repository_html: "loaded protocol %{protocol] to task %{task} from Protocol repository." + load_protocol_from_file_html: "loaded protocol %{protocol] to task %{task} from file." + revert_protocol_html: "reverted protocol %{protocol] to Protocol repository version." + check_step_checklist_item_html: completed checklist item %{checkbox] (%{completed_counter} completed) in step %{step_num} %{step_name}." + uncheck_step_checklist_item_html: "uncompleted checklist item %{checkbox] (%{completed_counter} completed) in step %{step_num} %{step_name}." + add_comment_to_step_html: "commented on step %{step_num} %{step_name}." + edit_step_comment_html: "edited comment on step %{step_num} %{step_name}." + delete_step_comment_html: "deleted comment on step %{step_num} %{step_name}." + complete_step_html: "completed step %{step_num} %{step_name} (%{completed_counter} completed)." + uncomplete_step_html: "uncompleted step %{step_num} %{step_name} (%{completed_counter} completed)." + uncomplete_task_html: "uncompleted task %{task}." + complete_task_html: "completed task %{task}." + assign_repository_record_html: "assigned inventory item(s) %{items} from inventory %{inventory} to task %{task}." + unassign_repository_record_html: "unassigned inventory item(s) %{items} from inventory %{inventory} to task %{task}." + assign_user_to_project_html: "assigned user %{user} with user role %{role} to project %{project}." + unassign_user_from_project_html: "removed user %{user} from project %{project}." + change_user_role_on_project_html: "changed %{user}'s role on project %{project} to %{role}." + assign_user_to_module_html: "assigned user %{user} to task %{task}." + unassign_user_from_module_html: "removed user %{user} from task %{task}." + create_experiment_html: "created experiment %{experiment}." + edit_experiment_html: "edited experiment %{experiment}." + move_experiment_html: "moved experiment %{experiment} from project %{original_project} to project %{new_project}." + clone_experiment_html: "copied experiment %{new_experiment} from experiment %{original_experiment} as a template." + 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}" user_my_modules: new: diff --git a/config/routes.rb b/config/routes.rb index d7a0fee59..f031bdaac 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -649,6 +649,7 @@ Rails.application.routes.draw do end resources :global_activities, only: [:index] + post 'global_activities', to: 'global_activities#index' namespace :global_activities do get 'search_subjects', to: 'global_activities#search_subjects', as: 'search_subjects' diff --git a/package.json b/package.json index 7ef350a3c..90c2a75df 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@fortawesome/fontawesome-free": "^5.2.0", "babel-eslint": "^8.2.6", "babel-plugin-transform-react-jsx-source": "^6.22.0", - "eslint": "^5.3.0", + "eslint": "^5.14.1", "eslint-config-airbnb": "^15.1.0", "eslint-config-airbnb-base": "^13.0.0", "eslint-config-google": "^0.9.1",