Skip to content

Commit 66fed2e

Browse files
committed
mapping of profile groups
1 parent af2518c commit 66fed2e

File tree

9 files changed

+94
-13
lines changed

9 files changed

+94
-13
lines changed

config.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ const config = {
4646
//
4747
// E.g. the 'bike' entry will add a "bike" profile for which we send a request with the specified 'details' parameter. You can even change the profile itself when you specify
4848
// bike: { profile: 'raw_bike', ... }
49+
50+
// Certain profiles should not appear in the list as it would be too many. Instead they're listed in the settings but still a 'main' profile needs to be shown.
51+
// profile_group_mapping: {
52+
// car_avoid_motorway: 'car',
53+
// car_avoid_ferry: 'car',
54+
// car_avoid_toll: 'car',
55+
// }
4956
}
5057

5158
// this is needed for jest (with our current setup at least)

src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ function LargeScreenLayout({ query, route, map, error, mapOptions, encodedValues
163163
</PlainButton>
164164
<RoutingProfiles
165165
routingProfiles={query.profiles}
166+
profileGroupMapping={query.profileGroupMapping}
166167
selectedProfile={query.routingProfile}
167168
showCustomModelBox={showCustomModelBox}
168169
toggleCustomModelBox={() => setShowCustomModelBox(!showCustomModelBox)}
@@ -177,7 +178,7 @@ function LargeScreenLayout({ query, route, map, error, mapOptions, encodedValues
177178
drawAreas={drawAreas}
178179
/>
179180
)}
180-
<Search points={query.queryPoints} />
181+
<Search points={query.queryPoints} profile={query.routingProfile} />
181182
<div>{!error.isDismissed && <ErrorMessage error={error} />}</div>
182183
<RoutingResults
183184
info={route.routingResult.info}

src/custom.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ declare module 'heightgraph/src/heightgraph'
55
declare module 'custom-model-editor/src/index'
66

77
declare module 'config' {
8+
import ol from 'ol/dist/ol'
9+
import array = ol.array
810
const routingApi: string
911
const geocodingApi: string
1012
const defaultTiles: string
@@ -31,6 +33,7 @@ declare module 'config' {
3133
}
3234
maxZoom?: number
3335
}
36+
const profile_group_mapping: Record<string, string>
3437
const profiles: object
3538
}
3639

src/sidebar/MobileSidebar.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export default function ({ query, route, error, encodedValues, drawAreas }: Mobi
5858
</div>
5959
<RoutingProfiles
6060
routingProfiles={query.profiles}
61+
profileGroupMapping={query.profileGroupMapping}
6162
selectedProfile={query.routingProfile}
6263
showCustomModelBox={showCustomModelBox}
6364
toggleCustomModelBox={() => setShowCustomModelBox(!showCustomModelBox)}
@@ -72,7 +73,7 @@ export default function ({ query, route, error, encodedValues, drawAreas }: Mobi
7273
drawAreas={drawAreas}
7374
/>
7475
)}
75-
<Search points={query.queryPoints} />
76+
<Search points={query.queryPoints} profile={query.routingProfile} />
7677
</div>
7778
)}
7879
{!error.isDismissed && <ErrorMessage error={error} />}

src/sidebar/SettingsBox.module.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@
2626
align-items: center;
2727
}
2828

