22 changed files with 412 additions and 202 deletions
@ -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 |
||||||
@ -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> |
||||||
@ -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 |
||||||
@ -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) |
||||||
|
} |
||||||
|
} |
||||||
@ -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)) |
||||||
@ -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 |
||||||
@ -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 %> |
||||||
@ -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> |
||||||
@ -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> |
||||||
Loading…
Reference in new issue