);
@@ -104,6 +111,8 @@ const DeparturesColumn = props => {
DeparturesColumn.propTypes = {
departures: PropTypes.array.isRequired,
stop: PropTypes.object.isRequired,
+ showBothDirections: PropTypes.bool.isRequired,
+ isLastStop: PropTypes.bool.isRequired,
};
const LineTableColumns = props => {
@@ -117,13 +126,12 @@ const LineTableColumns = props => {
});
return (
@@ -131,13 +139,12 @@ const LineTableColumns = props => {
}
return (
diff --git a/src/components/lineTimetable/lineTableHeader.css b/src/components/lineTimetable/lineTableHeader.css
index db5490be..8c9154e7 100644
--- a/src/components/lineTimetable/lineTableHeader.css
+++ b/src/components/lineTimetable/lineTableHeader.css
@@ -1,20 +1,27 @@
+.headerContainer {
+ display: flex;
+}
+
.stop {
flex-grow: 1;
- height: 60px;
+ height: 50px;
padding-right: 16px;
- margin-bottom: 2rem;
+ margin-bottom: 1.5rem;
}
.stopNamePrimary {
- font-size: 1.2em;
- margin: 0 0 0 2rem;
+ font-size: 1rem;
+ margin: 0 0 0 1.2rem;
font-family: GothamRounded-Medium;
- word-break: normal;
}
.stopNameSecondary {
- font-size: 1.2em;
- margin: 0 0 0 2rem;
+ font-size: 1rem;
+ margin: 0 0 0 1.2rem;
font-family: GothamXNarrow-Book;
- word-break: normal;
+}
+
+.directionBracket {
+ font-family: GothamRounded-Medium;
+ font-size: 1rem;
}
diff --git a/src/components/lineTimetable/lineTableHeader.js b/src/components/lineTimetable/lineTableHeader.js
index 2ca8c544..ffa2005e 100644
--- a/src/components/lineTimetable/lineTableHeader.js
+++ b/src/components/lineTimetable/lineTableHeader.js
@@ -4,17 +4,21 @@ import PropTypes from 'prop-types';
import styles from './lineTableHeader.css';
const LineTableHeader = props => {
- const { stop } = props;
+ const { stop, isLastStop } = props;
return (
-
-
{stop.nameFi}
-
{stop.nameSe}
+
+
+
{stop.nameFi}
+
{stop.nameSe}
+
+ {!isLastStop &&
>
}
);
};
LineTableHeader.propTypes = {
stop: PropTypes.object.isRequired,
+ isLastStop: PropTypes.bool.isRequired,
};
export default LineTableHeader;
diff --git a/src/components/lineTimetable/lineTimetable.css b/src/components/lineTimetable/lineTimetable.css
index c6699eb2..742cd477 100644
--- a/src/components/lineTimetable/lineTimetable.css
+++ b/src/components/lineTimetable/lineTimetable.css
@@ -143,14 +143,15 @@
}
.timetableDays {
- margin: 0 1rem 1rem 2rem;
- font-size: 1.5em;
+ margin: 0 1rem 1rem 1.2rem;
+ font-size: 0.8em;
font-family: GothamRounded-Book;
+ word-wrap: break-word;
}
.timetableDates {
margin: 0 1rem 1rem 2rem;
- font-size: 1.5em;
+ font-size: 0.8em;
font-family: GothamRounded-Book;
}
@@ -168,6 +169,17 @@
page-break-after: always;
}
+.fridayNote {
+ margin-left: 1.5rem;
+ font-family: GothamRounded-Book;
+ font-size: 12px;
+}
+
+.notesContainer {
+ margin: 0.5rem 0 1rem 0.5rem;
+ page-break-after: always;
+}
+
@media print {
.noPrint,
.noPrint * {
diff --git a/src/components/lineTimetable/lineTimetable.js b/src/components/lineTimetable/lineTimetable.js
index 7d38558f..6b173f68 100644
--- a/src/components/lineTimetable/lineTimetable.js
+++ b/src/components/lineTimetable/lineTimetable.js
@@ -21,7 +21,7 @@ import { scheduleSegments } from '../../util/domain';
import { addMissingFridayNote, combineConsecutiveDays } from '../timetable/timetableContainer';
import { shortenTrainParsedLineId } from '../../util/routes';
-const MAX_STOPS = 6; // Maximum amount of timed stops rendered on the timetable
+const MAX_STOPS = 4; // Maximum amount of timed stops rendered on the timetable
const getScheduleWeekdaysText = dayType => {
switch (dayType) {
@@ -183,6 +183,7 @@ const RouteDepartures = props => {
});
const combinedDepartureTables = Object.keys(mergedWeekdaysDepartures[0].combinedDays).map(key => {
+ const showDivider = departuresByStop.length === 1 ? false : !showTimedStops;
return (
{
{formatDate(new Date(dateBegin))}-{formatDate(new Date(dateEnd))}
@@ -232,16 +233,6 @@ RouteDepartures.propTypes = {
showTimedStops: PropTypes.bool,
};
-const dateRangeHasDepartures = routeDepartures => {
- const hasDepartures = find(
- Object.values(routeDepartures.departuresByStop[0].departures),
- weekday => {
- return !isEmpty(weekday);
- },
- );
- return hasDepartures;
-};
-
const checkForTrainRoutes = routes => {
return routes.map(route => {
if (route.mode === 'RAIL') {
@@ -251,12 +242,27 @@ const checkForTrainRoutes = routes => {
});
};
+// Add note for friday departures because of merged timetables
+const addFridayNote = notes => {
+ return notes.splice(0, 0, { noteText: 'p) Vain perjantaisin' });
+};
+
function LineTimetable(props) {
const { routes } = props;
+ const notes = props.line.notes.nodes;
+ addFridayNote(notes);
const showTimedStops = hasTimedStopRoutes(routes);
const checkedRoutes = checkForTrainRoutes(routes);
+ const mappedNotes = notes.map(note => {
+ return (
+
+ {note.noteText}
+
+ );
+ });
+
if (showTimedStops) {
return (
@@ -311,6 +317,12 @@ function LineTimetable(props) {
return routeDeparturesForDateRanges;
})}
+ {checkedRoutes.length >= 1 &&
{mappedNotes}
}
+ {checkedRoutes.length === 0 && (
+
+ Linjaa ei löytynyt, tarkista tulosteen asetukset
+
+ )}
);
}
@@ -362,27 +374,50 @@ function LineTimetable(props) {
return routeWithDepartures.departuresByDateRanges.map(departuresFordateRange => {
const { nameFi, nameSe, routeIdParsed } = routeWithDepartures;
const { dateBegin, dateEnd, departuresByStop } = departuresFordateRange;
+
+ const hasDepartures = some(departuresByStop, stop =>
+ some(stop.departures, departureDay => departureDay.length > 0),
+ );
+
+ if (
+ hasDepartures &&
+ departuresByStop[0].stop.stopId === departuresByStop[1].stop.stopId
+ ) {
+ departuresByStop.pop(1);
+ }
+
return (
-
-
+ {hasDepartures && (
+
+ )}
+ {hasDepartures && (
+
+ )}
+ {hasDepartures &&
}
);
});
})}
+ {checkedRoutes.length >= 1 && {mappedNotes}
}
+ {checkedRoutes.length === 0 && (
+
+ Linjaa ei löytynyt, tarkista tulosteen asetukset
+
+ )}
);
}
diff --git a/src/components/lineTimetable/lineTimetableContainer.js b/src/components/lineTimetable/lineTimetableContainer.js
index 3abadf85..b66d77b0 100644
--- a/src/components/lineTimetable/lineTimetableContainer.js
+++ b/src/components/lineTimetable/lineTimetableContainer.js
@@ -4,7 +4,7 @@ import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import mapProps from 'recompose/mapProps';
import compose from 'recompose/compose';
-import { filter, isEmpty, uniqBy } from 'lodash';
+import { filter, forEach, isEmpty, uniqBy, some } from 'lodash';
import apolloWrapper from 'util/apolloWrapper';
@@ -74,6 +74,7 @@ const lineQuery = gql`
dateEnd
timingStopType
stopIndex
+ note
}
}
}
@@ -90,6 +91,8 @@ const lineQuery = gql`
}
`;
+const VARIKKOLINJA_REGEX = /\d{4}[\w]\d+/;
+
const regularDayTypes = ['Ma', 'Ti', 'Ke', 'To', 'Pe', 'La', 'Su'];
const groupByValidityDateRange = departures => {
@@ -142,11 +145,59 @@ const groupDeparturesByWeekday = departuresByStop => {
});
};
-// Filters 'varikkolinja' routes from the timetable
-const removeExtraRoutes = routes => {
- return filter(routes, route => {
+const hasSameTimedStops = (variantRoute, regularRoute) => {
+ const regularTimedStops = regularRoute.timedStops.nodes;
+ const variantTimedStops = variantRoute.timedStops.nodes;
+
+ if (regularTimedStops.length !== variantTimedStops.length) {
+ return false;
+ }
+
+ let hasSameStops = true;
+ for (let i = 0; i < regularTimedStops.length; i++) {
+ const regularRouteStop = regularTimedStops[i];
+ const variantRouteStop = variantTimedStops[i];
+
+ if (regularRouteStop.stop.stopId !== variantRouteStop.stop.stopId) {
+ hasSameStops = false;
+ }
+ }
+ return hasSameStops;
+};
+
+// Merge variant routes from the timetable if they have the same timed stops.
+const mergeExtraRoutes = routes => {
+ // Filter 'varikkolinja' routes from the list
+ const filteredRoutes = filter(routes, route => {
+ if (route.mode === 'TRAM') {
+ return route.routeId.match(VARIKKOLINJA_REGEX) === null;
+ }
+ return true;
+ });
+
+ const regularRoutes = filter(filteredRoutes, route => {
return !route.routeId.includes(' ');
});
+
+ const variantRoutes = filter(filteredRoutes, route => {
+ return route.routeId.includes(' ');
+ });
+
+ forEach(variantRoutes, variantRoute => {
+ forEach(regularRoutes, regularRoute => {
+ if (
+ regularRoute.routeIdParsed === variantRoute.routeIdParsed &&
+ regularRoute.mode === variantRoute.mode &&
+ regularRoute.direction === variantRoute.direction
+ ) {
+ if (hasSameTimedStops(variantRoute, regularRoute)) {
+ // Found a matching "regular" route where we can merge variant departures
+ regularRoute.timedStopsDepartures.nodes.push(...variantRoute.timedStopsDepartures.nodes);
+ }
+ }
+ });
+ });
+ return regularRoutes;
};
// Filters empty routes from the timetable
@@ -160,9 +211,9 @@ const lineQueryMapper = mapProps(props => {
const line = props.data.lines.nodes[0];
const { showPrintBtn, lang } = props;
- const filteredRoutes = removeExtraRoutes(line.routes.nodes);
+ const mergedRoutes = mergeExtraRoutes(line.routes.nodes);
- const routesWithGroupedDepartures = filteredRoutes.map(route => {
+ const routesWithGroupedDepartures = mergedRoutes.map(route => {
const byValidityDateRange = groupByValidityDateRange(route.timedStopsDepartures.nodes);
const departuresByStopsAndDateRanges = groupDepartureDateRangesForStops(
route,
diff --git a/src/components/lineTimetable/lineTimetableHeader.css b/src/components/lineTimetable/lineTimetableHeader.css
index bca7631c..3a5502e4 100644
--- a/src/components/lineTimetable/lineTimetableHeader.css
+++ b/src/components/lineTimetable/lineTimetableHeader.css
@@ -2,10 +2,12 @@
display: flex;
margin-bottom: 1rem;
word-wrap: break-word;
+ page-break-before: always;
+ page-break-inside: avoid;
}
.lineId {
- font-size: 4rem;
+ font-size: 2rem;
margin: 2rem 2rem 0 2rem;
font-family: GothamRounded-Medium;
}
@@ -16,12 +18,12 @@
}
.lineName {
- font-size: 30px;
+ font-size: 20px;
font-family: GothamRounded-Medium;
}
.lineNameSecondary {
- font-size: 25px;
+ font-size: 15px;
font-family: GothamRounded-Book;
}
diff --git a/src/components/timetable/timetable.js b/src/components/timetable/timetable.js
index 330245a1..256880a5 100644
--- a/src/components/timetable/timetable.js
+++ b/src/components/timetable/timetable.js
@@ -46,7 +46,7 @@ const getZoneLetterStyle = zone => ({
: 'translate(-50%, -50%)', // No px adjustments for zone A and the "else" case.
});
-const getNotes = (notes, symbols) => {
+export const getNotes = (notes, symbols) => {
const parsedNotes = [];
symbols.forEach(symbol => {
notes.forEach(note => {
diff --git a/src/components/timetable/timetableContainer.js b/src/components/timetable/timetableContainer.js
index b4f1666a..af3e1ea4 100644
--- a/src/components/timetable/timetableContainer.js
+++ b/src/components/timetable/timetableContainer.js
@@ -258,7 +258,7 @@ export function addMissingFridayNote(departure) {
departure.dayType.includes('Pe') &&
(!departure.note || !departure.note.includes('p'))
? 'p'
- : null;
+ : departure.note;
}
function addMissingNonAccessibleNote(departure) {