Skip to content

Commit

Permalink
Merge LineTimetable features to Prod (#117)
Browse files Browse the repository at this point in the history
* Revert "Fix login url to prevent redirect"

This reverts commit 7127c16.

* Show prompt when template isn't selected instead of generating (#109)

* AB#32667: Add smaller TerminalPoster variant (#110)

* AB#32085: Add UI for testing line timetable generation (#111)

* Ab#32085: Prevent LineTimetable generation without dates (#112)

* AB#32085: Add UI for testing line timetable generation

* AB#32085: Disable linetimetable generation without dates

* AB#32085: Improve search UX, generate multiple line timetables at once (#113)

* AB#32085: Improve search UX, add capability to generate multiple line timetables at once

* Sort search results by lineId

* Shorten train IDs so they display correctly

* AB#32085: Print LineTimetable as A5 (#114)

* AB#46862: Tweak placeholder texts for route filtering (#115)

* Add local env

---------

Co-authored-by: Juho Hänninen <[email protected]>
  • Loading branch information
e-halinen and jhanninen authored Nov 26, 2024
1 parent 91d83d2 commit ec7371c
Show file tree
Hide file tree
Showing 7 changed files with 325 additions and 40 deletions.
12 changes: 12 additions & 0 deletions .env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Shared environment variables. Add env variables specific to your environment in .env

REACT_APP_API_URL=http://localhost:4000
REACT_APP_JORE_API_URL=https://dev.kartat.hsl.fi/jore/graphql
REACT_APP_CLIENT_ID=7833861618225795
REACT_APP_REDIRECT_URI=http://localhost:3000
REACT_APP_NAMESPACE=hsl-kartta

CYPRESS_TESTING_HSLID_USERNAME=
CYPRESS_TESTING_HSLID_PASSWORD=
CYPRESS_HSLID_CLIENT_ID=
CYPRESS_HSLID_CLIENT_SECRET=
144 changes: 109 additions & 35 deletions src/components/Generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import SelectTemplate from './SelectTemplate';
import SelectRuleTemplates from './SelectRuleTemplates';
import { componentsWithMapOptions } from '../stores/generatorStore';
import TerminalSelect from './TerminalSelect';
import LineSelect from './LineSelect';

const Root = styled.div`
display: flex;
Expand Down Expand Up @@ -59,6 +60,31 @@ const Generator = props => {
.map(({ stopIds }) => (generatorStore.component === 'TerminalPoster' ? 1 : stopIds.length))
.reduce((prev, cur) => prev + cur, 0);

const getAmount = () => {
let text = '';
switch (generatorStore.component) {
case 'StopPoster':
text = stopCount;
break;

case 'Timetable':
text = stopCount;
break;

case 'TerminalPoster':
text = 1;
break;

case 'LineTimetable':
text = generatorStore.selectedLines.length;
break;
default:
text = 0;
break;
}
return text;
};

return (
<Root>
<Row>
Expand All @@ -84,6 +110,15 @@ const Generator = props => {
/>
</div>
)}
{generatorStore.component === 'TerminalPoster' && (
<div>
<Checkbox
label="70x100 Juliste"
defaultValueTrue={generatorStore.isSmallTerminalPoster}
onChange={() => generatorStore.setIsSmallTerminalPoster()}
/>
</div>
)}
</div>
</Column>

Expand All @@ -93,7 +128,10 @@ const Generator = props => {
valuesByLabel={generatorStore.rowTypesByLabel}
valueSelected={generatorStore.rowType}
onChange={value => generatorStore.setRowType(value)}
disabled={generatorStore.component === 'TerminalPoster'}
disabled={
generatorStore.component === 'TerminalPoster' ||
generatorStore.component === 'LineTimetable'
}
/>
</Column>

Expand All @@ -103,6 +141,7 @@ const Generator = props => {
valuesByLabel={{ Talvi: false, Kesä: true }}
valueSelected={generatorStore.isSummerTimetable}
onChange={value => generatorStore.setIsSummerTimetable(value)}
disabled={generatorStore.component === 'LineTimetable'}
/>
</Column>

Expand All @@ -111,7 +150,7 @@ const Generator = props => {
<DatePicker
name="Päivämäärä"
value={generatorStore.date}
onChange={(event, value) => generatorStore.setDate(value)}
onChange={(_, value) => generatorStore.setDate(value)}
container="inline"
/>
</Column>
Expand Down Expand Up @@ -149,29 +188,50 @@ const Generator = props => {
</Main>
)}

<Main>
<StopList onCheck={generatorStore.setChecked} onReset={generatorStore.resetChecked} />
</Main>

<Main>
<SelectTemplate
currentTemplate={commonStore.currentTemplate}
templates={commonStore.templates}
onSelectTemplate={commonStore.selectTemplate}
showControls={false}
/>
</Main>

{generatorStore.component !== 'TerminalPoster' && (
{generatorStore.component === 'LineTimetable' && (
<Main>
<SelectRuleTemplates
selectedRuleTemplates={generatorStore.selectedRuleTemplates}
templates={commonStore.ruleTemplates}
setSelectedRuleTemplates={generatorStore.setSelectedRuleTemplates}
<LineSelect
setLineQuery={commonStore.setLineQuery}
lines={commonStore.lines}
lineQuery={commonStore.lineQuery}
addLine={generatorStore.addLine}
removeLine={generatorStore.removeLine}
selectedLines={generatorStore.selectedLines}
/>
</Main>
)}

{generatorStore.component !== 'LineTimetable' && (
<div>
<Main>
<StopList
onCheck={generatorStore.setChecked}
onReset={generatorStore.resetChecked}
disabled={generatorStore.component === 'LineTimetable'}
/>
</Main>
<Main>
<SelectTemplate
currentTemplate={commonStore.currentTemplate}
templates={commonStore.templates}
onSelectTemplate={commonStore.selectTemplate}
showControls={false}
/>
</Main>
</div>
)}

{generatorStore.component !== 'TerminalPoster' &&
generatorStore.component !== 'LineTimetable' && (
<Main>
<SelectRuleTemplates
selectedRuleTemplates={generatorStore.selectedRuleTemplates}
templates={commonStore.ruleTemplates}
setSelectedRuleTemplates={generatorStore.setSelectedRuleTemplates}
/>
</Main>
)}

{componentsWithMapOptions.includes(generatorStore.component) && (
<Row>
<Column>
Expand Down Expand Up @@ -218,16 +278,22 @@ const Generator = props => {
</Row>
)}

<h3>Poissuodatettavat linjat</h3>
<Row>
<TextField
data-cy="routeFilterInput"
onChange={(event, value) => commonStore.setRouteFilter(value)}
value={commonStore.routeFilter}
hintText="Esim. 1,7,9N"
fullWidth
/>
</Row>

{generatorStore.component !== 'LineTimetable' && (
<div>
<h3>Poissuodatettavat linjat</h3>
<Row>
<TextField
disabled={generatorStore.component === 'LineTimetable'}
data-cy="routeFilterInput"
onChange={(_, value) => commonStore.setRouteFilter(value)}
value={commonStore.routeFilter}
hintText="Esim. 1,7,9N"
fullWidth
/>
</Row>
</div>
)}

<Heading>Generointi</Heading>
<Footer>
Expand All @@ -245,12 +311,20 @@ const Generator = props => {
<RaisedButton
data-cy="generate-button"
disabled={
stopCount < 1 ||
(stopCount < 1 && generatorStore.component !== 'LineTimetable') ||
!generatorStore.buildId ||
(generatorStore.component === 'TerminalPoster' && generatorStore.terminalId === '')
(generatorStore.component === 'TerminalPoster' && generatorStore.terminalId === '') ||
(generatorStore.component === 'LineTimetable' && generatorStore.lineId === '') ||
(generatorStore.component === 'LineTimetable' && !generatorStore.dateBegin) ||
(generatorStore.component === 'LineTimetable' && !generatorStore.dateEnd)
}
onClick={() => {
if (commonStore.templateIsDirty) {
onClick={async () => {
if ((await commonStore.currentTemplate) === undefined) {
commonStore.showConfirm(
'Sommittelua ei ole valittu, generointia ei voida aloittaa !',
false,
);
} else if (commonStore.templateIsDirty) {
commonStore.showConfirm(
'Sommittelussa on tallentamattomia muutoksia. Julisteet generoidaan tallennetulla versiolla. Haluatko jatkaa?',
generatorStore.generate,
Expand All @@ -259,7 +333,7 @@ const Generator = props => {
generatorStore.generate();
}
}}
label={`Generoi (${generatorStore.component !== 'TerminalPoster' ? stopCount : 1})`}
label={`Generoi (${getAmount()})`}
style={{ height: 40, marginLeft: 10 }}
primary
/>
Expand Down
66 changes: 66 additions & 0 deletions src/components/LineSelect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import PropTypes from 'prop-types';
import { observer } from 'mobx-react';
import styled from 'styled-components';
import { ListItem, TextField } from 'material-ui';

const SectionHeading = styled.h3`
margin-bottom: 0.5rem;
`;

const ListItemTitle = styled.h4`
display: inline;
width: fit-content;
`;

const SelectedLinesTitle = styled.h3`
font-size: 1.2rem;
`;

const ListContainer = styled.div`
flex-grow: 1;
max-height: 500px;
overflow-y: scroll;
`;

const mapLineItems = (lines, onClick) => {
if (lines.length > 0) {
return lines.map((line, index) => (
<ListItem onClick={() => onClick(line)} key={index}>
<ListItemTitle>{line.lineIdParsed}</ListItemTitle> <p>{line.nameFi}</p>
</ListItem>
));
}
return '';
};

const LineSelect = props => (
<div>
<SectionHeading>Linja-aikataulu</SectionHeading>
<TextField
id="line-select"
hintText="Hae linjaa..."
onChange={event =>
event.target.value ? props.setLineQuery(event.target.value) : props.setLineQuery('')
}
value={props.lineQuery}
style={{ width: '100%' }}
/>
<ListContainer>{mapLineItems(props.lines, props.addLine)}</ListContainer>
<div>
<SelectedLinesTitle>Generoitavat linja-aikataulut</SelectedLinesTitle>
{mapLineItems(props.selectedLines, props.removeLine)}
</div>
</div>
);

LineSelect.propTypes = {
setLineQuery: PropTypes.func.isRequired,
lineQuery: PropTypes.string.isRequired,
lines: PropTypes.object.isRequired,
addLine: PropTypes.func.isRequired,
removeLine: PropTypes.func.isRequired,
selectedLines: PropTypes.object.isRequired,
};

export default observer(LineSelect);
37 changes: 36 additions & 1 deletion src/stores/commonStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,17 @@ import {
removeTemplate,
getImages,
removeImage,
getAllLines,
} from '../util/api';
import get from 'lodash/get';
import { isEmpty } from 'lodash';
import { filter, isEmpty, some } from 'lodash';
import reduce from 'lodash/reduce';
import generatorStore from './generatorStore';
import {
compareLineNameOrder,
shortenTrainParsedLineId,
TRANSPORTATION_MODES,
} from '../util/lines';

const store = observable({
confirm: null,
Expand All @@ -36,6 +42,8 @@ const store = observable({
images: [],
selectedTemplate: null,
prevSavedTemplate: null,
lines: [],
lineQuery: '',
get currentTemplate() {
const { selectedTemplate, templates } = store;
const currentTemplate = templates.find(template => template.id === selectedTemplate);
Expand Down Expand Up @@ -355,4 +363,31 @@ store.setRouteFilter = value => {
store.routeFilter = value;
};

store.setLineQuery = async query => {
store.lineQuery = query;
const results = await store.getLines();
store.lines = results;
};

store.getLines = async () => {
const { data } = await getAllLines();
const filteredLines = filter(
data.allLines.nodes,
line =>
line.lineId.toLowerCase().includes(store.lineQuery.toLowerCase()) ||
line.nameFi.toLowerCase().includes(store.lineQuery.toLowerCase()),
);

const checkedLines = filteredLines.map(line => {
if (some(line.routes.nodes, route => route.mode === TRANSPORTATION_MODES.RAIL)) {
return { ...line, lineIdParsed: shortenTrainParsedLineId(line.lineIdParsed) };
}
return line;
});

const sortedLines = checkedLines.sort(compareLineNameOrder);

return sortedLines;
};

export default store;
Loading

0 comments on commit ec7371c

Please sign in to comment.