Merge pull request #1144 from ZmagoD/zd_SCI_2371

adds save PDF report to inventory feature [fixes SCI-2371]
This commit is contained in:
Zmago Devetak 2018-05-17 15:25:13 +02:00 committed by GitHub
commit 5dbe978d34
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 657 additions and 16 deletions

View file

@ -210,8 +210,8 @@ var HelperModule = (function(){
}
helpers.flashAlertMsg = function(message, type) {
var alertType;
var glyphSign;
var alertType, glyphSign;
$('#notifications').html('');
if (type === 'success') {
alertType = ' alert-success ';

View file

@ -0,0 +1,282 @@
(function() {
'use strict';
var INVENTORY_PICKER, COLUMN_PICKER, ITEM_PICKER;
var SELECTED_IDS = {
repository_id: null,
respository_column_id: null,
repository_item_id: null,
};
function clearErrors() {
var $columnsAlertSection = $('#save-PDF-to-inventory-column-warnings');
var $itemsAlertSection = $('#save-PDF-to-inventory-warnings');
$itemsAlertSection.empty();
$columnsAlertSection.empty();
}
function toggleHasFileErrorMessage(value) {
var element = $('#selectInventoryItem [value="' + value + '"]');
var $alertSection = $('#save-PDF-to-inventory-warnings');
$alertSection.empty();
if(element.data('hasfile')) {
$alertSection.append(
'<div class="alert alert-danger">' +
'<%=I18n.t("projects.reports.new.save_PDF_to_inventory_modal.asset_present_warning_html") %>' +
'</div>'
)
}
}
function appendSearchResults(data) {
var items = [];
if(data.hasOwnProperty('results')){
$.each(data.results, function(index, el) {
items.push(
{
value: el.id,
text: el.name,
disabled: false
}
)
});
}
return items;
}
function appendSearchResultsForItems(data) {
var items = [];
if(data.hasOwnProperty('results')){
$('#selectInventoryItem').parent().find('button').removeAttr('disabled');
$.each(data.results, function(index, el) {
items.push(
{
value: el.id,
text: el.name,
disabled: false,
data: {
hasFile: el.hasOwnProperty('has_file_attached') ?
el.has_file_attached :
null
}
}
)
});
} else {
$('#selectInventoryItem').parent().find('button').attr('disabled', true);
clearErrors();
$('#save-PDF-to-inventory-warnings').append(
'<strong class="danger">' + data.no_items + '</strong>'
)
}
return items;
}
function appendSearchResultsForColumns(data) {
var items = [];
if(data.hasOwnProperty('results')){
$('#selectInventoryColumn').parent().find('button').removeAttr('disabled');
$.each(data.results, function(index, el) {
items.push(
{
value: el.id,
text: el.name,
disabled: false
}
)
});
} else {
$('#selectInventoryColumn').parent().find('button').attr('disabled', true);
clearErrors();
$('#save-PDF-to-inventory-column-warnings').append(
'<div class="save-PDF-to-inventory-alerts"><strong class="danger">' +
data.no_items + '</strong></div>'
)
}
return items;
}
function submitButtonEnableToggle(status) {
var button = $('#savePDFtoInventorySubmit');
if(status) {
button.removeAttr('disabled');
} else {
button.attr('disabled', true);
}
}
function deselect(element) {
if(element) {
element.selectpicker('val', null)
element.selectpicker('render');
element.attr('disabled', true);
}
}
// triggers first request and cleans the dropdown selectpicker
function clearDropdownResultsCallback(element) {
element.parent().find('button').on('click', function(el) {
$(this).parent().find('input').trigger('keyup');
});
}
function initInventoryItemSelectPicker() {
ITEM_PICKER =
$('#selectInventoryItem')
.removeAttr('disabled')
.selectpicker({liveSearch: true})
.ajaxSelectPicker({
ajax: {
url: '<%= Rails.application.routes.url_helpers.available_rows_path %>',
type: 'POST',
dataType: 'json',
data: function () {
return {
q: '{{{q}}}',
repository_id: SELECTED_IDS.repository_id,
repository_column_id: SELECTED_IDS.respository_column_id
};
}
},
locale: {
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
},
preprocessData: appendSearchResultsForItems,
emptyRequest: true,
clearOnEmpty: true,
cache: false,
preserveSelected: false
}).on('change.bs.select', function(el) {
var value = el.target.value;
toggleHasFileErrorMessage(value);
submitButtonEnableToggle(true);
SELECTED_IDS.repository_item_id = value;
});
clearDropdownResultsCallback(ITEM_PICKER);
}
function initInventoryColumnSelectPicker() {
COLUMN_PICKER =
$('#selectInventoryColumn')
.removeAttr('disabled')
.selectpicker({liveSearch: true})
.ajaxSelectPicker({
ajax: {
url: '<%= Rails.application.routes.url_helpers.available_asset_type_columns_path %>',
type: 'POST',
dataType: 'json',
data: function () {
return {
q: '{{{q}}}',
repository_id: SELECTED_IDS.repository_id
};
}
},
locale: {
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
},
preprocessData: appendSearchResultsForColumns,
emptyRequest: true,
clearOnEmpty: true,
cache: false,
preserveSelected: false
}).on('change.bs.select', function(el) {
SELECTED_IDS.respository_column_id = el.target.value;
deselect(ITEM_PICKER);
submitButtonEnableToggle(false);
initInventoryItemSelectPicker();
// refresh the dropdown state
$('#selectInventoryItem').parent().find('input').trigger('keyup');
clearErrors();
});
clearDropdownResultsCallback(COLUMN_PICKER);
}
function initInventoriesSelectPicker() {
INVENTORY_PICKER =
$('#selectInventory')
.selectpicker({liveSearch: true})
.ajaxSelectPicker({
ajax: {
url: '<%= Rails.application.routes.url_helpers.reports_available_repositories_path %>',
type: 'POST',
dataType: 'json',
data: function () {
return { q: '{{{q}}}' };
}
},
locale: {
emptyTitle: '<%= I18n.t('projects.reports.new.save_PDF_to_inventory_modal.nothing_selected') %>'
},
preprocessData: appendSearchResults,
emptyRequest: true,
clearOnEmpty: false,
cache: false,
preserveSelected: false
}).on('change.bs.select', function(el) {
SELECTED_IDS.repository_id = el.target.value;
deselect(COLUMN_PICKER);
deselect(ITEM_PICKER);
submitButtonEnableToggle(false);
initInventoryColumnSelectPicker();
clearErrors();
// refresh the dropdown state
$('#selectInventoryColumn').parent().find('input').trigger('keyup');
});
clearDropdownResultsCallback(INVENTORY_PICKER);
}
function initializeSubmitAction() {
$('#savePDFtoInventorySubmit').off().on('click', function() {
animateSpinner();
$.ajax({
url: '<%= Rails.application.routes.url_helpers.reports_save_pdf_to_inventory_item_path %>',
data: Object.assign(SELECTED_IDS, { html: $(REPORT_CONTENT).html() }, {}),
type: 'POST',
success: function(data) {
animateSpinner(null, false);
HelperModule.flashAlertMsg(data.message, 'success');
$('#savePDFtoInventory').modal('hide');
},
error: function(xhr) {
animateSpinner(null, false);
HelperModule.flashAlertMsg(xhr.responseJSON.message, 'danger');
$('#savePDFtoInventory').modal('hide');
}
});
});
}
/*
* INITIALIZERS
*/
function initializeSavePDFtoInventoryModal() {
$('#savePDFtoInventory').off().on('shown.bs.modal', function() {
initInventoriesSelectPicker();
initializeSubmitAction();
clearErrors();
// refresh the dropdown state
$('#selectInventory').parent().find('input').trigger('keyup');
}).on('hidden.bs.modal', function() {
// clear ids
SELECTED_IDS = {
repository_id: null,
respository_column_id: null,
repository_item_id: null,
}
// clear select picker objects
if(COLUMN_PICKER) {
deselect(COLUMN_PICKER);
}
if(ITEM_PICKER) {
deselect(ITEM_PICKER);
}
submitButtonEnableToggle(false);
});
}
$(document).ready(initializeSavePDFtoInventoryModal);
})();

View file

@ -537,3 +537,13 @@ label {
}
}
}
#save-PDF-to-inventory-warnings {
margin-top: 30px;
}
.save-PDF-to-inventory-alerts {
.danger {
color: $brand-danger;
}
}

