Skip to content

Commit 7c7c87b

Browse files
committed
Implement latest changes to line page
1 parent 37e07ab commit 7c7c87b

10 files changed

Lines changed: 381 additions & 36 deletions

File tree

ui/src/components/routes-and-lines/line-change-history/components/LineChangeHistoryDataRows.tsx

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,14 @@
11
import { FC } from 'react';
22
import { GetUserNameById } from '../../../../hooks';
33
import { PagingInfo } from '../../../../types';
4-
import { NoEarlierVersionExists } from '../../../common/ChangeHistory';
5-
import { LineChangeHistoryItem, PreviousLineChangeHistoryItem } from '../types';
4+
import { LineChangeHistoryItem } from '../types';
5+
import { findPreviousLineHistoryItemVersion } from '../utils';
66
import { LineChangeHistoryItemSections } from './LineChangeHistoryItem';
77

88
const testIds = {
99
group: (id: string) => `ChangeHistory::Group::${id}`,
1010
};
1111

12-
function findPreviousVersion(
13-
historyItemsSortedByVersion: ReadonlyArray<LineChangeHistoryItem>,
14-
item: LineChangeHistoryItem,
15-
): PreviousLineChangeHistoryItem {
16-
if (item.tgOperation === 'INSERT') {
17-
return NoEarlierVersionExists;
18-
}
19-
20-
const previous = historyItemsSortedByVersion.find(
21-
(other) =>
22-
other.id < item.id &&
23-
other.lineId === item.lineId &&
24-
other.routeId === item.routeId,
25-
);
26-
27-
if (previous) {
28-
return previous;
29-
}
30-
31-
throw new Error('Unable to find previous version!');
32-
}
33-
3412
type LineChangeHistoryDataRowsProps = {
3513
readonly getUserNameById: GetUserNameById;
3614
readonly historyItems: ReadonlyArray<LineChangeHistoryItem>;
@@ -62,7 +40,10 @@ export const LineChangeHistoryDataRows: FC<LineChangeHistoryDataRowsProps> = ({
6240
<LineChangeHistoryItemSections
6341
getUserNameById={getUserNameById}
6442
historyItem={historyItem}
65-
previousHistoryItem={findPreviousVersion(historyItems, historyItem)}
43+
previousHistoryItem={findPreviousLineHistoryItemVersion(
44+
historyItems,
45+
historyItem,
46+
)}
6647
/>
6748
</tbody>
6849
));
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { FC } from 'react';
2+
import {
3+
ErrorLoadingState,
4+
LoadingState,
5+
} from '../../../../common/ChangeHistory/latest';
6+
import { useGetLineChangeHistoryItemData } from '../../queries';
7+
import {
8+
LineChangeHistoryItem,
9+
LineData,
10+
PreviousLineChangeHistoryItem,
11+
} from '../../types';
12+
import { LatestLineChangeSection } from './LatestLineChangeSection';
13+
import { LatestRouteChangeSection } from './LatestRouteChangeSection';
14+
15+
const testIds = {
16+
loading: 'LatestLineChangeHistoryTable::Item::Loading',
17+
error: 'LatestLineChangeHistoryTable::Item::Error',
18+
};
19+
20+
type LatestLineChangeDataDiffProps = {
21+
readonly historyItem: LineChangeHistoryItem;
22+
readonly previousHistoryItem: PreviousLineChangeHistoryItem;
23+
readonly label: string;
24+
};
25+
26+
export const LatestLineChangeDataDiff: FC<LatestLineChangeDataDiffProps> = ({
27+
historyItem,
28+
previousHistoryItem,
29+
label,
30+
}) => {
31+
const result = useGetLineChangeHistoryItemData(
32+
historyItem,
33+
previousHistoryItem as LineChangeHistoryItem,
34+
);
35+
36+
if (result.loading) {
37+
return <LoadingState testIdPrefix={testIds.loading} />;
38+
}
39+
40+
if (result.error) {
41+
return (
42+
<ErrorLoadingState
43+
testIdPrefix={testIds.error}
44+
onRetry={result.refetch}
45+
/>
46+
);
47+
}
48+
49+
const currentItemData = result.currentItemData as LineData;
50+
const previousItemData = result.previousItemData as LineData;
51+
52+
if (historyItem.routeId) {
53+
return (
54+
<LatestRouteChangeSection
55+
historyItem={historyItem}
56+
currentItemData={currentItemData}
57+
previousItemData={previousItemData}
58+
label={label}
59+
/>
60+
);
61+
}
62+
63+
return (
64+
<LatestLineChangeSection
65+
historyItem={historyItem}
66+
currentItemData={currentItemData}
67+
previousItemData={previousItemData}
68+
label={label}
69+
/>
70+
);
71+
};
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { FC } from 'react';
2+
import { Trans, useTranslation } from 'react-i18next';
3+
import { Link } from 'react-router';
4+
import { Path, routeDetails } from '../../../../../router/routeDetails';
5+
import { NoEarlierVersionExists } from '../../../../common/ChangeHistory';
6+
import {
7+
LineChangeHistoryItem,
8+
PreviousLineChangeHistoryItem,
9+
} from '../../types';
10+
import { HistoricalRouteDirectionBadge } from '../HistoricalRouteDirectionBadge';
11+
import { LatestLineChangeDataDiff } from './LatestLineChangeDataDiff';
12+
13+
const testIds = {
14+
newItem: 'LatestLineChangeHistoryTable::Item::NewItem',
15+
};
16+
17+
type LatestLineChangeHistoryItemProps = {
18+
readonly historyItem: LineChangeHistoryItem;
19+
readonly previousHistoryItem: PreviousLineChangeHistoryItem;
20+
readonly label: string;
21+
};
22+
23+
export const LatestLineChangeHistoryItem: FC<
24+
LatestLineChangeHistoryItemProps
25+
> = ({ historyItem, previousHistoryItem, label }) => {
26+
const { t } = useTranslation();
27+
28+
if (previousHistoryItem === NoEarlierVersionExists) {
29+
return (
30+
<div className="mb-3 text-sm font-semibold" data-testid={testIds.newItem}>
31+
<Link
32+
to={routeDetails[Path.lineChangeHistory].getLink(label)}
33+
className="text-brand hover:underline"
34+
>
35+
{historyItem.routeId ? (
36+
<Trans
37+
t={t}
38+
i18nKey={($) => $.lineChangeHistory.newRouteVersion}
39+
components={{
40+
Direction: <HistoricalRouteDirectionBadge item={historyItem} />,
41+
}}
42+
values={historyItem}
43+
/>
44+
) : (
45+
t(($) => $.lineChangeHistory.newLineVersion, historyItem)
46+
)}
47+
</Link>
48+
</div>
49+
);
50+
}
51+
52+
return (
53+
<LatestLineChangeDataDiff
54+
historyItem={historyItem}
55+
previousHistoryItem={previousHistoryItem}
56+
label={label}
57+
/>
58+
);
59+
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { FC } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { Path, routeDetails } from '../../../../../router/routeDetails';
4+
import { LatestChangeHistoryItem } from '../../../../common/ChangeHistory/latest';
5+
import { LineChangeHistoryItem, LineData } from '../../types';
6+
import { diffLine } from '../../utils';
7+
8+
type LatestLineChangeSectionProps = {
9+
readonly historyItem: LineChangeHistoryItem;
10+
readonly currentItemData: LineData;
11+
readonly previousItemData: LineData;
12+
readonly label: string;
13+
};
14+
15+
export const LatestLineChangeSection: FC<LatestLineChangeSectionProps> = ({
16+
historyItem,
17+
currentItemData,
18+
previousItemData,
19+
label,
20+
}) => {
21+
const { t } = useTranslation();
22+
23+
const sections = [
24+
{
25+
title: t(($) => $.lineChangeHistory.lineSectionTitle, {
26+
lineLabel: currentItemData.label,
27+
name: currentItemData.name_i18n.fi_FI,
28+
}),
29+
changes: diffLine(t, previousItemData, currentItemData),
30+
},
31+
].filter((it) => it.changes.length > 0);
32+
33+
return (
34+
<LatestChangeHistoryItem
35+
historyItem={historyItem}
36+
sections={sections}
37+
link={routeDetails[Path.lineChangeHistory].getLink(label)}
38+
testId="LatestLineChangeHistoryTable::Item::Diff"
39+
/>
40+
);
41+
};
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { FC } from 'react';
2+
import { Trans, useTranslation } from 'react-i18next';
3+
import { Path, routeDetails } from '../../../../../router/routeDetails';
4+
import { LatestChangeHistoryItem } from '../../../../common/ChangeHistory/latest';
5+
import { LineChangeHistoryItem, LineData } from '../../types';
6+
import { diffRouteDetails } from '../../utils';
7+
import { HistoricalRouteDirectionBadge } from '../HistoricalRouteDirectionBadge';
8+
9+
type LatestRouteChangeSectionProps = {
10+
readonly historyItem: LineChangeHistoryItem;
11+
readonly currentItemData: LineData;
12+
readonly previousItemData: LineData;
13+
readonly label: string;
14+
};
15+
16+
export const LatestRouteChangeSection: FC<LatestRouteChangeSectionProps> = ({
17+
historyItem,
18+
currentItemData,
19+
previousItemData,
20+
label,
21+
}) => {
22+
const { t } = useTranslation();
23+
24+
const currentRoute = currentItemData.routes.find(
25+
(it) => it.route_id === historyItem.routeId,
26+
);
27+
const previousRoute = previousItemData.routes.find(
28+
(it) => it.route_id === historyItem.routeId,
29+
);
30+
31+
if (!currentRoute || !previousRoute) {
32+
return null;
33+
}
34+
35+
const title = (
36+
<Trans
37+
t={t}
38+
i18nKey={($) => $.lineChangeHistory.routeSectionTitle}
39+
components={{
40+
Direction: <HistoricalRouteDirectionBadge item={historyItem} />,
41+
}}
42+
values={{
43+
routeLabel: currentRoute.label,
44+
name: currentRoute.name_i18n.fi_FI,
45+
}}
46+
/>
47+
) as unknown as string;
48+
49+
const sections = [
50+
{
51+
title,
52+
changes: diffRouteDetails(t, previousRoute, currentRoute),
53+
},
54+
].filter((it) => it.changes.length > 0);
55+
56+
return (
57+
<LatestChangeHistoryItem
58+
historyItem={historyItem}
59+
sections={sections}
60+
link={routeDetails[Path.lineChangeHistory].getLink(label)}
61+
testId="LatestLineChangeHistoryTable::Item::Diff"
62+
/>
63+
);
64+
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { FC } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { Link } from 'react-router';
4+
import { Path, routeDetails } from '../../../../../router/routeDetails';
5+
import {
6+
ErrorLoadingState,
7+
LoadingState,
8+
} from '../../../../common/ChangeHistory/latest';
9+
import { useGetLatestLineChangeHistory } from '../../queries';
10+
import { findPreviousLineHistoryItemVersion } from '../../utils';
11+
import { LatestLineChangeHistoryItem } from './LatestLineChangeHistoryItem';
12+
13+
const testIds = {
14+
container: 'LatestLineChangeHistoryTable::Container',
15+
title: 'LatestLineChangeHistoryTable::Title',
16+
loading: 'LatestLineChangeHistoryTable::Loading',
17+
failedToLoad: 'LatestLineChangeHistoryTable::FailedToLoad',
18+
retryButton: 'LatestLineChangeHistoryTable::RetryButton',
19+
showAllLink: 'LatestLineChangeHistoryTable::ShowAllLink',
20+
};
21+
22+
type LineLatestChangesProps = {
23+
readonly className?: string;
24+
readonly label: string;
25+
};
26+
27+
export const LineLatestChanges: FC<LineLatestChangesProps> = ({
28+
className,
29+
label,
30+
}) => {
31+
const { t } = useTranslation();
32+
const { historyItems, latestHistoryItems, loading, error, refetch } =
33+
useGetLatestLineChangeHistory(label);
34+
35+
if (error) {
36+
return (
37+
<ErrorLoadingState
38+
onRetry={() => refetch()}
39+
testIdPrefix="LatestLineChangeHistoryTable"
40+
/>
41+
);
42+
}
43+
44+
if (loading) {
45+
return <LoadingState testIdPrefix="LatestLineChangeHistoryTable" />;
46+
}
47+
48+
return (
49+
<div className={className} data-testid={testIds.container}>
50+
<h3 className="mb-4" data-testid={testIds.title}>
51+
{t(($) => $.stopChangeHistory.titleLatest)}
52+
</h3>
53+
{latestHistoryItems.map((item) => {
54+
return (
55+
<LatestLineChangeHistoryItem
56+
key={item.id}
57+
historyItem={item}
58+
previousHistoryItem={findPreviousLineHistoryItemVersion(
59+
historyItems,
60+
item,
61+
)}
62+
label={label}
63+
/>
64+
);
65+
})}
66+
<Link
67+
to={routeDetails[Path.lineChangeHistory].getLink(label)}
68+
className="mt-4 text-sm font-bold text-brand hover:underline"
69+
data-testid={testIds.showAllLink}
70+
>
71+
{t(($) => $.stopChangeHistory.showAll)}
72+
</Link>
73+
</div>
74+
);
75+
};

0 commit comments

Comments
 (0)