Skip to content

Commit

Permalink
Merge pull request #50 from Marvell-Consulting/fix-paging-bug
Browse files Browse the repository at this point in the history
Fix paging bug
  • Loading branch information
j-maynard authored Nov 28, 2024
2 parents cc6811a + 95ab09a commit 148ff5a
Show file tree
Hide file tree
Showing 9 changed files with 221 additions and 283 deletions.
65 changes: 3 additions & 62 deletions src/controllers/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import { RelatedLinkDTO } from '../dtos/related-link';
import { DatasetProviderDTO } from '../dtos/dataset-provider';
import { ProviderSourceDTO } from '../dtos/provider-source';
import { ProviderDTO } from '../dtos/provider';
import { generateSequenceForNumber } from '../utils/pagination';
import { fileMimeTypeHandler } from '../utils/file-mimetype-handler';
import { TopicDTO } from '../dtos/topic';
import { DatasetTopicDTO } from '../dtos/dataset-topic';
import { nestTopics } from '../utils/nested-topics';
Expand Down Expand Up @@ -95,35 +97,7 @@ export const uploadFile = async (req: Request, res: Response, next: NextFunction
throw new Error('errors.csv.invalid');
}
const fileName = req.file.originalname;
if (req.file.mimetype === 'application/octet-stream') {
const ext = path.extname(req.file.originalname);
switch (ext) {
case '.parquet':
req.file.mimetype = 'application/vnd.apache.parquet';
break;
case '.json':
req.file.mimetype = 'application/json';
break;
case '.xls':
case '.xlsx':
req.file.mimetype = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
break;
case '.csv':
req.file.mimetype = 'text/csv';
break;
default:
throw new Error(`unsupported format ${ext}`);
}
} else if (req.file.mimetype === 'application/x-gzip') {
const ext = req.file.originalname.split('.').reverse()[1];
switch (ext) {
case 'json':
case 'csv':
break;
default:
throw new Error(`unsupported format ${ext}`);
}
}
req.file.mimetype = fileMimeTypeHandler(req.file.mimetype, req.file.originalname);
const fileData = new Blob([req.file.buffer], { type: req.file.mimetype });
await req.swapi.uploadCSVToDataset(dataset.id, fileData, fileName);
res.redirect(req.buildUrl(`/publish/${dataset.id}/preview`, req.language));
Expand All @@ -138,39 +112,6 @@ export const uploadFile = async (req: Request, res: Response, next: NextFunction
res.render('publish/upload', { revisit, errors });
};

// Special thanks ChatGPT... The GovUK pagination algorithm
function generateSequenceForNumber(highlight: number, end: number): (string | number)[] {
const sequence: (string | number)[] = [];

// Validate input
if (highlight > end) {
throw new Error(`Highlighted number must be between 1 and ${end}.`);
}

// Numbers before the highlighted number
if (highlight - 1 > 1) {
sequence.push(1, '...');
sequence.push(highlight - 1);
} else {
// eslint-disable-next-line @typescript-eslint/naming-convention
sequence.push(...Array.from({ length: highlight - 1 }, (_, index) => index + 1));
}

// Highlighted number
sequence.push(highlight);

// Numbers after the highlighted number
if (highlight + 1 < end) {
sequence.push(highlight + 1);
sequence.push('...', end);
} else {
// eslint-disable-next-line @typescript-eslint/naming-convention
sequence.push(...Array.from({ length: end - highlight }, (_, index) => highlight + 1 + index));
}

return sequence;
}

export const factTablePreview = async (req: Request, res: Response, next: NextFunction) => {
const { dataset, revision, factTable } = res.locals;
let errors: ViewErrDTO | undefined;
Expand Down
1 change: 1 addition & 0 deletions src/middleware/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const initServices = (req: Request, res: Response, next: NextFunction): v
req.swapi = statsWalesApi;
req.buildUrl = localeUrl; // for controllers
res.locals.buildUrl = localeUrl; // for templates
res.locals.url = req.originalUrl; // Allows the passing through of the URL
}
next();
};
34 changes: 34 additions & 0 deletions src/public/css/wales-overrides.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,27 @@ h1, h2, h3, h4, p, ol, ul, a, table, .govuk-header__link, .govuk-task-list__stat
}

