Skip to content
Open
Show file tree
Hide file tree
Changes from 8 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
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ select_permissions:
- is_service_road
- is_signalized
- location_id
- street_level
- latitude
- longitude
- council_district
Expand Down Expand Up @@ -74,7 +73,6 @@ select_permissions:
- is_service_road
- is_signalized
- location_id
- street_level
- latitude
- longitude
- council_district
Expand Down Expand Up @@ -106,7 +104,6 @@ select_permissions:
- is_service_road
- is_signalized
- location_id
- street_level
- latitude
- longitude
- council_district
Expand Down
2 changes: 1 addition & 1 deletion database/metadata/databases/default/tables/tables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@
- "!include public_afd__incidents.yaml"
- "!include public_atd__recommendation_status_lkp.yaml"
- "!include public_atd_apd_blueform.yaml"
- "!include public_locations.yaml"
- "!include public_change_log_crashes.yaml"
- "!include public_change_log_crashes_cris.yaml"
- "!include public_change_log_ems__incidents.yaml"
Expand All @@ -76,6 +75,7 @@
- "!include public_fatalities_view.yaml"
- "!include public_location_crashes_view.yaml"
- "!include public_location_notes.yaml"
- "!include public_locations.yaml"
- "!include public_locations_list_view.yaml"
- "!include public_moped_component_crashes.yaml"
- "!include public_people.yaml"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
alter table locations add column street_level text;

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
alter table locations drop column street_level;
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
services:
graphql-engine:
image: hasura/graphql-engine:v2.48.9
volumes:
- ./viewer/graphql-engine-metadata:/metadata
ports:
- 8084:8080
environment:
Expand All @@ -19,6 +17,7 @@ services:
env_file:
- .env
volumes:
- postgres_data:/var/lib/postgresql/data
- ./database/snapshots:/snapshots
ports:
- 5431:5432
Expand All @@ -43,3 +42,6 @@ services:
networks:
default:
name: vision-zero_default

volumes:
postgres_data:
8 changes: 5 additions & 3 deletions editor/configs/locationColumns.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ColDataCardDef } from "@/types/types";
import { Location } from "@/types/locations";
import { formatDollars } from "@/utils/formatters";
import { formatArrayToString, formatDollars } from "@/utils/formatters";

export const locationColumns = {
location_id: {
path: "location_id",
Expand All @@ -20,7 +21,8 @@ export const locationColumns = {
valueFormatter: formatDollars,
},
street_level: {
path: "street_level",
label: "ASMP Street level",
path: "street_levels",
label: "ASMP Street level(s)",
valueFormatter: formatArrayToString,
},
} satisfies Record<string, ColDataCardDef<Location>>;
2 changes: 1 addition & 1 deletion editor/queries/location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const GET_LOCATION = gql`
where: { location_id: { _eq: $locationId }, is_deleted: { _eq: false } }
) {
location_id
street_level
street_levels
location_name
geometry
latitude
Expand Down
2 changes: 1 addition & 1 deletion editor/types/locations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type Location = {
latitude: number | null;
longitude: number | null;
geometry: MultiPolygon | null;
street_level: string | null;
street_levels: string[] | null;
locations_list_view: LocationsListRow | null;
location_notes: LocationNote[]
};
14 changes: 14 additions & 0 deletions editor/utils/formatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,17 @@ export const formatTime = (value: unknown): string => {
export const formatFileTimestamp = (date: Date): string => {
return format(date, "yyyy-MM-dd h.mm.ss a");
};

/**
* Format an array of values to a comma-separated-string, removing
* null, undefined, and empty strings
*/
export const formatArrayToString = (value: unknown): string => {
if (value && Array.isArray(value)) {
return value
.filter((val) => val !== undefined && val !== null && val !== "")
.map((val) => String(val))
.join(", ");
}
return "";
};
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
shtab==1.*
python-dotenv==0.*
requests==2.*
68 changes: 56 additions & 12 deletions vision-zero
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#!/usr/bin/env python

import time
import argparse
import subprocess
from datetime import date, datetime
import os
import shtab
import shutil
from datetime import date, datetime
import pprint
import subprocess
import time

from dotenv import load_dotenv
import requests
import shtab

GRAPHQL_ENGINE_PORT = 8084

# check if the .env file exists
if not os.path.exists(".env"):
Expand Down Expand Up @@ -54,12 +56,32 @@ def checkDockerComposeAvailability():
exit()


def wait_for_hasura(max_attempts=5, delay=2):
"""Wait for Hasura to be ready by polling health endpoint"""
for attempt in range(max_attempts):
print("⏳ Waiting for GraphQL Engine to be ready...")
try:
response = requests.get(
f"http://localhost:{GRAPHQL_ENGINE_PORT}/healthz", timeout=1
)
if response.status_code == 200:
print("✅ GraphQL Engine is ready!")
return True
except requests.exceptions.RequestException:
pass
time.sleep(delay)

print("❌ GraphQL Engine failed to become ready")
return False


def doCommand(args):
apply_migrations = args.apply
if args.command == "build":
buildTools()
elif args.command == "local-stack-up":
dbUp()
graphqlEngineUp()
graphqlEngineUp(apply_migrations)
cr3UserApiUp()
elif args.command == "local-stack-down":
cr3UserApiDown()
Expand All @@ -71,7 +93,7 @@ def doCommand(args):
dbDown()
elif args.command == "graphql-engine-up":
dbUp()
graphqlEngineUp()
graphqlEngineUp(apply_migrations)
elif args.command == "graphql-engine-down":
graphqlEngineDown()
elif args.command == "api-up":
Expand Down Expand Up @@ -232,7 +254,7 @@ def replicateDb(args):
print(f"Error output: {result.stderr}")
exit(1)

graphqlEngineUp()
graphqlEngineUp(args.apply)


def dumpLocalDb():
Expand Down Expand Up @@ -317,7 +339,6 @@ def dbUp():
print(f"Error output: {result.stderr}")
exit(1)
subprocess.run(["docker", "ps"])
time.sleep(5)


def dbDown():
Expand All @@ -333,10 +354,9 @@ def dbDown():
]
)
subprocess.run(["docker", "ps"])
time.sleep(5)


def graphqlEngineUp():
def graphqlEngineUp(apply_migrations=False):
print("🚀 Starting GraphQL Engine")
subprocess.run(
docker_compose_invocation
Expand All @@ -348,6 +368,24 @@ def graphqlEngineUp():
"graphql-engine",
]
)

if apply_migrations:
if wait_for_hasura():
subprocess.call(
[
"hasura",
"migrate",
"apply",
"--all-databases",
"--disable-interactive",
],
cwd="./database",
)
subprocess.call(
["hasura", "metadata", "apply"],
cwd="./database",
)

subprocess.run(["docker", "ps"])
print("🚀 GraphQL Engine started.")
print("You can run './vision-zero hasura-console' to open the console.")
Expand Down Expand Up @@ -467,6 +505,12 @@ def get_main_parser():
],
)
parser.add_argument("-f", "--filename", required=False)
parser.add_argument(
"-a",
"--apply",
Copy link
Member Author

@johnclary johnclary Jan 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i considered trying to mirror the hasura CLI more closely such that we could use apply instead of --apply, but it would take some light refactoring of the parser setup to use suparsers. maybe i should go ahead and do that now?

./vision-zero local-stack-up apply

action="store_true",
help="Apply migrations and metadata after starting",
)
return parser


Expand Down