diff --git a/app/assets/javascripts/experiments/table.js b/app/assets/javascripts/experiments/table.js new file mode 100644 index 000000000..68ce42ae6 --- /dev/null +++ b/app/assets/javascripts/experiments/table.js @@ -0,0 +1,68 @@ +const ExperimnetTable = { + selectedId: [], + table: '.experiment-table', + render: {}, + init: function() { + $.get($('.experiment-table').data('my-modules-url'), (result) => { + $.each(result, (id, data) => { + // Checkbox selector + let row = ` +
+
+ + +
+
`; + // Task columns + $.each(data, (_i, cell) => { + row += ` +
+ ${ExperimnetTable.render[cell.column_type](cell.data)} +
+ `; + }); + // Menu + row += '
'; + $(`
${row}
`).appendTo(`${this.table} .table-body`); + }); + }); + } +}; + +ExperimnetTable.render.task_name = function(data) { + return `${data.name}`; +}; + +ExperimnetTable.render.id = function(data) { + return data; +}; + +ExperimnetTable.render.due_date = function(data) { + return data; +}; + +ExperimnetTable.render.age = function(data) { + return data; +}; + +ExperimnetTable.render.results = function(data) { + return `${data.count}`; +}; + +ExperimnetTable.render.status = function(data) { + return `
${data.name}
`; +}; + +ExperimnetTable.render.assigned = function(data) { + return data; +}; + +ExperimnetTable.render.tags = function(data) { + return data; +}; + +ExperimnetTable.render.comments = function(data) { + return data; +}; + +ExperimnetTable.init(); diff --git a/app/assets/stylesheets/experiment/table.scss b/app/assets/stylesheets/experiment/table.scss new file mode 100644 index 000000000..a1b9b499a --- /dev/null +++ b/app/assets/stylesheets/experiment/table.scss @@ -0,0 +1,85 @@ +// scss-lint:disable SelectorDepth NestingDepth IdSelector + +#experimentTable { + .experiment-table-container { + margin-top: 1em; + overflow-x: scroll; + } + + .experiment-table { + display: grid; + grid-auto-rows: 3em 1px; + grid-template-columns: max-content repeat(calc(var(--columns-count)), minmax(max-content, auto)) max-content; + min-width: 100%; + + .table-header-cell { + align-items: center; + background-color: $color-concrete; + border: 1px solid $color-white; + display: flex; + height: 3em; + padding: 0 .5em; + //position: sticky; + //position: -webkit-sticky; + //top: calc(var(--content-header-size) + var(--navbar-height)); + z-index: 2; + + &.select-all-checkboxes { + justify-content: center; + } + + .fa-comment { + color: $color-silver-chalice; + } + } + + .table-header { + display: contents; + + &::after { + content: ""; + grid-column: 1/-1; + } + } + + .table-body { + display: contents; + } + + .table-body-cell { + align-items: center; + display: flex; + padding: 0 .5em; + } + + .table-row { + display: contents; + + &:hover { + .table-body-cell { + background-color: $color-concrete; + } + } + + &::after { + background: $color-concrete; + content: ""; + display: inline-block; + grid-column: 1/-1; + height: 1px; + } + } + + .my-module-status { + color: $color-white; + display: inline-block; + margin: 3px 0; + max-width: 100%; + overflow: hidden; + padding: 2px 8px; + text-overflow: ellipsis; + white-space: nowrap; + } + + } +} diff --git a/app/controllers/experiments_controller.rb b/app/controllers/experiments_controller.rb index d2f485a97..f7aa2fa65 100644 --- a/app/controllers/experiments_controller.rb +++ b/app/controllers/experiments_controller.rb @@ -88,6 +88,17 @@ class ExperimentsController < ApplicationController .select('my_modules.*').group(:id) end + def table + redirect_to module_archive_experiment_path(@experiment) if @experiment.archived_branch? + @project = @experiment.project + @active_modules = @experiment.my_modules.active.order(:name) + end + + def load_table + active_modules = @experiment.my_modules.active + render json: Experiments::TableViewService.new(active_modules).call + end + def edit respond_to do |format| format.json do diff --git a/app/services/experiments/table_view_service.rb b/app/services/experiments/table_view_service.rb new file mode 100644 index 000000000..756657574 --- /dev/null +++ b/app/services/experiments/table_view_service.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +module Experiments + class TableViewService + include Rails.application.routes.url_helpers + include ActionView::Helpers::DateHelper + + COLUMNS = %i( + task_name + id + due_date + age + results + status + assigned + tags + comments + ).freeze + + PRELOAD = %i( + results + my_module_status + ).freeze + + def initialize(my_modules, _page = 1) + @my_modules = my_modules + @page = 1 + end + + def call + result = {} + @my_modules.includes(PRELOAD).each do |my_module| + prepared_my_module = [] + COLUMNS.each do |col| + column_data = { + column_type: col + } + column_data[:data] = __send__("#{col}_presenter", my_module) + prepared_my_module.push(column_data) + end + + result[my_module.id] = prepared_my_module + end + result + end + + private + + def task_name_presenter(my_module) + { + name: my_module.name, + url: protocols_my_module_path(my_module) + } + end + + def id_presenter(my_module) + my_module.id + end + + def due_date_presenter(my_module) + if my_module.due_date + I18n.l(my_module.due_date, format: :full_date) + else + '' + end + end + + def age_presenter(my_module) + time_ago_in_words(my_module.created_at) + end + + def results_presenter(my_module) + { + count: my_module.results.length, + url: results_my_module_path(my_module) + } + end + + def status_presenter(my_module) + { + name: my_module.my_module_status.name, + color: my_module.my_module_status.color + } + end + + def assigned_presenter(my_module); end + + def tags_presenter(my_module); end + + def comments_presenter(my_module); end + end +end diff --git a/app/views/experiments/canvas.html.erb b/app/views/experiments/canvas.html.erb index ec45b77b3..c850509e5 100644 --- a/app/views/experiments/canvas.html.erb +++ b/app/views/experiments/canvas.html.erb @@ -9,7 +9,7 @@
<%= render partial: 'experiments/show_header' %> -
+
<% if can_manage_experiment?(@experiment) %> <%=link_to canvas_edit_experiment_url(@experiment), diff --git a/app/views/experiments/table.html.erb b/app/views/experiments/table.html.erb new file mode 100644 index 000000000..0c7dd1ba6 --- /dev/null +++ b/app/views/experiments/table.html.erb @@ -0,0 +1,38 @@ +<% provide(:head_title, t("experiments.table.head_title", experiment: h(@experiment.name)).html_safe) %> +<% provide(:sidebar_title, t("sidebar.my_modules.sidebar_title")) %> +<% provide(:sidebar_url, sidebar_experiment_path(@experiment)) %> +<% provide(:container_class, 'no-second-nav-container') %> + +<%= content_for :sidebar do %> + <%= render partial: 'shared/sidebar/my_modules.html.erb', locals: { experiment: @experiment, my_modules: @active_modules } %> +<% end %> + +
+ <%= render partial: 'experiments/show_header' %> + +
+
+ > +
+
+
+ + +
+
+ <% Experiments::TableViewService::COLUMNS.each do |col| %> +
+ <%= t("experiments.table.column.#{col}_html") %> +
+ <% end %> +
+
+
+
+
+
+ + +<%= javascript_include_tag("experiments/table") %> diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index d8d6553fd..4defcc5d2 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -52,6 +52,7 @@ Rails.application.config.assets.precompile += %w(sidebar.js) Rails.application.config.assets.precompile += %w(projects/index.js) Rails.application.config.assets.precompile += %w(projects/canvas.js) Rails.application.config.assets.precompile += %w(experiments/dropdown_actions.js) +Rails.application.config.assets.precompile += %w(experiments/table.js) Rails.application.config.assets.precompile += %w(reports/new.js) Rails.application.config.assets.precompile += %w(protocols/index.js) Rails.application.config.assets.precompile += %w(protocols/external_protocols_tab.js) diff --git a/config/locales/en.yml b/config/locales/en.yml index 9d3b6fa13..205105163 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1292,6 +1292,18 @@ en: error_flash: ' Could not move the experiment. Experiment name is already in use. ' task_permission: 'No permission: You don’t have edit access to all experiment tasks.' no_projects: 'No projects: You don’t have edit access to any other projects.' + table: + head_title: "%{experiment} | Overview" + column: + id_html: 'ID' + task_name_html: 'Task name' + due_date_html: 'Due date' + age_html: 'Age' + results_html: 'Results' + status_html: 'Status' + assigned_html: 'Assigned to' + tags_html: 'Tags' + comments_html: '' canvas: archive_confirm: "Are you sure to archive this experiment?" actions: 'Experiment' diff --git a/config/routes.rb b/config/routes.rb index 332a6385c..d62b2a825 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -355,6 +355,8 @@ Rails.application.routes.draw do member do get 'permissions' get 'actions_dropdown' + get :table + get :load_table get 'canvas' # Overview/structure for single experiment # AJAX-loaded canvas edit mode (from canvas) get 'canvas/edit', to: 'canvas#edit'