Commit 8903ec0d authored by Dmitry's avatar Dmitry
Browse files

feat: release 2.0

parent bcb43f39
Pipeline #997 failed with stage
in 2 minutes and 9 seconds
......@@ -2,32 +2,5 @@
OSDU frontend tutorials in React
## How to run
Go to 'quickstart' folder and execute the following commands. Install dependencies with 'npm ci' and run application with 'npm start' command.
```
npm ci
```
```
npm run
```
### How to change backend host and port
Create `.env` file and define the following variables:
```
SERVER_HOST=backend
SERVER_PORT=8080
```
Note: when using docker-compose to define and run both UI and backend, the value of SERVER_HOST must be the same as the name of service for your backend:
```
services:
backend:
...
ui:
...
depends_on:
- backend
```
\ No newline at end of file
## quickstart
Simple Web App to quickly connect to and try out OSDU APIs
......@@ -5,4 +5,6 @@ commitlint.config.js
src/serviceWorker.ts
src/react-app-env.d.ts
setupProxy.js
server.js
\ No newline at end of file
server.js
proxy.js
config/*
\ No newline at end of file
// https://medium.com/@cosmvs/painless-migration-from-tslint-to-eslint-for-react-with-typescript-4befb4918ba8
module.exports = {
env: {
browser: true,
es6: true,
jest: true,
},
extends: [
'eslint:recommended',
'plugin:import/recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/react',
'prettier/@typescript-eslint',
],
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
env: {
browser: true,
es6: true,
jest: true,
},
project: './tsconfig.json',
ecmaVersion: 2018,
sourceType: 'module',
},
settings: {
react: {
version: 'detect',
},
},
plugins: ['react', 'prettier', '@typescript-eslint', 'react-hooks'],
rules: {
'prettier/prettier': [
0,
{
semi: true,
singleQuote: true,
trailingComma: 'es5',
printWidth: 100,
tabWidth: 2,
arrowParens: 'avoid',
jsxSingleQuote: false,
jsxBracketSameLine: true,
},
extends: [
'eslint:recommended',
'plugin:import/recommended',
'plugin:react/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
'prettier/react',
'prettier/@typescript-eslint',
],
'no-plusplus': 0,
// semi: 0,
// eqeqeq: [1, 'always'],
// quotes: [1, 'single'],
// 'jsx-quotes': [2, 'prefer-double'],
// 'no-undef': 0,
// 'no-console': 1,
// 'no-mixed-operators': [
// 1,
// {
// allowSamePrecedence: true,
// },
// ],
// 'eol-last': [2, 'always'],
// 'no-confusing-arrow': 0,
// 'arrow-parens': [2, 'as-needed'],
// 'arrow-spacing': ['error', { before: true, after: true }],
// 'arrow-body-style': [2, 'as-needed'],
// 'no-param-reassign': 0,
// 'prefer-template': 0,
// 'prefer-promise-reject-errors': 0,
// 'no-script-url': 0,
// 'no-unused-expressions': 0,
// 'dot-notation': 0,
'import/prefer-default-export': 0,
// 'import/no-useless-path-segments': 1,
'import/no-unresolved': 0,
// 'import/no-extraneous-dependencies': 0,
// 'import/no-named-as-default': 0,
// 'import/no-duplicates': 0,
// 'import/order': 0,
// 'import/newline-after-import': 1,
// 'import/no-named-as-default-member': 0,
// 'import/namespace': 0,
// 'import/named': 0,
// 'jsx-a11y/anchor-is-valid': 0,
// 'jsx-a11y/click-events-have-key-events': 0,
// 'jsx-a11y/no-static-element-interactions': 0,
// 'jsx-a11y/label-has-for': 0,
// 'jsx-a11y/iframe-has-title': 0,
// 'jsx-a11y/control-has-associated-label': 0,
// 'react/jsx-wrap-multilines': [
// 2,
// {
// declaration: 'parens-new-line',
// assignment: 'parens-new-line',
// return: 'parens-new-line',
// arrow: 'ignore',
// condition: 'ignore',
// logical: 'ignore',
// prop: 'ignore',
// },
// ],
'react/jsx-filename-extension': 0,
// 'react/jsx-indent': 0,
// 'react/jsx-boolean-value': 0,
// 'react/jsx-closing-tag-location': 0,
// 'react/jsx-closing-bracket-location': [
// 2,
// { selfClosing: 'props-aligned', nonEmpty: 'after-props' },
// ],
// 'react/button-has-type': 0,
// 'react/prop-types': 0,
// 'react/button-has-type': 0,
// 'react/jsx-tag-spacing': [2, { beforeSelfClosing: 'always' }],
// 'react/jsx-one-expression-per-line': 0,
// 'react/jsx-curly-spacing': 0,
// 'react/no-access-state-in-setstate': 0,
// 'react/destructuring-assignment': 0,
// 'react/jsx-no-bind': 0,
// 'react/require-default-props': 0,
// 'react/display-name': 0,
// 'react/jsx-first-prop-new-line': 0,
// 'react/jsx-props-no-spreading': 0,
// 'react/static-property-placement': 0,
// 'react/state-in-constructor': 0,
'@typescript-eslint/explicit-function-return-type': 0,
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none', ignoreRestSiblings: true }],
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
},
};
globals: {
Atomics: 'readonly',
SharedArrayBuffer: 'readonly',
},
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
jsx: true,
},
project: './tsconfig.json',
ecmaVersion: 2018,
sourceType: 'module',
},
settings: {
react: {
version: 'detect',
},
},
plugins: ['react', 'prettier', '@typescript-eslint', 'react-hooks'],
rules: {
'prettier/prettier': [
0,
{
semi: true,
singleQuote: true,
trailingComma: 'es5',
printWidth: 100,
tabWidth: 2,
arrowParens: 'avoid',
jsxSingleQuote: false,
jsxBracketSameLine: true,
},
],
'no-plusplus': 0,
'no-unused-vars': 'off',
'import/prefer-default-export': 0,
'import/no-unresolved': 0,
'react/jsx-filename-extension': 0,
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
'@typescript-eslint/no-unused-vars': ['warn', { args: 'none', ignoreRestSiblings: true }],
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/no-use-before-define': ["error", { "functions": false }]
},
};
\ No newline at end of file
......@@ -23,3 +23,6 @@ yarn-debug.log*
yarn-error.log*
.env
/src/api/test/*postman_environment*
!/src/api/test/*template*postman_environment*
\ No newline at end of file
# quickstart
Simple Web App to quickly connect to and try out OSDU APIs
## How to run
Execute the following commands:
install dependencies
```
npm ci
```
run an application
```
npm start
```
### How to change backend host and port
Create `.env` file and define the following variables:
```
SERVER_HOST=backend
SERVER_PORT=8080
```
Note: when using docker-compose to define and run both UI and backend, the value of SERVER_HOST must be the same as the name of service for your backend:
```
services:
backend:
...
ui:
...
depends_on:
- backend
```
## Implemented user-interface features
- Searching wells by a name part
- Viewing well's wellbores
- Drawing 3D trajectory of a wellbore
## User stories
### Searching wells by a name part
- Open the main page and take a look at the left top corner to locate pretty obvious search-bar interface
- Type a name of a well (it will be always treated as part of a name, no need for asterisk)
- Press "search", await results, gaze into a fancy spinner
- A list of up to 99 wells will be dispayed right under the search bar
- Or an error, if something goes wrong
### Viewing well's wellbores
- Search for a well
- Click on a name of a well or an "angle"-icon, placed before it, to run a fetch
- A list of wellbrores will be displayed under the well's row in a drop-down style
- Or an error, if something goes wrong
### Drawing 3D trajectory of a wellbore
- Search for a well
- Load its wellbores
- Press the VISUALIZE button, wait for a while
- Enjoy a 3D model of the wellbore trajectory
- If an error occures, button will be changed for an ERROR status and a description could be read in its tooltip
- It is possible to visualize multiple wellbores of a single well in the same 3D model
## Project composition and rationale
### create-react-app
the project is built on top of a create-react-app package as unified method of starting small react projects.
- designed for a purpose to create such small projects
- it is well-known and questions can be googled with ease
- supported by the react community
### typescript
we encourage all web developers to use a good practice - to write typed code
- typescript provides a comprehensive functionality for the subject
- widely used and supported
### css
- the easiest way to write styles
- project is small enough not to encounter harsh consequences
- perfect markup and styling are not the subject of the project
### redux
our application has sufficently complex inner state to use a state manager
- simple and descriptive idea
- fit for the project's small size
- in contrary to mobx redux is known more widely
### thunk
as the application performs an asyncronous communication with an API, interractively responding to user actions, we need to handle side effects of redux-actions
- simple and descriptive idea
- fit for the project's small size
- in contrary to redux-saga thunk is easier to comprehend
### react-router
to build a modern single page application route handler is required
- most popular and well-known router for react
### expressjs
small web server to deliver static files and perform api-requests proxying
- de-facto standart for such purposes at the moment
### jest
we encourage all web developers to use a good practice - to cover a code with test
- delivered with create-react-app
- comprehensive documentation
- easy to use
### enzyme
we use it to enhance react components testing
- HTML snapshots are more descriptive than a virtual DOM structure
- gives an ability to inspect component's children as thoroughly as we need
## external libraries
### three
- used for trajectory 3D model drawing
- well-known JS library for working with 3D
## Sequence diagrams, powered by Mermaid
[Mermaid Manual](https://mermaid-js.github.io/mermaid/#/sequenceDiagram)
### /api/find/wells_by_name
```mermaid
sequenceDiagram
UI->>SearchButton: click
SearchButton->>+Redux: find wells by name action
Redux->>+Api: find wells by well name
Api-x+Backend: request
Backend--x-Api: response
Api-->>-Redux: wells
Redux-->>-UI: list of wells
```
### /api/find/wellbores_by_well_id
```mermaid
sequenceDiagram
UI->>Well: click
Well->>+Redux: set find wellbore action
Redux->>+Api: find wellbores by well_id
Api-x+Backend: request
Backend--x-Api: response
Api-->>-Redux: wellbores
Redux-->>-UI: list of wellbores
```
### /api/fetch/trajectory_by_wellbore_id
```mermaid
sequenceDiagram
UI->>Wellbore Visualise: click
Wellbore Visualise->>+Redux: set visualize <br> trajectory action
Redux->>+Api: fetch trajectory by wellbore_id
Api-x+Backend: request
Backend--x-Api: response
Api-->>-Redux: trajectory data
Redux-->>-UI: trajectory
```
### /login
```mermaid
sequenceDiagram
UI->>LoginButton: click
LoginButton-x+Backend: redirect to /login
Backend--x-UI: redirect to / and set session cookie
```
### /logout
```mermaid
sequenceDiagram
UI->>LogoutButton: click
LogoutButton-x+Backend: redirect to /logout
Backend--x-UI: redirect to / and clear session cookie
```
require('dotenv').config();
module.exports = {
backendHost: process.env.BACKEND_HOST || 'localhost',
backendPort: process.env.BACKEND_PORT || '8080'
};
\ No newline at end of file
This diff is collapsed.
......@@ -3,11 +3,17 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"config": "^3.3.0",
"dotenv": "^6.2.0",
"express": "^4.17.1",
"papaparse": "^5.1.0",
"leaflet": "^1.6.0",
"react": "^16.11.0",
"react-dom": "^16.11.0",
"react-leaflet": "^2.6.1",
"react-redux": "^7.1.3",
"react-router-dom": "^5.1.2",
"recharts": "^2.0.0-beta.1",
"redux-thunk": "^2.3.0",
"three": "^0.110.0"
},
"scripts": {
......@@ -46,27 +52,51 @@
]
},
"devDependencies": {
"@commitlint/cli": "^8.2.0",
"@commitlint/config-conventional": "^8.2.0",
"@types/jest": "24.0.21",
"@types/node": "12.12.3",
"@types/papaparse": "^5.0.1",
"@types/react": "16.9.11",
"@types/react-dom": "16.9.3",
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@types/enzyme": "^3.10.4",
"@types/enzyme-adapter-react-16": "^1.0.5",
"@types/jest": "^24.0.21",
"@types/node": "^12.12.3",
"@types/react": "^16.9.11",
"@types/react-dom": "^16.9.3",
"@types/react-leaflet": "^2.5.0",
"@types/react-redux": "^7.1.7",
"@types/react-router-dom": "^5.1.3",
"@types/react-test-renderer": "^16.9.2",
"@types/recharts": "^1.8.5",
"@types/redux-mock-store": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^2.6.0",
"@typescript-eslint/parser": "^2.6.0",
"core-js": "^3.6.5",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"enzyme-to-json": "^3.4.4",
"eslint": "^6.6.0",
"eslint-config-prettier": "^6.5.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-flowtype": "^3.13.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-prettier": "^3.1.1",
"eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.16.0",
"eslint-plugin-react-hooks": "^2.2.0",
"eslint-plugin-react-hooks": "^1.7.0",
"fetch-mock": "^9.0.0-beta.2",
"http-proxy-middleware": "^0.20.0",
"husky": "^3.0.9",
"lint-staged": "^9.4.2",
"prettier": "^1.18.2",
"react-scripts": "3.2.0",
"typescript": "3.6.4"
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"node-fetch": "^2.6.0",
"prettier": "^1.19.1",
"react-scripts": "^3.3.0",
"react-test-renderer": "^16.12.0",
"redux-mock-store": "^1.5.4",
"typescript": "^3.7.5"
},
"jest": {
"transformIgnorePatterns": [
"node_modules/(?!three/)"
],
"snapshotSerializers": [
"enzyme-to-json/serializer"
]
}
}
}
\ No newline at end of file
const proxy = require('http-proxy-middleware');
module.exports = function (app, backendUrl) {
app.use(
proxy('/api', {
target: backendUrl,
pathRewrite: {
'^/api': '/', // rewrite path
},
})
);
app.use(
proxy('/login', {
target: backendUrl,
})
);
app.use(
proxy('/logout', {
target: backendUrl,
})
);
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
......@@ -21,9 +22,13 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<!-- This stylesheet is required for the leaflet package -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin="" />
<title>React App</title>
</head>
<body>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
......@@ -36,5 +41,6 @@
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
</body>
</html>
\ No newline at end of file
require('dotenv').config();
const express = require('express');
const path = require('path');
const proxy = require('http-proxy-middleware');
const proxyRouts = require('./proxy');
const app = express();
// Serve the static files from the React app
app.use(express.static(path.join(__dirname, 'build')));
const findProxyPort = process.env.FIND_SERVER_PORT || '8080';
const findProxyHost = process.env.FIND_SERVER_HOST || 'server';
app.use(