Skip to content

Commit e2d50a8

Browse files
authored
Sentry integration (#22)
Integration of the Sentry SDK for workspaces JS errors
2 parents 403f8d0 + 4cf8e57 commit e2d50a8

54 files changed

Lines changed: 13259 additions & 5411 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"biome.enabled": false,
3+
// Required in vscode-eslint < v3.0.10 only
4+
"eslint.useFlatConfig": true
5+
}

Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FROM node as builder
22

3+
# These are ARGs because nuxt bakes them into its minified version of the JS,
4+
# So they are actually set at build time vs. run-time
5+
#
36
ARG VITE_TDEI_API_URL
47
ARG VITE_TDEI_USER_API_URL
58
ARG VITE_API_URL
@@ -10,6 +13,9 @@ ARG VITE_IMAGERY_SCHEMA
1013
ARG VITE_IMAGERY_EXAMPLE_URL
1114
ARG VITE_LONG_FORM_QUEST_SCHEMA
1215
ARG VITE_LONG_FORM_QUEST_EXAMPLE_URL
16+
ARG VITE_SENTRY_AUTH_TOKEN
17+
ARG VITE_SENTRY_DSN
18+
1319
ARG CODE_VERSION=unknown
1420

1521
WORKDIR /app/

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,34 @@ Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introdu
66

77
## Dev Setup
88

9-
NB: This will start the dev server against the cloud-hosted backend. If you need to change both the frontend and the backend, you'll
10-
need to start a local copy of the backend (workspaces-tasking-manager) and set the environment vars appropriately below.
11-
12-
The below values are for cloud-hosted dev:
13-
149
```
10+
# set these e.g. to the dev TDEI instance--note: any tokens you get from these hosts must match the environment for other components
11+
# e.g. you can't use dev TDEI KeyCloak JWT tokens in stage or production environments.
1512
export VITE_TDEI_API_URL=https://api-dev.tdei.us/api/v1/
1613
export VITE_TDEI_USER_API_URL=https://portal-api-dev.tdei.us/api/v1/
17-
export VITE_API_URL=https://api.workspaces-dev.sidewalks.washington.edu/api/v1/
18-
export VITE_OSM_URL=https://osm.workspaces-dev.sidewalks.washington.edu/
14+
15+
# use your local workspaces-backend instance--or set to the dev instance of this component if not running locally
16+
export VITE_API_URL=http://localhost:3000/api/v1/
17+
export VITE_OSM_URL=http://localhost:3000/
18+
19+
# probably want to leave these as-is
1920
export VITE_RAPID_URL=https://rapid.workspaces-dev.sidewalks.washington.edu/
2021
export VITE_PATHWAYS_EDITOR_URL=https://pathways.workspaces-dev.sidewalks.washington.edu/
22+
23+
# probably don't need to change any of these
2124
export CODE_VERSION="local"
22-
export VITE_IMAGERY_SCHEMA=https://raw.githubusercontent.com/TaskarCenterAtUW/tdei-tools/main/docs/imagery-layer/schema.json
23-
export VITE_IMAGERY_EXAMPLE_URL=https://raw.githubusercontent.com/TaskarCenterAtUW/tdei-tools/main/docs/imagery-layer/example.json
24-
export VITE_LONG_FORM_QUEST_SCHEMA=https://raw.githubusercontent.com/TaskarCenterAtUW/tdei-tools/refs/heads/main/docs/quest-definition/schema.json
25-
export VITE_LONG_FORM_QUEST_EXAMPLE_URL=https://raw.githubusercontent.com/TaskarCenterAtUW/tdei-tools/refs/heads/main/docs/quest-definition/example.json
25+
export VITE_IMAGERY_SCHEMA=https://raw.githubusercontent.com/TaskarCenterAtUW/asr-imagery-list/refs/heads/main/schema/schema.json
26+
export VITE_IMAGERY_EXAMPLE_URL=https://github.com/TaskarCenterAtUW/asr-imagery-list/blob/main/examples/example.json
27+
export VITE_LONG_FORM_QUEST_SCHEMA=https://raw.githubusercontent.com/TaskarCenterAtUW/asr-quests/refs/heads/main/schema/schema.json
28+
export VITE_LONG_FORM_QUEST_EXAMPLE_URL=https://raw.githubusercontent.com/TaskarCenterAtUW/asr-quests/refs/heads/main/docs/quest-definition/example.json
2629
27-
# install deps
30+
# install deps (first time only)
2831
npm install
2932
3033
# start dev server
3134
npm run dev
3235
```
36+
37+
## Troubleshooting
38+
39+
If you run ```npm run dev``` and nothing happens, check that you've set your "exports" as above. Undefined environment variables are not handled gracefully right now.

components/AppIcon.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,23 @@
66
const props = defineProps({
77
variant: {
88
type: String,
9-
required: true
9+
required: true,
1010
},
1111
size: {
1212
type: [Number, String],
13-
default: 18
13+
default: 18,
1414
},
1515
noMargin: {
1616
type: Boolean,
17-
default: false
18-
}
17+
default: false,
18+
},
1919
})
2020
2121
const classes = computed(() => ([
2222
'material-icons',
2323
`md-${props.size}`,
2424
`md-${props.variant}`,
25-
props.noMargin ? undefined : 'me-2'
25+
props.noMargin ? undefined : 'me-2',
2626
]))
2727
</script>
2828

