Skip to content

Commit 4797482

Browse files
Refacto Demo Application (#690)
* Added demo app and removed test app * Removed useless i18n sync logic in the SDK * Added memoization optimizations in the SDK
1 parent bcf5ab1 commit 4797482

File tree

198 files changed

+4162
-1568
lines changed

Some content is hidden

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

198 files changed

+4162
-1568
lines changed

.github/workflows/analyze.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,16 @@ jobs:
1717

1818
steps:
1919
- name: Checkout repository
20-
uses: actions/checkout@v2
20+
uses: actions/checkout@v4
2121
- name: Set up Node.Js with Yarn
22-
uses: actions/setup-node@v3
22+
uses: actions/setup-node@v4
2323
with:
24-
node-version: "16"
24+
node-version: "20"
2525
- name: Printing tools versions
2626
run: echo NodeJs $(node -v), NPM v$(npm -v), Yarn v$(yarn -v)
2727
- name: Installing dependencies
2828
run: |
29-
yarn config set enableImmutableInstalls false
29+
yarn config set enableImmutableInstalls true
3030
yarn install
3131
- name: Building packages
3232
run: yarn build
File renamed without changes.
File renamed without changes.
File renamed without changes.

apps/demo-app/README.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Monk Demo App
2+
This application is a demo app used to showcase how to implement the Monk workflow (authentication, inspection creation,
3+
inspection capture and inspection report) using the MonkJs SDK.
4+
5+
# Features
6+
This app contains the following features :
7+
- Authentication guards to enforce user log in
8+
- User log in with browser pop-up using Auth0 and token caching in the local storage
9+
- Automatic creation of a Monk inspection
10+
- Inspection capture using the PhotoCapture workflow
11+
- Redirection to the Monk inspection report app (since the inspection report component is not yet available in MonkJs
12+
4.0)
13+
- Possiblity of passing the following configuration in the URL search params :
14+
- Encrypted authentication token using ZLib (the user does not have to log in)
15+
- Inspection ID (instead of creating a new one automatically)
16+
- Vehicle type used for the Sights (default one is Crossover)
17+
- Application language (English / French / German)
18+
19+
# Running the App
20+
In order to run the app, you will need to have [NodeJs](https://nodejs.org/en) >= 16 and
21+
[Yarn 3](https://yarnpkg.com/getting-started/install) installed. Then, you'll need to install the required dependencies
22+
using the following command :
23+
24+
```bash
25+
yarn install
26+
```
27+
28+
You then need to copy the local environment configuration available in the `env.txt` file at the root of the directory
29+
into an env file called `.env` :
30+
31+
```bash
32+
cp env.txt .env
33+
```
34+
35+
You can then start the app by running :
36+
37+
```bash
38+
yarn start
39+
```
40+
41+
The application is by default available at `https://localhost:17200/`.
42+
43+
# Building the App
44+
To build the app, you simply need to run the following command :
45+
46+
```bash
47+
yarn build
48+
```
49+
50+
Don't forget to update the environment variables defined in your `.env` file for the target website.
51+
52+
# Testing
53+
## Running the Tests
54+
To run the tests of the app, simply run the following command :
55+
56+
```bash
57+
yarn test
58+
```
59+
60+
To run the tests as well as collecgt coverage, run the following command :
61+
62+
```bash
63+
yarn test:coverage
64+
```
65+
66+
## Analyzing Bundle Size
67+
After building the app using the `yarn build` command, you can analyze the bundle size using the following command :
68+
69+
```bash
70+
yarn analyze
71+
```
72+
73+
This will open a new window on your desktop browser where you'll be able to see the sizes of each module in the final
74+
app.

apps/demo-app/env.txt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# App
2+
PORT=17200
3+
HTTPS=true
4+
REACT_APP_ENVIRONMENT=staging
5+
6+
# API
7+
REACT_APP_API_DOMAIN=api.preview.monk.ai/v1
8+
9+
# Authentication
10+
REACT_APP_AUTH_DOMAIN=idp.preview.monk.ai
11+
REACT_APP_AUTH_AUDIENCE=https://api.monk.ai/v1/
12+
REACT_APP_AUTH_CLIENT_ID=O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH
13+
14+
# Sentry
15+
REACT_APP_SENTRY_DSN=https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720
16+
17+
# ESLint config
18+
ESLINT_NO_DEV_ERRORS=true

apps/demo-app/jest.config.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const { react } = require('@monkvision/jest-config');
2+
3+
module.exports = {
4+
...react,
5+
coverageThreshold: {
6+
global: {
7+
branches: 0,
8+
functions: 0,
9+
lines: 0,
10+
statements: 0,
11+
},
12+
},
13+
};

apps/monk-test-app/package.json renamed to apps/demo-app/package.json

+32-20
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
{
2-
"name": "monk-test-app",
2+
"name": "monk-demo-app",
33
"version": "4.0.0",
44
"license": "BSD-3-Clause-Clear",
55
"packageManager": "yarn@3.2.4",
66
"description": "MonkJs test app with react and typescript",
77
"author": "monkvision",
88
"private": true,
99
"scripts": {
10-
"start": "HTTPS=true react-scripts start",
10+
"start": "react-scripts start",
1111
"build": "react-scripts build",
12-
"test": "react-scripts test --no-watch --no-watchAll --passWithNoTests",
12+
"test": "jest",
13+
"test:coverage": "jest --coverage",
14+
"analyze": "source-map-explorer 'build/static/js/*.js'",
1315
"eject": "react-scripts eject",
1416
"prettier": "prettier --check ./src",
1517
"prettier:fix": "prettier --write ./src",
@@ -19,49 +21,55 @@
1921
"lint:fix": "yarn run prettier:fix && yarn run eslint:fix"
2022
},
2123
"dependencies": {
22-
"@monkvision/camera-web": "4.0.0",
24+
"@auth0/auth0-react": "^2.2.4",
2325
"@monkvision/common": "4.0.0",
2426
"@monkvision/common-ui-web": "4.0.0",
2527
"@monkvision/inspection-capture-web": "4.0.0",
2628
"@monkvision/monitoring": "4.0.0",
29+
"@monkvision/network": "4.0.0",
2730
"@monkvision/sentry": "4.0.0",
2831
"@monkvision/sights": "4.0.0",
2932
"@monkvision/types": "4.0.0",
33+
"@types/babel__core": "^7",
34+
"@types/jest": "^27.5.2",
35+
"@types/node": "^16.18.18",
36+
"@types/react": "^17.0.2",
37+
"@types/react-dom": "^17.0.2",
38+
"@types/react-router-dom": "^5.3.3",
39+
"@types/sort-by": "^1",
3040
"axios": "^1.5.0",
3141
"i18next": "^23.4.5",
3242
"i18next-browser-languagedetector": "^7.1.0",
3343
"jest-watch-typeahead": "^2.2.2",
44+
"localforage": "^1.10.0",
45+
"match-sorter": "^6.3.4",
3446
"react": "^17.0.2",
3547
"react-dom": "^17.0.2",
3648
"react-i18next": "^13.2.0",
49+
"react-router-dom": "^6.22.3",
3750
"react-scripts": "5.0.1",
51+
"sort-by": "^1.2.0",
52+
"source-map-explorer": "^2.5.3",
3853
"typescript": "^4.9.5",
3954
"web-vitals": "^2.1.4"
4055
},
4156
"devDependencies": {
4257
"@babel/core": "^7.22.9",
58+
"@monkvision/eslint-config-base": "4.0.0",
59+
"@monkvision/eslint-config-typescript": "4.0.0",
60+
"@monkvision/eslint-config-typescript-react": "4.0.0",
61+
"@monkvision/jest-config": "4.0.0",
62+
"@monkvision/prettier-config": "4.0.0",
63+
"@monkvision/test-utils": "4.0.0",
64+
"@monkvision/typescript-config": "4.0.0",
4365
"@testing-library/dom": "^8.20.0",
4466
"@testing-library/jest-dom": "^5.16.5",
4567
"@testing-library/react": "^12.1.5",
4668
"@testing-library/react-hooks": "^8.0.1",
4769
"@testing-library/user-event": "^12.1.5",
48-
"@types/babel__core": "^7",
49-
"@types/jest": "^27.5.2",
50-
"@types/node": "^16.18.18",
51-
"@types/react": "^17.0.2",
52-
"@types/react-dom": "^17.0.2",
53-
"eslint": "^8.29.0",
54-
"eslint-plugin-jsx-a11y": "^6.7.1",
55-
"eslint-plugin-react": "^7.33.1",
56-
"eslint-plugin-react-hooks": "^4.6.0",
57-
"jest": "^29.3.1",
58-
"prettier": "^2.7.1",
59-
"regexpp": "^3.2.0",
60-
"ts-jest": "^29.0.3"
61-
},
62-
"peerDependencies": {
6370
"@typescript-eslint/eslint-plugin": "^5.43.0",
6471
"@typescript-eslint/parser": "^5.43.0",
72+
"eslint": "^8.29.0",
6573
"eslint-config-airbnb-base": "^15.0.0",
6674
"eslint-config-prettier": "^8.5.0",
6775
"eslint-formatter-pretty": "^4.1.0",
@@ -73,7 +81,11 @@
7381
"eslint-plugin-promise": "^6.1.1",
7482
"eslint-plugin-react": "^7.27.1",
7583
"eslint-plugin-react-hooks": "^4.3.0",
76-
"eslint-utils": "^3.0.0"
84+
"eslint-utils": "^3.0.0",
85+
"jest": "^29.3.1",
86+
"prettier": "^2.7.1",
87+
"regexpp": "^3.2.0",
88+
"ts-jest": "^29.0.3"
7789
},
7890
"prettier": "@monkvision/prettier-config",
7991
"browserslist": {

apps/demo-app/public/favicon.ico

14.7 KB
Binary file not shown.

apps/demo-app/public/index.html

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta
9+
name="description"
10+
content="Web site created using create-react-app"
11+
/>
12+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
13+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
14+
<title>React App</title>
15+
</head>
16+
<body>
17+
<noscript>You need to enable JavaScript to run this app.</noscript>
18+
<div id="root"></div>
19+
</body>
20+
</html>

apps/demo-app/public/logo192.png

9.58 KB
Loading

apps/demo-app/public/logo512.png

43.2 KB
Loading

apps/monk-test-app/public/manifest.json renamed to apps/demo-app/public/manifest.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"short_name": "React App",
3-
"name": "Create React App Sample",
2+
"short_name": "Monk Demo App",
3+
"name": "Monk Inspection Demo Application",
44
"icons": [
55
{
66
"src": "favicon.ico",
@@ -20,6 +20,6 @@
2020
],
2121
"start_url": ".",
2222
"display": "standalone",
23-
"theme_color": "#000000",
24-
"background_color": "#ffffff"
23+
"theme_color": "#274B9F",
24+
"background_color": "#202020"
2525
}

apps/demo-app/src/components/App.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Outlet, useNavigate } from 'react-router-dom';
2+
import { MonkAppParamsProvider, MonkProvider, useMonkTheme } from '@monkvision/common';
3+
import { Page } from '../pages';
4+
5+
export function App() {
6+
const navigate = useNavigate();
7+
const { rootStyles } = useMonkTheme();
8+
9+
return (
10+
<MonkAppParamsProvider onFetchAuthToken={() => navigate(Page.CREATE_INSPECTION)}>
11+
<MonkProvider>
12+
<div className='app-container' style={rootStyles}>
13+
<Outlet />
14+
</div>
15+
</MonkProvider>
16+
</MonkAppParamsProvider>
17+
);
18+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
2+
import { CreateInspectionPage, LogInPage, Page, PhotoCapturePage } from '../pages';
3+
import { AuthGuard } from './AuthGuard';
4+
import { App } from './App';
5+
6+
export function AppRouter() {
7+
return (
8+
<BrowserRouter>
9+
<Routes>
10+
<Route path='/' element={<App />}>
11+
<Route path='/' element={<Navigate to={Page.CREATE_INSPECTION} />} />
12+
<Route path={Page.LOG_IN} element={<LogInPage />} />
13+
<Route
14+
path={Page.CREATE_INSPECTION}
15+
element={
16+
<AuthGuard>
17+
<CreateInspectionPage />
18+
</AuthGuard>
19+
}
20+
index
21+
/>
22+
<Route
23+
path={Page.PHOTO_CAPTURE}
24+
element={
25+
<AuthGuard>
26+
<PhotoCapturePage />
27+
</AuthGuard>
28+
}
29+
index
30+
/>
31+
<Route path='*' element={<Navigate to={Page.CREATE_INSPECTION} />} />
32+
</Route>
33+
</Routes>
34+
</BrowserRouter>
35+
);
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { PropsWithChildren } from 'react';
2+
import { Navigate } from 'react-router-dom';
3+
import { useMonkAppParams } from '@monkvision/common';
4+
import { isTokenExpired, isUserAuthorized } from '@monkvision/network';
5+
import { Page } from '../../pages';
6+
import { REQUIRED_AUTHORIZATIONS } from '../../config';
7+
8+
export function AuthGuard({ children }: PropsWithChildren<unknown>) {
9+
const { authToken } = useMonkAppParams();
10+
11+
if (
12+
!authToken ||
13+
!isUserAuthorized(authToken, REQUIRED_AUTHORIZATIONS) ||
14+
isTokenExpired(authToken)
15+
) {
16+
return <Navigate to={Page.LOG_IN} replace />;
17+
}
18+
19+
return <>{children}</>;
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './AuthGuard';

apps/demo-app/src/components/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './App';
2+
export * from './AppRouter';
3+
export * from './AuthGuard';

apps/demo-app/src/config/auth.ts

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { MonkApiPermission } from '@monkvision/network';
2+
3+
export const REQUIRED_AUTHORIZATIONS = [
4+
MonkApiPermission.TASK_COMPLIANCES,
5+
MonkApiPermission.TASK_DAMAGE_DETECTION,
6+
MonkApiPermission.TASK_DAMAGE_IMAGES_OCR,
7+
MonkApiPermission.TASK_WHEEL_ANALYSIS,
8+
MonkApiPermission.INSPECTION_CREATE,
9+
MonkApiPermission.INSPECTION_READ,
10+
MonkApiPermission.INSPECTION_UPDATE,
11+
MonkApiPermission.INSPECTION_WRITE,
12+
];

apps/demo-app/src/config/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './auth';
2+
export * from './sights';

0 commit comments

Comments
 (0)