.table-display {
position: relative;
overflow: auto;
display: block;
max-height: 50vh;
width: 100%;
border: 1px solid #b1b4b6;
padding: 0;
margin-bottom: 1em;
}

.table-display > table > thead > tr > th {
position: sticky;
top: 0; /* Don't forget this, required for the stickiness */
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4);
background: #1d70b8;
color: white !important;
}

.table-display > table > thead > tr > th:first-child,
.table-display > table > tbody > tr > td:first-child {
padding-left: 1em;
}

.top-links {
Expand All @@ -96,3 +113,20 @@ h1, h2, h3, h4, p, ol, ul, a, table, .govuk-header__link, .govuk-task-list__stat
pointer-events: none;
z-index: 0;
}

.ignore-column {
background-color: #eeeeee;
}

.line-number {
color: #7f7f7f;
}

.region-subhead {
color: #aa1111;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
letter-spacing: 0.08em;
line-height: 20px;
text-transform: uppercase;
}
34 changes: 1 addition & 33 deletions src/routes/dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,42 +10,10 @@ import { DatasetListItemDTO } from '../dtos/dataset-list-item';
import { hasError, factTableIdValidator } from '../validators';
import { RevisionDTO } from '../dtos/revision';
import { FactTableDto } from '../dtos/fact-table';
import { generateSequenceForNumber } from '../utils/pagination';

export const dataset = Router();

// Special thanks ChatGPT... The GovUK pagination algorithm
function generateSequenceForNumber(highlight: number, end: number): (string | number)[] {
const sequence: (string | number)[] = [];

// Validate input
if (highlight > end) {
throw new Error(`Highlighted number must be between 1 and ${end}.`);
}

// Numbers before the highlighted number
if (highlight - 1 > 1) {
sequence.push(1, '...');
sequence.push(highlight - 1);
} else {
// eslint-disable-next-line @typescript-eslint/naming-convention
sequence.push(...Array.from({ length: highlight - 1 }, (_, index) => index + 1));
}

// Highlighted number
sequence.push(highlight);

// Numbers after the highlighted number
if (highlight + 1 < end) {
sequence.push(highlight + 1);
sequence.push('...', end);
} else {
// eslint-disable-next-line @typescript-eslint/naming-convention
sequence.push(...Array.from({ length: end - highlight }, (_, index) => highlight + 1 + index));
}

return sequence;
}

