Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DT-5904 (DT-5325) CO2 emissions #4881

Merged
merged 41 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ddca1ce
feat: dt-5325 co2 emissions
sharhio Jul 5, 2023
bfdc531
Merge branch 'v3' into DT-5325
sharhio Jul 5, 2023
ec56632
feat: dt-5325 co2 schemas
sharhio Jul 5, 2023
8e59711
feat: dt-5325 co2 schema update
sharhio Jul 5, 2023
bc1e0c5
chore: mobile styling, show emission info in mobile also
Antiik91 Jul 19, 2023
67aa244
chore: add placeholders for translations
Antiik91 Jul 19, 2023
a22b193
chore: update localStorage
Antiik91 Jul 19, 2023
b3488b2
refactor: do not add car value when car route is not available
Antiik91 Jul 24, 2023
ca5cebf
refactor: remove loading as it stays forever if no data
Antiik91 Jul 26, 2023
9051e97
feat: translations and links to emissions info
Antiik91 Jul 26, 2023
6de024d
chore: edit test
Antiik91 Jul 26, 2023
c6929be
feat: ft-5325 simplifying css
sharhio Aug 7, 2023
cffe172
feat: dt-5325 no localstorage, no separate force car setting
sharhio Aug 7, 2023
18b4628
feat: dt-5325 documentation for co2 setting, removed from defaultsett…
sharhio Aug 7, 2023
e1ed13f
feat: dt-5325 accessibility improvements
sharhio Aug 8, 2023
d522c69
Merge branch 'v3' into DT-5325
sharhio Sep 8, 2023
7cf37e6
feat: dt-5325 allow showing zero emissions
sharhio Sep 13, 2023
066feac
feat: dt-5325 show 0 emissions, short description when no car iti
sharhio Sep 14, 2023
02d6581
fix: dt-5325 emissions value nonzero if doesnt exist
sharhio Sep 18, 2023
5e68ad1
chore: dt-5325 emissions turned on in matka
sharhio Sep 19, 2023
b73671b
fix: dt-5325 emission zero values
sharhio Sep 20, 2023
b69bab3
fix: dt-5325 lowest co2 value filterting fix
sharhio Oct 4, 2023
2a7dcca
feat: dt-5325 co2 type changes
sharhio Oct 18, 2023
878dda8
feat: dt-5325 emissions naming changes, car value fix
sharhio Oct 19, 2023
5c06dbf
refactor: fix text and adjust new text to description of co2
Antiik91 Oct 23, 2023
92eb64d
feat: dt-5325 emissions schema changes
sharhio Oct 24, 2023
5cba798
fix: otp schema location update
sharhio Oct 31, 2023
abe684f
fix: dt-5325 translations
sharhio Nov 7, 2023
b7e854f
Merge branch 'v3' into DT-5325
sharhio Nov 7, 2023
ea0925a
fix: dt-5325 consistent texts, clearer screen reader text
sharhio Nov 15, 2023
d1e3063
fix: dt-5325 more space for emissions when only text zoomed in
sharhio Nov 20, 2023
d111fe7
fix: dt-5325 minor fixes for config, layout, naming, refactoring
sharhio Nov 20, 2023
4c02530
fix: dt-5325 single car itinerary, comment deleted, remove redundant …
sharhio Nov 20, 2023
6604e8e
fix: dt-5325 util for co2 value check
sharhio Nov 20, 2023
15a09fd
fix: dt-5325 Emissions components separated from itineraryTab
sharhio Nov 21, 2023
4180f2f
Merge branch 'v3' into DT-5325
sharhio Nov 21, 2023
13a7c4e
fix: dt-5325 null check for default null
sharhio Nov 21, 2023
a2e9dd0
fix: dt-5325 grammar
sharhio Nov 21, 2023
d606ab4
fix: dt-5325 open link in new tab
sharhio Nov 21, 2023
c332548
fix: dt-5325 no car value for park and ride without ride + link style
sharhio Nov 21, 2023
eee619d
fix: dt-5325 emissions description scaling
sharhio Nov 21, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ function ItinerarySummaryListContainer(
itineraries.length > 0 &&
!itineraries.includes(undefined)
) {
const lowestCo2value = Math.round(
itineraries
.filter(itinerary => itinerary.emissionsPerPerson?.co2 >= 0)
.reduce((a, b) => {
return a.emissionsPerPerson?.co2 < b.emissionsPerPerson?.co2 ? a : b;
}, 0).emissionsPerPerson?.co2,
);
const summaries = itineraries.map((itinerary, i) => (
<SummaryRow
refTime={searchTime}
Expand All @@ -72,6 +79,7 @@ function ItinerarySummaryListContainer(
zones={
config.zones.stops && itinerary.legs ? getZones(itinerary.legs) : []
}
lowestCo2value={lowestCo2value}
/>
));
if (
Expand Down Expand Up @@ -334,6 +342,9 @@ const containerComponent = createFragmentContainer(
walkDistance
startTime
endTime
emissionsPerPerson {
co2
}
legs {
realTime
realtimeState
Expand Down
91 changes: 87 additions & 4 deletions app/component/ItineraryTab.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import cx from 'classnames';
import { matchShape, routerShape } from 'found';
import { FormattedMessage, intlShape } from 'react-intl';
import connectToStores from 'fluxible-addons-react/connectToStores';

import Icon from './Icon';
import TicketInformation from './TicketInformation';
import RouteInformation from './RouteInformation';
Expand Down Expand Up @@ -44,6 +43,7 @@ import {
import CityBikeDurationInfo from './CityBikeDurationInfo';
import { getCityBikeNetworkId } from '../util/citybikes';
import { FareShape } from '../util/shapes';
import { getCo2Value } from '../util/itineraryUtils';

const AlertShape = PropTypes.shape({ alertSeverityLevel: PropTypes.string });

Expand All @@ -67,6 +67,9 @@ const ItineraryShape = PropTypes.shape({
}),
),
fares: PropTypes.arrayOf(FareShape),
emissionsPerPerson: PropTypes.shape({
co2: PropTypes.number,
}),
});

/* eslint-disable prettier/prettier */
Expand All @@ -81,6 +84,7 @@ class ItineraryTab extends React.Component {
isMobile: PropTypes.bool.isRequired,
currentTime: PropTypes.number.isRequired,
hideTitle: PropTypes.bool,
carItinerary: ItineraryShape,
currentLanguage: PropTypes.string,
changeHash: PropTypes.func,
};
Expand Down Expand Up @@ -185,7 +189,6 @@ class ItineraryTab extends React.Component {
if (!itinerary || !itinerary.legs[0]) {
return null;
}

const fares = getFares(itinerary.fares, getRoutes(itinerary.legs), config);
const extraProps = this.setExtraProps(itinerary);
const legsWithRentalBike = compressLegs(itinerary.legs).filter(leg =>
Expand Down Expand Up @@ -217,8 +220,15 @@ class ItineraryTab extends React.Component {
const suggestionIndex = this.context.match.params.secondHash
? Number(this.context.match.params.secondHash) + 1
: Number(this.context.match.params.hash) + 1;

const co2value = getCo2Value(itinerary);
const itineraryIsCar = itinerary.legs.every((leg) => leg.mode === 'CAR');
const carCo2Value = !itineraryIsCar && this.props.carItinerary ? Math.round(this.props.carItinerary?.emissionsPerPerson?.co2) : null;
const useCo2SimpleDesc = !carCo2Value || itineraryIsCar;
const co2DescriptionId = useCo2SimpleDesc ? "itinerary-co2.description-simple" : "itinerary-co2.description";

const itineraryContainsCallLegs = itinerary.legs.some(leg => isCallAgencyPickupType(leg));

return (
<div className="itinerary-tab">
<h2 className="sr-only">
Expand Down Expand Up @@ -288,12 +298,38 @@ class ItineraryTab extends React.Component {
fares={fares}
zones={getZones(itinerary.legs)}
/>) :
( <TicketInformation
(<TicketInformation
fares={fares}
zones={getZones(itinerary.legs)}
legs={itinerary.legs}
/>)
),
config.showCO2InItinerarySummary && co2value >= 0 && (
<div className={cx("itinerary-co2-information", { mobile: this.props.isMobile })}>
<div className="itinerary-co2-line">
<div className={cx("co2-container", { mobile: this.props.isMobile })}>
<div className="co2-title-container">
<Icon img="icon-icon_co2_leaf" className="co2-leaf" />
<span aria-hidden="true" className="itinerary-co2-title">
<FormattedMessage
id="itinerary-co2.title"
defaultMessage="CO2 emissions for this route"
/>
</span>
<span className="sr-only">
<FormattedMessage
id="itinerary-co2.title-sr"
defaultMessage="CO2 emissions for this route"
/>
</span>
</div>
<div className="itinerary-co2-value-container">
<div className="itinerary-co2-value">{co2value} g</div>
</div>
</div>
</div>
</div>
),
<div
className={cx('momentum-scroll itinerary-tabs__scroll', {
multirow: extraProps.isMultiRow,
Expand Down Expand Up @@ -354,6 +390,50 @@ class ItineraryTab extends React.Component {
/>
{config.showRouteInformation && <RouteInformation />}
</div>
{config.showCO2InItinerarySummary && co2value >= 0 ? (
<div className="itinerary-co2-comparison">
<div className="itinerary-co2-line">
<div className={cx('divider-top')} />
<div className="co2-container">
<div className="co2-description-container">
<Icon img="icon-icon_co2_leaf" className="co2-leaf" />
<span className={cx("itinerary-co2-description", { simple: useCo2SimpleDesc })}>
<span aria-hidden="true">
<FormattedMessage id={co2DescriptionId}
defaultMessage={`CO₂ emissions for this route: ${co2value} g`}
values={{
co2value,
carCo2Value,
}}
/>
</span>
<span className="sr-only">
<FormattedMessage id={`${co2DescriptionId}-sr`}
defaultMessage={`Carbondioxide emissions for this route: ${co2value} g`}
values={{
co2value,
carCo2Value,
}}
/>
</span>
{config.URL.EMISSIONSINFO && (
<div>
<a href={`${config.URL.EMISSIONSINFO[currentLanguage]}`}>
<FormattedMessage
id="itinerary-co2.link"
defaultMessage="Näin vähennämme päästöjä ›"
/>
</a>
</div>
)}
</span>
</div>
</div>
<div className={cx('divider-bottom')} />
</div>
</div>
) :
(null)}
{this.shouldShowDisclaimer(config) && (
<div className="itinerary-disclaimer">
<FormattedMessage
Expand Down Expand Up @@ -404,6 +484,9 @@ const withRelay = createFragmentContainer(
}
type
}
emissionsPerPerson {
co2
}
legs {
mode
nextLegs(numberOfLegs: 2 originModesWithParentStation: [RAIL] destinationModesWithParentStation: [RAIL]) {
Expand Down
3 changes: 3 additions & 0 deletions app/component/MobileItineraryWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { matchShape, routerShape } from 'found';
import { FormattedMessage, intlShape } from 'react-intl';
import ItineraryTab from './ItineraryTab';
import SwipeableTabs from './SwipeableTabs';
import ItineraryShape from '../prop-types/ItineraryShape';

const MobileItineraryWrapper = (props, context) => {
const index = props.params.secondHash
Expand Down Expand Up @@ -41,6 +42,7 @@ const MobileItineraryWrapper = (props, context) => {
focusToLeg={props.focusToLeg}
changeHash={props.changeHash}
isMobile
carItinerary={props.carItinerary}
/>
</div>
);
Expand Down Expand Up @@ -73,6 +75,7 @@ MobileItineraryWrapper.propTypes = {
plan: PropTypes.object,
serviceTimeRange: PropTypes.object.isRequired,
onSwipe: PropTypes.func,
carItinerary: ItineraryShape,
changeHash: PropTypes.func,
};

Expand Down
17 changes: 17 additions & 0 deletions app/component/SummaryPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -790,6 +793,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -849,6 +855,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -1029,6 +1038,9 @@ class SummaryPage extends React.Component {
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -2501,6 +2513,7 @@ class SummaryPage extends React.Component {
focusToPoint={this.focusToPoint}
focusToLeg={this.focusToLeg}
isMobile={false}
carItinerary={carPlan?.itineraries[0]}
/>
</div>
);
Expand Down Expand Up @@ -2732,6 +2745,7 @@ class SummaryPage extends React.Component {
serviceTimeRange={this.props.serviceTimeRange}
focusToLeg={this.focusToLeg}
onSwipe={this.changeHash}
carItinerary={carPlan?.itineraries[0]}
changeHash={this.changeHash}
>
{this.props.content &&
Expand Down Expand Up @@ -2961,6 +2975,9 @@ const containerComponent = createRefetchContainer(
endTime
...ItineraryTab_itinerary
...SummaryPlanContainer_itineraries
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down
6 changes: 6 additions & 0 deletions app/component/SummaryPlanContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ const connectedContainer = createFragmentContainer(
itineraries {
startTime
endTime
emissionsPerPerson {
co2
}
legs {
mode
...ItineraryLine_legs
Expand Down Expand Up @@ -401,6 +404,9 @@ const connectedContainer = createFragmentContainer(
...ItinerarySummaryListContainer_itineraries
endTime
startTime
emissionsPerPerson {
co2
}
legs {
mode
to {
Expand Down
31 changes: 30 additions & 1 deletion app/component/SummaryRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from '../util/citybikes';
import { getRouteMode } from '../util/modeUtils';
import { getCapacityForLeg } from '../util/occupancyUtil';
import { getCo2Value } from '../util/itineraryUtils';

const Leg = ({
mode,
Expand Down Expand Up @@ -244,6 +245,7 @@ const SummaryRow = (
intermediatePlaces,
zones,
onlyHasWalkingItineraries,
lowestCo2value,
...props
},
{ intl, intl: { formatMessage }, config },
Expand All @@ -259,7 +261,7 @@ const SummaryRow = (
const startTime = moment(data.startTime);
const endTime = moment(data.endTime);
const duration = endTime.diff(startTime);

const co2value = getCo2Value(data);
const mobile = bp => !(bp === 'large');
const legs = [];
let noTransitLegs = true;
Expand Down Expand Up @@ -720,6 +722,17 @@ const SummaryRow = (
/>
</div>
);
const co2summary = (
<div className="sr-only">
<FormattedMessage
id="itinerary-co2.description-simple"
defaultMessage="CO₂ emissions for this route"
values={{
co2value,
}}
/>
</div>
);

const ariaLabelMessage = intl.formatMessage(
{
Expand Down Expand Up @@ -755,6 +768,7 @@ const SummaryRow = (
/>
</h3>
{textSummary}
{config.showCO2InItinerarySummary && co2value >= 0 && co2summary}
<div
className="itinerary-summary-visible"
style={{
Expand Down Expand Up @@ -804,6 +818,14 @@ const SummaryRow = (
{(getTotalDistance(data) / 1000).toFixed(1)} km
</div>
)}
{config.showCO2InItinerarySummary && co2value >= 0 && (
<div className="itinerary-co2-value-container">
{lowestCo2value === co2value && (
<Icon img="icon-icon_co2_leaf" className="co2-leaf" />
)}
<div className="itinerary-co2-value">{co2value} g</div>
</div>
)}
<div className="itinerary-duration">
<RelativeDuration duration={duration} />
</div>
Expand Down Expand Up @@ -898,10 +920,17 @@ SummaryRow.propTypes = {
showCancelled: PropTypes.bool,
zones: PropTypes.arrayOf(PropTypes.string),
onlyHasWalkingItineraries: PropTypes.bool,
lowestCo2value: PropTypes.number,
};

SummaryRow.defaultProps = {
zones: [],
passive: false,
intermediatePlaces: [],
isCancelled: false,
showCancelled: false,
onlyHasWalkingItineraries: false,
lowestCo2value: 0,
};

SummaryRow.contextTypes = {
Expand Down
1 change: 1 addition & 0 deletions app/component/itinerary-profile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
font-size: 15px;
line-height: 18px;
margin-top: 7px;
margin-bottom: 7px;

&.small {
font-size: 10pt;
Expand Down
Loading