components/AppLogo.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
<template>
2-
<img class="app-logo img-fluid" src="~/assets/img/icon.svg" alt="" />
2+
<img
3+
class="app-logo img-fluid"
4+
src="~/assets/img/icon.svg"
5+
alt=""
6+
>
37
</template>
4-

components/AppNavbar.vue

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,99 @@
11
<template>
22
<nav class="app-navbar navbar navbar-expand-md shadow">
33
<div class="container-lg">
4-
<nuxt-link class="navbar-brand" to="/">
4+
<nuxt-link
5+
class="navbar-brand"
6+
to="/"
7+
>
58
<app-logo />
69
<span>TDEI</span>&nbsp;<span>Workspaces</span>
710
</nuxt-link>
811

9-
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
10-
<span class="navbar-toggler-icon"></span>
12+
<button
13+
class="navbar-toggler"
14+
type="button"
15+
data-bs-toggle="collapse"
16+
data-bs-target="#navbarSupportedContent"
17+
aria-controls="navbarSupportedContent"
18+
aria-expanded="false"
19+
aria-label="Toggle navigation"
20+
>
21+
<span class="navbar-toggler-icon" />
1122
</button>
1223

13-
<div class="collapse navbar-collapse" id="navbarSupportedContent">
14-
<ul v-show="auth.ok" class="navbar-nav me-auto mb-2 mb-lg-0">
24+
<div
25+
id="navbarSupportedContent"
26+
class="collapse navbar-collapse"
27+
>
28+
<ul
29+
v-show="auth.ok"
30+
class="navbar-nav me-auto mb-2 mb-lg-0"
31+
>
1532
<li class="nav-item">
16-
<nuxt-link class="nav-link" aria-current="page" to="/">Home</nuxt-link>
33+
<nuxt-link
34+
class="nav-link"
35+
aria-current="page"
36+
to="/"
37+
>Home</nuxt-link>
1738
</li>
1839
<li class="nav-item">
19-
<nuxt-link class="nav-link" to="/dashboard">Dashboard</nuxt-link>
40+
<nuxt-link
41+
class="nav-link"
42+
to="/dashboard"
43+
>Dashboard</nuxt-link>
2044
</li>
2145
<li class="nav-item">
22-
<nuxt-link class="nav-link" to="/workspace/create">Create Workspace</nuxt-link>
46+
<nuxt-link
47+
class="nav-link"
48+
to="/workspace/create"
49+
>Create Workspace</nuxt-link>
2350
</li>
2451
<li class="nav-item">
25-
<a class="nav-link" href="#">Help</a>
52+
<a
53+
class="nav-link"
54+
href="#"
55+
>Help</a>
2656
</li>
2757
</ul>
2858

2959
<span class="mx-auto" />
3060

31-
<nuxt-link v-show="!auth.ok" to="/signin" class="btn">Sign In</nuxt-link>
32-
<span v-show="auth.ok" class="nav-item dropdown">
33-
<a class="nav-link" href="#" id="navbarAccountMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
34-
<app-icon variant="account_circle" size="24" />{{ auth.displayName }}
61+
<nuxt-link
62+
v-show="!auth.ok"
63+
to="/signin"
64+
class="btn"
65+
>Sign In</nuxt-link>
66+
<span
67+
v-show="auth.ok"
68+
class="nav-item dropdown"
69+
>
70+
<a
71+
id="navbarAccountMenuLink"
72+
class="nav-link"
73+
href="#"
74+
role="button"
75+
data-bs-toggle="dropdown"
76+
aria-expanded="false"
77+
>
78+
<app-icon
79+
variant="account_circle"
80+
size="24"
81+
/>{{ auth.displayName }}
3582
</a>
36-
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarAccountMenuLink">
83+
<ul
84+
class="dropdown-menu dropdown-menu-end"
85+
aria-labelledby="navbarAccountMenuLink"
86+
>
3787
<li>
38-
<nuxt-link class="dropdown-item" to="/" @click="auth.clear()">
39-
<app-icon variant="logout" class="me-3" />Logout
88+
<nuxt-link
89+
class="dropdown-item"
90+
to="/"
91+
@click="auth.clear()"
92+
>
93+
<app-icon
94+
variant="logout"
95+
class="me-3"
96+
/>Logout
4097
</nuxt-link>
4198
</li>
4299
</ul>

components/AppSpinner.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
<template>
2-
<div :class="classes" role="status">
2+
<div
3+
:class="classes"
4+
role="status"
5+
>
36
<span class="visually-hidden">Loading...</span>
47
</div>
58
</template>
69

