Browse Source

Merge pull request #55 from lexintegritastech/improve-main-ui

Improve main UI
pull/56/head
Alexander D. Bondoc 4 years ago committed by GitHub
parent
commit
62a46f3053
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/components/document_advanced_search_component.rb
  2. 5
      app/components/document_advanced_search_component/document_advanced_search_component.html.erb
  3. 32
      app/components/document_doctrine_index_component/document_doctrine_index_component.html.erb
  4. 47
      app/components/reports_search_results_component.rb
  5. 40
      app/components/reports_search_results_component/reports_search_results_component.html.erb
  6. 3
      app/components/sidenav_component/sidenav_component.html.erb
  7. 4
      app/controllers/concerns/doctrine_search.rb
  8. 17
      app/controllers/reports_controller.rb
  9. 2
      app/javascript/controllers/application_controller.js
  10. 148
      app/javascript/controllers/document_controller.js
  11. 17
      app/javascript/controllers/reports_controller.js
  12. 2
      app/javascript/controllers/subjects_controller.js
  13. 25
      app/javascript/packs/application.js
  14. 145
      app/javascript/packs/application/footnotes.js
  15. 2
      app/javascript/src/application.scss
  16. 10
      app/reflexes/reports_reflex.rb
  17. 12
      app/views/reports/_search_results_table.html.erb
  18. 45
      app/views/reports/index.html.erb
  19. 15
      app/views/shared/_reports_pagination.html.erb
  20. 2
      config/routes.rb
  21. 4
      package.json
  22. 33
      yarn.lock

4
app/components/document_advanced_search_component.rb

@ -4,4 +4,8 @@ class DocumentAdvancedSearchComponent < BaseComponent
def initialize(current_user:, opts: {})
@opts = opts
end
def years
(1901..Time.zone.today.year).entries.reverse
end
end

5
app/components/document_advanced_search_component/document_advanced_search_component.html.erb

@ -13,6 +13,11 @@
<%= text_field_tag :title, params[:short_title], class: "form-control" %>
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-white">Year</label>
<%= select_tag :year, options_for_select(years, params[:year]), class: "form-select" %>
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-white">Citation Finder</label>
<%= text_field_tag :citation_finder, params[:citation_finder], class: "form-control" %>

32
app/components/document_doctrine_index_component/document_doctrine_index_component.html.erb

@ -1,27 +1,29 @@
<div class="row-flex m-3 mt-0 doctrine-content-body clickable-link" href="<%= jurisprudence.present? ? document_doctrine_path(jurisprudence.id, id) : doctrine_path(id)%>">
<% if opts[:is_subjects_index].blank? %>
<% if opts[:is_doctrines_index].present? && opts[:subject_ids].reject(&:blank?).present? %>
<h5 style="color: darkred;"> <%= subjects.where(id: opts[:subject_ids].map(&:to_i)).map(&:lineage_name).join(" ") %> </h5>
<% elsif subjects.present? %>
<% subjects.each do |subject| %>
<h5 style="color: darkred;"> <%= subject.lineage_name %> </h5>
<% if opts[:is_doctrines_index].blank? %>
<% if opts[:is_subjects_index].blank? %>
<% if opts[:is_doctrines_index].present? && opts[:subject_ids].reject(&:blank?).present? %>
<h5 style="color: darkred;"> <%= subjects.where(id: opts[:subject_ids].map(&:to_i)).map(&:lineage_name).join(" ") %> </h5>
<% elsif subjects.present? %>
<% subjects.each do |subject| %>
<h5 style="color: darkred;"> <%= subject.lineage_name %> </h5>
<% end %>
<% else %>
<h5> (No Subjects Provided) </h5>
<% end %>
<% else %>
<h5> (No Subjects Provided) </h5>
<% end %>
<% end %>
<div class="container-sm <%= opts[:is_subjects_index].present? ? 'm-0 ps-0' : '' %>">
<p class="mb-0"> <%= raw content.html_safe %> </p>
<div class="container-sm ms-3">
<% annotations.each do |annotation| %>
<% if opts[:is_doctrines_index].present? %>
<% document_title = annotation.doctrine.document.short_title || annotation.doctrine.document.title %>
<% date_or_year = annotation.doctrine.document.docdate.present? ? annotation.doctrine.document.docdate.to_date.strftime("%B %d, %Y") : annotation.document.year %>
<span> <%= [document_title, annotation.document.reference_number, date_or_year].join(", ") %> </span>
<% end %>
<div class="container-fluid p-0">
<% if opts[:is_doctrines_index].present? %>
<% document_title = jurisprudence.short_title || jurisprudence.title %>
<% date_or_year = jurisprudence.docdate.present? ? jurisprudence.docdate.to_date.strftime("%B %d, %Y") : jurisprudence.year %>
<h5 style="color: darkred;"> <%= [document_title, jurisprudence.reference_number, date_or_year].join(", ") %> </h5>
<% end %>
<% annotations.each do |annotation| %>
<p class="mb-0 ms-3">
<% annotated_documents_title = [] %>
<% annotation.documents.each do |annotated_document| %>

