Skip to content

Commit

Permalink
Merge pull request #6588 from fecgov/feature/6445-mur-citation-filters
Browse files Browse the repository at this point in the history
6445 MUR citation filters
  • Loading branch information
patphongs authored Jan 16, 2025
2 parents c600934 + 3b55354 commit aa852a8
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 88 deletions.
51 changes: 48 additions & 3 deletions fec/fec/static/js/modules/typeahead.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,18 @@ function getUrl_names(resource) {
}

function getUrl_legal(resource) {
// Which parameters do we know we're going to query?
const queryParams = {
api_key: window.API_KEY_PUBLIC
};

// If there's a doc_type, let's add that to the query
const docTypeInput = document.querySelector('input[name="doc_type"]');
if (docTypeInput && docTypeInput.value != '') queryParams.doc_type = docTypeInput.value;

return URI(window.API_LOCATION)
.path([window.API_VERSION, 'legal', resource, encodeURIComponent('%QUERY')].join('/'))
.query({
api_key: window.API_KEY_PUBLIC
})
.query(queryParams)
.readable();
}

Expand Down Expand Up @@ -342,6 +349,42 @@ const aoStatutoryCitationDataset = {
}
};

const caseRegulatoryCitationDataset = {
name: 'caseRegulatoryCitation',
display: 'name',
limit: 10,
source: citationRegulationEngine,
templates: {
header: '<span class="tt-suggestion__header">Select a citation:</span>',
pending:
'<span class="tt-suggestion__loading">Loading citations&hellip;</span>',
notFound: compileHBS(''), // This has to be empty to not show anything
suggestion: function(datum) {
return (
'<span>' + datum.name + '</span>'
);
}
}
};

const caseStatutoryCitationDataset = {
name: 'caseStatutoryCitation',
display: 'name',
limit: 10,
source: citationStatuteEngine,
templates: {
header: '<span class="tt-suggestion__header">Select a citation:</span>',
pending:
'<span class="tt-suggestion__loading">Loading citations&hellip;</span>',
notFound: compileHBS(''), // This has to be empty to not show anything
suggestion: function(datum) {
return (
'<span>' + datum.name + '</span>'
);
}
}
};

