Add experiment table view [SCI-7174]

This commit is contained in:
Anton 2022-10-20 10:42:38 +02:00
parent e5276eafcb
commit bc86f11404
9 changed files with 310 additions and 1 deletions

View file

@ -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 = `
<div class="table-body-cell">
<div class="sci-checkbox-container">
<input type="checkbox" class="sci-checkbox">
<span class="sci-checkbox-label"></span>
</div>
</div>`;
// Task columns
$.each(data, (_i, cell) => {
row += `
<div class="table-body-cell">
${ExperimnetTable.render[cell.column_type](cell.data)}
</div>
`;
});
// Menu
row += '<div class="table-body-cell"></div>';
$(`<div class="table-row">${row}</div>`).appendTo(`${this.table} .table-body`);
});
});
}
};
ExperimnetTable.render.task_name = function(data) {
return `<a href="${data.url}">${data.name}</a>`;
};
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 `<a href="${data.url}">${data.count}</a>`;
};
ExperimnetTable.render.status = function(data) {
return `<div class="my-module-status" style="background-color: ${data.color}">${data.name}</div>`;
};
ExperimnetTable.render.assigned = function(data) {
return data;
};
ExperimnetTable.render.tags = function(data) {
return data;
};
ExperimnetTable.render.comments = function(data) {
return data;
};
ExperimnetTable.init();

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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

View file

@ -9,7 +9,7 @@
<div class="content-pane flexible" id="experiment-canvas">
<%= render partial: 'experiments/show_header' %>
<div class="toolbar-row">
<div class="toolbar-row" id="diagram-buttons">
<div id="toolbar-left-block">
<% if can_manage_experiment?(@experiment) %>
<%=link_to canvas_edit_experiment_url(@experiment),

View file

@ -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 %>
<div class="content-pane flexible" id="experimentTable">
<%= render partial: 'experiments/show_header' %>
<div class="experiment-table-container">
<div class="experiment-table"
style="--columns-count: <%= Experiments::TableViewService::COLUMNS.length%>"
data-my-modules-url= <%= load_table_experiment_path(@experiment) %>
>
<div class="table-header">
<div class="table-header-cell select-all-checkboxes">
<div class="sci-checkbox-container">
<input type="checkbox" class="sci-checkbox">
<span class="sci-checkbox-label"></span>
</div>
</div>
<% Experiments::TableViewService::COLUMNS.each do |col| %>
<div class="table-header-cell">
<%= t("experiments.table.column.#{col}_html") %>
</div>
<% end %>
<div class="table-header-cell"></div>
</div>
<div class="table-body"></div>
</div>
</div>
</div>
<%= javascript_include_tag("experiments/table") %>

View file

@ -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)

View file

@ -1292,6 +1292,18 @@ en:
error_flash: ' Could not move the experiment. Experiment name is already in use. '
task_permission: 'No permission: You dont have edit access to all experiment tasks.'
no_projects: 'No projects: You dont 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: '<i class="fas fa-comment"></i>'
canvas:
archive_confirm: "Are you sure to archive this experiment?"
actions: 'Experiment'

View file

@ -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'