Merge pull request #3218 from aignatov-bio/ai-sci-5548-new-render-index-page-layout

New report index page layout, new pdf and docx columns [SCI-5548][SCI-5549][SCI-5550]
This commit is contained in:
Alex Kriuchykhin 2021-03-17 13:36:54 +01:00 committed by GitHub
commit 6393337bc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 304 additions and 60 deletions

View file

@ -1,3 +1,5 @@
/* global I18n DataTableHelpers */
(function(global) { (function(global) {
'use strict'; 'use strict';
@ -91,6 +93,54 @@
</div>`; </div>`;
} }
function renderDocxFile(data) {
if (data.error) {
return `<span class="processing-error">
<i class="fas fa-exclamation-triangle"></i>
${I18n.t('projects.reports.index.error')}
</span>`;
}
if (data.processing) {
return `<span class="processing docx">
${I18n.t('projects.reports.index.generating')}
</span>`;
}
if (data.file) {
return `<a href="${data.file}">
<i class="fas fa-file-word"></i>
${I18n.t('projects.reports.index.docx')}
</a>`;
}
return `<a href="#" class="generate-docx">${I18n.t('projects.reports.index.generate')}</a>`;
}
function renderPdfFile(data) {
if (data.error) {
return `<span class="processing-error">
<i class="fas fa-exclamation-triangle"></i>
${I18n.t('projects.reports.index.error')}
</span>`;
}
if (data.processing) {
return `<span class="processing pdf">
${I18n.t('projects.reports.index.generating')}
</span>`;
}
if (data.file) {
return `<a href="${data.file}">
<i class="fas fa-file-pdf"></i>
${I18n.t('projects.reports.index.pdf')}
</a>`;
}
return '';
}
function appendEditPathToRow(row, data) { function appendEditPathToRow(row, data) {
$(row).addClass('report-row') $(row).addClass('report-row')
.attr('data-edit-path', data['edit']) .attr('data-edit-path', data['edit'])
@ -115,17 +165,38 @@
} }
function updateButtons() { function updateButtons() {
var editReportButton = $('#edit-report-btn');
var deleteReportsButton = $('#delete-reports-btn');
if (CHECKED_REPORTS.length === 0) { if (CHECKED_REPORTS.length === 0) {
editReportButton.addClass('disabled hidden'); $('.single-object-action, .multiple-object-action').addClass('disabled hidden');
deleteReportsButton.addClass('disabled hidden');
} else if (CHECKED_REPORTS.length === 1) { } else if (CHECKED_REPORTS.length === 1) {
editReportButton.removeClass('disabled hidden'); $('.single-object-action, .multiple-object-action').removeClass('disabled hidden');
deleteReportsButton.removeClass('disabled hidden');
let $row = $(`.report-row[data-id=${CHECKED_REPORTS[0]}]`);
let pdfProcessing = $row.has('.processing.pdf').length > 0;
let docxProcessing = $row.has('.processing.docx').length > 0;
let docxGenerate = $row.has('.generate-docx').length > 0;
if (pdfProcessing) {
$('#updatePdf').addClass('disabled');
} else {
$('#updatePdf').removeClass('disabled');
}
if (docxGenerate) {
$('#requestDocx').removeClass('hidden');
$('#updateDocx').addClass('hidden');
} else {
$('#requestDocx').addClass('hidden');
$('#updateDocx').removeClass('hidden');
if (docxProcessing) {
$('#updateDocx').addClass('disabled');
} else {
$('#updateDocx').removeClass('disabled');
}
}
} else { } else {
editReportButton.removeClass('hidden').addClass('disabled'); $('.single-object-action').removeClass('hidden').addClass('disabled');
deleteReportsButton.removeClass('disabled hidden'); $('.multiple-object-action').removeClass('disabled hidden');
} }
} }
@ -134,27 +205,46 @@
function initDatatable() { function initDatatable() {
var $table = $('#reports-table') var $table = $('#reports-table')
DATATABLE = $table.dataTable({ DATATABLE = $table.dataTable({
'order': [[2, 'desc']], dom: "Rt<'pagination-row hidden'<'pagination-info'li><'pagination-actions'p>>",
'processing': true, order: [[2, 'desc']],
'serverSide': true, sScrollX: '100%',
'ajax': $table.data('source'), sScrollXInner: '100%',
'pagingType': 'simple_numbers', processing: true,
'colReorder': { serverSide: true,
'fixedColumnsLeft': 1000000 // Disable reordering ajax: $table.data('source'),
pagingType: 'simple_numbers',
colReorder: {
fixedColumnsLeft: 1000000 // Disable reordering
}, },
'columnDefs': [{ columnDefs: [{
'targets': 0, targets: 0,
'searchable': false, searchable: false,
'orderable': false, orderable: false,
'className': 'dt-body-center', className: 'dt-body-center',
'sWidth': '1%', sWidth: '1%',
'render': renderCheckboxHTML render: renderCheckboxHTML
},
{
targets: 3,
searchable: false,
sWidth: '60',
render: renderPdfFile
},
{
targets: 4,
searchable: false,
sWidth: '60',
render: renderDocxFile
}], }],
'oLanguage': { oLanguage: {
'sSearch': I18n.t('general.filter') sSearch: I18n.t('general.filter')
}, },
'fnDrawCallback': tableDrowCallback, fnDrawCallback: tableDrowCallback,
'createdRow': appendEditPathToRow createdRow: appendEditPathToRow,
fnInitComplete: function() {
DataTableHelpers.initLengthApearance($table.closest('.dataTables_wrapper'));
$('.pagination-row').removeClass('hidden');
}
}); });
} }

View file

@ -0,0 +1,63 @@
// scss-lint:disable SelectorDepth NestingDepth IdSelector SelectorFormat
.reports-index {
.report-actions-dropdown {
display: inline-block;
float: left;
position: relative;
.report-actions-menu {
width: 200px;
li {
padding: 0;
}
a {
padding: .5em 1em;
}
}
}
}
.reports-datatable {
height: calc(100vh - var(--navbar-height) - var(--content-header-size));
#reports-table_wrapper {
display: flex;
flex-direction: column;
height: 100%;
.dataTables_scroll {
display: flex;
flex-direction: column;
flex-grow: 1;
height: calc(100% - var(--datatable-pagination-row));
.dataTables_scrollHead {
flex-shrink: 0;
}
}
.pagination-row {
flex-shrink: 0;
}
}
.report-row {
.processing-error {
color: $brand-danger;
}
.generate-docx {
display: none;
}
&:hover {
.generate-docx {
display: initial;
}
}
}
}

View file

@ -2,7 +2,7 @@
// scss-lint:disable NestingDepth QualifyingElement // scss-lint:disable NestingDepth QualifyingElement
.dataTables_wrapper { .dataTables_wrapper {
--datatable-pagination-row: 68px;
.main-actions { .main-actions {
align-items: center; align-items: center;
display: flex; display: flex;
@ -24,7 +24,7 @@
align-items: center; align-items: center;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
min-height: 68px; min-height: var(--datatable-pagination-row);
width: 100%; width: 100%;
.pagination-info, .pagination-info,

View file

@ -2,10 +2,13 @@
class ReportDatatable < CustomDatatable class ReportDatatable < CustomDatatable
include InputSanitizeHelper include InputSanitizeHelper
include Rails.application.routes.url_helpers
TABLE_COLUMNS = %w( TABLE_COLUMNS = %w(
Report.project_name Report.project_name
Report.name Report.name
Report.pdf_file
Report.docx_file
Report.created_by Report.created_by
Report.modified_by Report.modified_by
Report.created_at Report.created_at
@ -27,6 +30,22 @@ class ReportDatatable < CustomDatatable
@searchable_columns ||= TABLE_COLUMNS @searchable_columns ||= TABLE_COLUMNS
end end
def sort_records(records)
case sort_column(order_params)
when 'reports.docx_file'
records.left_joins(:docx_file_attachment)
.order(active_storage_attachments: sort_direction(order_params))
.order(docx_file_processing: sort_direction(order_params) == 'ASC' ? :desc : :asc)
when 'reports.pdf_file'
records.left_joins(:pdf_file_attachment)
.order(active_storage_attachments: sort_direction(order_params))
.order(pdf_file_processing: sort_direction(order_params) == 'ASC' ? :desc : :asc)
else
sort_by = "#{sort_column(order_params)} #{sort_direction(order_params)}"
records.order(sort_by)
end
end
private private
def data def data
@ -35,15 +54,35 @@ class ReportDatatable < CustomDatatable
'0' => record.id, '0' => record.id,
'1' => sanitize_input(record.project_name), '1' => sanitize_input(record.project_name),
'2' => sanitize_input(record.name), '2' => sanitize_input(record.name),
'3' => sanitize_input(record.created_by), '3' => pdf_file(record),
'4' => sanitize_input(record.modified_by), '4' => docx_file(record),
'5' => I18n.l(record.created_at, format: :full), '5' => sanitize_input(record.created_by),
'6' => I18n.l(record.updated_at, format: :full), '6' => sanitize_input(record.modified_by),
'7' => I18n.l(record.created_at, format: :full),
'8' => I18n.l(record.updated_at, format: :full),
'edit' => edit_project_report_path(record.project_id, record.id) 'edit' => edit_project_report_path(record.project_id, record.id)
} }
end end
end end
def docx_file(report)
docx = rails_blob_path(report.docx_file, disposition: 'attachment') if report.docx_file.attached?
{
processing: report.docx_file_processing,
file: docx,
error: false
}
end
def pdf_file(report)
pdf = rails_blob_path(report.pdf_file, disposition: 'attachment') if report.pdf_file.attached?
{
processing: report.pdf_file_processing,
file: pdf,
error: false
}
end
def get_raw_records def get_raw_records
res = @reports.joins(:project) res = @reports.joins(:project)
.joins( .joins(

View file

@ -0,0 +1,10 @@
<div class="content-header sticky-header">
<div class="title-row">
<h1>
<%= t('projects.reports.index.head_title') %>
</h1>
</div>
<div id="toolbarWrapper" class="toolbar-row">
<%= render partial: 'reports/index_toolbar' %>
</div>
</div>

View file

@ -0,0 +1,49 @@
<% if can_manage_reports?(current_team) %>
<div class="sci-btn-group">
<%= link_to '#', remote: true, class: 'btn btn-primary', id: 'new-report-btn' do %>
<span class="fas fa-plus" aria-hidden="true"></span>
<span class="hidden-xs"><%= t("projects.reports.index.new") %></span>
<% end %>
<div class="report-actions-dropdown sci-dropdown">
<button class="btn btn-light dropdown-toggle single-object-action disabled hidden" type="button" id="reportMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fas fa-file"></i>
<%= t("projects.reports.index.report_button") %>
<span class="caret pull-right"></span>
</button>
<ul id="reportMenuDropdown" class="dropdown-menu report-actions-menu" aria-labelledby="reportMenu">
<li>
<%= link_to '#', remote: true, id: 'updatePdf' do %>
<i class="fas fa-file-pdf"></i>
<%= t("projects.reports.index.update_pdf") %>
<% end %>
</li>
<li>
<%= link_to '#', remote: true, id: 'savePdfToInventory' do %>
<i class="fas fa-save"></i>
<%= t("projects.reports.index.save_pdf_to_inventory") %>
<% end %>
</li>
<li>
<%= link_to '#', remote: true, id: 'requestDocx' do %>
<i class="fas fa-file-word"></i>
<%= t("projects.reports.index.request_docx") %>
<% end %>
</li>
<li>
<%= link_to '#', remote: true, id: 'updateDocx' do %>
<i class="fas fa-file-word"></i>
<%= t("projects.reports.index.update_docx") %>
<% end %>
</li>
</ul>
</div>
<%= link_to "", remote: true, class: "btn btn-light disabled hidden single-object-action", id: "edit-report-btn" do %>
<span class="fas fa-pencil-alt" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.reports.index.edit" %></span>
<% end %>
<%= link_to "", remote: true, class: "btn btn-light disabled hidden multiple-object-action", id: "delete-reports-btn" do %>
<span class="fas fa-times" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.reports.index.delete" %></span>
<% end %>
</div>
<% end %>

View file

@ -2,30 +2,11 @@
<meta name="turbolinks-cache-control" content="no-cache"> <meta name="turbolinks-cache-control" content="no-cache">
<% end %> <% end %>
<% provide(:head_title, t('projects.reports.index.head_title').html_safe) %>
<%= stylesheet_link_tag 'datatables' %> <%= stylesheet_link_tag 'datatables' %>
<div class="content-pane"> <div class="content-pane flexible reports-index">
<%= render partial: 'reports/index_header' %>
<div id="content-reports-index"> <div id="content-reports-index">
<div class="row">
<div class="col-md-12">
<% if can_manage_reports?(current_team) %>
<%= link_to '#', remote: true, class: 'btn btn-primary', id: 'new-report-btn' do %>
<span class="fas fa-plus" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.reports.index.new" %></span>
<% end %>
<%= link_to "", remote: true, class: "btn btn-light disabled hidden", id: "edit-report-btn" do %>
<span class="fas fa-pencil-alt" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.reports.index.edit" %></span>
<% end %>
<%= link_to "", remote: true, class: "btn btn-light disabled hidden", id: "delete-reports-btn" do %>
<span class="fas fa-times" aria-hidden="true"></span>
<span class="hidden-xs"><%=t "projects.reports.index.delete" %></span>
<% end %>
<% end %>
</div>
</div>
<br />
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="reports-datatable"> <div class="reports-datatable">
@ -40,12 +21,14 @@
<span class="sci-checkbox-label"></span> <span class="sci-checkbox-label"></span>
</div> </div>
</th> </th>
<th id="project-name"><%=t 'projects.reports.index.thead_project_name' %></th> <th id="project-name"><%= t('projects.reports.index.thead_project_name') %></th>
<th id="report-name"><%=t 'projects.reports.index.thead_name' %></th> <th id="report-name"><%= t('projects.reports.index.thead_name') %></th>
<th id="report-created-by"><%=t 'projects.reports.index.thead_created_by' %></th> <th id="report-pdf"><%= t('projects.reports.index.pdf') %></th>
<th id="report-last-modified-by"><%=t 'projects.reports.index.thead_last_modified_by' %></th> <th id="report-docx"><%= t('projects.reports.index.docx') %></th>
<th id="report-created-at"><%=t 'projects.reports.index.thead_created_at' %></th> <th id="report-created-by"><%= t('projects.reports.index.thead_created_by') %></th>
<th id="report-updated-at"><%=t 'projects.reports.index.thead_updated_at' %></th> <th id="report-last-modified-by"><%= t('projects.reports.index.thead_last_modified_by') %></th>
<th id="report-created-at"><%= t('projects.reports.index.thead_created_at') %></th>
<th id="report-updated-at"><%= t('projects.reports.index.thead_updated_at') %></th>
</tr> </tr>
</thead> </thead>
<tbody></tbody> <tbody></tbody>

View file

@ -490,8 +490,13 @@ en:
reports: reports:
print_title: "%{project} | Report" print_title: "%{project} | Report"
index: index:
head_title: " Reports" head_title: "Reports"
new: "New report" new: "New report"
report_button: "Report"
update_pdf: "Update PDF"
save_pdf_to_inventory: "Save PDF to Inventory"
request_docx: "Request DOCX"
update_docx: "Update DOCX"
edit: "Edit" edit: "Edit"
delete: "Delete" delete: "Delete"
deleted: "(Deleted)" deleted: "(Deleted)"
@ -502,6 +507,11 @@ en:
thead_created_at: "Created at" thead_created_at: "Created at"
thead_updated_at: "Last updated at" thead_updated_at: "Last updated at"
no_reports: "No reports!" no_reports: "No reports!"
pdf: "PDF"
docx: "DOCX"
error: "Error"
generating: "Generating"
generate: "Generate"
modal_new: modal_new:
projects: "Projects" projects: "Projects"
head_title: "Create new report" head_title: "Create new report"