View file

@ -26,6 +26,8 @@ class ReportsController < ApplicationController
before_action :load_vars, only: %i(edit update)
before_action :load_vars_nested, only: BEFORE_ACTION_METHODS
before_action :load_visible_projects, only: %i(index visible_projects)
before_action :load_available_repositories,
only: %i(new edit available_repositories)
before_action :check_manage_permissions, only: BEFORE_ACTION_METHODS
@ -166,18 +168,40 @@ class ReportsController < ApplicationController
# Generation action
# Currently, only .PDF is supported
def generate
content = params[:html]
content = I18n.t('projects.reports.new.no_content_for_PDF_html') if content.blank?
respond_to do |format|
format.pdf do
@html = params[:html]
@html = '<h1>No content</h1>' if @html.blank?
render pdf: 'report',
header: { right: '[page] of [topage]' },
template: 'reports/report.pdf.erb',
disable_javascript: true
render pdf: 'report', header: { right: '[page] of [topage]' },
locals: { content: content },
template: 'reports/report.pdf.erb',
disable_javascript: true
end
end
end
def save_pdf_to_inventory_item
save_pdf_to_inventory_item = ReportActions::SavePdfToInventoryItem.new(
current_user, current_team, save_PDF_params
)
if save_pdf_to_inventory_item.save
render json: {
message: I18n.t(
'projects.reports.new.save_PDF_to_inventory_modal.success_flash'
)
}, status: :ok
else
render json: { message: save_pdf_to_inventory_item.error_messages },
status: :unprocessable_entity
end
rescue ReportActions::RepositoryPermissionError => error
render json: { message: error },
status: :forbidden
rescue Exception => error
render json: { message: error.message },
status: :internal_server_error
end
# Modal for saving the existsing/new report
def save_modal
# Assume user is updating existing report
@ -428,10 +452,15 @@ class ReportsController < ApplicationController
render json: { projects: @visible_projects }, status: :ok
end
def available_repositories
render json: { results: @available_repositories }, status: :ok
end
private
include StringUtility
VisibleProject = Struct.new(:path, :name)
AvailableRepository = Struct.new(:id, :name)
def load_vars
@report = Report.find_by_id(params[:id])
@ -456,7 +485,18 @@ class ReportsController < ApplicationController
.select(:id, :name)
@visible_projects = projects.collect do |project|
VisibleProject.new(new_project_reports_path(project),
ellipsisize(project.name, 75, 50))
ellipsize(project.name, 75, 50))
end
end
def load_available_repositories
repositories = current_team.repositories
.name_like(search_params[:q])
.limit(Constants::SEARCH_LIMIT)
.select(:id, :name)
@available_repositories = repositories.collect do |repository|
AvailableRepository.new(repository.id,
ellipsize(repository.name, 75, 50))
end
end
@ -468,4 +508,11 @@ class ReportsController < ApplicationController
def search_params
params.permit(:q)
end
def save_PDF_params
params.permit(:repository_id,
:respository_column_id,
:repository_item_id,
:html)
end
end

