Skip to content

Commit 88c14f9

Browse files
committed
Formatting
1 parent f058ecc commit 88c14f9

File tree

15 files changed

+7763
-4196
lines changed

15 files changed

+7763
-4196
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches:
66
- main
77
tags-ignore:
8-
- '**'
8+
- "**"
99
workflow_dispatch:
1010

1111
permissions:

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ Vue 3 / Nuxt frontend for [cupcake](https://github.com/javaBin/cupcake). Lets ja
1313

1414
## Pages
1515

16-
| Route | Description |
17-
|---|---|
18-
| `/` | Home — shows authenticated user and role check |
19-
| `/conference/[conferenceId]` | Session browser with filtering for a conference |
16+
| Route | Description |
17+
| ------------------------------------------------ | ------------------------------------------------------------ |
18+
| `/` | Home — shows authenticated user and role check |
19+
| `/conference/[conferenceId]` | Session browser with filtering for a conference |
2020
| `/conference/[conferenceId]/session/[sessionId]` | Session detail with full speaker info (bio, email, location) |
2121

2222
## Authentication
@@ -61,12 +61,12 @@ ESLint and Prettier are also enforced via pre-commit hooks (lint-staged).
6161

6262
## Configuration
6363

64-
| Environment Variable | Description | Default |
65-
|---|---|---|
66-
| `CUPCAKE_BACKEND` | Backend base URL for the server-side proxy | `http://127.0.0.1:8080` (dev) / `https://cupcake-backend.java.no` (prod) |
67-
| `CUPCAKE_FRONTEND` | Hostname the dev server allows (Vite `allowedHosts`) | `localhost` |
68-
| `NUXT_PUBLIC_OIDC_AUTHORITY` | OIDC authority URL (e.g. Keycloak realm URL) | `https://auth.home.chrissearle.org/realms/HA12` |
69-
| `NUXT_PUBLIC_OIDC_CLIENT_ID` | OIDC client ID | `cupcake-client` |
64+
| Environment Variable | Description | Default |
65+
| ---------------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------ |
66+
| `CUPCAKE_BACKEND` | Backend base URL for the server-side proxy | `http://127.0.0.1:8080` (dev) / `https://cupcake-backend.java.no` (prod) |
67+
| `CUPCAKE_FRONTEND` | Hostname the dev server allows (Vite `allowedHosts`) | `localhost` |
68+
| `NUXT_PUBLIC_OIDC_AUTHORITY` | OIDC authority URL (e.g. Keycloak realm URL) | `https://auth.home.chrissearle.org/realms/HA12` |
69+
| `NUXT_PUBLIC_OIDC_CLIENT_ID` | OIDC client ID | `cupcake-client` |
7070

7171
`NUXT_PUBLIC_OIDC_AUTHORITY` and `NUXT_PUBLIC_OIDC_CLIENT_ID` must match the `OIDC_WELL_KNOWN_URL` and `OIDC_EXPECTED_AZP` values configured on the backend.
7272

@@ -94,8 +94,8 @@ The image uses a multi-stage build (Node build stage, slim runtime stage) and se
9494

9595
## CI/CD
9696

97-
| Trigger | Workflow | What it does |
98-
|---|---|---|
99-
| Push to `main` | `build.yaml` | Builds and pushes multi-platform Docker image, tags as `staging` |
100-
| Pull request | `pr.yaml` | Runs `pnpm lint` and `pnpm build` |
101-
| Tag `v*` | `release.yaml` | Promotes `staging` image to `release` and version tag |
97+
| Trigger | Workflow | What it does |
98+
| -------------- | -------------- | ---------------------------------------------------------------- |
99+
| Push to `main` | `build.yaml` | Builds and pushes multi-platform Docker image, tags as `staging` |
100+
| Pull request | `pr.yaml` | Runs `pnpm lint` and `pnpm build` |
101+
| Tag `v*` | `release.yaml` | Promotes `staging` image to `release` and version tag |

app/components/nav/index.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ const conferenceItems = computed(() => [
3636
to: conferenceLink(c),
3737
})),
3838
39-
...(conferencesLoaded.value && !conferencesError.value && conferenceCount.value === 0
39+
...(conferencesLoaded.value &&
40+
!conferencesError.value &&
41+
conferenceCount.value === 0
4042
? [[{ label: "No conferences found", disabled: true }]]
4143
: []),
4244
])

