Merge pull request #2260 from aignatov-bio/ai-sci-4121-add-edit-mode-to-checklist

Add checklist and list edit mode [SCI-4121]
This commit is contained in:
aignatov-bio 2019-12-13 09:23:14 +01:00 committed by GitHub
commit 2da7eeaedd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 289 additions and 140 deletions

View file

@ -0,0 +1,57 @@
/* global dropdownSelector I18n */
/* eslint-disable no-unused-vars */
var ChecklistColumnHelper = (function() {
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="${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, values) {
var idList = [];
if (values) {
$.each(values, function(i, option) {
idList.push(option.value);
});
} else {
idList = '';
}
return $(`<input form="${formId}"
type="hidden"
name="repository_cells[${columnId}]"
value="${JSON.stringify(idList)}"
data-type="RepositoryChecklistValue">`);
}
function initialChecklistEditMode(formId, columnId, cell, values) {
var select = 'checklist-' + columnId;
var checklistUrl = $('.repository-column#' + columnId).data('items-url');
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() {
$hiddenField.val(JSON.stringify(dropdownSelector.getValues('#' + select)));
}
});
}
return {
initialChecklistEditMode: initialChecklistEditMode
};
}());

View file

@ -1,52 +1,45 @@
/* global dropdownSelector */
/* eslint-disable no-unused-vars */
var List = (function() {
function listItemDropdown(options, currentValueId, columnId, formId) {
var html = `<select class="form-control selectpicker repository-dropdown"
data-abs-min-length="2" data-live-search="true" from="${formId}"
data-container="body" column_id="${columnId}">
<option value="-1"></option>`;
$.each(options, function(index, value) {
var selected = (parseInt(currentValueId, 10) === value[0]) ? 'selected' : '';
html += `<option value="${value[0]}" ${selected}>${value[1]}</option>`;
});
html += '</select>';
return html;
var ListColumnHelper = (function() {
function listSelect(select, url, value) {
var selectedOption = '';
if (value && value.value) {
selectedOption = `<option value="${value.value}">${value.label}</option>`;
}
return $(`<select
id="${select}"
data-placeholder = "Select option..."
data-ajax-url = "${url}"
>${selectedOption}</select>`);
}
function initialListItemsRequest(columnId, currentValueId, formId, url) {
var massageResponse = [];
$.ajax({
url: url,
type: 'POST',
dataType: 'json',
async: false,
data: {
column_id: columnId
}
}).done(function(data) {
$.each(data.list_items, function(index, el) {
massageResponse.push([el.id, el.data]);
});
});
return listItemDropdown(massageResponse, currentValueId, columnId, formId);
function listHiddenField(formId, columnId, value) {
var originalValue = value ? value.value : '';
return $(`<input form="${formId}"
type="hidden"
name="repository_cells[${columnId}]"
value="${originalValue}"
data-type="RepositoryListValue">`);
}
function initSelectPicker($select, $hiddenField) {
dropdownSelector.init($select, {
noEmptyOption: true,
function initialListEditMode(formId, columnId, cell, value = null) {
var select = 'list-' + columnId;
var listUrl = $('.repository-column#' + columnId).data('items-url');
var $select = listSelect(select, listUrl, value);
var $hiddenField = listHiddenField(formId, columnId, value);
cell.html($select).append($hiddenField);
dropdownSelector.init('#' + select, {
singleSelect: true,
closeOnSelect: true,
selectAppearance: 'simple',
onChange: function() {
$hiddenField.val(dropdownSelector.getValues($select));
var values = dropdownSelector.getValues('#' + select);
$hiddenField.val(values);
}
});
}
return {
initialListItemsRequest: initialListItemsRequest,
initSelectPicker: initSelectPicker
initialListEditMode: initialListEditMode
};
}());

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());
@ -58,19 +58,17 @@ $.fn.dataTable.render.editRepositoryTextValue = function(formId, columnId, cell)
};
$.fn.dataTable.render.editRepositoryListValue = function(formId, columnId, cell) {
let $cell = $(cell.node());
let currentValueId = $cell.find('.list-label').attr('data-value-id');
let url = $cell.closest('table').data('list-items-path');
let hiddenField = `
<input form="${formId}"
type="hidden"
name="repository_cells[${columnId}]"
value=""
data-type="RepositoryListValue">`;
var $cell = $(cell.node());
var currentElement = $cell.find('.list-label');
var currentValue = null;
if (currentElement.length) {
currentValue = {
value: currentElement.attr('data-value-id'),
label: currentElement.text()
};
}
$cell.html(hiddenField + List.initialListItemsRequest(columnId, currentValueId, formId, url));
List.initSelectPicker($cell.find('select'), $cell.find(`[name='repository_cells[${columnId}]']`));
ListColumnHelper.initialListEditMode(formId, columnId, $cell, currentValue);
};
$.fn.dataTable.render.editRepositoryStatusValue = function(formId, columnId, cell) {
@ -114,6 +112,8 @@ $.fn.dataTable.render.editRepositoryTimeRangeValue = function(formId, columnId,
return '';
};
$.fn.dataTable.render.editRepositoryCheckboxValue = function(formId, columnId, cell) {
return '';
$.fn.dataTable.render.editRepositoryChecklistValue = function(formId, columnId, cell) {
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,17 +48,7 @@ $.fn.dataTable.render.newRepositoryTextValue = function(formId, columnId, $cell)
};
$.fn.dataTable.render.newRepositoryListValue = function(formId, columnId, $cell) {
let url = $cell.closest('table').data('list-items-path');
let hiddenField = `
<input form="${formId}"
type="hidden"
name="repository_cells[${columnId}]"
value=""
data-type="RepositoryListValue">`;
$cell.html(hiddenField + List.initialListItemsRequest(columnId, '', formId, url));
List.initSelectPicker($cell.find('select'), $cell.find(`[name='repository_cells[${columnId}]']`));
ListColumnHelper.initialListEditMode(formId, columnId, $cell);
};
$.fn.dataTable.render.newRepositoryStatusValue = function(formId, columnId, $cell) {
@ -75,6 +65,6 @@ $.fn.dataTable.render.newRepositoryStatusValue = function(formId, columnId, $cel
Status.initStatusSelectPicker($cell.find('select'), $cell.find(`[name='repository_cells[${columnId}]']`));
};
$.fn.dataTable.render.newRepositoryCheckboxValue = function(formId, columnId) {
return '';
$.fn.dataTable.render.newRepositoryChecklistValue = function(formId, columnId, $cell) {
ChecklistColumnHelper.initialChecklistEditMode(formId, columnId, $cell);
};

View file

@ -1,3 +1,5 @@
/* global I18n */
$.fn.dataTable.render.RepositoryAssetValue = function(data) {
var asset = data.value;
return `
@ -96,10 +98,31 @@ $.fn.dataTable.render.RepositoryDateRangeValue = function(data) {
return data.value;
};
$.fn.dataTable.render.RepositoryCheckboxValue = function(data) {
return '';
$.fn.dataTable.render.RepositoryChecklistValue = function(data) {
var render = '&#8212;';
var options = data.value;
var optionsList;
if (options.length === 1) {
render = `<span class="checklist-options" data-checklist-items='${JSON.stringify(options)}'>
${options[0].label}
</span>`;
} else if (options.length > 1) {
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.defaultRepositoryCheckboxValue = function() {
return '';
$.fn.dataTable.render.defaultRepositoryChecklistValue = function() {
return '&#8212;';
};

View file

@ -29,3 +29,7 @@ $.fn.dataTable.render.RepositoryAssetValueValidator = function($input) {
$btn.attr('data-error-text', errorMessage);
return false;
};
$.fn.dataTable.render.RepositoryChecklistValueValidator = function() {
return true;
};

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

@ -55,16 +55,29 @@ var dropdownSelector = (function() {
var containerPosition = container[0].getBoundingClientRect().top;
var containerHeight = container[0].getBoundingClientRect().height;
var containerWidth = container[0].getBoundingClientRect().width;
var bottomSpace = windowHeight - containerPosition - containerHeight;
if (bottomSpace < 280) {
var bottomSpace;
var modalContainer = container.closest('.modal-dialog');
var modalContainerBottom = 0;
var maxHeight = 0;
if (modalContainer.length) {
windowHeight = modalContainer.height() + modalContainer[0].getBoundingClientRect().top;
modalContainerBottom = modalContainer[0].getBoundingClientRect().bottom;
maxHeight += modalContainerBottom;
}
bottomSpace = windowHeight - containerPosition - containerHeight;
if ((modalContainerBottom + bottomSpace) < 280) {
container.addClass('inverse');
container.find('.dropdown-container').css('max-height', `${(containerPosition - 122)}px`)
container.find('.dropdown-container').css('max-height', `${(containerPosition - 122 + maxHeight)}px`)
.css('margin-bottom', `${(containerPosition * -1)}px`)
.css('width', `${containerWidth}px`);
} else {
container.removeClass('inverse');
container.find('.dropdown-container').css('max-height', `${(bottomSpace - 32)}px`)
.css('width', '');
container.find('.dropdown-container').css('max-height', `${(bottomSpace - 32 + maxHeight)}px`)
.css('width', `${containerWidth}px`)
.css('margin-top', `${(bottomSpace * -1)}px`);
}
}
@ -265,7 +278,7 @@ var dropdownSelector = (function() {
$(`
<div class="dropdown-container"></div>
<div class="input-field">
<input type="text" class="search-field" placeholder="${selectElement.data('placeholder') || ''}"></input>
<input type="text" class="search-field" data-options-selected=0 placeholder="${selectElement.data('placeholder') || ''}"></input>
${prepareCustomDropdownIcon(config)}
</div>
<input type="hidden" class="data-field" value="[]">
@ -368,12 +381,15 @@ 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(() => {
if (dropdownContainer.hasClass('open') && config.onClose) {
if (dropdownContainer.hasClass('open')) {
dropdownContainer.find('.search-field').val('');
}
if (dropdownContainer.hasClass('open') && config.onClose) {
config.onClose();
}
dropdownContainer.removeClass('open active');
@ -544,7 +560,7 @@ var dropdownSelector = (function() {
}
// First we clear search field
container.find('.search-field').val('');
if (selector.data('config').singleSelect) container.find('.search-field').val('');
// Now we check all options in dropdown for selection and add them to array
$.each(container.find('.dropdown-container .dropdown-option'), function(oi, option) {
@ -575,8 +591,6 @@ var dropdownSelector = (function() {
updateCurrentData(container, selectArray);
// Redraw tags
updateTags(selector, container, { select: true });
// Reload options in option container
loadData(selector, container);
}
// Refresh tags in input field
@ -650,6 +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);
// Add stretch class for visual improvments
if (!selector.data('combine-tags')) {
@ -772,7 +787,6 @@ var dropdownSelector = (function() {
values = $.map(getCurrentData($(selector).next()), (v) => {
return v.value;
});
if ($(selector).data('config').singleSelect) return values[0];
return values;

View file

@ -94,11 +94,17 @@
var mouse = { x: e.clientX, y: e.clientY };
$('.popover.tooltip-open').each(function(i, obj) {
var tooltipObj = '*[data-tooltip-id="' + obj.dataset.popoverId + '"]';
var objHeight = $(tooltipObj)[0].clientHeight;
var objWidth = $(tooltipObj)[0].clientWidth;
var objLeft = $(tooltipObj)[0].offsetLeft;
var objTop = $(tooltipObj)[0].offsetTop;
var objCorners = {
var objHeight;
var objWidth;
var objLeft;
var objTop;
var objCorners;
if ($(tooltipObj).length === 0) return;
objHeight = $(tooltipObj)[0].clientHeight;
objWidth = $(tooltipObj)[0].clientWidth;
objLeft = $(tooltipObj)[0].offsetLeft;
objTop = $(tooltipObj)[0].offsetTop;
objCorners = {
tl: { x: objLeft, y: objTop },
tr: { x: (objLeft + objWidth), y: objTop },
bl: { x: objLeft, y: (objTop + objHeight) },

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

@ -109,8 +109,8 @@
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.12), 0 0 4px 0 rgba(0, 0, 0, 0.08);
display: none;
overflow: hidden;
position: absolute;
top: calc(100% - 30px);
position: fixed;
bottom: calc(100% - 30px);
transition: .2s;
transition-property: top, bottom, box-shadow;
width: 100%;
@ -167,7 +167,7 @@
cursor: pointer;
display: flex;
min-height: 32px;
padding: 0 10px;
padding: 3px 10px;
position: relative;
user-select: none;
@ -236,9 +236,19 @@
bottom: 3px;
display: none;
position: absolute;
&[data-options-selected="0"] {
display: block;
}
}
.ds-simple {
.tag-label {
overflow: hiddens;
text-overflow: ellipsis;
white-space: nowrap;
}
.fa-times {
display: none;
}
@ -263,6 +273,7 @@
.dropdown-container {
border-top: 0;
bottom: auto;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.12), 0 0 4px 0 rgba(0, 0, 0, 0.08);
display: block;
top: 100%;
@ -289,6 +300,10 @@
.search-field {
display: block;
line-height: 14px;
&[data-options-selected="0"] {
line-height: 24px;
}
}
.ds-simple {

View file

@ -2,9 +2,9 @@
module RepositoryColumns
class ChecklistColumnsController < BaseColumnsController
before_action :load_column, only: %i(update destroy)
before_action :load_column, only: %i(update destroy items)
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions, only: %i(update destroy)
before_action :check_manage_permissions, only: %i(update destroy items)
helper_method :delimiters
def create
@ -45,8 +45,21 @@ module RepositoryColumns
end
end
def items
column_checklist_items = @repository_column.repository_checklist_items
.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
private
def search_params
params.permit(:query, :column_id)
end
def repository_column_params
params.require(:repository_column).permit(:name, :delimiter, repository_checklist_items_attributes: %i(data))
end

View file

@ -2,9 +2,9 @@
module RepositoryColumns
class ListColumnsController < BaseColumnsController
before_action :load_column, only: %i(update destroy)
before_action :load_column, only: %i(update destroy items)
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions, only: %i(update destroy)
before_action :check_manage_permissions, only: %i(update destroy items)
helper_method :delimiters
def create
@ -45,8 +45,22 @@ module RepositoryColumns
end
end
def items
column_list_items = @repository_column.repository_list_items
.where('data ILIKE ?',
"%#{search_params[:query]}%")
.limit(Constants::SEARCH_LIMIT)
.select(:id, :data)
render json: column_list_items.map { |i| { value: i.id, label: escape_input(i.data) } }, status: :ok
end
private
def search_params
params.permit(:query, :column_id)
end
def repository_column_params
params.require(:repository_column).permit(:name, :delimiter, repository_list_items_attributes: %i(data))
end

View file

@ -1,28 +0,0 @@
class RepositoryListItemsController < ApplicationController
before_action :load_vars, only: :search
def search
column_list_items = @repository_column.repository_list_items
.where('data ILIKE ?',
"%#{search_params[:q]}%")
.limit(Constants::SEARCH_LIMIT)
.select(:id, :data)
render json: { list_items: column_list_items }, status: :ok
end
private
def search_params
params.permit(:q, :column_id)
end
def load_vars
@repository_column = RepositoryColumn.find_by_id(search_params[:column_id])
repository = @repository_column.repository if @repository_column
unless @repository_column&.data_type == 'RepositoryListValue'
render_404 and return
end
render_403 unless can_manage_repository_rows?(repository)
end
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

@ -1,11 +1,11 @@
# frozen_string_literal: true
module RepositoryDatatable
class RepositoryCheckboxValueSerializer < ActiveModel::Serializer
class RepositoryChecklistValueSerializer < ActiveModel::Serializer
attributes :value, :value_type
def value
object.repository_checkbox_value.data
object.repository_checklist_value.data
end
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

@ -19,7 +19,7 @@
data-columns-changed="<%= I18n.t('repositories.columns_changed') %>"
data-default-order="<%= default_table_order_as_js_array %>"
data-default-table-columns="<%= default_table_columns %>"
data-list-items-path="<%= Rails.application.routes.url_helpers.repository_list_items_path %>"
data-checklist-items-path="<%= Rails.application.routes.url_helpers.repository_list_items_path %>"
data-status-items-path="<%= Rails.application.routes.url_helpers.repository_status_items_path %>"
data-editable="<%= can_manage_repository_rows?(repository) %>">
<thead>
@ -31,7 +31,13 @@
<th id="added-on"><%= t("repositories.table.added_on") %></th>
<th id="added-by"><%= t("repositories.table.added_by") %></th>
<% repository.repository_columns.order(:id).each do |column| %>
<th class="repository-column" id="<%= column.id %>" data-type="<%= column.data_type %>">
<th
class="repository-column"
id="<%= column.id %>"
data-type="<%= column.data_type %>"
<%= "data-items-url=#{items_repository_repository_columns_checklist_column_path(repository, column)}" if column.data_type == 'RepositoryChecklistValue' %>
<%= "data-items-url=#{items_repository_repository_columns_list_column_path(repository, column)}" if column.data_type == 'RepositoryListValue' %>
>
<%= display_tooltip(column.name) %>
</th>
<% 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 = {

View file

@ -581,12 +581,20 @@ Rails.application.routes.draw do
namespace :repository_columns do
resources :text_columns, only: %i(create update destroy)
resources :number_columns, only: %i(create update destroy)
resources :list_columns, only: %i(create update destroy)
resources :list_columns, only: %i(create update destroy) do
member do
get 'items'
end
end
resources :asset_columns, only: %i(create update destroy)
resources :date_columns, only: %i(create update destroy)
resources :status_columns, only: %i(create update destroy)
resources :date_time_columns, only: %i(create update destroy)
resources :checklist_columns, only: %i(create update destroy)
resources :checklist_columns, only: %i(create update destroy) do
member do
get 'items'
end
end
end
end

View file

@ -7123,3 +7123,4 @@ INSERT INTO "schema_migrations" (version) VALUES
('20191210103004');