29+
.carProfileOptionsHeader {
30+
font-weight: bold;
31+
}
32+
33+
.carProfileOptions div {
34+
padding: 4px 14px;
35+
}
36+
37+
.carProfileOptions label,
38+
input {
39+
cursor: pointer;
40+
}
41+
42+
.carProfileOptions label {
43+
margin-left: 10px;
44+
}
45+
46+
.carProfileOptions {
47+
padding: 12px 5px;
48+
}
49+
2950
.toggleButton {
3051
display: flex;
3152
align-items: center;

src/sidebar/SettingsBox.tsx

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { UpdateSettings } from '@/actions/Actions'
1+
import { SetVehicleProfile, UpdateSettings } from '@/actions/Actions'
22
import Dispatcher from '@/stores/Dispatcher'
33
import styles from '@/sidebar/SettingsBox.module.css'
44
import { tr } from '@/translation/Translation'
@@ -7,14 +7,39 @@ import OnIcon from '@/sidebar/toggle_on.svg'
77
import OffIcon from '@/sidebar/toggle_off.svg'
88
import { useContext, useState } from 'react'
99
import { SettingsContext } from '@/contexts/SettingsContext'
10+
import { RoutingProfile } from '@/api/graphhopper'
1011

11-
export default function SettingsBox() {
12+
export default function SettingsBox({ profile }: { profile: RoutingProfile }) {
1213
const settings = useContext(SettingsContext)
14+
function setProfile(n: string) {
15+
Dispatcher.dispatch(new SetVehicleProfile({ name: profile.name === n ? 'car' : n }))
16+
}
1317

1418
return (
1519
<div className={styles.parent}>
1620
<div className={styles.title}>{tr('settings')}</div>
1721
<div className={styles.settingsTable}>
22+
{/* TODO make generic so that it could be used to collapse e.g. hike & foot */}
23+
{profile.name.startsWith('car') && (
24+
<div className={styles.carProfileOptions}>
25+
<span className={styles.carProfileOptionsHeader}>{tr('Avoid')}</span>
26+
<div>
27+
{/*prettier-ignore*/}
28+
<input checked={profile.name === 'car_avoid_motorway'} type="radio" id="motorway" name="car" value="motorway" onClick={e => setProfile('car_avoid_motorway')} />
29+
<label htmlFor="motorway">{tr('motorway')}</label>
30+
</div>
31+
<div>
32+
{/*prettier-ignore*/}
33+
<input checked={profile.name === 'car_avoid_ferry'} type="radio" id="ferry" name="car" value="ferry" onClick={e => setProfile('car_avoid_ferry')} />
34+
<label htmlFor="ferry">{tr('ferry')}</label>
35+
</div>
36+
<div>
37+
{/*prettier-ignore*/}
38+
<input checked={profile.name === 'car_avoid_toll'} type="radio" id="toll" name="car" value="toll" onClick={e => setProfile('car_avoid_toll')} />
39+
<label htmlFor="toll">{tr('toll and ferry')}</label>
40+
</div>
41+
</div>
42+
)}
1843
<SettingsToggle
1944
title={tr('distance_unit', [tr(settings.showDistanceInMiles ? 'mi' : 'km')])}
2045
enabled={settings.showDistanceInMiles}

src/sidebar/search/Search.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ import AddressInput from '@/sidebar/search/AddressInput'
1212
import { MarkerComponent } from '@/map/Marker'
1313
import { tr } from '@/translation/Translation'
1414
import SettingsBox from '@/sidebar/SettingsBox'
15+
import { RoutingProfile } from '@/api/graphhopper'
1516

16-
export default function Search({ points }: { points: QueryPoint[] }) {
17+
export default function Search({ points, profile }: { points: QueryPoint[]; profile: RoutingProfile }) {
1718
const [showSettings, setShowSettings] = useState(false)
1819
const [showTargetIcons, setShowTargetIcons] = useState(true)
1920
const [moveStartIndex, onMoveStartSelect] = useState(-1)
@@ -60,7 +61,7 @@ export default function Search({ points }: { points: QueryPoint[] }) {
6061
{showSettings ? tr('settings_close') : tr('settings')}
6162
</PlainButton>
6263
</div>
63-
{showSettings && <SettingsBox />}
64+
{showSettings && <SettingsBox profile={profile} />}
6465
</div>
6566
)
6667
}

src/sidebar/search/routingProfiles/RoutingProfiles.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@ import { icons } from '@/sidebar/search/routingProfiles/profileIcons'
1111

1212
export default function ({
1313
routingProfiles,
14+
profileGroupMapping,
1415
selectedProfile,
1516
showCustomModelBox,
1617
toggleCustomModelBox,
1718
customModelBoxEnabled,
1819
}: {
1920
routingProfiles: RoutingProfile[]
21+
profileGroupMapping: Record<string, string>
2022
selectedProfile: RoutingProfile
2123
showCustomModelBox: boolean
2224
toggleCustomModelBox: () => void
@@ -100,10 +102,12 @@ export default function ({
100102
</PlainButton>
101103
<ul className={styles.profiles} id="profiles_carousel_items" onScroll={onScroll}>
102104
{routingProfiles.map(profile => {
103-
const className =
104-
profile.name === selectedProfile.name
105-
? styles.selectedProfile + ' ' + styles.profileBtn
106-
: styles.profileBtn
105+
const isProfileSelected =
106+
profile.name === selectedProfile.name ||
107+
profile.name === profileGroupMapping[selectedProfile.name]
108+
const className = isProfileSelected
109+
? styles.selectedProfile + ' ' + styles.profileBtn
110+
: styles.profileBtn
107111
return (
108112
<li key={profile.name}>
109113
<PlainButton

src/stores/QueryStore.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
} from '@/actions/Actions'
2121
import { Bbox, RoutingArgs, RoutingProfile } from '@/api/graphhopper'
2222
import { calcDist } from '@/distUtils'
23-
import config from 'config'
23+
import config, { profile_group_mapping } from 'config'
2424
import { customModel2prettyString, customModelExamples } from '@/sidebar/CustomModelExamples'
2525

2626
export interface Coordinate {
@@ -34,6 +34,8 @@ export function getBBoxFromCoord(c: Coordinate, offset: number = 0.005): Bbox {
3434

3535
export interface QueryStoreState {
3636
readonly profiles: RoutingProfile[]
37+
readonly profileGroupMapping: Record<string, string>
38+
readonly lastProfiles: Record<string, string>
3739
readonly queryPoints: QueryPoint[]
3840
readonly nextQueryPointId: number
3941
readonly currentRequest: CurrentRequest
@@ -99,6 +101,8 @@ export default class QueryStore extends Store<QueryStoreState> {
99101

100102
return {
101103
profiles: [],
104+
profileGroupMapping: {},
105+
lastProfiles: {},
102106
queryPoints: [
103107
QueryStore.getEmptyPoint(0, QueryPointType.From),
104108
QueryStore.getEmptyPoint(1, QueryPointType.To),
@@ -258,16 +262,30 @@ export default class QueryStore extends Store<QueryStoreState> {
258262
{
259263
...state,
260264
profiles,
265+
profileGroupMapping: config.profile_group_mapping,
261266
routingProfile: profile,
262267
},
263268
true
264269
)
265270
} else if (action instanceof SetVehicleProfile) {
271+
const mainProfile = profile_group_mapping[action.profile.name]
272+
const prevProfile = this.state.lastProfiles[action.profile.name]
273+
let name = action.profile.name,
274+
key = action.profile.name,
275+
value = ''
276+
if (prevProfile && !profile_group_mapping[this.state.routingProfile.name]) {
277+
name = prevProfile
278+
value = prevProfile
279+
} else if (mainProfile) {
280+
key = mainProfile
281+
value = action.profile.name
282+
}
283+
266284
const newState: QueryStoreState = {
267285
...state,
268-
routingProfile: action.profile,
286+
routingProfile: { name: name },
287+
lastProfiles: { ...state.lastProfiles, [key]: value },
269288
}
270-
271289
return this.routeIfReady(newState, true)
272290
} else if (action instanceof SetCustomModel) {
273291
const newState = {

0 commit comments

Comments
 (0)