diff --git a/scripts/server.js b/scripts/server.js index f9e6e622..01e17675 100644 --- a/scripts/server.js +++ b/scripts/server.js @@ -62,11 +62,8 @@ const cancelSignalRedis = new Redis(REDIS_CONNECTION_STRING); async function generatePoster(buildId, component, props, index) { const { stopId, date, template, selectedRuleTemplates } = props; - // RuleTemplates are not available for TerminalPoster and LineTimetable - const data = - component !== 'TerminalPoster' && component !== 'LineTimetable' - ? await getStopInfo({ stopId, date }) - : null; + // RuleTemplates are not available for TerminalPoster + const data = component !== 'TerminalPoster' ? await getStopInfo({ stopId, date }) : null; // Checks if any rule template will match the stop, and returns *the first one*. // If no match, returns the default template. diff --git a/src/components/app.js b/src/components/app.js index 11daadc2..5cd9195b 100644 --- a/src/components/app.js +++ b/src/components/app.js @@ -10,7 +10,6 @@ import StopPoster from 'components/stopPoster/stopPosterContainer'; import Timetable from 'components/timetable/timetableContainer'; import A3StopPoster from 'components/a3stopPoster/a3StopPosterContainer'; import TerminalPoster from 'components/stopPoster/terminalPosterContainer'; -import LineTimetable from 'components/lineTimetable/lineTimetableContainer'; import renderQueue from 'util/renderQueue'; const components = { @@ -18,7 +17,6 @@ const components = { Timetable, A3StopPoster, TerminalPoster, - LineTimetable, }; const graphqlUrl = process.env.JORE_GRAPHQL_URL || 'https://kartat.hsl.fi/jore/graphql'; diff --git a/src/components/lineTimetable/allStopsList.css b/src/components/lineTimetable/allStopsList.css deleted file mode 100644 index 1c96db48..00000000 --- a/src/components/lineTimetable/allStopsList.css +++ /dev/null @@ -1,26 +0,0 @@ -.stopListsContainer { - margin-top: 2rem; - max-width: 1171px; -} - -.stopList { - margin-bottom: 2rem; - padding-left: 1.2rem; -} - -.lineInfoText { - font-family: GothamRounded-Medium; - font-weight: bold; - font-size: 2rem; -} - -.stopListText { - font-size: medium; - font-family: GothamRounded-Book; -} - -@media print { - .stopListsContainer { - page-break-inside: avoid; - } -} diff --git a/src/components/lineTimetable/allStopsList.js b/src/components/lineTimetable/allStopsList.js deleted file mode 100644 index 6d822576..00000000 --- a/src/components/lineTimetable/allStopsList.js +++ /dev/null @@ -1,71 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import styles from './allStopsList.css'; - -const TEXT_LANG = { - FI: 'fi', - SE: 'se', -}; - -const getLineInfoText = (lang, lineId) => { - let infoText = null; - switch (lang) { - case TEXT_LANG.FI: - infoText = `Linjan ${lineId} pysäkit:`; - break; - - case TEXT_LANG.SE: - infoText = `Hållplatser for linje ${lineId}:`; - break; - - default: - infoText = ''; - } - - return infoText; -}; - -const parseStopNames = stops => { - return { - namesFi: stops.map(item => { - return item.stop.nameFi; - }), - namesSe: stops.map(item => { - return item.stop.nameSe; - }), - }; -}; - -const StopList = props => { - const { stops, lang, lineId } = props; - return ( -
-

{getLineInfoText(lang, lineId)}

-

{stops.join(' - ')}

-
- ); -}; - -StopList.propTypes = { - stops: PropTypes.array.isRequired, - lang: PropTypes.string.isRequired, - lineId: PropTypes.string.isRequired, -}; - -const AllStopsList = props => { - const { stops, lineId } = props; - const parsedStopLists = parseStopNames(stops); - return ( -
- - -
- ); -}; - -AllStopsList.propTypes = { - stops: PropTypes.array.isRequired, - lineId: PropTypes.string.isRequired, -}; - -export default AllStopsList; diff --git a/src/components/lineTimetable/lineTableColumns.css b/src/components/lineTimetable/lineTableColumns.css deleted file mode 100644 index c1cb9eac..00000000 --- a/src/components/lineTimetable/lineTableColumns.css +++ /dev/null @@ -1,31 +0,0 @@ -.departureRowContainer { - max-width: 1171px; - font-family: GothamRounded-Medium; -} - -.departureRowContainer > *:nth-child(odd) { - background-color: #e8e8e8; -} - -.departureRow { - font-size: 1.2rem; - margin-left: 2rem; - padding-top: 5px; - padding-bottom: 5px; -} - -.departureColumnContainer { - flex-grow: 1; - align-items: normal; -} - -.tableContainer { - display: flex; - margin-top: 1rem; -} - -@media print { - .departureRow { - page-break-inside: avoid; - } -} diff --git a/src/components/lineTimetable/lineTableColumns.js b/src/components/lineTimetable/lineTableColumns.js deleted file mode 100644 index 74efdd76..00000000 --- a/src/components/lineTimetable/lineTableColumns.js +++ /dev/null @@ -1,92 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { combineConsecutiveDays } from '../timetable/timetableContainer'; -import { Column, Row, WrappingRow } from '../util'; -import LineTableHeader from './lineTableHeader'; -import styles from './lineTableColumns.css'; - -const LineTimetableRow = props => { - const { hours, minutes } = props; - const paddedMins = minutes.toString().padStart(2, '0'); - return ( - - - {hours}.{paddedMins} - - - ); -}; - -LineTimetableRow.propTypes = { - hours: PropTypes.number.isRequired, - minutes: PropTypes.number.isRequired, -}; - -const DeparturesColumn = props => { - const { departures, stop } = props; - const departureRows = departures.map(departure => ( - - )); - - return ( -
- -
{departureRows}
-
- ); -}; - -DeparturesColumn.propTypes = { - departures: PropTypes.array.isRequired, - stop: PropTypes.object.isRequired, -}; - -const LineTableColumns = props => { - const selectedDepartureDays = props.days; - - const mapWeekdayDepartures = props.departures.map(departuresForStop => { - const { - mondays, - tuesdays, - wednesdays, - thursdays, - fridays, - saturdays, - sundays, - } = departuresForStop.departures; - - return { - stop: departuresForStop.stop, - combinedDays: combineConsecutiveDays({ - mondays, - tuesdays, - wednesdays, - thursdays, - fridays, - saturdays, - sundays, - }), - }; - }); - - const departureColums = mapWeekdayDepartures.map(departures => { - return ( - - - - ); - }); - - return
{departureColums}
; -}; - -LineTableColumns.propTypes = { - departures: PropTypes.arrayOf(PropTypes.any).isRequired, - stopSequence: PropTypes.arrayOf(PropTypes.string).isRequired, - days: PropTypes.string.isRequired, -}; - -export default LineTableColumns; diff --git a/src/components/lineTimetable/lineTableHeader.css b/src/components/lineTimetable/lineTableHeader.css deleted file mode 100644 index 486b6dd5..00000000 --- a/src/components/lineTimetable/lineTableHeader.css +++ /dev/null @@ -1,9 +0,0 @@ -.stop { - flex-grow: 1; -} - -.stopName { - font-size: 1.2em; - margin: 0 0 0 2rem; - font-family: GothamRounded-Medium; -} diff --git a/src/components/lineTimetable/lineTableHeader.js b/src/components/lineTimetable/lineTableHeader.js deleted file mode 100644 index 2b0fb808..00000000 --- a/src/components/lineTimetable/lineTableHeader.js +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; - -import styles from './lineTableHeader.css'; - -const LineTableHeader = props => { - const { stop } = props; - return ( -
-

{stop.nameFi}

-

{stop.nameSe}

-
- ); -}; - -LineTableHeader.propTypes = { - stop: PropTypes.object.isRequired, -}; - -export default LineTableHeader; diff --git a/src/components/lineTimetable/lineTimetable.css b/src/components/lineTimetable/lineTimetable.css deleted file mode 100644 index ad4853cf..00000000 --- a/src/components/lineTimetable/lineTimetable.css +++ /dev/null @@ -1,194 +0,0 @@ -.root { - position: relative; - width: 100%; - padding: var(--border-radius); - padding-top: calc(var(--border-radius) - 15px); - border-radius: var(--border-radius); - color: var(--hsl-blue); - background: var(--light-background); - --timetable-accent-color: white; - font-size: 16px; - margin-bottom: 10px; - font-family: GothamRounded-Medium; -} - -.root.a3 { - border-radius: 30px; - padding: 15px 0px 30px 0px; -} - -.root.standalone { - font-size: 22px; -} - -.root.summer { - background: white; - --timetable-accent-color: var(--light-background); -} - -.root.greyscale { - background: white; - color: black; - --timetable-accent-color: #eaeaea; -} - -.root.printable { - width: auto; - border-radius: 0; -} - -.header { - padding: 0 0 0 0.4em; -} - -.headerTitle { - font-size: 1.75em; -} - -.componentName { - padding: 0 0 0 0.205em; - font-size: 1.875em; -} - -.title { - font-family: GothamRounded-Medium; - white-space: nowrap; - font-size: 0.9em; -} - -.subtitle { - font-family: GothamRounded-Book; - font-size: 0.9em; -} - -.footnote { - padding: 0.125em 0.625em; - font-family: GothamXNarrow-Book; - font-size: 0.813em; -} - -.validity { - font-family: GothamXNarrow-Book; - font-size: 0.75em; - line-height: 1.1; - letter-spacing: -0.025em; - text-align: right; - margin-left: auto; - position: absolute; - margin-top: -5px; - top: calc(var(--border-radius)); - right: var(--border-radius); -} - -.validity .shortId { - font-family: GothamRounded-Medium; - font-size: 1.75em; -} - -.address { - font-family: GothamRounded-Medium; - font-size: 0.6rem; - color: black; - position: absolute; - top: 1110px; - right: var(--border-radius); -} - -.validity .title { - font-family: GothamRounded-Medium; -} - -.stopZone { - padding-left: 0.5em; - margin-top: 0.875em; - display: flex; - flex-direction: row; - align-items: center; -} - -.zoneTitle { - font-size: 0.75em; - line-height: 1.1; - font-family: GothamRounded-Medium; - white-space: nowrap; - margin-right: 0.4em; -} - -.zoneSubtitle { - font-size: 0.75em; - composes: zoneTitle; - font-family: GothamRounded-Book; -} - -.zone { - position: relative; - box-sizing: border-box; - flex: none; - width: 1.5em; - height: 1.5em; - color: white; - background: var(--hsl-blue); - border-radius: 50%; -} - -.zoneLetter { - font-size: 1.25em; - position: absolute; - top: 50%; - left: 50%; - text-align: center; - line-height: 1; - font-family: GothamRounded-Medium; - text-transform: uppercase; -} - -.printBtn { - margin-left: 2rem; - background-color: var(--hsl-blue); - margin-top: 1.5rem; - height: 2rem; - width: fit-content; - padding: 0 1rem 0 1rem; - font-size: 0.9rem; - border-radius: 10px; - color: white; - border: none; -} - -.printBtn:hover { - background-color: white; - cursor: pointer; - color: var(--hsl-blue); - border: 1px solid var(--hsl-blue); -} - -.timetableDays { - margin: 0 1rem 1rem 2rem; - font-size: 1em; - font-family: GothamRounded-Book; -} - -.timetableDates { - margin: 0 1rem 1rem 4rem; - font-size: 1em; - font-family: GothamRounded-Book; -} - -.pageBreak { - display: none; -} - -@media print { - .noPrint, - .noPrint * { - display: none !important; - } - .pageBreak { - display: block; - page-break-before: always; - } - - body { - overflow-y: visible; - } -} diff --git a/src/components/lineTimetable/lineTimetable.js b/src/components/lineTimetable/lineTimetable.js deleted file mode 100644 index 1c319c1d..00000000 --- a/src/components/lineTimetable/lineTimetable.js +++ /dev/null @@ -1,120 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import styles from './lineTimetable.css'; -import LineTimetableHeader from './lineTimetableHeader'; -import LineTableColumns from './lineTableColumns'; -import AllStopsList from './allStopsList'; - -const SCHEDULE_SEGMENT = { - weekdays: 'mondays-fridays', - saturdays: 'saturdays', - sundays: 'sundays', -}; - -const formatDate = date => { - const monthNames = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', - ]; - - const day = date.getDate(); - const monthIndex = date.getMonth(); - const year = date.getFullYear(); - - return `${day}.${monthIndex}.${year}`; -}; - -const PrintButton = lang => { - const PRINT_TEXT = { - fi: 'TULOSTA AIKATAULU', - sv: 'SKRIV UT TIDTABEL', - en: 'PRINT SCHEDULE', - }; - - return ( -
- -
- ); -}; - -class LineTimetable extends Component { - constructor(props) { - super(props); - this.state = { - isMultiLineTimetable: false, // Placeholder for implementation of "multiple lines" version - }; - } - - render() { - const { lineIdParsed, nameFi, nameSe } = this.props.line; - const { allStops } = this.props; - - return ( -
- -

{this.state.isMultiLineTimetable}

- Maanantai-Perjantai - Måndag-Fredag - - {formatDate(new Date(this.props.dateBegin))}-{formatDate(new Date(this.props.dateEnd))} - - - -
 
- - Lauantai/Lördag - -
 
- - Sunnuntai/Söndag - -
 
- -
- ); - } -} - -LineTimetable.defaultProps = { - dateBegin: null, - dateEnd: null, - departures: {}, - timedStops: {}, - allStops: [], -}; - -LineTimetable.propTypes = { - line: PropTypes.object.isRequired, - dateBegin: PropTypes.string, - dateEnd: PropTypes.string, - departures: PropTypes.object, - timedStops: PropTypes.object, - allStops: PropTypes.array, -}; - -export default LineTimetable; diff --git a/src/components/lineTimetable/lineTimetableContainer.js b/src/components/lineTimetable/lineTimetableContainer.js deleted file mode 100644 index ac9d3e7f..00000000 --- a/src/components/lineTimetable/lineTimetableContainer.js +++ /dev/null @@ -1,175 +0,0 @@ -/* eslint-disable no-undef */ -import PropTypes from 'prop-types'; -import { graphql } from 'react-apollo'; -import gql from 'graphql-tag'; -import mapProps from 'recompose/mapProps'; -import compose from 'recompose/compose'; -import { filter, find } from 'lodash'; - -import apolloWrapper from 'util/apolloWrapper'; - -import LineTimetable from './lineTimetable'; -import { groupDeparturesByDay } from '../timetable/timetableContainer'; - -const lineQuery = gql` - query lineQuery($lineId: String!, $dateBegin: Date!, $dateEnd: Date!) { - line: lineByLineIdAndDateBeginAndDateEnd( - lineId: $lineId - dateBegin: $dateBegin - dateEnd: $dateEnd - ) { - lineId - lineIdParsed - nameFi - nameSe - dateBegin - dateEnd - trunkRoute - routes { - nodes { - routeId - direction - dateBegin - dateEnd - mode - nameFi - line { - nodes { - trunkRoute - lineIdParsed - } - } - routeSegments { - nodes { - stopIndex - timingStopType - duration - line { - nodes { - trunkRoute - } - } - stop: stopByStopId { - stopId - lat - lon - shortId - nameFi - nameSe - platform - } - } - } - } - } - notes { - nodes { - noteType - noteText - dateEnd - } - } - } - } -`; - -const departureQuery = gql` - query getTimedStopDepartures($routeIdentifier: String!, $routeDirection: String!, $date: Date!) { - departures: getRouteDeparturesForTimedStops( - routeIdentifier: $routeIdentifier - routeDirection: $routeDirection - date: $date - ) { - nodes { - stopId - routeId - direction - departureId - dayType - hours - minutes - isNextDay - timingStopType - } - } - } -`; - -const filterTimedStopsListFromLineQuery = props => { - const routeForSelectedDirection = find(props.data.line.routes.nodes, route => { - return route.direction === props.routeDirection; - }); - const stopList = routeForSelectedDirection.routeSegments.nodes; - const filteredStopsList = filter(stopList, stop => { - return stop.stopIndex <= 1 || stop.timingStopType > 0; - }); - return { timedStops: filteredStopsList, allStops: stopList }; -}; - -const lineQueryMapper = mapProps(props => { - const { dateBegin, dateEnd, routeDirection } = props; - const { line } = props.data; - const { timedStops, allStops } = filterTimedStopsListFromLineQuery(props); - - return { - line, - dateBegin, - dateEnd, - timedStops, - allStops, - date: props.date, - routeIdentifier: props.lineId, - routeDirection, - }; -}); - -const departuresMapper = mapProps(props => { - console.log(props); - const departures = props.data.departures.nodes; - - const departuresByStop = props.timedStops.map(timedStop => { - const stopDepartures = departures.filter( - departure => departure.stopId === timedStop.stop.stopId, - ); - return { - stop: timedStop.stop, - departures: groupDeparturesByDay(stopDepartures), - }; - }); - - return { - line: props.line, - dateBegin: props.dateBegin, - dateEnd: props.dateEnd, - departures: departuresByStop, - timedStops: props.timedStops, - allStops: props.allStops, - }; -}); - -const hoc = compose( - graphql(lineQuery), - apolloWrapper(lineQueryMapper), - graphql(departureQuery), - apolloWrapper(departuresMapper), -); - -const LineTimetableContainer = hoc(LineTimetable); - -LineTimetableContainer.defaultProps = { - dateBegin: null, - dateEnd: null, - date: null, - routeDirection: '1', -}; - -LineTimetableContainer.propTypes = { - lineId: PropTypes.string.isRequired, - stopId: PropTypes.string.isRequired, - dateBegin: PropTypes.string, - dateEnd: PropTypes.string, - date: PropTypes.string, - routeDirection: PropTypes.string, -}; - -export default LineTimetableContainer; diff --git a/src/components/lineTimetable/lineTimetableHeader.css b/src/components/lineTimetable/lineTimetableHeader.css deleted file mode 100644 index e63276be..00000000 --- a/src/components/lineTimetable/lineTimetableHeader.css +++ /dev/null @@ -1,29 +0,0 @@ -.header { - display: flex; - page-break-before: always; - margin-bottom: 1rem; -} - -.lineId { - font-size: 4rem; - font-weight: bold; - margin: 2rem 2rem 0 2rem; - font-family: GothamRounded-Medium; -} - -.nameContainer { - display: block; - padding-top: 2rem; -} - -.lineName { - font-size: 30px; - font-weight: bold; - font-family: GothamRounded-Medium; -} - -.lineNameSecondary { - font-size: 25px; - font-weight: normal; - font-family: GothamRounded-Book; -} diff --git a/src/components/lineTimetable/lineTimetableHeader.js b/src/components/lineTimetable/lineTimetableHeader.js deleted file mode 100644 index 82e1f631..00000000 --- a/src/components/lineTimetable/lineTimetableHeader.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; - -import styles from './lineTimetableHeader.css'; - -const LineTimetableHeader = props => { - return ( -
-
- {props.lineIdParsed} -
-
-
- {props.nameFi} -
-
- {props.nameSe} -
-
-
- ); -}; - -LineTimetableHeader.defaultProps = { - nameFi: '', - nameSe: '', -}; - -LineTimetableHeader.propTypes = { - lineIdParsed: PropTypes.string.isRequired, - nameFi: PropTypes.string, - nameSe: PropTypes.string, -}; - -export default LineTimetableHeader; diff --git a/src/components/timetable/timetableContainer.js b/src/components/timetable/timetableContainer.js index fbf66e39..4a09f362 100644 --- a/src/components/timetable/timetableContainer.js +++ b/src/components/timetable/timetableContainer.js @@ -38,7 +38,7 @@ function groupDepartures(departures) { }; } -export function groupDeparturesByDay(departures) { +function groupDeparturesByDay(departures) { return { mondays: departures.filter(departure => departure.dayType.includes('Ma')), tuesdays: departures.filter(departure => departure.dayType.includes('Ti')), @@ -83,7 +83,7 @@ function areDepartureArraysEqual(arr1, arr2) { return true; } -export function combineConsecutiveDays(daysObject) { +function combineConsecutiveDays(daysObject) { let currentStartDay = null; let currentDepartures = null; diff --git a/test/testStops.js b/test/testStops.js index 41479a69..866f1ab0 100644 --- a/test/testStops.js +++ b/test/testStops.js @@ -9,20 +9,12 @@ const path = require('path'); const stopIds = ['1020105', '1284188', '6301068', '1040411']; -// Lines for testing the LineTimetable component -const testLines = [ - { lineId: '2015', routeDirection: '2', dateBegin: '1999-02-02', dateEnd: '2050-12-31' }, - { lineId: '1052', routeDirection: '1', dateBegin: '2021-12-13', dateEnd: '2050-12-31' }, - { lineId: '1500', routeDirection: '1', dateBegin: '2023-10-12', dateEnd: '2050-12-31' }, -]; - const TEST_RESULTS_PATH = './test/results'; const POSTER_COMPONENTS = { TIMETABLE: 'Timetable', STOP_POSTER: 'StopPoster', A3_STOP_POSTER: 'A3StopPoster', - LINE_TIMETABLE: 'LineTimetable', }; async function sleep(millis) { @@ -31,41 +23,24 @@ async function sleep(millis) { // Build the body for the poster generation requests function buildGenerationRequestBody(buildId, component, printAsA4) { - let props = null; - - if (component === POSTER_COMPONENTS.LINE_TIMETABLE) { - props = testLines.map(line => { - const { lineId, routeDirection, dateBegin, dateEnd } = line; - return { - lineId, - routeDirection, - dateBegin, - dateEnd, - date: new Date().toISOString().split('T')[0], - selectedRuleTemplates: [], - template: 'default', // Server throws error if template and selectedRuleTemplate aren't included in properties, however they aren't needed for rendering though - }; - }); - } else { - props = stopIds.map(stopId => { - return { - date: new Date().toISOString().split('T')[0], - isSummerTime: false, - legend: true, - mapZoneSymbols: true, - mapZones: true, - minimapZoneSymbols: true, - minimapZones: true, - printTimetablesAsA4: printAsA4, - printTimetablesAsGreyscale: false, - routeFilter: '', - salesPoint: true, - selectedRuleTemplates: [], - stopId, - template: 'default', - }; - }); - } + const props = stopIds.map(stopId => { + return { + date: new Date().toISOString().split('T')[0], + isSummerTime: false, + legend: true, + mapZoneSymbols: true, + mapZones: true, + minimapZoneSymbols: true, + minimapZones: true, + printTimetablesAsA4: printAsA4, + printTimetablesAsGreyscale: false, + routeFilter: '', + salesPoint: true, + selectedRuleTemplates: [], + stopId, + template: 'default', + }; + }); return { buildId, @@ -142,7 +117,7 @@ async function pollForCompletedPosters(listId) { } console.log( `Completed posters - ${completedPosters.length}/${completedPosters.length + failedPosters.length}`, + ${completedPosters.length}/${stopIds.length * Object.keys(POSTER_COMPONENTS).length}`, ); return completedPosters; }