dataset.get('/', async (req: Request, res: Response, next: NextFunction) => {
try {
const datasets: DatasetListItemDTO[] = await req.swapi.getActiveDatasetList();
Expand Down
31 changes: 31 additions & 0 deletions src/utils/file-mimetype-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import path from 'node:path';

export function fileMimeTypeHandler(mimetype: string, originalFileName: string): string {
let ext = 'unknown';
if (mimetype === 'application/octet-stream') {
ext = path.extname(originalFileName);
switch (ext) {
case '.parquet':
return 'application/vnd.apache.parquet';
case '.json':
return 'application/json';
case '.xls':
case '.xlsx':
return 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
case '.csv':
return 'text/csv';
default:
throw new Error(`unsupported format ${ext}`);
}
} else if (mimetype === 'application/x-gzip') {
ext = originalFileName.split('.').reverse()[1];
switch (ext) {
case 'json':
case 'csv':
return 'application/x-gzip';
default:
throw new Error(`unsupported format ${ext}`);
}
}
return mimetype;
}
64 changes: 64 additions & 0 deletions src/utils/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* eslint-disable @typescript-eslint/naming-convention */

// Special thanks ChatGPT... The GovUK pagination algorithm
export function generateSequenceForNumber(highlight: number, end: number): (string | number)[] {
const sequence: (string | number)[] = [];

// Validate input
if (highlight < 1 || highlight > end) {
throw new Error(`Highlighted number must be between 1 and ${end}.`);
}

if (end - 1 < 3) {
sequence.push(
...Array.from({ length: end - 1 + 1 }, (_, index) => 1 + index).map((num) =>
num === highlight ? num : num
)
);
return sequence;
}

// Case 1: Highlight is within the first 3 pages
if (highlight <= 3) {
sequence.push(...Array.from({ length: 3 }, (_, index) => 1 + index));
sequence[highlight - 1] = highlight; // Highlight the specific number
if (end > 4) {
sequence.push('...');
sequence.push(end);
}
return sequence;
}

// Case 2: Highlight is near or at the last 3 pages
if (highlight >= end - 2) {
if (end - 3 > 1) {
sequence.push(1, '...');
}
for (let i = end - 3; i <= end; i++) {
if (i === highlight) {
sequence.push(i);
} else {
sequence.push(i);
}
}
return sequence;
}

// Case 3: General case
if (highlight - 2 > 1) {
sequence.push(1, '...');
sequence.push(highlight - 1);
} else {
sequence.push(...Array.from({ length: highlight - 1 }, (_, index) => index + 1));
}

sequence.push(highlight); // Highlight the number

if (highlight + 1 < end) {
sequence.push(highlight + 1, '...', end);
} else {
sequence.push(...Array.from({ length: end - highlight }, (_, index) => highlight + 1 + index));
}

return sequence;
}
80 changes: 80 additions & 0 deletions src/views/partials/pagination.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
<nav class="govuk-pagination" role="navigation" aria-label="Pagination">
<% if (locals.total_pages === 1) { %>
<ul class="govuk-pagination__list">
<li class="govuk-pagination__item govuk-pagination__item--current">
<a href="#" aria-current="page" class="govuk-link govuk-pagination__link">
<%= locals.current_page %>
</a>
</li>
</ul>
<% } else { %>
<% if (locals.current_page > 1) { %>
<div class="govuk-pagination__prev">
<a class="govuk-link govuk-pagination__link"
href="<%= buildUrl(url, i18n.language, { page_number: locals.current_page - 1, page_size: locals.page_size }) %>"
rel="prev">
<svg class="govuk-pagination__icon govuk-pagination__icon--prev" xmlns="http://www.w3.org/2000/svg"
height="13" width="15" aria-hidden="true" focusable="false" viewBox="0 0 15 13">
<path
d="m6.5938-0.0078125-6.7266 6.7266 6.7441 6.4062 1.377-1.449-4.1856-3.9768h12.896v-2h-12.984l4.2931-4.293-1.414-1.414z">
</path>
</svg>
<span class="govuk-pagination__link-title">
<%= t('pagination.previous') %>
</span>
</a>
</div>
<% } %>
<ul class="govuk-pagination__list">
<% locals.pagination.forEach((item) => { %>
<% if (item === '...') { %>
<li class="govuk-pagination__item govuk-pagination__item--ellipses">
&ctdot;
</li>
<% } else if(item === locals.current_page) { %>
<li class="govuk-pagination__item govuk-pagination__item--current">
<a href="#" aria-current="page" class="govuk-link govuk-pagination__link">
<%= item %>
</a>
</li>
<% } else { %>
<li class="govuk-pagination__item">
<a class="govuk-link govuk-pagination__link"
href="<%= buildUrl(url, i18n.language, { page_number: item, page_size: locals.page_size }) %>"
aria-label="Page <%= item %>">
<%= item %>
</a>
</li>
<% }%>
<% }); %>
</ul>
<% if (locals.current_page < locals.total_pages) { %>
<div class="govuk-pagination__next">
<a class="govuk-link govuk-pagination__link"
href="<%= buildUrl(url, i18n.language, { page_number: locals.current_page + 1, page_size: locals.page_size }) %>"
rel="next">
<span class="govuk-pagination__link-title">
<%= t('pagination.next') %>
</span>
<svg class="govuk-pagination__icon govuk-pagination__icon--next"
xmlns="http://www.w3.org/2000/svg" height="13" width="15" aria-hidden="true"
focusable="false" viewBox="0 0 15 13">
<path
d="m8.107-0.0078125-1.4136 1.414 4.2926 4.293h-12.986v2h12.896l-4.1855 3.9766 1.377 1.4492 6.7441-6.4062-6.7246-6.7266z">
</path>
</svg>
</a>
</div>
<% } %>
<% } %>
</nav>
</div>

<div class="govuk-grid-column-one-third">
<p class="govuk-body" style="text-align: right; padding-top: 10px">
<%= t('publish.preview.showing_rows', {start: locals.page_info.start_record, end: locals.page_info.end_record, total: locals.page_info.total_records}) %>
</p>
</div>
</div>
Loading

0 comments on commit 148ff5a

Please sign in to comment.