app/components/sessions/browser.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ const props = defineProps<{
66
conference: Conference
77
}>()
88
9-
const { sessions, sessionsPending, sessionsError, fetchSessions } = useSessionData(props.conference.id)
9+
const { sessions, sessionsPending, sessionsError, fetchSessions } =
10+
useSessionData(props.conference.id)
1011
await fetchSessions()
1112
12-
1313
type Filters = {
1414
format?: string
1515
status?: string
@@ -146,7 +146,11 @@ const rangeText = computed(() => {
146146
</div>
147147

148148
<UProgress v-if="sessionsPending" indeterminate class="w-full" />
149-
<SessionsTable v-else :sessions="paginatedSessions" :conference="conference" />
149+
<SessionsTable
150+
v-else
151+
:sessions="paginatedSessions"
152+
:conference="conference"
153+
/>
150154

151155
<div class="flex justify-end">
152156
<UPagination

app/composables/conferences.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,14 @@ import { ApiError, apiJson } from "~/composables/useApiFetch"
33

44
export const useConferences = () => {
55
const conferences = useState<Conference[]>("conferences-data", () => [])
6-
const conferencesPending = useState<boolean>("conferences-pending", () => false)
7-
const conferencesError = useState<ApiError | null>("conferences-error", () => null)
6+
const conferencesPending = useState<boolean>(
7+
"conferences-pending",
8+
() => false,
9+
)
10+
const conferencesError = useState<ApiError | null>(
11+
"conferences-error",
12+
() => null,
13+
)
814
const conferencesLoaded = useState<boolean>("conferences-loaded", () => false)
915

1016
const fetchConferences = async (): Promise<void> => {
@@ -14,7 +20,8 @@ export const useConferences = () => {
1420
try {
1521
conferences.value = await apiJson<Conference[]>("/api/conferences")
1622
} catch (e) {
17-
conferencesError.value = e instanceof ApiError ? e : new ApiError(0, "Unknown error")
23+
conferencesError.value =
24+
e instanceof ApiError ? e : new ApiError(0, "Unknown error")
1825
conferences.value = []
1926
} finally {
2027
conferencesPending.value = false

app/composables/useApiFetch.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ensureAccessToken } from './useAuth'
1+
import { ensureAccessToken } from "./useAuth"
22

33
export class ApiError extends Error {
44
public readonly status: number
@@ -11,9 +11,12 @@ export class ApiError extends Error {
1111
}
1212
}
1313

14-
function buildHeaders(existing: HeadersInit | undefined, token: string | null): Headers {
14+
function buildHeaders(
15+
existing: HeadersInit | undefined,
16+
token: string | null,
17+
): Headers {
1518
const h = new Headers(existing)
16-
if (token) h.set('Authorization', `Bearer ${token}`)
19+
if (token) h.set("Authorization", `Bearer ${token}`)
1720
return h
1821
}
1922

@@ -39,10 +42,13 @@ export async function apiFetch(
3942
})
4043
}
4144

42-
export async function apiJson<T>(input: RequestInfo | URL, init: RequestInit = {}): Promise<T> {
45+
export async function apiJson<T>(
46+
input: RequestInfo | URL,
47+
init: RequestInit = {},
48+
): Promise<T> {
4349
const res = await apiFetch(input, init)
4450
if (!res.ok) {
45-
const bodyText = await res.text().catch(() => '')
51+
const bodyText = await res.text().catch(() => "")
4652
throw new ApiError(res.status, bodyText)
4753
}
4854
return (await res.json()) as T

app/composables/useAuth.ts

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { User, UserManager, WebStorageStateStore, Log } from 'oidc-client-ts'
1+
import { User, UserManager, WebStorageStateStore, Log } from "oidc-client-ts"
22

33
interface AuthState {
44
returnUrl: string
55
}
66

77
function isAuthState(value: unknown): value is AuthState {
88
return (
9-
typeof value === 'object' &&
10-
value !== null &&
11-
'returnUrl' in value &&
12-
typeof (value as { returnUrl?: unknown }).returnUrl === 'string'
9+
typeof value === "object" &&
10+
value !== null &&
11+
"returnUrl" in value &&
12+
typeof (value as { returnUrl?: unknown }).returnUrl === "string"
1313
)
1414
}
1515

@@ -35,8 +35,8 @@ function getUserManager(): UserManager {
3535
authority: oidcAuthority,
3636
client_id: oidcClientId,
3737
redirect_uri: `${origin}/`,
38-
response_type: 'code',
39-
scope: 'openid profile email offline_access',
38+
response_type: "code",
39+
scope: "openid profile email offline_access",
4040
userStore: new WebStorageStateStore({ store: window.sessionStorage }),
4141
automaticSilentRenew: false,
4242
loadUserInfo: false,
@@ -84,19 +84,23 @@ let tokenEndpointPromise: Promise<string> | null = null
8484
async function getTokenEndpoint(): Promise<string> {
8585
if (!tokenEndpointPromise) {
8686
const { oidcAuthority } = useRuntimeConfig().public
87-
tokenEndpointPromise = fetch(`${oidcAuthority}/.well-known/openid-configuration`)
88-
.then(async (r) => {
89-
if (!r.ok) throw new Error('Failed to fetch OIDC discovery')
90-
return (await r.json()) as Discovery
91-
})
92-
.then((d) => d.token_endpoint)
87+
tokenEndpointPromise = fetch(
88+
`${oidcAuthority}/.well-known/openid-configuration`,
89+
)
90+
.then(async (r) => {
91+
if (!r.ok) throw new Error("Failed to fetch OIDC discovery")
92+
return (await r.json()) as Discovery
93+
})
94+
.then((d) => d.token_endpoint)
9395
}
9496
return tokenEndpointPromise
9597
}
9698

9799
let refreshInFlight: Promise<string | null> | null = null
98100

99-
export async function ensureAccessToken(skewSeconds = 30): Promise<string | null> {
101+
export async function ensureAccessToken(
102+
skewSeconds = 30,
103+
): Promise<string | null> {
100104
const user = await getUser()
101105

102106
if (!user) {
@@ -134,13 +138,13 @@ export async function ensureAccessToken(skewSeconds = 30): Promise<string | null
134138
const { oidcClientId } = useRuntimeConfig().public
135139

136140
const body = new URLSearchParams()
137-
body.set('grant_type', 'refresh_token')
138-
body.set('client_id', oidcClientId)
139-
body.set('refresh_token', refreshToken)
141+
body.set("grant_type", "refresh_token")
142+
body.set("client_id", oidcClientId)
143+
body.set("refresh_token", refreshToken)
140144

141145
const resp = await fetch(tokenEndpoint, {
142-
method: 'POST',
143-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
146+
method: "POST",
147+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
144148
body,
145149
})
146150

app/composables/useSessionData.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,46 @@ import type { Session } from "@/types/session"
22
import { ApiError, apiJson } from "~/composables/useApiFetch"
33

44
export const useSessionData = (conferenceId: string) => {
5-
const sessions = useState<Session[]>(`sessions-data-${conferenceId}`, () => [])
6-
const sessionsPending = useState<boolean>(`sessions-pending-${conferenceId}`, () => false)
7-
const sessionsError = useState<ApiError | null>(`sessions-error-${conferenceId}`, () => null)
8-
const sessionsLoaded = useState<boolean>(`sessions-loaded-${conferenceId}`, () => false)
5+
const sessions = useState<Session[]>(
6+
`sessions-data-${conferenceId}`,
7+
() => [],
8+
)
9+
const sessionsPending = useState<boolean>(
10+
`sessions-pending-${conferenceId}`,
11+
() => false,
12+
)
13+
const sessionsError = useState<ApiError | null>(
14+
`sessions-error-${conferenceId}`,
15+
() => null,
16+
)
17+
const sessionsLoaded = useState<boolean>(
18+
`sessions-loaded-${conferenceId}`,
19+
() => false,
20+
)
921

1022
const fetchSessions = async (): Promise<void> => {
1123
if (sessionsLoaded.value || sessionsPending.value) return
1224
sessionsPending.value = true
1325
sessionsError.value = null
1426
try {
15-
sessions.value = await apiJson<Session[]>(`/api/conferences/${conferenceId}/sessions`)
27+
sessions.value = await apiJson<Session[]>(
28+
`/api/conferences/${conferenceId}/sessions`,
29+
)
1630
} catch (e) {
17-
sessionsError.value = e instanceof ApiError ? e : new ApiError(0, "Unknown error")
31+
sessionsError.value =
32+
e instanceof ApiError ? e : new ApiError(0, "Unknown error")
1833
sessions.value = []
1934
} finally {
2035
sessionsPending.value = false
2136
sessionsLoaded.value = true
2237
}
2338
}
2439

25-
return { sessions, sessionsPending, sessionsError, sessionsLoaded, fetchSessions }
40+
return {
41+
sessions,
42+
sessionsPending,
43+
sessionsError,
44+
sessionsLoaded,
45+
fetchSessions,
46+
}
2647
}

app/composables/useUser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ export const useUser = () => {
1414
try {
1515
user.value = await apiJson<User>("/api/me")
1616
} catch (e) {
17-
userError.value = e instanceof ApiError ? e : new ApiError(0, "Unknown error")
17+
userError.value =
18+
e instanceof ApiError ? e : new ApiError(0, "Unknown error")
1819
user.value = null
1920
} finally {
2021
userPending.value = false

app/pages/conference/[conferenceId]/index.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
import type { Conference } from "@/types/conference"
33
44
const route = useRoute()
5-
const { conferencesPending, fetchConferences, findConference } = useConferences()
5+
const { conferencesPending, fetchConferences, findConference } =
6+
useConferences()
67
78
const conferenceId = String(route.params.conferenceId)
89
910
await fetchConferences()
1011
11-
const conference = computed<Conference | undefined>(() => findConference(conferenceId))
12+
const conference = computed<Conference | undefined>(() =>
13+
findConference(conferenceId),
14+
)
1215
</script>
1316

1417
<template>
1518
<div v-if="!conferencesPending" class="mx-2">
16-
<SessionsBrowser
17-
v-if="conference"
18-
:conference="conference"
19-
/>
19+
<SessionsBrowser v-if="conference" :conference="conference" />
2020
</div>
2121

22-
<UProgress v-else indeterminate class="w-full"/>
22+
<UProgress v-else indeterminate class="w-full" />
2323
</template>

0 commit comments

Comments
 (0)