View file

@ -1,11 +1,15 @@
class RepositoryColumnsController < ApplicationController
include InputSanitizeHelper
before_action :load_vars, except: %i(create index create_html)
before_action :load_vars_nested, only: %i(create index create_html)
ACTIONS = %i(create index create_html available_asset_type_columns).freeze
before_action :load_vars,
except: ACTIONS
before_action :load_vars_nested,
only: ACTIONS
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions, except: %i(create index create_html)
before_action :check_manage_permissions,
except: ACTIONS
before_action :load_repository_columns, only: :index
before_action :load_asset_type_columns, only: :available_asset_type_columns
def index; end
@ -139,8 +143,23 @@ class RepositoryColumnsController < ApplicationController
end
end
def available_asset_type_columns
if @asset_columns.empty?
render json: {
no_items: t(
'projects.reports.new.save_PDF_to_inventory_modal.no_columns'
)
}, status: :ok
else
render json: { results: @asset_columns }, status: :ok
end
end
private
include StringUtility
AvailableRepositoryColumn = Struct.new(:id, :name)
def load_vars
@repository = Repository.find_by_id(params[:repository_id])
render_404 unless @repository
@ -158,6 +177,11 @@ class RepositoryColumnsController < ApplicationController
.order(created_at: :desc)
end
def load_asset_type_columns
render_403 unless can_read_team?(@repository.team)
@asset_columns = load_asset_columns(search_params[:q])
end
def check_create_permissions
render_403 unless can_create_repository_columns?(@repository.team)
end
@ -170,6 +194,23 @@ class RepositoryColumnsController < ApplicationController
params.require(:repository_column).permit(:name, :data_type)
end
def search_params
params.permit(:q, :repository_id)
end
def load_asset_columns(query)
@repository.repository_columns
.asset_type.name_like(query)
.limit(Constants::SEARCH_LIMIT)
.select(:id, :name)
.collect do |column|
AvailableRepositoryColumn.new(
column.id,
ellipsize(column.name, 75, 50)
)
end
end
def generate_repository_list_items(item_names)
return true unless @repository_column.data_type == 'RepositoryListValue'
column_items = @repository_column.repository_list_items.size

