Add checklist and list edit mode

This commit is contained in:
aignatov-bio 2019-12-11 14:49:14 +01:00
parent 7fc9c0d1e4
commit 7664f4be78
17 changed files with 111 additions and 49 deletions

View file

@ -1,19 +1,25 @@
/* global dropdownSelector */
/* global dropdownSelector I18n */
/* eslint-disable no-unused-vars */
var ChecklistColumnHelper = (function() {
function checklistSelect(select, url) {
function checklistSelect(select, url, values) {
var selectedOptions = '';
if (values) {
$.each(values, function(i, option) {
selectedOptions += `<option value="${option.value}">${option.label}</option>`;
});
}
return $(`<select
id="${select}"
data-placeholder = "Select options..."
data-ajax-url = "${url}"
data-combine-tags="true"
data-select-multiple-all-selected="All options"
data-select-multiple-name="options"
></select>`);
data-select-multiple-all-selected="${I18n.t('libraries.manange_modal_column.checklist_type.all_options')}"
data-select-multiple-name="${I18n.t('libraries.manange_modal_column.checklist_type.multiple_options')}"
>${selectedOptions}</select>`);
}
function checklistHiddenField(formId, columnId, value) {
function checklistHiddenField(formId, columnId, values) {
return $(`<input form="${formId}"
type="hidden"
name="repository_cells[${columnId}]"
@ -21,19 +27,18 @@ var ChecklistColumnHelper = (function() {
data-type="RepositoryChecklistValue">`);
}
function initialChecklistEditMode(formId, columnId, cell, value) {
function initialChecklistEditMode(formId, columnId, cell, values) {
var select = 'checklist-' + columnId;
var checklistUrl = $('.repository-column#' + columnId).data('items-url');
var $select = checklistSelect(select, checklistUrl);
var $hiddenField = checklistHiddenField(formId, columnId, value)
var $select = checklistSelect(select, checklistUrl, values);
var $hiddenField = checklistHiddenField(formId, columnId, values);
cell.html($select).append($hiddenField);
dropdownSelector.init('#' + select, {
noEmptyOption: true,
optionClass: 'checkbox-icon',
selectAppearance: 'simple',
onChange: function() {
var values = JSON.stringify(dropdownSelector.getValues('#' + select));
$hiddenField.val(values)
$hiddenField.val(JSON.stringify(dropdownSelector.getValues('#' + select)));
}
});
}

View file

@ -4,7 +4,7 @@
var ListColumnHelper = (function() {
function listSelect(select, url, value) {
var selectedOption = '';
if (value) {
if (value && value.value) {
selectedOption = `<option value="${value.value}">${value.label}</option>`;
}
return $(`<select
@ -33,7 +33,7 @@ var ListColumnHelper = (function() {
singleSelect: true,
selectAppearance: 'simple',
onChange: function() {
var values = JSON.stringify(dropdownSelector.getValues('#' + select));
var values = dropdownSelector.getValues('#' + select);
$hiddenField.val(values);
}
});

View file

@ -1,4 +1,4 @@
/* global List Status SmartAnnotation I18n GLOBAL_CONSTANTS */
/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS */
$.fn.dataTable.render.editRowName = function(formId, cell) {
let $cell = $(cell.node());
@ -59,13 +59,16 @@ $.fn.dataTable.render.editRepositoryTextValue = function(formId, columnId, cell)
$.fn.dataTable.render.editRepositoryListValue = function(formId, columnId, cell) {
var $cell = $(cell.node());
var currentElement = $cell.find('.list-label')
var currentValue = {
value: currentElement.attr('data-value-id'),
label: currentElement.text()
var currentElement = $cell.find('.list-label');
var currentValue = null;
if (currentElement.length) {
currentValue = {
value: currentElement.attr('data-value-id'),
label: currentElement.text()
};
}
ListColumnHelper.initialListEditMode(formId, columnId, $cell, currentValue)
ListColumnHelper.initialListEditMode(formId, columnId, $cell, currentValue);
};
$.fn.dataTable.render.editRepositoryStatusValue = function(formId, columnId, cell) {
@ -110,5 +113,7 @@ $.fn.dataTable.render.editRepositoryTimeRangeValue = function(formId, columnId,
};
$.fn.dataTable.render.editRepositoryChecklistValue = function(formId, columnId, cell) {
return '';
var $cell = $(cell.node());
var currentValue = $cell.find('.checklist-options').data('checklist-items');
ChecklistColumnHelper.initialChecklistEditMode(formId, columnId, $cell, currentValue);
};

View file

@ -1,4 +1,4 @@
/* global List Status SmartAnnotation I18n GLOBAL_CONSTANTS */
/* global ListColumnHelper ChecklistColumnHelper Status SmartAnnotation I18n GLOBAL_CONSTANTS */
$.fn.dataTable.render.newRowName = function(formId, $cell) {
$cell.html(`
@ -48,7 +48,7 @@ $.fn.dataTable.render.newRepositoryTextValue = function(formId, columnId, $cell)
};
$.fn.dataTable.render.newRepositoryListValue = function(formId, columnId, $cell) {
ListColumnHelper.initialListEditMode(formId, columnId, $cell)
ListColumnHelper.initialListEditMode(formId, columnId, $cell);
};
$.fn.dataTable.render.newRepositoryStatusValue = function(formId, columnId, $cell) {
@ -66,5 +66,5 @@ $.fn.dataTable.render.newRepositoryStatusValue = function(formId, columnId, $cel
};
$.fn.dataTable.render.newRepositoryChecklistValue = function(formId, columnId, $cell) {
ChecklistColumnHelper.initialChecklistEditMode(formId, columnId, $cell)
ChecklistColumnHelper.initialChecklistEditMode(formId, columnId, $cell);
};

View file

@ -97,8 +97,27 @@ $.fn.dataTable.render.RepositoryDateRangeValue = function(data) {
};
$.fn.dataTable.render.RepositoryChecklistValue = function(data) {
console.log(data)
return '';
var render = '&#8212;';
var options = data.value;
if (options.length == 1) {
render = `<span class="checklist-options" data-checklist-items='${JSON.stringify(options)}'>
${options[0].label}
</span>`
} else if (options.length > 1) {
var optionsList = $(' <ul class="dropdown-menu checklist-dropdown-menu" role="menu"></ul');
$.each(options, function(i, option) {
$(`<li class="checklist-item">${option.label}</li>`).appendTo(optionsList)
})
render = `
<span class="dropdown checklist-dropdown">
<span data-toggle="dropdown" class="checklist-options" aria-haspopup="true" data-checklist-items='${JSON.stringify(options)}'>
${options.length} ${I18n.t('libraries.manange_modal_column.checklist_type.multiple_options')}
</span>
${optionsList[0].outerHTML}
</span>`
}
return render;
};
$.fn.dataTable.render.defaultRepositoryChecklistValue = function() {

View file

@ -63,7 +63,7 @@ var RepositoryChecklistColumnType = (function() {
checkValidation: () => {
var $manageModal = $(manageModal);
var count = $manageModal.find(previewContainer).find('.items-count').attr('data-count');
return count < GLOBAL_CONSTANTS.REPOSITORY_LIST_ITEMS_PER_COLUMN;
return count < GLOBAL_CONSTANTS.REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN;
},
loadParams: () => {
var repositoryColumnParams = {};

View file

@ -5,5 +5,6 @@ const GLOBAL_CONSTANTS = {
FILENAME_TRUNCATION_LENGTH: <%= Constants::FILENAME_TRUNCATION_LENGTH %>,
FILE_MAX_SIZE_MB: <%= Rails.configuration.x.file_max_size_mb %>,
IS_SAFARI: /^((?!chrome|android).)*safari/i.test(navigator.userAgent),
REPOSITORY_LIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN %>
REPOSITORY_LIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN %>,
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN %>
};

View file

@ -63,11 +63,11 @@ var dropdownSelector = (function() {
if (modalContainer.length) {
windowHeight = modalContainer.height() + modalContainer[0].getBoundingClientRect().top;
modalContainerBottom = modalContainer[0].getBoundingClientRect().bottom;
maxHeight += modalContainerBottom
maxHeight += modalContainerBottom;
}
bottomSpace = windowHeight - containerPosition - containerHeight;
if ((modalContainerBottom + bottomSpace) < 280) {
container.addClass('inverse');
container.find('.dropdown-container').css('max-height', `${(containerPosition - 122 + maxHeight)}px`)
@ -77,7 +77,7 @@ var dropdownSelector = (function() {
container.removeClass('inverse');
container.find('.dropdown-container').css('max-height', `${(bottomSpace - 32 + maxHeight)}px`)
.css('width', `${containerWidth}px`)
.css('margin-top', `${(bottomSpace * -1)}px`)
.css('margin-top', `${(bottomSpace * -1)}px`);
}
}
@ -381,7 +381,8 @@ var dropdownSelector = (function() {
});
// When user will resize browser we must check dropdown position
$(window).resize(function() { updateDropdownDirection(selectElement, dropdownContainer); });
$(window).resize(() => { updateDropdownDirection(selectElement, dropdownContainer); });
$(window).scroll(() => { updateDropdownDirection(selectElement, dropdownContainer); });
// When user will click away, we must close dropdown
$(window).click(() => {
@ -663,7 +664,7 @@ var dropdownSelector = (function() {
// If we have alteast one tag, we need to remove placeholder from search field
searchFieldValue.attr('placeholder',
selectedOptions.length > 0 ? '' : (selector.data('placeholder') || ''));
searchFieldValue.attr('data-options-selected', selectedOptions.length)
searchFieldValue.attr('data-options-selected', selectedOptions.length);
// Add stretch class for visual improvments
if (!selector.data('combine-tags')) {

View file

@ -0,0 +1,17 @@
// scss-lint:disable SelectorDepth SelectorFormat QualifyingElement
// scss-lint:disable NestingDepth ImportantRule
@import "constants";
.repository-table {
// Cells
// Checklists
.checklist-dropdown {
.dropdown-menu {
.checklist-item {
padding: 5px;
}
}
}
}

View file

@ -167,7 +167,7 @@
cursor: pointer;
display: flex;
min-height: 32px;
padding: 0 10px;
padding: 3px 10px;
position: relative;
user-select: none;

View file

@ -47,10 +47,9 @@ module RepositoryColumns
def items
column_checklist_items = @repository_column.repository_checklist_items
.where('data ILIKE ?',
"%#{search_params[:query]}%")
.limit(Constants::SEARCH_LIMIT)
.select(:id, :data)
.where('data ILIKE ?',
"%#{search_params[:query]}%")
.select(:id, :data)
render json: column_checklist_items.map { |i| { value: i.id, label: escape_input(i.data) } }, status: :ok
end

View file

@ -18,5 +18,22 @@ class RepositoryChecklistValue < ApplicationRecord
def data
repository_cell.repository_column.repository_checklist_items
.where(id: repository_checklist_items).select(:id, :data)
.map { |i| { value: i.id, label: i.data } }
end
def data_changed?(new_data)
JSON.parse(new_data) != repository_checklist_items
end
def update_data!(new_data, user)
self.repository_checklist_items = JSON.parse(new_data)
self.last_modified_by = user
save!
end
def self.new_with_payload(payload, attributes)
value = new(attributes)
value.repository_checklist_items = JSON.parse(payload)
value
end
end

View file

@ -14,12 +14,12 @@ module RepositoryColumns
@column.lock!
updating_items_names = @params[:repository_checklist_items_attributes].to_a.map { |e| e[:data] }
existing_items_names = @column.repository_checkbox_items.pluck(:data)
existing_items_names = @column.repository_checklist_items.pluck(:data)
to_be_deleted = existing_items_names - updating_items_names
to_be_created = updating_items_names - existing_items_names
if @column.repository_list_items.size - to_be_deleted.size + to_be_created.size >=
Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN
Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN
@errors[:repository_column] = { repository_checklist_items: 'too many items' }
end
@ -30,7 +30,7 @@ module RepositoryColumns
ActiveRecord::Base.transaction do
to_be_deleted.each do |item|
@column.repository_checkbox_items.find_by(data: item).destroy!.id
@column.repository_checklist_items.find_by(data: item).destroy!.id
end
to_be_created.each do |item|

View file

@ -25,7 +25,7 @@ module RepositoryRows
params[:repository_cells]&.each do |column_id, value|
column = @repository.repository_columns.find_by(id: column_id)
next unless column
next if !column || value.empty?
RepositoryCell.create_with_value!(@repository_row, column, value, @user)
end

View file

@ -31,15 +31,12 @@ module RepositoryRows
next
end
unless cell
RepositoryCell.create_with_value!(@repository_row, column, value, @user)
@record_updated = true
next
end
if cell.value.data_changed?(value)
if cell&.value&.data_changed?(value)
cell.value.update_data!(value, @user)
@record_updated = true
elsif !value.empty?
RepositoryCell.create_with_value!(@repository_row, column, value, @user)
@record_updated = true
end
end

View file

@ -33,7 +33,7 @@
</select>
<div class="limit-counter-container">
<span class="items-count"></span>
<span class="items-limit">/<%= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN %> </span>
<span class="items-limit">/<%= Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN %> </span>
<span class="items-label"></span></div>
</div>
</div>

View file

@ -976,6 +976,7 @@ class Constants
EXPORTABLE_ZIP_EXPIRATION_DAYS = 7
REPOSITORY_LIST_ITEMS_PER_COLUMN = 500
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN = 50
REPOSITORY_NUMBER_TYPE_MAX_DECIMALS = 11
REPOSITORY_LIST_ITEMS_DELIMITERS_MAP = {