Skip to content

Commit

Permalink
Finished frontend boilerplate and added coding guidelines
Browse files Browse the repository at this point in the history
  • Loading branch information
GabriFila committed Apr 27, 2021
1 parent df41684 commit 910b744
Show file tree
Hide file tree
Showing 25 changed files with 320 additions and 37 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,29 @@ jobs:

- name: Run shellcheck
uses: azohra/shell-linter@v0.4.0


frontend-lint:
name: Lint frontend files
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.sha }}
repository: ${{github.event.pull_request.head.repo.full_name}}
persist-credentials: false

- name: Setup nodeJS
uses: actions/setup-node@v1
with:
node-version: 14

- name: Install the packages necessary for lint checking
working-directory: ./frontend
run: yarn install

- name: Check linting
working-directory: ./frontend
run: yarn check-format-lint
1 change: 0 additions & 1 deletion frontend/.eslintignore

This file was deleted.

3 changes: 2 additions & 1 deletion frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ yarn-debug.log*
yarn-error.log*

storybook-static
yarn.lock
yarn.lock
.env
1 change: 1 addition & 0 deletions frontend/.husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
5 changes: 5 additions & 0 deletions frontend/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
# shellcheck disable=SC1090
. "$(dirname "$0")/_/husky.sh"

yarn --cwd=frontend pre-commit
43 changes: 41 additions & 2 deletions frontend/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,47 @@
const path = require('path');

module.exports = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/preset-create-react-app'
]
{
// allows to theme antd in the storybook
name: '@storybook/preset-ant-design',
options: {
lessOptions: {
modifyVars: {
'@primary-color': '#1c7afd',
'@secondary-color': '#FF7C11',
},
},
},
},
{
// allows to use less in the storybook in create-react-app (required for antd theming)
name: '@storybook/preset-create-react-app',
options: {
craOverrides: {
fileLoaderExcludes: ['less'],
},
},
},
],
// allows to use tailwind utilities in the storybook
webpackFinal: async config => {
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: [require('tailwindcss'), require('autoprefixer')],
},
},
],
include: path.resolve(__dirname, '../'),
});
return config;
},
};
9 changes: 6 additions & 3 deletions frontend/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// include tailwind classes in the storybook
import '../src/includeTailwind.css';

export const parameters = {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/
}
}
date: /Date$/,
},
},
};
81 changes: 81 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# CrownLabs frontend

This file describes the structure and general coding guidelines of the CrownLabs frontend.

## Setup

