Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ repos:
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.910-1
rev: v1.15.0
hooks:
- id: mypy
additional_dependencies:
Expand Down
10 changes: 10 additions & 0 deletions backend/databasemodel/alembic/versions/3d38553ecec1/downgrade.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DELETE FROM kooste.osm_metadata;
INSERT INTO kooste.osm_metadata (tags_to_include, tags_to_exclude)
VALUES (
'{"amenity": ["parking", "bicycle_parking", "bbq", "bench", "cafe", "ice_cream", "recycling", "restaurant", "shelter", "toilets", "waste_basket"],
"tourism": ["camp_site", "caravan_site", "chalet", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "viewpoint", "wilderness_hut"],
"leisure": ["bird_hide", "picnic_table", "sauna"],
"shop": ["kiosk"],
"building": ["church"]}',
'{"access": ["private", "permit"]}'
);
10 changes: 10 additions & 0 deletions backend/databasemodel/alembic/versions/3d38553ecec1/upgrade.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
DELETE FROM kooste.osm_metadata;
INSERT INTO kooste.osm_metadata (tags_to_include, tags_to_exclude)
VALUES (
'{"amenity": ["parking", "bicycle_parking", "bbq", "bench", "cafe", "ice_cream", "recycling", "restaurant", "shelter", "toilets", "waste_basket"],
"tourism": ["camp_site", "caravan_site", "chalet", "guest_house", "hostel", "hotel", "information", "motel", "museum", "picnic_site", "viewpoint", "wilderness_hut"],
"leisure": ["bird_hide", "picnic_table", "sauna"],
"shop": ["kiosk"],
"building": ["church"]}',
'{"access": ["private", "permit"], "shelter_type": ["public_transport"]}'
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""remove public transport shelters

Revision ID: 3d38553ecec1
Revises: 9f3e55c9d75f
Create Date: 2025-03-11 18:22:40.100843