View file

@ -6,7 +6,11 @@ class RepositoryRowsController < ApplicationController
before_action :load_info_modal_vars, only: :show
before_action :load_vars, only: %i(edit update)
before_action :load_repository,
only: %i(create delete_records index copy_records)
only: %i(create
delete_records
index
copy_records
available_rows)
before_action :check_create_permissions, only: :create
before_action :check_manage_permissions,
only: %i(edit update delete_records copy_records)
@ -297,8 +301,26 @@ class RepositoryRowsController < ApplicationController
}, status: :ok
end
def available_rows
if @repository.repository_rows.empty?
no_items_string =
"#{t('projects.reports.new.save_PDF_to_inventory_modal.no_items')} " \
"#{link_to(t('projects.reports.new.save_PDF_to_inventory_modal.here'),
repository_path(@repository),
data: { 'no-turbolink' => true })}"
render json: { no_items: no_items_string },
status: :ok
else
render json: { results: load_available_rows(search_params[:q]) },
status: :ok
end
end
private
include StringUtility
AvailableRepositoryRow = Struct.new(:id, :name, :has_file_attached)
def load_info_modal_vars
@repository_row = RepositoryRow.eager_load(:created_by, repository: [:team])
.find_by_id(params[:id])
@ -343,6 +365,27 @@ class RepositoryRowsController < ApplicationController
params.permit(selected_rows: []).to_h[:selected_rows]
end
def load_available_rows(query)
@repository.repository_rows
.includes(:repository_cells)
.name_like(search_params[:q])
.limit(Constants::SEARCH_LIMIT)
.select(:id, :name)
.collect do |row|
with_asset_cell = row.repository_cells.where(
'repository_cells.repository_column_id = ?',
search_params[:repository_column_id]
)
AvailableRepositoryRow.new(row.id,
ellipsize(row.name, 75, 50),
with_asset_cell.present?)
end
end
def search_params
params.permit(:q, :repository_id, :repository_column_id)
end
def record_annotation_notification(record, cell, old_text = nil)
table_url = params.fetch(:request_url) { :request_url_must_be_present }
smart_annotation_notification(

View file

@ -1,5 +1,5 @@
module StringUtility
def ellipsisize(
def ellipsize(
string,
minimum_length = Constants::MAX_NAME_TRUNCATION,
edge_length = Constants::MAX_EDGE_LENGTH

View file

@ -57,6 +57,10 @@ class Repository < ApplicationRecord
end
end
def self.name_like(query)
where('repositories.name ILIKE ?', "%#{query}%")
end
def importable_repository_fields
fields = {}
# First and foremost add record name

View file

@ -23,6 +23,11 @@ class RepositoryColumn < ApplicationRecord
around_destroy :update_repository_table_states_with_removed_column
scope :list_type, -> { where(data_type: 'RepositoryListValue') }
scope :asset_type, -> { where(data_type: 'RepositoryAssetValue') }
def self.name_like(query)
where('repository_columns.name ILIKE ?', "%#{query}%")
end
def update_repository_table_states_with_new_column
service = RepositoryTableStateColumnUpdateService.new

View file

@ -26,4 +26,8 @@ class RepositoryRow < ApplicationRecord
where(id: ids).joins(:my_module_repository_rows)
.where('my_module_repository_rows.my_module' => my_module)
end
def self.name_like(query)
where('repository_rows.name ILIKE ?', "%#{query}%")
end
end

View file

@ -0,0 +1,113 @@
# frozen_string_literal: true
module ReportActions
class SavePdfToInventoryItem
def initialize(user, team, params)
@user = user
@team = team
@params = params
load_repository_collaborators
end
def save
file_path = generate_pdf(@params[:html])
asset = create_new_asset(file_path)
cell = fetch_repository_cell
cell.destroy if cell
@new_cell_value = create_new_cell_value(asset)
@new_cell_value.save
end
def error_messages
return I18n.t('general.error') unless @new_cell_value
@new_cell_value.errors.full_messages.join
end
private
include Canaid::Helpers::PermissionsHelper
def load_repository_collaborators
@repository = load_repository
@repository_column = load_repository_column
@repository_item = load_repository_item
unless can_create_repository_rows?(@user, @repository.team)
raise ReportActions::RepositoryPermissionError,
I18n.t('projects.reports.new.no_permissions')
end
end
def generate_pdf(content)
file_path = create_temporary_file
pdf_file = WickedPdf.new.pdf_from_string(
action_view_context.render(
template: 'reports/report.pdf.erb',
locals: { content: prepare_pdf_content(content) }
),
header: { right: '[page] of [topage]' },
disable_javascript: true
)
File.open(file_path, 'wb') do |file|
file << pdf_file
end
file_path
end
def create_new_asset(file_path)
asset = Asset.new(
file: file_path, created_by: @user, last_modified_by: @user, team: @team
)
asset.post_process_file(@team) if asset.save
asset
end
def fetch_repository_cell
RepositoryCell.where(repository_row: @repository_item,
repository_column: @repository_column,
value_type: 'RepositoryAssetValue').first
end
def create_new_cell_value(asset)
RepositoryAssetValue.new(
asset: asset,
created_by: @user,
last_modified_by: @user,
repository_cell_attributes: {
repository_row: @repository_item,
repository_column: @repository_column
}
)
end
def load_repository
Repository.find_by_id(@params[:repository_id])
end
def load_repository_column
RepositoryColumn.find_by_id(@params[:respository_column_id])
end
def load_repository_item
RepositoryRow.find_by_id(@params[:repository_item_id])
end
def action_view_context
av = ActionView::Base.new(ActionController::Base.view_paths, {})
av.extend ReportsHelper # include reports helper methods to view
av.extend InputSanitizeHelper # include input sanitize methods to view
av
end
def create_temporary_file
Tempfile.open(['report', '.pdf'], Rails.root.join('tmp'))
end
def prepare_pdf_content(content)
return content unless content.blank?
I18n.t('projects.reports.new.no_content_for_PDF_html')
end
end
RepositoryPermissionError = Class.new(StandardError)
end

View file

@ -1,5 +1,6 @@
<% provide(:head_title, t("projects.reports.new.head_title", project: h(@project.name)).html_safe) %>
<div id="notifications"></div>
<%= render partial: "reports/new/report_navigation" %>
<div class="content-pane" id="report-new">
@ -72,8 +73,11 @@
</div>
</div>
<%= render partial: 'reports/new/save_PDF_to_inventory_modal' %>
<%= javascript_include_tag "handsontable.full.min" %>
<%= javascript_include_tag("reports/new") %>
<%= javascript_include_tag 'reports/save_pdf_to_inventory' %>
<!-- Libraries for formulas -->
<%= javascript_include_tag "lodash" %>

View file

@ -27,6 +27,12 @@
</div>
<% end %>
<button
onclick="$('#savePDFtoInventory').modal('show')"
class="btn btn-default">
<%=t 'projects.reports.new.save_PDF_to_inventory'%>
</button>
<div class="pull-right">
<%= link_to reports_path, data: { no_turbolink: false }, id: "cancel-report-link", class: "btn btn-default" do %>
<span class="hidden-xs"><%=t "projects.reports.new.nav_close" %></span>

View file

@ -0,0 +1,53 @@
<div
id="savePDFtoInventory"
class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title"><%=t 'projects.reports.new.save_PDF_to_inventory' %></h4>
</div>
<div class="modal-body">
<p><%=t 'projects.reports.new.save_PDF_to_inventory_modal.description_one' %></p>
<br />
<p><%=t 'projects.reports.new.save_PDF_to_inventory_modal.description_two' %></p>
<% if @available_repositories && @available_repositories.length > 0 %>
<label><%=t 'projects.reports.new.save_PDF_to_inventory_modal.inventory' %></label>
<select
id="selectInventory"
class="form-control selectpicker"
data-live-search="true">
</select>
<label><%=t 'projects.reports.new.save_PDF_to_inventory_modal.inventory_column' %></label>
<select
id="selectInventoryColumn"
class="form-control selectpicker"
data-live-search="true"
disabled>
</select>
<div id="save-PDF-to-inventory-column-warnings"></div>
<label><%=t 'projects.reports.new.save_PDF_to_inventory_modal.inventory_item' %></label>
<select
id="selectInventoryItem"
class="form-control selectpicker"
data-live-search="true"
disabled>
</select>
<% else %>
<p><%=t 'projects.reports.new.save_PDF_to_inventory_modal.no_inventories' %></p>
<% end %>
<div class="save-PDF-to-inventory-alerts" id="save-PDF-to-inventory-warnings"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal"><%=t 'general.cancel' %></button>
<button
id="savePDFtoInventorySubmit"
type="button"
class="btn btn-primary"
disabled
><%=t 'general.save' %></button>
</div>
</div>
</div>
</div>

View file

@ -10,7 +10,7 @@
<body class="print-report-body">
<div class="print-report">
<% # Also whitelist <img> and <input type="checkbox"> tags %>
<%= sanitize_input(fix_smart_annotation_image(@html),
<%= sanitize_input(fix_smart_annotation_image(content),
%w(img input),
%w(type disabled checked)) %>
</div>

View file

@ -87,6 +87,7 @@ Rails.application.config.assets.precompile += %w(repository_columns/index.js)
Rails.application.config.assets.precompile += %w(repositories/show.js)
Rails.application.config.assets.precompile += %w(sidebar_toggle.js)
Rails.application.config.assets.precompile += %w(reports/reports_datatable.js)
Rails.application.config.assets.precompile += %w(reports/save_pdf_to_inventory.js)
# Libraries needed for Handsontable formulas
Rails.application.config.assets.precompile += %w(lodash.js)

View file

@ -318,6 +318,7 @@ en:
nav_title: "Report for: "
nav_print: "Print"
nav_pdf: "Download PDF"
save_PDF_to_inventory: "Save PDF to Inventory"
nav_save: "Save"
nav_close: "Cancel"
nav_sort_by: "Sort by"
@ -327,6 +328,21 @@ en:
sidebar_title: "Navigation"
global_sort: "Sorting whole report will undo any custom sorting you might have done. Proceed?"
unsaved_work: "Are you sure you want to leave this page? All unsaved data will be lost."
no_content_for_PDF_html: "<h1>No content</h1>"
no_permissions: "You don't have permissions on that repository"
save_PDF_to_inventory_modal:
description_one: "Here you can save PDF report to an inventory item."
description_two: "First select an inventory, then a column and finally the item within the inventory to which you would like to save the PDF report to. Note that the column has to be of type \"file\"."
inventory: "Select inventory:"
inventory_column: "Select inventory column:"
inventory_item: "Select inventory item:"
no_inventories: "No inventories available!"
success_flash: "Report successfully saved to Inventory item."
asset_present_warning_html: "The selected cell already contains a file. If you would like to replace the file click Save. Replacing the file will have the following consequences: <ul><li>previous file will be permanently deleted;</li><li>new file will be added to the Inventory item.</li></ul>"
no_items: "Selected Inventory does not contain any items yet. Add the first item"
here: "here"
no_columns: "You do not have any Inventories with File columns. Add a File column to existing Inventory or create a new Inventory."
nothing_selected: "Nothing selected"
elements:
modals:
project_contents:
@ -1915,6 +1931,7 @@ en:
length_too_short: "Search query is too short (minimum is %{min_length} characters)"
busy: "The server is still processing your request. If you leave this page, the changes will be lost! Are you sure you want to continue?"
no_name: "(no name)"
error: "An error has occurred, please try again later."
filter: "Filter:"
api:

View file

@ -193,6 +193,14 @@ Rails.application.routes.draw do
get 'reports/datatable', to: 'reports#datatable'
post 'reports/visible_projects', to: 'reports#visible_projects',
defaults: { format: 'json' }
post 'reports/available_repositories', to: 'reports#available_repositories',
defaults: { format: 'json' }
post 'reports/save_pdf_to_inventory_item',
to: 'reports#save_pdf_to_inventory_item',
defaults: { format: 'json' }
post 'available_asset_type_columns',
to: 'repository_columns#available_asset_type_columns',
defaults: { format: 'json' }
post 'reports/destroy', to: 'reports#destroy'
resources :projects, except: [:new, :destroy] do
@ -491,6 +499,9 @@ Rails.application.routes.draw do
end
end
post 'available_rows', to: 'repository_rows#available_rows',
defaults: { format: 'json' }
post 'repository_list_items', to: 'repository_list_items#search',
defaults: { format: 'json' }