Skip to content

Commit ad52344

Browse files
committed
refactor: remove unnecessary comments and code
1 parent ed5e18a commit ad52344

22 files changed

Lines changed: 73 additions & 249 deletions

File tree

Lines changed: 16 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
11
/**
2-
* Modal dialog shown when `httpClient` latches `sessionExpiredStore`
2+
* Non-dismissable Modal dialog shown when `httpClient` latches `sessionExpiredStore`
33
* on a 401. Pure presentation: state and the popup handshake live in
44
* `useReauthFlow` (under `platform/auth`).
5-
*
6-
* Built on the native `<dialog>` element via `showModal()`, which gives
7-
* us focus trap, top-layer rendering, and focus restoration for free.
8-
* Esc is intercepted (`cancel` event) to keep the dialog modal-required
9-
* — dismissing only delays the next 401, which immediately re-opens
10-
* the dialog. The only escape is "Sign in".
115
*/
126

13-
import { Button, Card, Typography } from '@equinor/eds-core-react'
7+
import { Button, Dialog as EDSDialog, Typography } from '@equinor/eds-core-react'
148
import { useQueryClient } from '@tanstack/react-query'
15-
import { type SyntheticEvent, useEffect, useRef } from 'react'
169
import { useReauthFlow } from '@/shared/platform/auth'
1710

1811
const TITLE_ID = 'session-expired-title'
@@ -21,58 +14,29 @@ const DESC_ID = 'session-expired-description'
2114
export const SessionExpiredDialog = () => {
2215
const queryClient = useQueryClient()
2316
const { open, signingIn, requestSignIn } = useReauthFlow(queryClient)
24-
return open ? <Dialog signingIn={signingIn} onSignIn={requestSignIn} /> : null
25-
}
26-
27-
interface DialogProps {
28-
signingIn: boolean
29-
onSignIn: () => void
30-
}
31-
32-
const Dialog = ({ signingIn, onSignIn }: DialogProps) => {
33-
const ref = useRef<HTMLDialogElement>(null)
34-
35-
useEffect(() => {
36-
const dialog = ref.current
37-
if (!dialog) return
38-
dialog.showModal()
39-
return () => {
40-
if (dialog.open) dialog.close()
41-
}
42-
}, [])
43-
44-
// Block Esc-to-dismiss; see file header.
45-
const blockCancel = (e: SyntheticEvent<HTMLDialogElement>) => e.preventDefault()
46-
47-
return (
48-
<dialog
49-
ref={ref}
17+
return open ? (
18+
<EDSDialog
5019
aria-labelledby={TITLE_ID}
5120
aria-describedby={DESC_ID}
52-
onCancel={blockCancel}
53-
style={{
54-
border: 'none',
55-
padding: 0,
56-
background: 'transparent',
57-
maxWidth: '24rem',
58-
margin: 'auto',
59-
}}
21+
isDismissable={false}
22+
open
23+
style={{ width: '100vw', maxWidth: 420 }}
6024
>
61-
<Card style={{ padding: '1.5rem', display: 'grid', gap: '1rem' }}>
62-
<Typography id={TITLE_ID} variant="h5">
63-
Session expired
64-
</Typography>
25+
<EDSDialog.Header>
26+
<EDSDialog.Title id={TITLE_ID}>Session expired</EDSDialog.Title>
27+
</EDSDialog.Header>
28+
<EDSDialog.Content>
6529
<Typography id={DESC_ID} variant="body_short">
6630
{signingIn
6731
? 'Complete sign-in in the popup window. This dialog will close automatically when you’re done.'
6832
: 'Your session has expired. Sign in again in a popup — this page and your work will stay as they are.'}
6933
</Typography>
70-
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
71-
<Button onClick={onSignIn} disabled={signingIn}>
34+
<div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '1rem' }}>
35+
<Button onClick={requestSignIn} disabled={signingIn}>
7236
{signingIn ? 'Waiting for sign-in…' : 'Sign in'}
7337
</Button>
7438
</div>
75-
</Card>
76-
</dialog>
77-
)
39+
</EDSDialog.Content>
40+
</EDSDialog>
41+
) : null
7842
}

web/src/app/bootstrap/Providers.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import { QueryClientProvider } from '@tanstack/react-query'
1+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
22
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
33
import { SessionExpiredDialog } from '@/app/auth/SessionExpiredDialog/SessionExpiredDialog'
44
import { ApplicationError } from '@/app/bootstrap/ApplicationError'
5-
import { TelemetryErrorBoundary, TelemetryProvider } from '@/shared/platform/telemetry'
5+
import { Telemetry, TelemetryErrorBoundary, TelemetryProvider } from '@/shared/platform/telemetry'
66
import { ToastContainer } from '@/shared/platform/toast'
7-
import type { ProvidersProps } from './Providers.types'
87

