Skip to content

Commit af429b9

Browse files
authored
Schreiaj/blank main page (#221)
* Add root page with structure in place. Added playwright tests to ensure behavior Updated dev docker image to support playwright which required moving to a Debian based base image (Alpine linux base image is smaller but doesn't work well with Chrome runner because Chrome doesn't publish a precompiled package for it in Alpine) * Remove inline styles Remove commented out code * Update Playwright tests to work in CI Parameterize baseURL so we can just work with internal routes
1 parent 553ee1c commit af429b9

13 files changed

+163
-77
lines changed

OCR/dev-env.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ services:
1515
dockerfile: dev-dockerfile
1616
ports:
1717
- "5173:5173"
18+
- "8080:8080"
1819
volumes:
1920
- ./frontend:/app
2021
restart: no
21-
command: "/bin/sh -c 'npm install && npm run dev -- --host'"
22+
command: "/bin/sh -c 'npm install && npx playwright install && npx playwright test --ui-port=8080 --ui-host=0.0.0.0 & npm run dev -- --host'"
2223

OCR/frontend/dev-dockerfile

+3-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
FROM node:20.17.0-alpine3.20
2-
3-
RUN apk add --update nodejs npm
4-
5-
1+
FROM node:20.17.0
62
COPY . /app
73

84
WORKDIR /app
95
RUN npm install
6+
RUN npx playwright install --with-deps
107

11-
EXPOSE 5173
8+
EXPOSE 5173 8080
129
CMD npm run dev -- --host

OCR/frontend/e2e/App.spec.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { test, expect } from '@playwright/test';
2+
import {Simulate} from "react-dom/test-utils";
3+
import click = Simulate.click;
4+
5+
test('has STLT Name', async ({ page }) => {
6+
await page.goto('/');
7+
8+
await expect(page.getByText('Demo STLT')).toBeVisible()
9+
});
10+
11+
test('has new template button', async ({ page , baseURL}) => {
12+
await page.goto('/');
13+
await expect(page.getByRole('button', { name: '+ New Template' })).toBeVisible()
14+
await page.getByRole('button', { name: '+ New Template' }).click()
15+
expect(page.url()).toEqual(`${baseURL}/new-template/upload`)
16+
17+
});

OCR/frontend/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"type": "module",
66
"scripts": {
77
"dev": "vite",
8-
"build": "tsc -b && vite build",
8+
"build": "vite build",
99
"lint": "eslint .",
1010
"preview": "vite preview",
1111
"test": "vitest",

OCR/frontend/playwright.config.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export default defineConfig({
2525
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
2626
use: {
2727
/* Base URL to use in actions like `await page.goto('/')`. */
28-
// baseURL: 'http://127.0.0.1:3000',
28+
baseURL: 'http://localhost:5173',
2929

3030
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
3131
trace: 'on-first-retry',
@@ -70,9 +70,9 @@ export default defineConfig({
7070
],
7171

7272
/* Run your local dev server before starting the tests */
73-
// webServer: {
74-
// command: 'npm run start',
75-
// url: 'http://127.0.0.1:3000',
76-
// reuseExistingServer: !process.env.CI,
77-
// },
73+
webServer: {
74+
command: 'npm run build && npm run preview -- --host',
75+
url: 'http://127.0.0.1:5173',
76+
reuseExistingServer: !process.env.CI,
77+
},
7878
});

OCR/frontend/src/App.scss

+8-32
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,20 @@
22
max-width: 100vw;
33
width: 100vw;
44
height: 100vh;
5-
margin: 0 auto;
6-
padding: 0;
7-
text-align: center;
8-
background-color: --background-lighter-blue;
5+
//margin: 0 auto;
6+
//padding: 0;
97
}
108

11-
.logo {
12-
height: 6em;
13-
padding: 1.5em;
14-
will-change: filter;
15-
transition: filter 300ms;
16-
}
17-
.logo:hover {
18-
filter: drop-shadow(0 0 2em #646cffaa);
19-
}
20-
.logo.react:hover {
21-
filter: drop-shadow(0 0 2em #61dafbaa);
9+
.bg-idwa-light {
10+
background-color: #f5fbff
2211
}
2312

24-
@keyframes logo-spin {
25-
from {
26-
transform: rotate(0deg);
27-
}
28-
to {
29-
transform: rotate(360deg);
30-
}
13+
.flex-gap-1 {
14+
gap: 1rem;
3115
}
3216

33-
@media (prefers-reduced-motion: no-preference) {
34-
a:nth-of-type(2) .logo {
35-
animation: logo-spin infinite 20s linear;
36-
}
17+
.maxw-30 {
18+
max-width: 30rem;
3719
}
3820

39-
.card {
40-
padding: 2em;
41-
}
4221

43-
.read-the-docs {
44-
color: #888;
45-
}

OCR/frontend/src/App.tsx

+45-30
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,52 @@
1-
import { useState } from 'react'
2-
import reactLogo from './assets/react.svg'
3-
import viteLogo from '/vite.svg'
1+
import {useState} from 'react'
42
import './App.scss'
5-
import { Button } from '@trussworks/react-uswds'
3+
import {Button, Link, SideNav} from "@trussworks/react-uswds";
4+
import {useLocation, useNavigate, useNavigation} from "react-router-dom";
65

6+
import {AppHeader} from "./components/AppHeader/AppHeader.tsx";
7+
import dataLinkLogo from "./assets/datalink_placeholder_logo.svg";
8+
import extractImage from "./assets/extract_image.svg"
79
function App() {
8-
const [count, setCount] = useState(0)
10+
const {pathname} = useLocation()
11+
const navigate = useNavigate()
12+
const navLinks = [
13+
{text: "Annotate and Extract", url: "/annotate"},
14+
{text: "Label Management", url: "/labels"},
15+
{text: "Dashboard", url: "/"}
16+
]
917

10-
return (
11-
<>
12-
<div>
13-
<a href="https://vitejs.dev" target="_blank">
14-
<img src={viteLogo} className="logo" alt="Vite logo" />
15-
</a>
16-
<a href="https://react.dev" target="_blank">
17-
<img src={reactLogo} className="logo react" alt="React logo" />
18-
</a>
19-
</div>
20-
<h1>Vite + React</h1>
21-
<div className="card">
22-
<button onClick={() => setCount((count) => count + 1)}>
23-
count is {count}
24-
</button>
25-
<p>
26-
Edit <code>src/App.tsx</code> and save to test HMR
27-
</p>
28-
</div>
29-
<p className="read-the-docs">
30-
Click on the Vite and React logos to learn more
31-
</p>
32-
<Button type="button">Click Me</Button>
33-
</>
34-
)
18+
19+
return (
20+
<>
21+
<div className='display-flex flex-column width-full height-full'>
22+
<AppHeader jurisdiction={`Demo STLT`}/>
23+
<div className="display-flex flex-row height-full">
24+
<div
25+
className="flex-3 padding-top-1 padding-left-1 padding-right-4 minw-15 usa-dark-background bg-primary-dark text-base-lightest display-flex flex-column flex-gap-1 maxw-30"
26+
>
27+
<div className='display-flex flex-column flex-align-start padding-top-2'>
28+
{navLinks.map((i, idx) => {
29+
return <Link key={idx} href={i.url}
30+
className={`border-left-2px padding-left-1 padding-top-2 padding-bottom-2 ${i.url === pathname ? 'text-bold' : 'border-primary-dark'}`}>{i.text}</Link>
31+
})}
32+
</div>
33+
</div>
34+
<div className="flex-10 display-flex flex-column">
35+
<h2 className="padding-left-2">Annotate and Extract</h2>
36+
<div className=" flex-1 padding-left-2 padding-right-2 bg-idwa-light" >
37+
<p><span className="text-bold">Welcome Blake, </span></p>
38+
<p>Extract data from any PDFs, or images to send to your surveillance systems using data from your saved templates or create new segmentations.</p>
39+
<img className="display-block margin-left-auto margin-right-auto padding-top-8" src={extractImage} alt="Extract From Documents"/>
40+
<p className="text-bold text-center">You have no segmentation templates set up yet. The templates will be used to extract data for your lab forms.</p>
41+
<Button type="button" className="usa-button display-flex flex-align-center margin-left-auto margin-right-auto" onClick={() => navigate("/new-template/upload")}>+ New Template</Button>
42+
</div>
43+
</div>
44+
</div>
45+
46+
</div>
47+
48+
</>
49+
)
3550
}
3651

3752
export default App
Loading
Loading

OCR/frontend/src/assets/react.svg

-1
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
.flex-gap-half {
3+
gap: 0.5rem;
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import {FC} from "react";
2+
import {Button, Icon, Header} from "@trussworks/react-uswds";
3+
4+
import './AppHeader.scss'
5+
import dataLinkLogo from '../../assets/datalink_placeholder_logo.svg';
6+
import {useNavigate} from "react-router-dom";
7+
8+
interface IndexHeaderProps {
9+
jurisdiction: string
10+
}
11+
12+
export const AppHeader: FC<IndexHeaderProps> = ({jurisdiction}: IndexHeaderProps) => {
13+
const navigate = useNavigate()
14+
return (
15+
<>
16+
<Header basic={true} role={`banner`}
17+
className='header width-full display-flex flex-row flex-justify-start bg-primary-darker padding-1 padding-left-4 padding-right-4 text-base-lightest flex-gap-half'
18+
>
19+
<div className="display-flex flex-justify-center">
20+
<Button unstyled type="button" onClick={() => navigate("/")}>
21+
<img
22+
className='width-3'
23+
src={dataLinkLogo}
24+
alt={`IDWA`}
25+
/>
26+
</Button>
27+
</div>
28+
<div className='text-bold font-ui-md display-flex flex-align-center'>
29+
Datalink
30+
</div>
31+
<div className='padding-left-1 display-flex flex-align-center'>{jurisdiction}</div>
32+
<div className='flex-align-end flex-justify-end flex-1'></div>
33+
<div className=" display-flex flex-justify-center">
34+
<a>
35+
Log Out
36+
</a>
37+
</div>
38+
<div className="display-flex flex-justify-center">
39+
<a>
40+
<Icon.Person className={`text-base-lightest usa-icon--size-3`}/>
41+
</a>
42+
</div>
43+
<div className="display-flex flex-justify-center">
44+
<a>
45+
<Icon.Settings className={`text-base-lightest usa-icon--size-3`}/>
46+
</a>
47+
</div>
48+
49+
</Header>
50+
</>
51+
)
52+
}

OCR/frontend/vite.config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ export default defineConfig({
1414
'**/e2e/**',
1515
],
1616
},
17+
preview: {
18+
port: 5173,
19+
},
1720
css: {
1821
preprocessorOptions: {
1922
scss: {

0 commit comments

Comments
 (0)