"""
import os

from alembic import op

here = os.path.dirname(os.path.realpath(__file__))

# revision identifiers, used by Alembic.
revision = "3d38553ecec1"
down_revision = "9f3e55c9d75f"
branch_labels = None
depends_on = None

revision_dir = f"{here}/{revision}"


# idea from https://github.com/tbobm/alembic-sequeled
def process_migration(script_name: str):
filename = f"{revision_dir}/{script_name}.sql"

query = "\n".join(open(filename))
if len(query) > 0:
op.execute(query)


def upgrade():
process_migration("upgrade")


def downgrade():
process_migration("downgrade")
2 changes: 1 addition & 1 deletion backend/databasemodel/model.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1462,7 +1462,7 @@ INSERT INTO kooste.osm_metadata (
"leisure": ["bird_hide", "picnic_table", "sauna"],
"shop": ["kiosk"],
"building": ["church"]}',
'{"access": ["private", "permit"]}'
'{"access": ["private", "permit"], "shelter_type": ["public_transport"]}'
);

-- object: kooste.tamperewfs_luonnonmuistomerkit | type: TABLE --
Expand Down
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
"settings": {
"react": {
"pragma": "React",
"version": "detect"
"version": "17.0.2"
},
"import/parsers": {
"@typescript-eslint/parser": [
Expand Down
67 changes: 52 additions & 15 deletions web/src/components/InfoSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import SwipeableViews from "react-swipeable-views";
import palette from "../theme/palette";
import shadows from "../theme/shadows";
import { DataSource, gqlPattern, PopupInfo } from "../types";
import { getCategoryIcon, getCategoryPlural } from "../utils/utils";
import { compareParts, getCategoryIcon, getCategoryPlural } from "../utils/utils";
import { useElementSize } from "../utils/UseElementSize";
import PropertyListItem from "./PropertyListItem";
import { LayerId } from "./style";
Expand Down Expand Up @@ -236,6 +236,56 @@ export default function InfoSlider({ popupInfo }: PopupProps) {
return null;
};

/**
* Render GraphQL patterns
*
* Only filter and sort line numbers when rendering. Most of the time,
* the user does not click on any stop. Makes no sense to do any of this
* until we are actually rendering the list for a specific stop.
*/
const renderPatterns = (patterns: Array<gqlPattern>) => {
return <List>
{patterns.reduce<Array<gqlPattern>>(
(unique: Array<gqlPattern>, pattern: gqlPattern) =>
// Don't display identical lines with the same destinations
unique.some((other: gqlPattern) =>
pattern["route"]["shortName"] == other["route"]["shortName"] &&
pattern["headsign"] == other["headsign"]
) ? unique : [...unique, pattern],
[] // Initial array value
).sort(
(pattern: gqlPattern, other: gqlPattern) => {
// Order first by first part, second by second part
// Note that first and second parts may both be number *or* letter.
const line_parts = pattern["route"]["shortName"].match('([0-9]+|[A-Z]+)( )?([0-9]*[A-Z]*)')
const other_line_parts = other["route"]["shortName"].match('([0-9]+|[A-Z]+)( )?([0-9]*[A-Z]*)')
if (line_parts && other_line_parts) {
// part 0 is the whole match, parts 1 to 3 are capture groups
const first = line_parts[1]
const other_first = other_line_parts[1]
const second = line_parts.length == 4 ? line_parts[3] : ""
const other_second = other_line_parts.length == 4 ? other_line_parts[3] : ""
const compare_first = compareParts(first, other_first)
return compare_first ? compare_first : compareParts(second, other_second)
}
return line_parts ? -1 : 0
}
).map(
(value: gqlPattern, index: number) => (
<ListItem key={index}>
<ListItemAvatar sx={{ mr: 1 }}>
<Typography variant="h4">
{value["route"]["shortName"]}
</Typography>
</ListItemAvatar>
<ListItemText primary={value["headsign"]} />
</ListItem>
)
)}
</List>
};


/**
* Basic information slide
*/
Expand Down Expand Up @@ -313,20 +363,7 @@ export default function InfoSlider({ popupInfo }: PopupProps) {
{properties["patterns"] && (
<>
<Typography variant="h4">Linjat</Typography>
<List>
{JSON.parse(properties["patterns"]).map(
(value: gqlPattern, index: number) => (
<ListItem key={index}>
<ListItemAvatar sx={{ mr: 1 }}>
<Typography variant="h4">
{value["route"]["shortName"]}
</Typography>
</ListItemAvatar>
<ListItemText primary={value["headsign"]} />
</ListItem>
)
)}
</List>
{renderPatterns(JSON.parse(properties["patterns"]))}
</>
)}
</Stack>
Expand Down
39 changes: 38 additions & 1 deletion web/src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,41 @@
import { FeatureCollection, Feature } from "geojson";
import { Category, gqlStop, gqlBikeStation, gqlResponse, stopType } from "../types";

/**
* Compare string parts that may be strings or strigified integers. Returns integers
* (sorted numerically) before strings (sorted alphabetically).
*
* @param one String that may or may not represent an integer
* @param other String that may or may not represent an integer
* @returns
*/
export const compareParts = (one: string, other: string) => {
const one_number = parseInt(one)
const other_number = parseInt(other)
// compare numbers
if (one_number && other_number) {
return one_number - other_number
}
if (one_number) {
return -1
}
if (other_number) {
return 1
}
// compare strings
if (one && other) {
return one.localeCompare(other)
}
// empty strings before strings
if (one) {
return 1
}
if (other) {
return -1
}
return 0
}

export const buildQuery = (
gqlQuery: string,
params: Map<string, string>
Expand All @@ -27,7 +62,9 @@ export const parseStop = (gqlFeature: gqlStop): Feature => {
type = stopType.Tram;
tarmo_category = "Ratikkapysäkki";
}
if (gqlFeature.gtfsId.startsWith("TampereVR")) {
// Nowadays, train station ids seem to have the format digitraffic:ABC_1,
// while bus and tram stop ids have the format tampere:xxxx.
if (gqlFeature.gtfsId.startsWith("digitraffic:")) {
type = stopType.Train;
tarmo_category = "Rautatieasema";
}
Expand Down