47
app/components/reports_search_results_component.rb

@ -0,0 +1,47 @@
class ReportsSearchResultsComponent < BaseComponent
with_collection_parameter :search_result
attr_reader :search_result, :opts
def initialize(search_result:, current_user:, opts: {})
@search_result = search_result
@opts = opts
end
delegate :id, to: :search_result
delegate :headnote, to: :search_result
delegate :subject_ids, to: :search_result
delegate :content, to: :search_result
delegate :annotations, to: :search_result
delegate :subjects, to: :search_result
delegate :doctrine_jurisprudences, to: :search_result
def annotation_form_url
doctrine_annotations_path(doctrine_id: id)
end
def subject_names
"(No Subjects Provided)"
end
def jurisprudence
return nil if doctrine_jurisprudences.blank?
doctrine_jurisprudences.first.jurisprudence
end
def document_title(annotation)
return annotation.document.short_title if annotation.document.short_title.present?
annotation.document.title
end
def date_or_year(annotation)
return annotation.document.docdate.to_date.strftime("%B %d, %Y") if annotation.document.docdate.present?
annotation.document.year
end
def render?
opts[:is_render].present?
end
end

40
app/components/reports_search_results_component/reports_search_results_component.html.erb

@ -0,0 +1,40 @@
<div class="row-flex m-3 mt-0 doctrine-content-body clickable-link" href="<%= jurisprudence.present? ? document_doctrine_path(jurisprudence.id, id) : doctrine_path(id)%>">
<div class="container-sm <%= opts[:is_subjects_index].present? ? 'm-0 ps-0' : '' %>">
<p class="mb-0"> <%= raw content.html_safe %> </p>
<div class="container-fluid p-0">
<% document_title = jurisprudence.short_title || jurisprudence.title %>
<% date_or_year = jurisprudence.docdate.present? ? jurisprudence.docdate.strftime : jurisprudence.year %>
<h5 style="color: darkred;"> <%= [document_title, jurisprudence.reference_number, date_or_year].join(", ") %> </h5>
<% annotations.each do |annotation| %>
<p class="mb-0 ms-5">
<% annotated_documents_title = [] %>
<% annotation.documents.each do |annotated_document| %>
<% ad_title = annotated_document.short_title || annotated_document.title %>
<% ad_date_or_year = annotated_document.docdate.present? ? annotated_document.docdate.strftime("%B %d, %Y") : annotated_document.year %>
<% annotated_documents_title << [" citing #{ad_title}", annotated_document.reference_number, ad_date_or_year].join(", ") %>
<% end %>
<strong> <%= "#{annotation.annomarks.map { |annomark| "(#{annomark.code})" }.join(" ")}" %> </strong>
<%= raw [document_title(annotation), annotation.document.reference_number, date_or_year(annotation), annotation.phil_rep, annotated_documents_title].reject(&:blank?).join(', ') %>
</p>
<% if annotation.editor_notes.present? %>
<div class="row ms-5">
<div class="col-sm-2 p-0" style="width: 105px;">
<span> Editors Note: </span>
</div>
<div class="col-sm-10 ps-0">
<%= raw annotation.editor_notes %>
</div>
</div>
<% end %>
<% end %>
</div>
</div>
<hr/>
</div>

3
app/components/sidenav_component/sidenav_component.html.erb

@ -107,6 +107,9 @@
<li class="nav-item p-2">
<%= link_to '<i class="fas fa-cog me-2"></i>Settings'.html_safe, subject_indexes_path, class: "nav-link" %>
</li>
<li class="nav-item p-2">
<%= link_to '<i class="fa-solid fa-file-lines"></i>Reports'.html_safe, reports_path, class: "nav-link" %>
</li>
<li class="nav-item p-2 active-red">
<%= link_to '<i class="fas fa-sign-out-alt"></i> Sign Out'.html_safe, destroy_user_session_path, class:" text-white nav-link" %>
</li>

4
app/controllers/concerns/doctrine_search.rb

@ -5,9 +5,9 @@ module DoctrineSearch
search = ::Doctrine.search do
fulltext search_params[:q], fields: fulltext_fields if search_params[:q].present?
with(:subject_ids).any_of(search_params[:subject_ids]) if search_params[:subject_ids].present?
with(:subject_ids).any_of(search_params[:subject_ids].map(&:to_i)) if search_params[:subject_ids].present?
with(:user_ids).any_of(search_params[:user_ids]) if search_params[:user_ids].present?
with(:user_ids).any_of(search_params[:user_ids].map(&:to_i)) if search_params[:user_ids].present?
if search_params[:created_at].present?
with(:created_at).between(Date.parse(search_params[:created_at])..Time.zone.today.to_date)

17
app/controllers/reports_controller.rb

@ -0,0 +1,17 @@
class ReportsController < ApplicationController
include DoctrineSearch
def index
authorize! :display, Doctrine
search = doctrine_search(search_params)
@results = search.results
@users = User.all
end
private
def search_params
params.permit(:created_at, :q, :page, :per_page, exclude_ids: [], subject_ids: [], user_ids: [])
end
end

2
app/javascript/controllers/application_controller.js

@ -5,8 +5,10 @@ import { end } from '@popperjs/core'
require("selectize/dist/js/selectize.min");
require("selectize/dist/css/selectize");
require("bootstrap/dist/js/bootstrap")
import Selectize from "selectize";
import Bootstrap from 'bootstrap';
/* This is your ApplicationController.
* All StimulusReflex controllers should inherit from this class.

148
app/javascript/controllers/document_controller.js

@ -4,154 +4,6 @@ export default class extends ApplicationController {
connect () {
super.connect()
$.fn.footnotes = function () {
var a, b, c;
a = $(this), b = a.find('a[href^="#footnote"]')
c = a.find('p>span, p>a[href^="#fn"]>span').filter(function() {
return ($(this).css('color') == 'rgb(255, 0, 0)')
})
b.each(function(){
var $this = $(this);
if($this.anchor_check()) {
if(!$this.parent('span.footnote-x').length) {
// Wrap the anchor with 'footnote-x'
$this.wrap('<span class="footnote-x"></span>')
}
}
})
// Append index to every anchor
b = a.find('span.footnote-x a[href^="#footnote"]')
b.each(function() {
var $this = $(this);
var $matches = $($this.prop("tagName") + '#' + $this.attr("id") + ':not([data-index])')
var index = 0;
$matches.each(function(){
$(this).attr('id', $(this).attr('id') + '_' + index)
$(this).attr('name', $(this).attr('name') + '_' + index)
$(this).attr('href', $(this).attr('href') + '_' + index)
$(this).attr('data-index', index)
index = index + 1;
})
})
c.each(function(){
var $this = $(this)
$this.footnote_check()
})
c = a.find('a[href^="#fn"]')
c.each(function() {
var $this = $(this);
var $matches = $($this.prop("tagName") + '#' + $this.attr("id") + ':not([data-index])')
var index = 0;
$matches.each(function(){
var self, parent
self = $(this), parent = self.parent()
self.closest('p').find('#cdasiatab').detach()
self.attr('id', self.attr('id') + '_' + index)
self.attr('name', self.attr('name') + '_' + index)
self.attr('href', self.attr('href') + '_' + index)
self.attr('data-index', index)
parent.is('a') ? parent.replaceWith(self) : parent.closest('a').replaceWith(parent) // Remove parent its parent 'a' tag
index = index + 1;
})
})
}
$.fn.anchor_check = function () {
var a, b, c, d;
a = $(this), b = a.attr('href'), c = $.trim(a.text())
if (!$.isNumeric($.trim(c)) && c != '*' && c != 'n') { return false }
if($.trim(b) && a.is('[href^="#footnote"]')){
// Check whether href, name and text is valid
var a_href_id = a.attr('href').substring(9) // Get only the value after '#footnote'
var a_name_id = a.attr('name') ? a.attr('name').substring(2) : a_href_id // Get only the value after 'fn' if name attr is present if not return a_href_id
var a_id = a.attr('id') ? a.attr('id').substring(2) : ''
if(a_href_id != a_name_id || a_href_id != c || a_id != c || a_name_id != c){
a.attr('href', '#footnote' + c), a.attr('id', 'fn' + c), a.attr('name', 'fn' + c)
}
} else {
// If anchor to footnote is invalid by href=#footnote*** or no href
// the text inside the 'a' tag will use as a reference
a.attr('href', '#footnote' + c), a.attr('id', 'fn' + c), a.attr('name', 'fn' + c)
}
return true;
}
$.fn.footnote_check = function () {
var a, b, c, d;
a = $(this), d = null
if (a.find('a:not([href^="#footnote"])').size()) {
a.find('a').each(function(){
b = $.trim($(this).text()), c = b.match(/([\*]{1,3}|[\d]{1,3})/)
if (c!= null) {
c = c[0]
d = $(document.createElement('a'))
d.text(b), d.attr('href', '#fn' + c), d.attr('id', 'footnote' + c), d.attr('name', 'footnote' + c), d.addClass('m-r-lg'), d.css('color', 'red')
a.html(''), a.append(d)
return true;
}
})
if (d=null) {
return false
}
} else if (!a.find('a').size()) {
b = $.trim(a.text()), c = b.match(/([\*]{1,3}|[\d]{1,3})/)
if(c!= null){
c = c[0]
d = $(document.createElement('a'))
d.text(b), d.attr('href', '#fn' + c), d.attr('id', 'footnote' + c), d.attr('name', 'footnote' + c), d.addClass('m-r-lg'), d.css('color', 'red')
a.html(''), a.append(d)
}else{
return false
}
}
return true
}
$.fn.footnote = function () {
var a = $(this)
var b, c, d;
b = $(a.attr('href'))
if (b.length<=0 && a.data('index')>0) {
var a_id = a.attr('id').substring(0, a.attr('id').indexOf('_'))
var a_like = $('a[href^="#footnote"][id^="' + a_id + '"]')
var a_found = false;
a_like.each(function() {
if(!a_found){ b = $($(this).attr('href')) }
a_found = b.length > 0
})
}
if (b.length>0) {
c = b.closest('p')
d = c.footnote_text(b.parent('span') || b), d = d.substring(0,499) + (d.length > 500 ? '...' : '')
a.attr('data-original-title', d), a.attr('data-toggle', 'tooltip')
a.tooltip({title: d}), a.tooltip('show')
}
return a
}
$.fn.footnote_text = function (except) {
var a = '';
$(this).children().not(except).each(function() {
// Check first if the current select element not equal to except
var self = $(this)
a += self.text()
})
return a;
}
}
search () {

17
app/javascript/controllers/reports_controller.js

@ -0,0 +1,17 @@
import ApplicationController from './application_controller'
export default class extends ApplicationController {
static targets = ["q", "headnote", "date_created"]
connect () {
super.connect()
}
search () {
var $search_box = $('.advanced-search-box'),
search_params = { q: this.qTarget.value, headnote: this.headnoteTarget.value,
subject_ids: $search_box.find("select[name='subject_ids[]']").val(),
user_ids: $search_box.find("select[name='user_ids[]']").val() }
this.stimulate("ReportsReflex#render_search_results", search_params)
}
}

2
app/javascript/controllers/subjects_controller.js

@ -5,7 +5,7 @@ export default class extends ApplicationController {
}
loadSubjectsAccordion () {
var $this = this, params = { per_page: 200 }, parent_id = $this.element.dataset["subjectParentId"],
var $this = this, params = { per_page: 10000 }, parent_id = $this.element.dataset["subjectParentId"],
opts = { parent_accordion_id: $this.element.dataset["accordionId"], accordionTarget: $this.element.dataset["accordionTarget"],
accordionFor: $this.element.dataset["accordionFor"] }

25
app/javascript/packs/application.js

@ -19,6 +19,7 @@ import "chosen-js";
import 'trix/dist/trix.css';
import 'trix/dist/trix.js';
import "cable_ready";
import "flatpickr/dist/flatpickr";
window.jQuery = $;
window.$ = $;
@ -50,7 +51,31 @@ $(document).on("ready turbolinks:load", function () {
window.open($href);
}
})
var default_config = { altFormat: "m/d/Y", altInput: true, enableTime: false, dateFormat: "Y-m-d", isMobile: true };
$('.default-flatpickr').flatpickr(default_config);
if ($.fn.footnotes) {
$('#documentTabContent').footnotes()
}
$(document).on('click', 'a[href="#footnotes"]', function(event){
event.preventDefault();
$(this).each(function(){
var a, b, c, d;
a = $(this), b = a.attr('href'), c = a.text(), d = '#footnote' + c
a.attr('href', d), a.attr('id', 'fn' + c)
a.trigger('click')
})
}).on('click', 'a[href^="#footnote"], a[href^="#fn"]', function(event){
var a, b;
a = $(this), b = $(a.attr('href'))
if(b.length<=0)return
event.preventDefault()
$(document).wrap('<span class="footnote-x"></span>')
})
});
import "channels"
import "controllers"
import "./application/footnotes"

145
app/javascript/packs/application/footnotes.js

@ -0,0 +1,145 @@
(function ($) {
'use strict';
$.fn.footnotes = function () {
var a, b, c;
a = $(this), b = a.find('a[href^="#footnote"]')
c = a.find('p>span, p>a[href^="#fn"]>span').filter(function() {
return ($(this).css('color') == 'rgb(255, 0, 0)')
})
b.each(function(){
var $this = $(this);
console.log($this)
if($this.anchor_check()){
if(!$this.parent('span.footnote-x').length){
// Wrap the anchor with 'footnote-x'
$this.wrap('<span class="footnote-x"></span>')
}
}
})
// Append index to every anchor
b = a.find('span.footnote-x a[href^="#footnote"]')
b.each(function(){
var $this = $(this);
var $matches = $($this.prop("tagName") + '#' + $this.attr("id") + ':not([data-index])')
var index = 0;
$matches.each(function(){
$(this).attr('id', $(this).attr('id') + '_' + index)
$(this).attr('name', $(this).attr('name') + '_' + index)
$(this).attr('href', $(this).attr('href') + '_' + index)
$(this).attr('data-index', index)
index = index + 1;
})
})
c.each(function(){
var $this = $(this)
$this.footnote_check()
})
c = a.find('a[href^="#fn"]')
c.each(function(){
var $this = $(this);
var $matches = $($this.prop("tagName") + '#' + $this.attr("id") + ':not([data-index])')
var index = 0;
$matches.each(function(){
var self, parent
self = $(this), parent = self.parent()
self.closest('p').find('#cdasiatab').detach()
self.attr('id', self.attr('id') + '_' + index)
self.attr('name', self.attr('name') + '_' + index)
self.attr('href', self.attr('href') + '_' + index)
self.attr('data-index', index)
parent.is('a') ? parent.replaceWith(self) : parent.closest('a').replaceWith(parent) // Remove parent its parent 'a' tag
index = index + 1;
})
})
}
$.fn.anchor_check = function () {
var a, b, c, d;
a = $(this), b = a.attr('href'), c = $.trim(a.text())
if(!$.isNumeric($.trim(c)) && c != '*' && c != 'n'){return false}
if($.trim(b) && a.is('[href^="#footnote"]')){
// Check whether href, name and text is valid
var a_href_id = a.attr('href').substring(9) // Get only the value after '#footnote'
var a_name_id = a.attr('name') ? a.attr('name').substring(2) : a_href_id // Get only the value after 'fn' if name attr is present if not return a_href_id
var a_id = a.attr('id') ? a.attr('id').substring(2) : ''
if(a_href_id != a_name_id || a_href_id != c || a_id != c || a_name_id != c){
a.attr('href', '#footnote' + c), a.attr('id', 'fn' + c), a.attr('name', 'fn' + c)
}
}else{
// If anchor to footnote is invalid by href=#footnote*** or no href
// the text inside the 'a' tag will use as a reference
a.attr('href', '#footnote' + c), a.attr('id', 'fn' + c), a.attr('name', 'fn' + c)
}
return true;
}
$.fn.footnote_check = function () {
var a, b, c, d;
a = $(this), d = null
if(a.find('a:not([href^="#footnote"])').length){
a.find('a').each(function(){
b = $.trim($(this).text()), c = b.match(/([\*]{1,3}|[\d]{1,3})/)
if(c!= null){
c = c[0]
d = $(document.createElement('a'))
d.text(b), d.attr('href', '#fn' + c), d.attr('id', 'footnote' + c), d.attr('name', 'footnote' + c), d.addClass('m-r-lg'), d.css('color', 'red')
a.html(''), a.append(d)
return true;
}
})
if(d=null){
return false
}
}else if(!a.find('a').length){
b = $.trim(a.text()), c = b.match(/([\*]{1,3}|[\d]{1,3})/)
if(c!= null){
c = c[0]
d = $(document.createElement('a'))
d.text(b), d.attr('href', '#fn' + c), d.attr('id', 'footnote' + c), d.attr('name', 'footnote' + c), d.addClass('m-r-lg'), d.css('color', 'red')
a.html(''), a.append(d)
}else{
return false
}
}
return true
}
$.fn.footnote = function () {
var a = $(this)
// Validation of footnote
var b, c, d;
b = $(a.attr('href'))
if(b.length<=0 && a.data('index')>0){
var a_id = a.attr('id').substring(0, a.attr('id').indexOf('_'))
var a_like = $('a[href^="#footnote"][id^="' + a_id + '"]')
var a_found = false;
a_like.each(function(){
if(!a_found){b = $($(this).attr('href'))}
a_found = b.length>0
})
}
if(b.length>0){
c = b.closest('p')
d = c.footnote_text(b.parent('span') || b), d = d.substring(0,499) + (d.length > 500 ? '...' : '')
a.attr('data-original-title', d), a.attr('data-toggle', 'tooltip')
a.tooltip({title: d}), a.tooltip('show')
}else{
// typeof a._errorReport === "function" && a._errorReport({
// type: 'footnote',
// details: 'Footnote not found @ ' + a.attr('href')
// })
}
return a
}
$.fn.footnote_text = function (except) {
var a = '';
$(this).children().not(except).each(function(){
// Check first if the current select element not equal to except
var self = $(this)
a += self.text()
})
return a;
}
$(document).on('mouseover mouseenter focus', 'a[href^="#footnote"]', function(event){
event.preventDefault()
$(this).footnote()
})
}(jQuery))

2
app/javascript/src/application.scss

@ -1,4 +1,6 @@
@import "~bootstrap/scss/bootstrap";
@import '~flatpickr/dist/flatpickr.min';
@import '~flatpickr/dist/themes/airbnb';
@import "./application/sidenav";
@import "./application/sessions";
@import "./application/pagination";

10
app/reflexes/reports_reflex.rb

@ -0,0 +1,10 @@
# frozen_string_literal: true
class ReportsReflex < ApplicationReflex
include DoctrineSearch
def render_search_results(search_params)
search = doctrine_search(search_params.reject { |k, v| v.blank? })
morph "div#searchResultsTable", render(partial: "search_results_table", locals: { search: search, current_user: current_user })
end
end

12
app/views/reports/_search_results_table.html.erb

@ -0,0 +1,12 @@
<% if search.results.present? %>
<%= render(ReportsSearchResultsComponent.with_collection(search.results, current_user: current_user, opts: { is_render: true })) %>
<% else %>
<div class="d-flex justify-content-center flex-column no-search-body">
<div class="text-center ">
<%= image_pack_tag 'application/search-icon.png', class: "search-doc-icon"%>
</div>
<div class="text-center label-no-search" >
No Results Found
</div>
</div>
<% end %>

45
app/views/reports/index.html.erb

@ -0,0 +1,45 @@
<div class="container-fluid row p-0 m-0">
<div class="container col-xs-12 col-sm-12 col-md-3 col-lg-3 col-xl-3" >
<div class="advanced-search-box">
<%= form_with(url: reports_path, method: :get) do %>
<div class="mb-3">
<%= text_field_tag :q, params[:q], placeholder: 'Full text search', class: "form-control" %>
</div>
<hr class="simple">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-white"> Subjects </label>
<select class="form-control subject-ids-selectize p-0" name="subject_ids[]" id="subject_ids_" multiple="true"> </select>
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-white"> Date Created At </label>
<%= text_field_tag :created_at, params[:created_at], class: "default-flatpickr" %>
</div>
<hr class="simple">
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label text-white"> Users </label>
<%= select_tag :user_ids, options_from_collection_for_select(@users, :id, :name, params[:user_ids]), class: "form-control default-selectize p-0", multiple: true %>
</div>
<div class="d-flex justify-content-end mt-5">
<button type="button" class="btn btn-success me-2 mb-3">Refresh</button>
<button type="submit" class="btn btn-danger mb-3">Search</button>
</div>
<% end %>
</div>
</div>
<div class="container col-xs-12 col-sm-12 col-md-9 col-lg-9 col-xl-9" id="searchResultsTable">
<div class="m-2 ps-0"> <%= render PaginationComponent.new(data: @results, opts: { is_subject_breadcrums: true, subject_ids: params[:subject_ids] }) %> </div>
<% if @results.present? %>
<%= render(ReportsSearchResultsComponent.with_collection(@results, current_user: current_user, opts: { is_render: true })) %>
<% else %>
<div class="d-flex justify-content-center flex-column no-search-body">
<div class="text-center ">
<%= image_pack_tag 'application/search-icon.png', class: "search-doc-icon"%>
</div>
<div class="text-center label-no-search" >
No Results Found
</div>
</div>
<% end %>
</div>
</div>

15
app/views/shared/_reports_pagination.html.erb

@ -0,0 +1,15 @@
<nav>
<ul class="pagination">
<li class="page-item"><a href="#" class="page-link" data-reflex="click->TabularReflex#paginate" data-page="<%= prev_page %>">←</a></li>
<% @pagy.series.each do |item| %>
<% if item == :gap %>
<li class="page-item disabled"><a class="page-link">...</a></li>
<% else %>
<li class="page-item <%= "active" if item.is_a?(String) %>">
<a href="#" class="page-link" data-reflex="click->TabularReflex#paginate" data-page="<%= item %>"><%= item %></a>
</li>
<% end %>
<% end %>
<li class="page-item"><a href="#" class="page-link" data-reflex="click->TabularReflex#paginate" data-page="<%= next_page %>">→</a></li>
</ul>
</nav>

2
config/routes.rb

@ -25,6 +25,8 @@ Rails.application.routes.draw do
end
end
resources :reports, only: %i[index]
namespace :api, defaults: { format: :json } do
resources :doctrines do
scope module: :doctrine do

4
package.json

@ -16,11 +16,7 @@
"jquery": "^3.6.0",
"moment": "^2.29.1",
"popper.js": "^1.16.1",
"select2": "^4.1.0-rc.0",
"select2-bootstrap-5-theme": "^1.2.0",
"select2-bootstrap-theme": "^0.1.0-beta.10",
"selectize": "^0.12.6",
"selectize.js": "^0.12.12",
"stimulus": "^3.0.1",
"stimulus_reflex": "3.4.1",
"trix": "^2.0.0-alpha.0",

33
yarn.lock generated

@ -1542,7 +1542,7 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
bootstrap@^5.0.2, bootstrap@^5.1.3:
bootstrap@^5.1.3:
version "5.1.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.1.3.tgz#ba081b0c130f810fa70900acbc1c6d3c28fa8f34"
integrity sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==
@ -3892,11 +3892,6 @@ jest-worker@^26.5.0:
merge-stream "^2.0.0"
supports-color "^7.0.0"
jquery@^1.7.0:
version "1.12.4"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-1.12.4.tgz#01e1dfba290fe73deba77ceeacb0f9ba2fec9e0c"
integrity sha1-AeHfuikP5z3rp3zurLD5ui/sngw=
jquery@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470"
@ -6017,32 +6012,6 @@ select-hose@^2.0.0:
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=
select2-bootstrap-5-theme@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/select2-bootstrap-5-theme/-/select2-bootstrap-5-theme-1.2.0.tgz#36282520c7a88b89818350217600f3440dab718e"
integrity sha512-ia8yvInGTU9XntLQM1+ByGNA+nY2LPqgdB4XA/D766gihZjRpPJlum2eXbg/ur4q+H5hAnoCkY5TcFcX3DseKg==
dependencies:
bootstrap "^5.0.2"
select2-bootstrap-theme@^0.1.0-beta.10:
version "0.1.0-beta.10"
resolved "https://registry.yarnpkg.com/select2-bootstrap-theme/-/select2-bootstrap-theme-0.1.0-beta.10.tgz#b9426ecfc03bf4a235e76a132377574310469ac0"
integrity sha1-uUJuz8A79KI152oTI3dXQxBGmsA=
select2@^4.1.0-rc.0:
version "4.1.0-rc.0"
resolved "https://registry.yarnpkg.com/select2/-/select2-4.1.0-rc.0.tgz#ba3cd3901dda0155e1c0219ab41b74ba51ea22d8"
integrity sha512-Hr9TdhyHCZUtwznEH2CBf7967mEM0idtJ5nMtjvk3Up5tPukOLXbHUNmh10oRfeNIhj+3GD3niu+g6sVK+gK0A==
selectize.js@^0.12.12:
version "0.12.12"
resolved "https://registry.yarnpkg.com/selectize.js/-/selectize.js-0.12.12.tgz#67321487881a81506abe388b2995d3af3ad6edcd"
integrity sha1-ZzIUh4gagVBqvjiLKZXTrzrW7c0=
dependencies:
jquery "^1.7.0"
microplugin "0.0.3"
sifter "^0.5.1"
selectize@^0.12.6:
version "0.12.6"
resolved "https://registry.yarnpkg.com/selectize/-/selectize-0.12.6.tgz#c2cf08cbaa4cb06c5e99bb452919d71b080690d6"

Loading…
Cancel
Save