Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/analyze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up Node.Js with Yarn
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"
- name: Printing tools versions
run: echo NodeJs $(node -v), NPM v$(npm -v), Yarn v$(yarn -v)
- name: Installing dependencies
run: |
yarn config set enableImmutableInstalls false
yarn config set enableImmutableInstalls true
yarn install
- name: Building packages
run: yarn build
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
74 changes: 74 additions & 0 deletions apps/demo-app/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Monk Demo App
This application is a demo app used to showcase how to implement the Monk workflow (authentication, inspection creation,
inspection capture and inspection report) using the MonkJs SDK.

# Features
This app contains the following features :
- Authentication guards to enforce user log in
- User log in with browser pop-up using Auth0 and token caching in the local storage
- Automatic creation of a Monk inspection
- Inspection capture using the PhotoCapture workflow
- Redirection to the Monk inspection report app (since the inspection report component is not yet available in MonkJs
4.0)
- Possiblity of passing the following configuration in the URL search params :
- Encrypted authentication token using ZLib (the user does not have to log in)
- Inspection ID (instead of creating a new one automatically)
- Vehicle type used for the Sights (default one is Crossover)
- Application language (English / French / German)

# Running the App
In order to run the app, you will need to have [NodeJs](https://nodejs.org/en) >= 16 and
[Yarn 3](https://yarnpkg.com/getting-started/install) installed. Then, you'll need to install the required dependencies
using the following command :

```bash
yarn install
```

You then need to copy the local environment configuration available in the `env.txt` file at the root of the directory
into an env file called `.env` :

```bash
cp env.txt .env
```

You can then start the app by running :

```bash
yarn start
```

The application is by default available at `https://localhost:17200/`.

# Building the App
To build the app, you simply need to run the following command :

```bash
yarn build
```

Don't forget to update the environment variables defined in your `.env` file for the target website.

# Testing
## Running the Tests
To run the tests of the app, simply run the following command :

```bash
yarn test
```

To run the tests as well as collecgt coverage, run the following command :

```bash
yarn test:coverage
```

## Analyzing Bundle Size
After building the app using the `yarn build` command, you can analyze the bundle size using the following command :

```bash
yarn analyze
```

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
app.
18 changes: 18 additions & 0 deletions apps/demo-app/env.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# App
PORT=17200
HTTPS=true
REACT_APP_ENVIRONMENT=staging

# API
REACT_APP_API_DOMAIN=api.preview.monk.ai/v1

# Authentication
REACT_APP_AUTH_DOMAIN=idp.preview.monk.ai
REACT_APP_AUTH_AUDIENCE=https://api.monk.ai/v1/
REACT_APP_AUTH_CLIENT_ID=O7geYcPM6zEJrHw0WvQVzSIzw4WzrAtH

# Sentry
REACT_APP_SENTRY_DSN=https://74f50bfe6f11de7aefd54acfa5dfed96@o4505669501648896.ingest.us.sentry.io/4506863461662720

# ESLint config
ESLINT_NO_DEV_ERRORS=true
13 changes: 13 additions & 0 deletions apps/demo-app/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { react } = require('@monkvision/jest-config');

module.exports = {
...react,
coverageThreshold: {
global: {
branches: 0,
functions: 0,
lines: 0,
statements: 0,
},
},
};
52 changes: 32 additions & 20 deletions apps/monk-test-app/package.json → apps/demo-app/package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
{
"name": "monk-test-app",
"name": "monk-demo-app",
"version": "4.0.0",
"license": "BSD-3-Clause-Clear",
"packageManager": "yarn@3.2.4",
"description": "MonkJs test app with react and typescript",
"author": "monkvision",
"private": true,
"scripts": {
"start": "HTTPS=true react-scripts start",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --no-watch --no-watchAll --passWithNoTests",
"test": "jest",
"test:coverage": "jest --coverage",
"analyze": "source-map-explorer 'build/static/js/*.js'",
"eject": "react-scripts eject",
"prettier": "prettier --check ./src",
"prettier:fix": "prettier --write ./src",
Expand All @@ -19,49 +21,55 @@
"lint:fix": "yarn run prettier:fix && yarn run eslint:fix"
},
"dependencies": {
"@monkvision/camera-web": "4.0.0",
"@auth0/auth0-react": "^2.2.4",
"@monkvision/common": "4.0.0",
"@monkvision/common-ui-web": "4.0.0",
"@monkvision/inspection-capture-web": "4.0.0",
"@monkvision/monitoring": "4.0.0",
"@monkvision/network": "4.0.0",
"@monkvision/sentry": "4.0.0",
"@monkvision/sights": "4.0.0",
"@monkvision/types": "4.0.0",
"@types/babel__core": "^7",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.18",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
"@types/react-router-dom": "^5.3.3",
"@types/sort-by": "^1",
"axios": "^1.5.0",
"i18next": "^23.4.5",
"i18next-browser-languagedetector": "^7.1.0",
"jest-watch-typeahead": "^2.2.2",
"localforage": "^1.10.0",
"match-sorter": "^6.3.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-i18next": "^13.2.0",
"react-router-dom": "^6.22.3",
"react-scripts": "5.0.1",
"sort-by": "^1.2.0",
"source-map-explorer": "^2.5.3",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4"
},
"devDependencies": {
"@babel/core": "^7.22.9",
"@monkvision/eslint-config-base": "4.0.0",
"@monkvision/eslint-config-typescript": "4.0.0",
"@monkvision/eslint-config-typescript-react": "4.0.0",
"@monkvision/jest-config": "4.0.0",
"@monkvision/prettier-config": "4.0.0",
"@monkvision/test-utils": "4.0.0",
"@monkvision/typescript-config": "4.0.0",
"@testing-library/dom": "^8.20.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^12.1.5",
"@types/babel__core": "^7",
"@types/jest": "^27.5.2",
"@types/node": "^16.18.18",
"@types/react": "^17.0.2",
"@types/react-dom": "^17.0.2",
"eslint": "^8.29.0",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.33.1",
"eslint-plugin-react-hooks": "^4.6.0",
"jest": "^29.3.1",
"prettier": "^2.7.1",
"regexpp": "^3.2.0",
"ts-jest": "^29.0.3"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": "^5.43.0",
"@typescript-eslint/parser": "^5.43.0",
"eslint": "^8.29.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0",
"eslint-formatter-pretty": "^4.1.0",
Expand All @@ -73,7 +81,11 @@
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.27.1",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-utils": "^3.0.0"
"eslint-utils": "^3.0.0",
"jest": "^29.3.1",
"prettier": "^2.7.1",
"regexpp": "^3.2.0",
"ts-jest": "^29.0.3"
},
"prettier": "@monkvision/prettier-config",
"browserslist": {
Expand Down
Binary file added apps/demo-app/public/favicon.ico
Binary file not shown.
20 changes: 20 additions & 0 deletions apps/demo-app/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
Binary file added apps/demo-app/public/logo192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/demo-app/public/logo512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "Monk Demo App",
"name": "Monk Inspection Demo Application",
"icons": [
{
"src": "favicon.ico",
Expand All @@ -20,6 +20,6 @@
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
"theme_color": "#274B9F",
"background_color": "#202020"
}
File renamed without changes.
18 changes: 18 additions & 0 deletions apps/demo-app/src/components/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Outlet, useNavigate } from 'react-router-dom';
import { MonkAppParamsProvider, MonkProvider, useMonkTheme } from '@monkvision/common';
import { Page } from '../pages';

export function App() {
const navigate = useNavigate();
const { rootStyles } = useMonkTheme();

return (
<MonkAppParamsProvider onFetchAuthToken={() => navigate(Page.CREATE_INSPECTION)}>
<MonkProvider>
<div className='app-container' style={rootStyles}>
<Outlet />
</div>
</MonkProvider>
</MonkAppParamsProvider>
);
}
36 changes: 36 additions & 0 deletions apps/demo-app/src/components/AppRouter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { CreateInspectionPage, LogInPage, Page, PhotoCapturePage } from '../pages';
import { AuthGuard } from './AuthGuard';
import { App } from './App';

export function AppRouter() {
return (
<BrowserRouter>
<Routes>
<Route path='/' element={<App />}>
<Route path='/' element={<Navigate to={Page.CREATE_INSPECTION} />} />
<Route path={Page.LOG_IN} element={<LogInPage />} />
<Route
path={Page.CREATE_INSPECTION}
element={
<AuthGuard>
<CreateInspectionPage />
</AuthGuard>
}
index
/>
<Route
path={Page.PHOTO_CAPTURE}
element={
<AuthGuard>
<PhotoCapturePage />
</AuthGuard>
}
index
/>
<Route path='*' element={<Navigate to={Page.CREATE_INSPECTION} />} />
</Route>
</Routes>
</BrowserRouter>
);
}
20 changes: 20 additions & 0 deletions apps/demo-app/src/components/AuthGuard/AuthGuard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PropsWithChildren } from 'react';
import { Navigate } from 'react-router-dom';
import { useMonkAppParams } from '@monkvision/common';
import { isTokenExpired, isUserAuthorized } from '@monkvision/network';
import { Page } from '../../pages';
import { REQUIRED_AUTHORIZATIONS } from '../../config';

export function AuthGuard({ children }: PropsWithChildren<unknown>) {
const { authToken } = useMonkAppParams();

if (
!authToken ||
!isUserAuthorized(authToken, REQUIRED_AUTHORIZATIONS) ||
isTokenExpired(authToken)
) {
return <Navigate to={Page.LOG_IN} replace />;
}

return <>{children}</>;
}
1 change: 1 addition & 0 deletions apps/demo-app/src/components/AuthGuard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './AuthGuard';
3 changes: 3 additions & 0 deletions apps/demo-app/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './App';
export * from './AppRouter';
export * from './AuthGuard';
12 changes: 12 additions & 0 deletions apps/demo-app/src/config/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { MonkApiPermission } from '@monkvision/network';

export const REQUIRED_AUTHORIZATIONS = [
MonkApiPermission.TASK_COMPLIANCES,
MonkApiPermission.TASK_DAMAGE_DETECTION,
MonkApiPermission.TASK_DAMAGE_IMAGES_OCR,
MonkApiPermission.TASK_WHEEL_ANALYSIS,
MonkApiPermission.INSPECTION_CREATE,
MonkApiPermission.INSPECTION_READ,
MonkApiPermission.INSPECTION_UPDATE,
MonkApiPermission.INSPECTION_WRITE,
];
2 changes: 2 additions & 0 deletions apps/demo-app/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './auth';
export * from './sights';
Loading