Before starting set the necessary environment variables either using a `.env` file (preferred on windows) or by defining them on your local machine. To setup the repo, use the following commands ([yarn](https://yarnpkg.com/cli/install) use is mandatory).

```bash
# If you don't have yarn installed
npm install -g yarn

# install necessary packages
yarn install

# To run the app locally
yarn start

# To run the storybook locally
yarn storybook

# To build the app locally
yarn build-app

# To build the storybook locally
yarn build-storybook
```

After the setup is complete, if you start the app locally and see the apiserver url on the home page everything is working fine.

## Structure

Our frontend is a [React](https://it.reactjs.org/) application. We use [antd](https://ant.design/) as the main component library and [Tailwind](https://tailwindcss.com/) utilities to handle specific css scenarios (padding and margin). We also use [Storybook](https://storybook.js.org/) to ease teamwork. We chose to use [Typescript](https://www.typescriptlang.org/) to have a bettere development experience.

The application is made to be deployed using docker and can be hosted on a custom subroute. The application takes some environment variables, each needs to have the `REACT_APP_CROWNLABS` prefix. In order to define environment variables at container run-time they need to be defined on the `window` object in the `public/config.js` file.

## CI checks

We use ESLint to enforce linting and code quality. We use Prettier to have a uniform code style. These checks are enforced by a GitHub Action run on PRs. Also locally a pre-commit hook written with [husky](https://typicode.github.io/husky/#/) uses [lint-staged](https://github.com/okonet/lint-staged) to format and check files in the staging area before each commit.

## Guidelines

We define some coding guidelines to ease the collaboration in our team and to ease the review process.

### Dir structure

The components are in `src/components`. The folder has subdirs, one for each page of the app, plus `misc` for the miscellaneous UI elements (those common between all components) and a `util` dir for custom UI elements used multiple times across the code (custom dialogs, inputs, etc...).

Each component needs to have its own folder with the following structure, e.g. for an `Example` component:

- `Example.tsx` - component definition
- `Example.stories.ts` - storybook stories to show component usage
- `Exmaple.css` - css specific code for component
- `index.ts` - utility file to shorten component import statement in other files

### File structure

Refer to the [Example component](./src/components/Example/) for a demo

#### Component

Each component file needs to host a single component and needs to have the following structure:

- import declarations (when you can use non-default imports use them to reduce bundle size)
- general constant declarations for the components (if needed)
- component props interface with the name `${ComponentName}Props` (if needed)
- functional component declaration

#### Storybook

Each storybook file needs to have the following structure:

- import declarations
- default export containing necessary story info (title, component, argTypes,...)
- default component args declaration (use `someKeysOf` type function)
- template declaration
- component stories

## Useful links

- [Useful answer for deploying react app on subroute](https://stackoverflow.com/a/58508562/11143279)
25 changes: 25 additions & 0 deletions frontend/craco.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const CracoLessPlugin = require('craco-less');

module.exports = {
style: {
postcss: {
plugins: [require('tailwindcss'), require('autoprefixer')],
},
},
plugins: [
{
plugin: CracoLessPlugin,
options: {
lessLoaderOptions: {
lessOptions: {
modifyVars: {
'@primary-color': '#1c7afd',
'@secondary-color': '#FF7C11',
},
javascriptEnabled: true,
},
},
},
},
],
};
61 changes: 52 additions & 9 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@craco/craco": "^6.1.1",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
Expand All @@ -12,6 +13,7 @@
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.7",
"antd": "^4.15.2",
"craco-less": "^1.17.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
Expand All @@ -20,17 +22,20 @@
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "react-scripts start",
"build-app": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"start": "craco start",
"build-app": "craco build",
"test": "craco test",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public -o build"
"build-storybook": "build-storybook -s public -o build",
"prepare": "cd .. && husky install frontend/.husky",
"check-format-lint": "prettier --check **/*.{ts,tsx,js,jsx,json,css} && eslint . --ext .ts --ext .tsx --ext .js --ext .jsx --max-warnings=0",
"pre-commit": "lint-staged"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
"react-app/jest",
"plugin:prettier/recommended"
],
"overrides": [
{
Expand All @@ -41,7 +46,28 @@
"import/no-anonymous-default-export": "off"
}
}
]
],
"rules": {
"react/no-multi-comp": "error",
"react/jsx-pascal-case": "error",
"react/prop-types": "off",
"no-nested-ternary": "off",
"no-console": [
"warn",
{
"allow": [
"error"
]
}
],
"react/jsx-indent": "off",
"react/jsx-wrap-multilines": [
"error",
{
"declaration": false
}
]
}
},
"browserslist": {
"production": [
Expand All @@ -60,20 +86,37 @@
"@storybook/addon-essentials": "^6.2.8",
"@storybook/addon-links": "^6.2.8",
"@storybook/node-logger": "^6.2.8",
"@storybook/preset-ant-design": "^0.0.2",
"@storybook/preset-create-react-app": "^3.1.7",
"@storybook/react": "^6.2.8"
"@storybook/react": "^6.2.8",
"@tailwindcss/postcss7-compat": "^2.1.2",
"autoprefixer": "^9",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"husky": "^6.0.0",
"lint-staged": "^10.5.4",
"postcss": "^7",
"prettier": "^2.2.1",
"tailwindcss": "npm:@tailwindcss/postcss7-compat"
},
"resolutions": {
"babel-loader": "8.1.0"
},
"homepage": "/",
"prettier": {
"printWidth": 80,
"trailingComma": "none",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"lint-staged": {
"*.{ts,tsx,js,jsx,json,css}": [
"prettier --write"
],
"*.{ts,tsx,js,jsx}": [
"eslint --max-warnings=0 --ignore-pattern=!.storybook"
]
}
}
22 changes: 14 additions & 8 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import './App.css';
import { REACT_APP_CROWNLABS_APISERVER_URL, PUBLIC_URL } from './env';
import { PUBLIC_URL, REACT_APP_CROWNLABS_APISERVER_URL } from './env';
import { BrowserRouter, Link, Route, Switch } from 'react-router-dom';

function App() {
Expand All @@ -13,24 +13,30 @@ function App() {
height: '100%',
fontSize: '2.7rem',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center'
textAlign: 'center',
}}
>
<BrowserRouter basename={PUBLIC_URL}>
<Switch>
<Route path="/active">
ACTIVE
<Link to="/account">to account</Link>
<div>Active</div>
<Link to="/">Go Home</Link>
</Route>
<Route path="/account">
ACCOUNT
<Link to="/active">to active</Link>
<div>Account</div>
<Link to="/">Go Home</Link>
</Route>
<Route path="/" exact>
CrownLabs will get a new look! <br /> Apiserver at{' '}
{REACT_APP_CROWNLABS_APISERVER_URL}
<div className="p-10 m-10">
CrownLabs will get a new look!
<br /> Apiserver at {REACT_APP_CROWNLABS_APISERVER_URL}{' '}
</div>

<Link to="/active">Go to active</Link>
<Link to="/account">Go to account</Link>
</Route>
</Switch>
</BrowserRouter>
Expand Down
15 changes: 15 additions & 0 deletions frontend/src/components/Example/Example.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.rainbow-text {
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
background-image: linear-gradient(
to left,
violet,
indigo,
blue,
green,
yellow,
orange,
red
);
}
Loading

0 comments on commit 910b744

Please sign in to comment.