Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/helpers/errata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export type Errata = {
resolutionNotes: string;
};

type Detail = Pick<
export type Detail = Pick<
Errata,
'id' | 'status' | 'errorType' | 'detail' | 'resolutionNotes'
> & {
Expand Down
63 changes: 0 additions & 63 deletions src/app/pages/errata-detail/detail/detail.js

This file was deleted.

70 changes: 70 additions & 0 deletions src/app/pages/errata-detail/detail/detail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import RawHTML from '~/components/jsx-helpers/raw-html';
import {
useErrataDetail,
shouldShowDecisionDetails,
Errata,
Detail as DetailData
} from '~/helpers/errata';
import './detail.scss';

type Pairs = Array<[s: string, i: keyof DetailData]>;

const detailDataPairs: Pairs = [
['Submission ID', 'id'],
['Title', 'bookTitle'],
['Source', 'source'],
['Status', 'status'],
['Error Type', 'errorType'],
['Location', 'location'],
['Description', 'detail'],
['Date Submitted', 'date']
];
const decisionDataPairs: Pairs = [['Decision', 'resolutionNotes']];

function LabelValuePairs({detail, pairs}: {detail: DetailData; pairs: Pairs}) {
return (
<React.Fragment>
{pairs.map((pair) => (
<div className="label-value-pair" key={pair[0]}>
<div className="label">{pair[0]}</div>
<RawHTML className="value" html={detail[pair[1]] ?? ''} />
</div>
))}
</React.Fragment>
);
}

export default function Detail({data}: {data: Errata}) {
const detail = useErrataDetail(data);

if (!detail) {
return null;
}
const showDecisionDetails = shouldShowDecisionDetails(data);

return (
<React.Fragment>
{showDecisionDetails && (
<div className="info body-block graybottom">
<LabelValuePairs
detail={detail}
pairs={decisionDataPairs}
/>
</div>
)}
<div className="info body-block">
<LabelValuePairs detail={detail} pairs={detailDataPairs} />
</div>
<div className="note">
{'You can check the status of all errata submissions on the '}
<a
href={`/errata/?book=${encodeURIComponent(detail.bookTitle)}`}
>
<RawHTML Tag="span" html={detail.bookTitle} /> Errata Page
</a>
.
</div>
</React.Fragment>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import LoaderPage from '~/components/jsx-helpers/loader-page';
import React from 'react';
import ProgressBar from './progress-bar/progress-bar';
import Detail from './detail/detail';
import {getDisplayStatus} from '~/helpers/errata';
import {getDisplayStatus, Errata} from '~/helpers/errata';
import {useLocation} from 'react-router-dom';
import './errata-detail.scss';

function ProgressBarBlock({data}) {
function ProgressBarBlock({data}: {data: Errata}) {
const {status, barStatus} = getDisplayStatus(data);

return (
Expand All @@ -15,21 +16,20 @@ function ProgressBarBlock({data}) {
);
}

export function ErrataDetailBlock({data}) {
export function ErrataDetailBlock({data}: {data: Errata}) {
return (
<div className="errata-detail-block">
<Detail data={data} />
</div>
);
}

function ErrataDetail({data}) {
if (!data) {
return null;
}
function ErrataDetail({data}: {data: Errata}) {
return (
<React.Fragment>
<div className="hero padded"><h1>Errata Submission Details</h1></div>
<div className="hero padded">
<h1>Errata Submission Details</h1>
</div>
<div className="boxed">
<ProgressBarBlock data={data} />
<ErrataDetailBlock data={data} />
Expand All @@ -39,9 +39,11 @@ function ErrataDetail({data}) {
}

export default function ErrataDetailLoader() {
const slug = useLocation().pathname.substring(1);

return (
<div className="errata-detail page">
<LoaderPage slug={window.location.pathname.substring(1)} Child={ErrataDetail} doDocumentSetup />
<LoaderPage slug={slug} Child={ErrataDetail} doDocumentSetup />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@ import React from 'react';
import './progress-bar.scss';

// eslint-disable-next-line complexity
export default function ProgressBar({status, barStatus}) {
const thirdNodeFill = ['Corrected', 'Will correct'].includes(barStatus) ?
' filled' : ' filled-no';
const bars = barStatus ? 2 : {
'In Review': 0,
'Reviewed': 1,
'Will Correct': 1
}[status];
export default function ProgressBar({
status,
barStatus
}: {
status: string;
barStatus: string;
}) {
const thirdNodeFill = ['Corrected', 'Will correct'].includes(barStatus)
? ' filled'
: ' filled-no';
const bars = barStatus
? 2
: ({
'In Review': 0,
Reviewed: 1,
'Will Correct': 1
}[status] as number);
const firstNodeClass = bars === 0 ? ' filled ' : '';
const secondNodeClass = bars === 1 ? ' filled' : '';
const thirdNodeClass = bars > 1 ? thirdNodeFill : '';
Expand Down
66 changes: 66 additions & 0 deletions test/src/pages/errata/errata-detail.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import {render, screen} from '@testing-library/preact';
import ErrataDetailLoader from '~/pages/errata-detail/errata-detail';
import MemoryRouter from '~/../../test/helpers/future-memory-router';
import ProgressBar from '~/pages/errata-detail/progress-bar/progress-bar';
import * as HE from '~/helpers/errata';
import * as DH from '~/helpers/use-document-head';

jest.spyOn(DH, 'setPageTitleAndDescriptionFromBookData').mockReturnValue();

describe('Errata Detail', () => {
it('renders', async () => {
render(
<MemoryRouter initialEntries={['/errata/7199']}>
<ErrataDetailLoader />
</MemoryRouter>
);
await screen.findByRole('heading', {
level: 1,
name: 'Errata Submission Details'
});
await screen.findByText('You can check', {exact: false});
});
it('renders decision details', async () => {
const spySSED = jest
.spyOn(HE, 'shouldShowDecisionDetails')
.mockReturnValueOnce(true);

render(
<MemoryRouter initialEntries={['/errata/7199']}>
<ErrataDetailLoader />
</MemoryRouter>
);
await screen.findByText('You can check', {exact: false});
const bb = document.querySelector('.body-block.graybottom');

expect(bb?.textContent).toBe('Decision');
spySSED.mockReset();
});
describe('progress bar', () => {
it('represents reviewed', () => {
render(<ProgressBar status="Reviewed" barStatus="" />);
const bar = document.querySelectorAll('.progress-bar-layer')[1];

expect(bar?.innerHTML).toBe(
'<div class="node"></div><div class="node filled"></div><div class="node"></div>'
);
});
it('represents will-correct', () => {
render(<ProgressBar status="Will Correct" barStatus="" />);
const bar = document.querySelectorAll('.progress-bar-layer')[1];

expect(bar?.innerHTML).toBe(
'<div class="node"></div><div class="node filled"></div><div class="node"></div>'
);
});
it('represents corrected', () => {
render(<ProgressBar status="anything" barStatus="Corrected" />);
const bar = document.querySelectorAll('.progress-bar-layer')[1];

expect(bar?.innerHTML).toBe(
'<div class="node"></div><div class="node"></div><div class="node filled"></div>'
);
});
});
});