9-
// No `<AppInsightsContext.Provider>`: page-views use `enableAutoRouteTracking`
10-
// and nothing currently calls `useAppInsightsContext`.
8+
export interface ProvidersProps {
9+
telemetry: Telemetry
10+
queryClient: QueryClient
11+
children: React.ReactNode
12+
}
13+
1114
export const Providers = ({ telemetry, queryClient, children }: ProvidersProps) => (
1215
<TelemetryProvider telemetry={telemetry}>
1316
<TelemetryErrorBoundary telemetry={telemetry} fallback={ApplicationError}>
1417
<QueryClientProvider client={queryClient}>
1518
<SessionExpiredDialog />
1619
{children}
1720
<ToastContainer />
18-
{/* `import.meta.env.DEV` is statically replaced by Vite, so the
19-
devtools import is tree-shaken from production builds. */}
2021
{import.meta.env.DEV && <ReactQueryDevtools initialIsOpen={false} />}
2122
</QueryClientProvider>
2223
</TelemetryErrorBoundary>

web/src/app/bootstrap/Providers.types.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

web/src/app/layout/Header/components/ColorSchemaToggle/ColorSchemaToggle.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@reference "tailwindcss";
1+
@reference "../../../../styles/index.css";
22

33
.color-schema-radio {
44
@apply flex flex-1 flex-col items-center text-center px-4 py-2 border border-border rounded cursor-pointer;

web/src/app/layout/VersionText/VersionText.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ENV } from '@/config/env'
44
import type { CommitInfo } from './VersionText.types'
55
import { EMPTY_COMMIT_INFO, parseVersionFile } from './VersionText.utils'
66

7-
const useCommitInfo = () => {
7+
export const VersionText = () => {
88
const [commitInfo, setCommitInfo] = useState<CommitInfo>(EMPTY_COMMIT_INFO)
99

1010
useEffect(() => {
@@ -17,11 +17,6 @@ const useCommitInfo = () => {
1717
.catch(() => setCommitInfo(EMPTY_COMMIT_INFO))
1818
}, [])
1919

20-
return commitInfo
21-
}
22-
23-
export const VersionText = () => {
24-
const commitInfo = useCommitInfo()
2520
const label = commitInfo.refs || commitInfo.hash || 'unknown'
2621

2722
return (

web/src/app/routes/__root.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ export interface RouterContext {
1212
}
1313

1414
export const Route = createRootRouteWithContext<RouterContext>()({
15-
// Resolve the user once before any component mounts so suspense reads
16-
// are synchronous, and bridge identity to telemetry in the same step.
1715
beforeLoad: async ({ context: { queryClient, telemetry } }) => {
16+
// Resolve the user once before any component mounts
1817
const user = await queryClient.ensureQueryData(userQuery())
1918
telemetry.setUser(user.id)
2019
},

web/src/app/routes/todos.tsx

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,21 @@
11
import { createFileRoute } from '@tanstack/react-router'
22
import { z } from 'zod'
33
import { hasPermissionCheck } from '@/config/accessControl'
4-
import { todoListQuery, TodosPage } from '@/features/todos'
4+
import { TodosPage, todoListQuery } from '@/features/todos'
55
import { userQuery } from '@/shared/platform/auth'
66

7-
// `?status=` is the only piece of URL state owned by this page; the
8-
// schema doubles as the runtime validator and the type fed to
9-
// `useSearch`. Defaulting to `'all'` keeps the URL clean — TanStack
10-
// Router omits defaulted keys from the rendered query string.
7+
// Validate the `status` search param and provide a default value of 'all' if it's not present.
118
const searchSchema = z.object({
129
status: z.enum(['all', 'active', 'done']).default('all'),
1310
})
1411

1512
export const Route = createFileRoute('/todos')({
16-
// Gate the route on `todos:read`. The root route already primed
17-
// `userQuery`, so this is a cheap cache hit; calling it here keeps
18-
// the route self-contained and matches the pattern documented in
19-
// `shared/platform/access-control/README.md`. A 403 `Response` is
20-
// caught by `RouteErrorBoundary`.
2113
beforeLoad: async ({ context: { queryClient } }) => {
2214
const user = await queryClient.ensureQueryData(userQuery())
2315
if (hasPermissionCheck(user, 'todos', 'read') !== true) {
2416
throw new Response(null, { status: 403 })
2517
}
2618
},
27-
// Prime the todo list cache so `useTodos` (useSuspenseQuery) gets an
28-
// instant cache hit on first paint instead of suspending.
2919
loader: ({ context: { queryClient } }) => queryClient.ensureQueryData(todoListQuery()),
3020
component: TodosPage,
3121
validateSearch: searchSchema,

web/src/app/styles/index.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@
130130
outline: 2px dashed var(--border-focus);
131131
outline-offset: 2px;
132132
}
133+
/* Fix tailwind reset on EDS dialog */
134+
dialog { margin: auto }
133135
dialog::backdrop {
134136
background: rgba(0, 0, 0, 0.4);
135137
}

web/src/config/accessControl.ts

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,47 +9,29 @@
99
* - `hasPermissionCheck(user, resource, action, data?)` — the bound
1010
* checker. Returns `boolean | 'loading'`. Used from route
1111
* `beforeLoad` (throws a 403 `Response`).
12-
* - `isAllowed(user, resource, action, data?)` — strict-boolean
13-
* variant for components and tests; `'loading'` collapses to
14-
* `false`.
15-
*
16-
* Leaf-shaped on purpose (no React, no auth imports beyond the
17-
* type-only `CurrentUser`) so it can be safely imported from anywhere
18-
* including `userQuery`.
19-
*
20-
* To add a role: extend the `Role` union, give it an entry in `ROLES`,
21-
* and make sure the backend (`/whoami`) emits the matching string in
22-
* its `roles` array. Unknown role strings are silently ignored.
12+
* - `isAllowed(user, resource, action, data?)` — Strict-boolean variant of {@link hasPermissionCheck}: `
13+
* 'loading'` collapses to `false`. Prefer this in components and tests; loaders
14+
* should keep using `hasPermissionCheck` so they can distinguish`'loading'` from a real deny if needed.
2315
*/
2416

2517
import type { Todo } from '@/features/todos'
2618
import { createHasPermission, createIsAllowed, type RolesWithPermissions } from '@/shared/platform/access-control'
2719
import type { CurrentUser } from '@/shared/platform/auth'
2820

29-
// ---------------------------------------------------------------------------
30-
// Roles
31-
// ---------------------------------------------------------------------------
32-
21+
/* Make sure roles stay in sync with the backend's `/whoami`
22+
* response as unknown role strings are silently ignored.
23+
*/
3324
export type Role = 'admin' | 'editor' | 'viewer'
3425

35-
// ---------------------------------------------------------------------------
36-
// Permissions
37-
// ---------------------------------------------------------------------------
38-
3926
export type Permissions = {
4027
todos: {
4128
dataType: Todo | null
4229
action: 'read' | 'create' | 'update' | 'delete'
4330
}
4431
}
4532

46-
/** True iff `todo` exists and its `user_id` matches the current user. */
4733
const isOwnTodo = (user: CurrentUser, todo: Todo | null): boolean => todo != null && todo.user_id === user.id
4834

49-
// ---------------------------------------------------------------------------
50-
// Roles → permissions table
51-
// ---------------------------------------------------------------------------
52-
5335
export const ROLES: RolesWithPermissions<Role, Permissions, CurrentUser> = {
5436
admin: {
5537
todos: { read: true, create: true, update: true, delete: true },
@@ -58,7 +40,6 @@ export const ROLES: RolesWithPermissions<Role, Permissions, CurrentUser> = {
5840
todos: {
5941
read: true,
6042
create: true,
61-
// Editors may only modify todos they own.
6243
update: isOwnTodo,
6344
delete: isOwnTodo,
6445
},
@@ -68,17 +49,5 @@ export const ROLES: RolesWithPermissions<Role, Permissions, CurrentUser> = {
6849
},
6950
}
7051

71-
/**
72-
* Singleton check bound to {@link ROLES}. Loader call sites (`*.route.ts`)
73-
* call this directly and throw a 403 `Response` — caught by
74-
* `RouteErrorBoundary` → `<ForbiddenPage />`.
75-
*/
7652
export const hasPermissionCheck = createHasPermission<Role, Permissions, CurrentUser>(ROLES)
77-
78-
/**
79-
* Strict-boolean variant of {@link hasPermissionCheck}: `'loading'`
80-
* collapses to `false`. Prefer this in components and tests; loaders
81-
* should keep using `hasPermissionCheck` so they can distinguish
82-
* `'loading'` from a real deny if needed.
83-
*/
8453
export const isAllowed = createIsAllowed<Permissions, CurrentUser>(hasPermissionCheck)

web/src/features/todos/index.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
// Public surface — for cross-feature imports only (e.g. `src/routes/`).
2-
// Files inside this feature must use relative paths instead of importing from
3-
// here; otherwise we get circular imports and the lazy-chunked page bundle
4-
// pulls in everything reachable from this barrel.
5-
//
6-
// Enforced by the `no-restricted-imports` rule in `eslint.config.mts` —
7-
// outside files cannot deep-import `@/features/<name>/...`.
8-
//
9-
// Code-splitting is now handled by the TanStack Router Vite plugin's
10-
// `autoCodeSplitting` — the chunk boundary is the route file (`routes/index.tsx`),
11-
// not the import path. Re-exporting `TodosPage` here is therefore safe.
121
export { todoListQuery } from './api'
132
export type { Todo } from './api/schema'
143
export { TodosPage } from './pages/TodosPage/TodosPage'

0 commit comments

Comments
 (0)