Skip to content

Commit b92183b

Browse files
nickpnickp
authored andcommitted
it builds
1 parent 017ff27 commit b92183b

File tree

3 files changed

+192
-17
lines changed

3 files changed

+192
-17
lines changed

.eleventy.js

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,18 +298,39 @@ module.exports = function(eleventyConfig) {
298298
: firstPage.document_metadata?.date
299299
};
300300

301-
return {
301+
// Create lightweight pages array (keep full_text but make them lazy)
302+
const lightPages = docPages.map(p => {
303+
const lightPage = { ...p };
304+
// Keep full_text reference for document rendering, but it won't be duplicated
305+
return lightPage;
306+
});
307+
308+
// Only include full_text when needed (for individual document pages)
309+
// For the main documents array, we skip it to save memory
310+
const docData = {
302311
unique_id: normalizedDocNum, // Normalized version for unique URLs
303312
document_number: rawDocNums.length === 1 ? rawDocNums[0] : normalizedDocNum, // Show original if consistent, else normalized
304313
raw_document_numbers: rawDocNums, // All variations found
305-
pages: docPages,
314+
pages: lightPages,
306315
page_count: docPages.length,
307316
document_metadata: normalizedMetadata,
308317
entities: deduplicatedEntities,
309-
full_text: docPages.map(p => p.full_text).join('\n\n--- PAGE BREAK ---\n\n'),
310318
folder: folders.join(', '), // Show all folders if document spans multiple
311319
folders: folders // Keep array for reference
312320
};
321+
322+
// Add full_text getter that loads on demand
323+
Object.defineProperty(docData, 'full_text', {
324+
get: function() {
325+
if (!this._full_text) {
326+
this._full_text = this.pages.map(p => p.full_text).join('\n\n--- PAGE BREAK ---\n\n');
327+
}
328+
return this._full_text;
329+
},
330+
enumerable: true
331+
});
332+
333+
return docData;
313334
});
314335

