mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-28 07:54:28 +08:00
Merge pull request #5326 from rekonder/aj_SCI_8082
Reverse table header/row numbering for plate templates [SCI-8082]
This commit is contained in:
commit
0cc253172f
8 changed files with 135 additions and 37 deletions
35
app/assets/javascripts/protocols/handson.js
Normal file
35
app/assets/javascripts/protocols/handson.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* global tableColRowName*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const handsontableInitDataElem = $('#handson');
|
||||||
|
const HANDSONTABLE_INIT_ROWS_CNT = handsontableInitDataElem.data('init-rows-cnt');
|
||||||
|
const HANDSONTABLE_INIT_COLS_CNT = handsontableInitDataElem.data('init-cols-cnt');
|
||||||
|
|
||||||
|
$("[data-role='hot-table']").each(function() {
|
||||||
|
var hot;
|
||||||
|
var $container = $(this).find("[data-role='step-hot-table']");
|
||||||
|
var contents = $(this).find('.hot-contents');
|
||||||
|
var metadataJson = $(this).find('.hot-metadata');
|
||||||
|
var metadata = JSON.parse(metadataJson.val() || '{}');
|
||||||
|
|
||||||
|
$container.handsontable({
|
||||||
|
startRows: HANDSONTABLE_INIT_ROWS_CNT,
|
||||||
|
startCols: HANDSONTABLE_INIT_COLS_CNT,
|
||||||
|
rowHeaders: tableColRowName.tableRowHeaders(metadata.plateTemplate),
|
||||||
|
colHeaders: tableColRowName.tableColHeaders(metadata.plateTemplate),
|
||||||
|
fillHandle: false,
|
||||||
|
formulas: true,
|
||||||
|
data: JSON.parse(contents.attr('value')).data,
|
||||||
|
cell: metadata.cells || [],
|
||||||
|
readOnly: true
|
||||||
|
});
|
||||||
|
|
||||||
|
hot = $container.handsontable('getInstance');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
hot.render();
|
||||||
|
}, 500);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.print();
|
||||||
|
}());
|
|
@ -1,4 +1,35 @@
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
function tableColHeaders(isPlateTemplate) {
|
||||||
|
if (isPlateTemplate) {
|
||||||
|
return function(visualColumnIndex) {
|
||||||
|
return visualColumnIndex + 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tableRowHeaders(isPlateTemplate) {
|
||||||
|
if (isPlateTemplate) {
|
||||||
|
return function(visualColumnIndex) {
|
||||||
|
var ordA = 'A'.charCodeAt(0);
|
||||||
|
var ordZ = 'Z'.charCodeAt(0);
|
||||||
|
var len = (ordZ - ordA) + 1;
|
||||||
|
var num = visualColumnIndex;
|
||||||
|
|
||||||
|
var colName = '';
|
||||||
|
while (num >= 0) {
|
||||||
|
colName = String.fromCharCode((num % len) + ordA) + colName;
|
||||||
|
num = Math.floor(num / len) - 1;
|
||||||
|
}
|
||||||
|
return colName;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the hands on table on the given
|
* Initialize the hands on table on the given
|
||||||
* element with the specified data.
|
* element with the specified data.
|
||||||
|
@ -7,11 +38,12 @@
|
||||||
function initializeHandsonTable(el) {
|
function initializeHandsonTable(el) {
|
||||||
var input = el.siblings('input.hot-table-contents');
|
var input = el.siblings('input.hot-table-contents');
|
||||||
var inputObj = JSON.parse(input.attr('value'));
|
var inputObj = JSON.parse(input.attr('value'));
|
||||||
var metadata = el.siblings('input.hot-table-metadata');
|
var metadataJson = el.siblings('input.hot-table-metadata');
|
||||||
var data = inputObj.data;
|
var data = inputObj.data;
|
||||||
var headers;
|
var headers;
|
||||||
var parentEl;
|
var parentEl;
|
||||||
var order;
|
var order;
|
||||||
|
var metadata;
|
||||||
|
|
||||||
// Special handling if this is a repository table
|
// Special handling if this is a repository table
|
||||||
if (input.hasClass('hot-repository-items')) {
|
if (input.hasClass('hot-repository-items')) {
|
||||||
|
@ -32,15 +64,16 @@
|
||||||
|
|
||||||
el.handsontable('getInstance').getPlugin('columnSorting').sort(3, order);
|
el.handsontable('getInstance').getPlugin('columnSorting').sort(3, order);
|
||||||
} else {
|
} else {
|
||||||
|
metadata = JSON.parse(metadataJson.val() || '{}');
|
||||||
el.handsontable({
|
el.handsontable({
|
||||||
disableVisualSelection: true,
|
disableVisualSelection: true,
|
||||||
rowHeaders: true,
|
rowHeaders: tableRowHeaders(metadata.plateTemplate),
|
||||||
colHeaders: true,
|
colHeaders: tableColHeaders(metadata.plateTemplate),
|
||||||
editor: false,
|
editor: false,
|
||||||
copyPaste: false,
|
copyPaste: false,
|
||||||
formulas: true,
|
formulas: true,
|
||||||
data: data,
|
data: data,
|
||||||
cell: JSON.parse(metadata.val() || '{}').cells || []
|
cell: metadata.cells || []
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
42
app/assets/javascripts/sitewide/table_col_row_name.js
Normal file
42
app/assets/javascripts/sitewide/table_col_row_name.js
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* eslint-disable no-unused-vars, no-use-before-define */
|
||||||
|
|
||||||
|
var tableColRowName = (function() {
|
||||||
|
function tableColHeaders(isPlateTemplate) {
|
||||||
|
if (isPlateTemplate) {
|
||||||
|
return function(visualColumnIndex) {
|
||||||
|
return visualColumnIndex + 1;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function tableRowHeaders(isPlateTemplate) {
|
||||||
|
if (isPlateTemplate) {
|
||||||
|
return function(visualColumnIndex) {
|
||||||
|
var ordA = 'A'.charCodeAt(0);
|
||||||
|
var ordZ = 'Z'.charCodeAt(0);
|
||||||
|
var len = (ordZ - ordA) + 1;
|
||||||
|
var num = visualColumnIndex;
|
||||||
|
|
||||||
|
var colName = '';
|
||||||
|
while (num >= 0) {
|
||||||
|
colName = String.fromCharCode((num % len) + ordA) + colName;
|
||||||
|
num = Math.floor(num / len) - 1;
|
||||||
|
}
|
||||||
|
return colName;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
tableColHeaders: function(isPlateTemplate) {
|
||||||
|
return tableColHeaders(isPlateTemplate);
|
||||||
|
},
|
||||||
|
tableRowHeaders: function(isPlateTemplate) {
|
||||||
|
return tableRowHeaders(isPlateTemplate);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
|
@ -5,7 +5,7 @@ module StepElements
|
||||||
before_action :load_table, only: %i(update destroy duplicate)
|
before_action :load_table, only: %i(update destroy duplicate)
|
||||||
|
|
||||||
def create
|
def create
|
||||||
predefined_table_dimensions = params[:tableDimensions].map(&:to_i)
|
predefined_table_dimensions = create_table_params[:tableDimensions].map(&:to_i)
|
||||||
name = if predefined_table_dimensions[0] == predefined_table_dimensions[1]
|
name = if predefined_table_dimensions[0] == predefined_table_dimensions[1]
|
||||||
t('protocols.steps.table.default_name',
|
t('protocols.steps.table.default_name',
|
||||||
position: @step.step_tables.length + 1)
|
position: @step.step_tables.length + 1)
|
||||||
|
@ -18,6 +18,7 @@ module StepElements
|
||||||
name: name,
|
name: name,
|
||||||
contents: { data: Array.new(predefined_table_dimensions[0],
|
contents: { data: Array.new(predefined_table_dimensions[0],
|
||||||
Array.new(predefined_table_dimensions[1], '')) }.to_json,
|
Array.new(predefined_table_dimensions[1], '')) }.to_json,
|
||||||
|
metadata: { plateTemplate: create_table_params[:plateTemplate] == 'true' },
|
||||||
created_by: current_user,
|
created_by: current_user,
|
||||||
team: @step.protocol.team
|
team: @step.protocol.team
|
||||||
))
|
))
|
||||||
|
@ -36,7 +37,9 @@ module StepElements
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
@table.assign_attributes(table_params.except(:metadata))
|
@table.assign_attributes(table_params.except(:metadata))
|
||||||
begin
|
begin
|
||||||
@table.metadata = JSON.parse(table_params[:metadata]) if table_params[:metadata].present?
|
if table_params[:metadata].present?
|
||||||
|
@table.metadata = @table.metadata.merge(JSON.parse(table_params[:metadata]))
|
||||||
|
end
|
||||||
rescue JSON::ParserError
|
rescue JSON::ParserError
|
||||||
@table.metadata = {}
|
@table.metadata = {}
|
||||||
end
|
end
|
||||||
|
@ -79,6 +82,10 @@ module StepElements
|
||||||
params.permit(:name, :contents, :metadata)
|
params.permit(:name, :contents, :metadata)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_table_params
|
||||||
|
params.permit(:plateTemplate, tableDimensions: [])
|
||||||
|
end
|
||||||
|
|
||||||
def load_table
|
def load_table
|
||||||
@table = @step.tables.find_by(id: params[:id])
|
@table = @step.tables.find_by(id: params[:id])
|
||||||
return render_404 unless @table
|
return render_404 unless @table
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
|
|
||||||
<ul class="dropdown-submenu">
|
<ul class="dropdown-submenu">
|
||||||
<li v-for="option in wellPlateOptions" :key="option.dimensions.toString()" class="action" @click="createElement('table', option.dimensions)">
|
<li v-for="option in wellPlateOptions" :key="option.dimensions.toString()" class="action" @click="createElement('table', option.dimensions, true)">
|
||||||
{{ i18n.t(option.label) }}
|
{{ i18n.t(option.label) }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -437,8 +437,8 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
createElement(elementType, tableDimensions = [5,5]) {
|
createElement(elementType, tableDimensions = [5,5], plateTemplate = false) {
|
||||||
$.post(this.urls[`create_${elementType}_url`], { tableDimensions: tableDimensions }, (result) => {
|
$.post(this.urls[`create_${elementType}_url`], { tableDimensions: tableDimensions, plateTemplate: plateTemplate }, (result) => {
|
||||||
result.data.isNew = true;
|
result.data.isNew = true;
|
||||||
this.elements.push(result.data)
|
this.elements.push(result.data)
|
||||||
this.$emit('stepUpdated')
|
this.$emit('stepUpdated')
|
||||||
|
|
|
@ -181,13 +181,14 @@
|
||||||
let container = this.$refs.hotTable;
|
let container = this.$refs.hotTable;
|
||||||
let data = JSON.parse(this.element.attributes.orderable.contents);
|
let data = JSON.parse(this.element.attributes.orderable.contents);
|
||||||
let metadata = this.element.attributes.orderable.metadata || {};
|
let metadata = this.element.attributes.orderable.metadata || {};
|
||||||
|
|
||||||
this.tableObject = new Handsontable(container, {
|
this.tableObject = new Handsontable(container, {
|
||||||
data: data.data,
|
data: data.data,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
startRows: 5,
|
startRows: 5,
|
||||||
startCols: 5,
|
startCols: 5,
|
||||||
rowHeaders: true,
|
rowHeaders: tableColRowName.tableRowHeaders(metadata.plateTemplate),
|
||||||
colHeaders: true,
|
colHeaders: tableColRowName.tableColHeaders(metadata.plateTemplate),
|
||||||
cell: metadata.cells || [],
|
cell: metadata.cells || [],
|
||||||
contextMenu: this.editingTable,
|
contextMenu: this.editingTable,
|
||||||
formulas: true,
|
formulas: true,
|
||||||
|
|
|
@ -10,31 +10,10 @@
|
||||||
<%= stylesheet_link_tag 'layouts/print_protocol', media: 'print, screen' %>
|
<%= stylesheet_link_tag 'layouts/print_protocol', media: 'print, screen' %>
|
||||||
<body>
|
<body>
|
||||||
<%= yield %>
|
<%= yield %>
|
||||||
<script>
|
<div id="handson"
|
||||||
$("[data-role='hot-table']").each(function() {
|
data-init-rows-cnt="<%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>"
|
||||||
var $container = $(this).find("[data-role='step-hot-table']");
|
data-init-cols-cnt="<%= Constants::HANDSONTABLE_INIT_COLS_CNT %>"
|
||||||
var contents = $(this).find('.hot-contents');
|
></div>
|
||||||
var metadata = $(this).find('.hot-metadata');
|
<%= javascript_include_tag 'protocols/handson', nonce: true %>
|
||||||
|
|
||||||
$container.handsontable({
|
|
||||||
startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>,
|
|
||||||
startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>,
|
|
||||||
rowHeaders: true,
|
|
||||||
colHeaders: true,
|
|
||||||
fillHandle: false,
|
|
||||||
formulas: true,
|
|
||||||
data: JSON.parse(contents.attr('value')).data,
|
|
||||||
cell: JSON.parse(metadata.val() || '{}').cells || [],
|
|
||||||
readOnly: true
|
|
||||||
});
|
|
||||||
var hot = $container.handsontable('getInstance');
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
hot.render()
|
|
||||||
}, 500)
|
|
||||||
});
|
|
||||||
|
|
||||||
window.print();
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -63,6 +63,7 @@ Rails.application.config.assets.precompile += %w(protocols/edit.js)
|
||||||
Rails.application.config.assets.precompile += %w(protocols/import_export/eln_table.js)
|
Rails.application.config.assets.precompile += %w(protocols/import_export/eln_table.js)
|
||||||
Rails.application.config.assets.precompile += %w(protocols/import_export/import.js)
|
Rails.application.config.assets.precompile += %w(protocols/import_export/import.js)
|
||||||
Rails.application.config.assets.precompile += %w(protocols/import_export/export.js)
|
Rails.application.config.assets.precompile += %w(protocols/import_export/export.js)
|
||||||
|
Rails.application.config.assets.precompile += %w(protocols/handson.js)
|
||||||
Rails.application.config.assets.precompile += %w(layouts/print_protocol.css)
|
Rails.application.config.assets.precompile += %w(layouts/print_protocol.css)
|
||||||
Rails.application.config.assets.precompile += %w(datatables.js)
|
Rails.application.config.assets.precompile += %w(datatables.js)
|
||||||
Rails.application.config.assets.precompile += %w(search/index.js)
|
Rails.application.config.assets.precompile += %w(search/index.js)
|
||||||
|
|
Loading…
Add table
Reference in a new issue