export const datasets = {
candidates: candidateDataset,
committees: committeeDataset,
Expand All @@ -350,6 +393,8 @@ export const datasets = {
regulations: regulationDataset,
aoRegulatoryCitations: aoRegulatoryCitationDataset,
aoStatutoryCitations: aoStatutoryCitationDataset,
caseRegulatoryCitations: caseRegulatoryCitationDataset,
caseStatutoryCitations: caseStatutoryCitationDataset,
allData: [candidateDataset, committeeDataset],
all: [candidateDataset, committeeDataset, individualDataset, siteDataset, legalDataset]
};
Expand Down
29 changes: 28 additions & 1 deletion fec/legal/templates/layouts/legal-doc-search-results.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@
const tag = this.getAttribute('data-tag');
const url = new URL(window.location);
// Remove tags logic
// "Remove tags" logic
// Assigns a URL to each remove/"⤫" button that removes its own value from the URL
if (tag === 'query') {
url.searchParams.delete('search');
url.searchParams.delete('search_exclude');
Expand Down Expand Up @@ -135,6 +136,32 @@
} else if (tag && tag == 'secondary_subject_id') { // Check if tag is not null or undefined
// Remove 'secondary_subject_id' from the URL
url.searchParams.delete('secondary_subject_id');
} else if (tag && tag == 'case_citation_require_all') {
url.searchParams.delete('case_citation_require_all');
} else if (tag && tag.startsWith('case_regulatory_citation')) {
// Get the 0-indexed position of this item
const index = tag.split('_').at(-1);
// Hold all the case_regulatory_citation from the URL
const citations = url.searchParams.getAll('case_regulatory_citation');
// Remove all of the case_regulatory_citation from the URL
url.searchParams.delete('case_regulatory_citation');
// For all of the held citations,
citations.forEach((cite, i) => {
// Add all but this element back to the URL
if (i != index) url.searchParams.append('case_regulatory_citation', cite);
});
} else if (tag && tag.startsWith('case_statutory_citation')) {
// Get the 0-indexed position of this item
const index = tag.split('_').at(-1);
// Hold all the case_statutory_citation from the URL
const citations = url.searchParams.getAll('case_statutory_citation');
// Remove all of the case_statutory_citation from the URL
url.searchParams.delete('case_statutory_citation');
// For all of the held citations,
citations.forEach((cite, i) => {
// Add all but this element back to the URL
if (i != index) url.searchParams.append('case_statutory_citation', cite);
});
} else {
url.searchParams.delete(tag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@
<button type="button" class="js-accordion-trigger accordion__button">Citations</button>
<div class="accordion__content">
<label>If more than one citation is entered:</label>
<input type="radio" id="citation_require_all_false" name="ao_citation_require_all" value="false" checked="">
<label for="citation_require_all_false">Show cases citing any of them</label>
<input type="radio" id="citation_require_all_true" name="ao_citation_require_all" value="true">
<label for="citation_require_all_true">Show cases citing all of them</label>
<input type="radio" id="ao_citation_require_all_false" name="ao_citation_require_all" value="false"{% if not ao_citation_require_all %} checked{% endif %}>
<label for="ao_citation_require_all_false">Show cases citing any of them</label>
<input type="radio" id="ao_citation_require_all_true" name="ao_citation_require_all" value="true"{% if ao_citation_require_all %} checked{% endif %}>
<label for="ao_citation_require_all_true">Show cases citing all of them</label>
{{ typeahead.field('ao_regulatory_citation', 'Regulatory citation', False, dataset='aoRegulatoryCitations', allow_text=False) }}
{{ typeahead.field('ao_statutory_citation', 'Statutory citation', False, dataset='aoStatutoryCitations', allow_text=False) }}
</div>
Expand Down
175 changes: 112 additions & 63 deletions fec/legal/templates/legal-search-results-murs.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{% import 'macros/legal.jinja' as legal %}
{% import 'macros/filters/checkbox.jinja' as checkbox %}
{% import 'macros/filters/dropdown-json.jinja' as dropdown %}
{% import 'macros/filters/typeahead-filter.jinja' as typeahead %}
{% set document_type_display_name = 'Closed Matters Under Review' %}

{% block header %}
Expand All @@ -12,8 +13,9 @@

{% block filters %}
<input id="sort" type="hidden" name="sort" value="{{ sort }}">
<input id="doc_type" type="hidden" name="doc_type" value="murs">
<div class="filters__inner">
{{ legal.keyword_search(result_type, query) }}

<div class="filter">
<label class="label" for="case_no">MUR number</label>
<input id="case_no" name="case_no" type="text" value="{{ case_no }}">
Expand All @@ -22,61 +24,50 @@
<label class="label" for="case_respondents">MUR respondents</label>
<input id="case_respondents" name="case_respondents" type="text" value="{{ case_respondents }}">
</div>
<div class="filter">
</div>

<div class="js-accordion accordion--neutral" data-content-prefix="filter" data-open-first="true">

<button type="button" class="js-accordion-trigger accordion__button">Documents</button>
<div class="accordion__content">
{{ legal.keyword_search(result_type, query) }}

<div class="filter">
<legend class="label">Document Type</legend>
{% for category_id, category_label in mur_document_categories.items() %}
<div>
<input type="checkbox" id="case_doc_category_id_{{ category_id }}" name="case_doc_category_id" value="{{ category_id }}" {% if category_id in selected_doc_category_ids %}checked{% endif %}>
<label for="case_doc_category_id_{{ category_id }}">{{ category_label }}</label>
<input type="checkbox" id="case_doc_category_id_{{ category_id }}" name="case_doc_category_id" value="{{ category_id }}" {% if category_id in selected_doc_category_ids %}checked{% endif %}>
<label for="case_doc_category_id_{{ category_id }}">{{ category_label }}</label>
</div>
{% endfor %}
</div>
<div class="filter">
<legend class="label">Document date range</legend>
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_document_date">Beginning</label>
<input id="case_min_document_date" name="case_min_document_date" placeholder="mm/dd/yyyy" value="{{ case_min_document_date }}">
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_document_date">Ending</label>
<input id="case_max_document_date" name="case_max_document_date" placeholder="mm/dd/yyyy" value="{{ case_max_document_date }}">
</div>
</div>
</div>
<div class="filter">
<legend class="label">Case open date range</legend>
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_open_date">Beginning</label>
<input id="case_min_open_date" name="case_min_open_date" placeholder="mm/dd/yyyy" value="{{ case_min_open_date }}">
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_open_date">Ending</label>
<input id="case_max_open_date" name="case_max_open_date" placeholder="mm/dd/yyyy" value="{{ case_max_open_date }}">
</div>
</div>
</div>
<div class="filter">
<legend class="label">Case close date range</legend>
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_close_date">Beginning</label>
<input id="case_min_close_date" name="case_min_close_date" placeholder="mm/dd/yyyy" value="{{ case_min_close_date }}">
<div class="filter">
<label class="label t-inline-block">Document date range</label>
<div class="tooltip__container" tabindex="0">
<button class="tooltip__trigger"><span class="u-visually-hidden">Learn more</span></button>
<div class="tooltip tooltip--left tooltip--above">
<p class="tooltip__content tooltip__content">Document date range does not search archived cases</p>
</div>
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_close_date">Ending</label>
<input id="case_max_close_date" name="case_max_close_date" placeholder="mm/dd/yyyy" value="{{ case_max_close_date }}">
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_document_date">Beginning</label>
<input id="case_min_document_date" name="case_min_document_date" placeholder="mm/dd/yyyy" value="{{ case_min_document_date }}">
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_document_date">Ending</label>
<input id="case_max_document_date" name="case_max_document_date" placeholder="mm/dd/yyyy" value="{{ case_max_document_date }}">
</div>
</div>
</div>
</div>
</div>
<div class="js-accordion accordion--neutral" data-content-prefix="filter" data-open-first="true">
{# </div> #}
{# <div class="js-accordion accordion--neutral" data-content-prefix="filter" data-open-first="false"> #}

<button type="button" class="js-accordion-trigger accordion__button">Case details</button>
<div class="accordion__content">

{{ checkbox.checkbox_dropdown_multiple(
'mur_disposition_category_id',
'Final disposition',
Expand All @@ -86,25 +77,20 @@
prefix='mur_disposition_category_id',
show_tooltip_text='Final disposition does not search archived cases'
) }}
{{ dropdown.select_json(
'primary_subject_id',
'Case subject',
options=constants.primary_subject_ids,
default="",
show_tooltip_text='Case subject does not search archived cases'
) }}
{{ dropdown.select_json_indentation(
'secondary_subject_id',
'Secondary case subject',
options=constants.secondary_subject_placeholder,
default=""
) }}

{{
dropdown.select_json(
'primary_subject_id',
'Case subject',
options=constants.primary_subject_ids,
default="",
show_tooltip_text='Case subject does not search archived cases'

)
}}
{{
dropdown.select_json_indentation(
'secondary_subject_id',
'Secondary case subject',
options=constants.secondary_subject_placeholder,
default=""
)
}}
<div class="filter">
<legend class="label">Penalty amount by respondent</legend>
<div class="range range--currency">
Expand All @@ -119,12 +105,56 @@
</div>
</div>
</div>

<div class="filter">
<legend class="label">Case open date range</legend>
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_open_date">Beginning</label>
<input id="case_min_open_date" name="case_min_open_date" placeholder="mm/dd/yyyy" value="{{ case_min_open_date }}">
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_open_date">Ending</label>
<input id="case_max_open_date" name="case_max_open_date" placeholder="mm/dd/yyyy" value="{{ case_max_open_date }}">
</div>
</div>
</div>

<div class="filter">
<legend class="label">Case close date range</legend>
<div class="range range--date js-date-range">
<div class="range__input range__input--min" data-filter="range">
<label for="case_min_close_date">Beginning</label>
<input id="case_min_close_date" name="case_min_close_date" placeholder="mm/dd/yyyy" value="{{ case_min_close_date }}">
</div>
<div class="range__hyphen">-</div>
<div class="range__input range__input--max" data-filter="range">
<label for="case_max_close_date">Ending</label>
<input id="case_max_close_date" name="case_max_close_date" placeholder="mm/dd/yyyy" value="{{ case_max_close_date }}">
</div>
</div>
</div>
</div>

{# </div> #}
{# <div class="js-accordion accordion--neutral" data-content-prefix="filter" data-open-first="false"> #}
<button type="button" class="js-accordion-trigger accordion__button">Citations</button>

<div class="accordion__content">
<label>If more than one citation is entered:</label>
<input type="radio" id="case_citation_require_all_false" name="case_citation_require_all" value="false"{% if not case_citation_require_all %} checked{% endif %}>
<label for="case_citation_require_all_false">Show cases citing any of them</label>
<input type="radio" id="case_citation_require_all_true" name="case_citation_require_all" value="true"{% if case_citation_require_all %} checked{% endif %}>
<label for="case_citation_require_all_true">Show cases citing all of them</label>
{{ typeahead.field('case_regulatory_citation', 'Regulatory citation', False, dataset='caseRegulatoryCitations', allow_text=False) }}
{{ typeahead.field('case_statutory_citation', 'Statutory citation', False, dataset='caseStatutoryCitations', allow_text=False) }}

</div>
</div>
<div class="filters__inner">
<button type="submit" class="button button--cta u-margin--top">Apply filters</button>
</div>

{% endblock %}

{% block message %}
Expand Down Expand Up @@ -216,6 +246,25 @@
{% endif %}
</li>
{% endif %}
{% if case_citation_require_all %}
<li data-tag-category="case_regulatory_citation" class="tag__category">
<div data-removable="true" class="tag__item">Cases with all citations<button class="button js-close tag__remove" data-tag="case_citation_require_all"><span class="u-visually-hidden">Remove</span></button></div>
</li>
{% endif %}
{% if case_regulatory_citation %}
<li data-tag-category="case_regulatory_citation" class="tag__category">
{% for case_reg_citation in case_regulatory_citation %}
<div data-removable="true" class="tag__item">{{ case_reg_citation }}<button class="button js-close tag__remove" data-tag="case_regulatory_citation_{{ loop.index0 }}"><span class="u-visually-hidden">Remove</span></button></div>
{% endfor %}
</li>
{% endif %}
{% if case_statutory_citation %}
<li data-tag-category="case_statutory_citation" class="tag__category">
{% for case_stat_citation in case_statutory_citation %}
<div data-removable="true" class="tag__item">{{ case_stat_citation }}<button class="button js-close tag__remove" data-tag="case_statutory_citation_{{ loop.index0 }}"><span class="u-visually-hidden">Remove</span></button></div>
{% endfor %}
</li>
{% endif %}
</ul>
</div>
</div>
Expand Down
Loading

0 comments on commit aa852a8

Please sign in to comment.