710
<script setup lang="ts">
811
const props = defineProps({
9-
size: String
12+
size: String,
1013
})
1114
1215
const classes = computed(() => ({
1316
'spinner-border': true,
1417
'spinner-border-sm': props.size === 'sm',
15-
'spinner-border-lg': props.size === 'lg'
18+
'spinner-border-lg': props.size === 'lg',
1619
}))
1720
</script>

components/DatasetPicker.vue

Lines changed: 47 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,58 @@
11
<template>
2-
<input type="text" v-model="searchText" placeholder="Start typing a dataset name to filter datasets..." aria-label="Dataset Filter" class="form-control" />
3-
<select
4-
v-model="model"
5-
class="dataset-picker form-select"
6-
aria-label="Dataset Selection"
2+
<input
3+
v-model="searchText"
4+
type="text"
5+
placeholder="Start typing a dataset name to filter datasets..."
6+
aria-label="Dataset Filter"
7+
class="form-control"
8+
>
9+
<select
10+
v-model="model"
11+
class="dataset-picker form-select"
12+
aria-label="Dataset Selection"
13+
>
14+
<option
15+
:selected
16+
value="null"
17+
disabled
718
>
8-
<option :selected value=null disabled>Select a (matching) dataset...</option>
9-
<option v-for="ds in datasets" :key="ds.id" :value="ds.id" >
10-
{{ ds.name }} (version {{ ds.version }})
11-
</option>
12-
</select>
19+
Select a (matching) dataset...
20+
</option>
21+
<option
22+
v-for="ds in datasets"
23+
:key="ds.id"
24+
:value="ds.id"
25+
>
26+
{{ ds.name }} (version {{ ds.version }})
27+
</option>
28+
</select>
1329
</template>
1430

1531
<script setup lang="ts">
16-
import { tdeiClient } from '~/services/index'
17-
18-
const model = defineModel({ required: true });
19-
const props = defineProps({
20-
projectGroupId: {
21-
type: String,
22-
required: true
23-
}
24-
});
32+
import { tdeiClient } from '~/services/index'
33+
34+
const model = defineModel({ required: true })
35+
const props = defineProps({
36+
projectGroupId: {
37+
type: String,
38+
required: true,
39+
},
40+
})
2541
26-
const { projectGroupId } = toRefs(props);
27-
const searchText = ref('');
28-
const datasets = ref([]);
29-
refreshDatasets(projectGroupId.value, searchText.value);
42+
const { projectGroupId } = toRefs(props)
43+
const searchText = ref('')
44+
const datasets = ref([])
45+
refreshDatasets(projectGroupId.value, searchText.value)
3046
31-
watch(projectGroupId, (val) => refreshDatasets(val, searchText.value));
32-
watch(searchText, (val) => refreshDatasets(projectGroupId.value, val));
47+
watch(projectGroupId, val => refreshDatasets(val, searchText.value))
48+
watch(searchText, val => refreshDatasets(projectGroupId.value, val))
3349
34-
async function refreshDatasets(projectGroupId: string, name: string) {
35-
datasets.value = (await tdeiClient.getDatasetsByProjectGroupAndName(projectGroupId, name))
36-
.sort((a, b) => a.name.localeCompare(b.name));
50+
async function refreshDatasets(projectGroupId: string, name: string) {
51+
datasets.value = (await tdeiClient.getDatasetsByProjectGroupAndName(projectGroupId, name))
52+
.sort((a, b) => a.name.localeCompare(b.name))
3753
38-
if (datasets.value.length === 0) {
39-
model.value = null;
40-
}
54+
if (datasets.value.length === 0) {
55+
model.value = null
4156
}
57+
}
4258
</script>
43-

components/DatasetTypeRadio.vue

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11
<template>
22
<div class="btn-group">
33
<input
4+
id="radio_type_osw"
45
v-model="model"
56
type="radio"
6-
id="radio_type_osw"
77
name="radio_type"
88
class="btn-check"
99
autocomplete="off"
1010
value="osw"
1111
>
12-
<label class="btn btn-outline-primary" for="radio_type_osw">OpenSidewalks</label>
12+
<label
13+
class="btn btn-outline-primary"
14+
for="radio_type_osw"
15+
>OpenSidewalks</label>
1316

1417
<input
18+
id="radio_type_pathways"
1519
v-model="model"
1620
type="radio"
17-
id="radio_type_pathways"
1821
name="radio_type"
1922
class="btn-check"
2023
autocomplete="off"
2124
value="pathways"
2225
>
23-
<label class="btn btn-outline-primary" for="radio_type_pathways">GTFS Pathways</label>
26+
<label
27+
class="btn btn-outline-primary"
28+
for="radio_type_pathways"
29+
>GTFS Pathways</label>
2430
</div>
2531
</template>
2632

2733
<script setup lang="ts">
28-
const model = defineModel({ required: true });
34+
const model = defineModel({ required: true })
2935
</script>

components/LoadingSpinner.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<template>
2-
<div class="spinner-border" role="status">
2+
<div
3+
class="spinner-border"
4+
role="status"
5+
>
36
<span class="visually-hidden">Loading...</span>
47
</div>
58
</template>

0 commit comments

Comments
 (0)