315336
cachedDocuments = documents;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "1.0.0",
44
"description": "Static site for exploring OCR'd documents",
55
"scripts": {
6-
"build": "eleventy",
6+
"build": "NODE_OPTIONS='--max-old-space-size=8192' eleventy",
77
"start": "eleventy --serve"
88
},
99
"devDependencies": {

src/analyses.njk

Lines changed: 167 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Document Analyses
44
---
55

66
<h1>Document Analyses</h1>
7-
<p class="subtitle">AI-generated summaries for {{ analyses.length }} documents</p>
7+
<p class="subtitle">AI-generated summaries for <span id="total-count">{{ analyses.length }}</span> documents</p>
88

99
<div class="search-box">
1010
<input type="text" id="search" placeholder="Search analyses...">
@@ -17,6 +17,22 @@ title: Document Analyses
1717
{% endfor %}
1818
</div>
1919

20+
<div class="pagination-controls">
21+
<button id="prev-page" disabled>← Previous</button>
22+
<span id="page-info">Page 1</span>
23+
<button id="next-page">Next →</button>
24+
<span class="page-size-selector">
25+
Show:
26+
<select id="page-size">
27+
<option value="50">50</option>
28+
<option value="100" selected>100</option>
29+
<option value="250">250</option>
30+
<option value="500">500</option>
31+
</select>
32+
per page
33+
</span>
34+
</div>
35+
2036
<div class="table-container">
2137
<table class="analyses-table">
2238
<thead>
@@ -29,7 +45,7 @@ title: Document Analyses
2945
</thead>
3046
<tbody id="results">
3147
{% for item in analyses %}
32-
<tr class="analysis-row" data-content="{{ [item.document_number, item.analysis.document_type, item.analysis.summary, item.analysis.significance, item.analysis.key_topics | join(' ')] | join(' ') | lower }}" data-type="{{ item.analysis.document_type | lower }}">
48+
<tr class="analysis-row" data-type="{{ item.analysis.document_type | lower }}">
3349
<td class="doc-number">
3450
<a href="/document/{{ item.document_id | slugify }}/">{{ item.document_number }}</a>
3551
</td>
@@ -75,6 +91,56 @@ title: Document Analyses
7591
color: white;
7692
}
7793
94+
.pagination-controls {
95+
display: flex;
96+
align-items: center;
97+
gap: 1rem;
98+
margin-bottom: 1.5rem;
99+
padding: 1rem;
100+
background: white;
101+
border: 1px solid #e0e0e0;
102+
border-radius: 6px;
103+
}
104+
105+
.pagination-controls button {
106+
padding: 0.5rem 1rem;
107+
background: white;
108+
border: 1px solid #e0e0e0;
109+
border-radius: 4px;
110+
cursor: pointer;
111+
font-size: 0.875rem;
112+
transition: all 0.2s;
113+
}
114+
115+
.pagination-controls button:hover:not(:disabled) {
116+
border-color: #3498db;
117+
color: #3498db;
118+
}
119+
120+
.pagination-controls button:disabled {
121+
opacity: 0.5;
122+
cursor: not-allowed;
123+
}
124+
125+
#page-info {
126+
font-size: 0.875rem;
127+
color: #666;
128+
margin: 0 0.5rem;
129+
}
130+
131+
.page-size-selector {
132+
margin-left: auto;
133+
font-size: 0.875rem;
134+
color: #666;
135+
}
136+
137+
.page-size-selector select {
138+
padding: 0.25rem 0.5rem;
139+
border: 1px solid #e0e0e0;
140+
border-radius: 4px;
141+
margin: 0 0.5rem;
142+
}
143+
78144
.table-container {
79145
overflow-x: auto;
80146
background: white;
@@ -188,7 +254,33 @@ title: Document Analyses
188254
}
189255
}
190256
257+
@media (max-width: 900px) {
258+
.pagination-controls {
259+
flex-wrap: wrap;
260+
}
261+
262+
.page-size-selector {
263+
margin-left: 0;
264+
width: 100%;
265+
text-align: center;
266+
}
267+
}
268+
191269
@media (max-width: 600px) {
270+
.pagination-controls {
271+
padding: 0.75rem;
272+
gap: 0.5rem;
273+
}
274+
275+
.pagination-controls button {
276+
font-size: 0.8rem;
277+
padding: 0.4rem 0.75rem;
278+
}
279+
280+
#page-info {
281+
font-size: 0.75rem;
282+
}
283+
192284
/* Stack table on mobile */
193285
.analyses-table thead {
194286
display: none;
@@ -251,35 +343,97 @@ title: Document Analyses
251343
const results = document.getElementById('results');
252344
const allRows = Array.from(results.querySelectorAll('.analysis-row'));
253345
const filterButtons = document.querySelectorAll('.filter-btn');
346+
const prevButton = document.getElementById('prev-page');
347+
const nextButton = document.getElementById('next-page');
348+
const pageInfo = document.getElementById('page-info');
349+
const pageSizeSelect = document.getElementById('page-size');
350+
const totalCount = document.getElementById('total-count');
254351
255352
let currentFilter = 'all';
256353
let currentSearch = '';
257-
258-
// Filter function that applies both type filter and search
259-
function applyFilters() {
260-
allRows.forEach(row => {
354+
let currentPage = 1;
355+
let pageSize = 100;
356+
let filteredRows = allRows;
357+
358+
// Filter and pagination function
359+
function applyFiltersAndPagination() {
360+
// First, filter rows based on type and search
361+
filteredRows = allRows.filter(row => {
261362
const matchesType = currentFilter === 'all' || row.dataset.type === currentFilter;
262-
const matchesSearch = currentSearch === '' || row.dataset.content.includes(currentSearch);
263-
row.style.display = (matchesType && matchesSearch) ? '' : 'none';
363+
364+
let matchesSearch = true;
365+
if (currentSearch !== '') {
366+
const rowText = row.textContent.toLowerCase();
367+
matchesSearch = rowText.includes(currentSearch);
368+
}
369+
370+
return matchesType && matchesSearch;
264371
});
372+
373+
// Update total count
374+
totalCount.textContent = filteredRows.length;
375+
376+
// Calculate pagination
377+
const totalPages = Math.ceil(filteredRows.length / pageSize);
378+
const startIndex = (currentPage - 1) * pageSize;
379+
const endIndex = startIndex + pageSize;
380+
381+
// Hide all rows first
382+
allRows.forEach(row => row.style.display = 'none');
383+
384+
// Show only current page rows
385+
filteredRows.slice(startIndex, endIndex).forEach(row => {
386+
row.style.display = '';
387+
});
388+
389+
// Update pagination controls
390+
pageInfo.textContent = `Page ${currentPage} of ${totalPages || 1} (${filteredRows.length} total)`;
391+
prevButton.disabled = currentPage <= 1;
392+
nextButton.disabled = currentPage >= totalPages;
265393
}
266394
267395
// Search handler
268396
search.addEventListener('input', (e) => {
269397
currentSearch = e.target.value.toLowerCase().trim();
270-
applyFilters();
398+
currentPage = 1; // Reset to first page on search
399+
applyFiltersAndPagination();
271400
});
272401
273402
// Filter button handlers
274403
filterButtons.forEach(btn => {
275404
btn.addEventListener('click', () => {
276-
// Update active state
277405
filterButtons.forEach(b => b.classList.remove('active'));
278406
btn.classList.add('active');
279-
280-
// Update filter and apply
281407
currentFilter = btn.dataset.type;
282-
applyFilters();
408+
currentPage = 1; // Reset to first page on filter change
409+
applyFiltersAndPagination();
283410
});
284411
});
412+
413+
// Pagination handlers
414+
prevButton.addEventListener('click', () => {
415+
if (currentPage > 1) {
416+
currentPage--;
417+
applyFiltersAndPagination();
418+
window.scrollTo({ top: 0, behavior: 'smooth' });
419+
}
420+
});
421+
422+
nextButton.addEventListener('click', () => {
423+
const totalPages = Math.ceil(filteredRows.length / pageSize);
424+
if (currentPage < totalPages) {
425+
currentPage++;
426+
applyFiltersAndPagination();
427+
window.scrollTo({ top: 0, behavior: 'smooth' });
428+
}
429+
});
430+
431+
pageSizeSelect.addEventListener('change', (e) => {
432+
pageSize = parseInt(e.target.value);
433+
currentPage = 1; // Reset to first page on page size change
434+
applyFiltersAndPagination();
435+
});
436+
437+
// Initial render
438+
applyFiltersAndPagination();
285439
</script>

0 commit comments

Comments
 (0)