This is an internal documentation. There is a good chance you’re looking for something else. See Disclaimer.
Coding Styleguide¶
General¶
ESlint¶
Most code styles are enforced by ESLint. The gitlab build will fail if not every ESlint rule is fulfilled. Active ESlint rules can be seen here: https://gitlab.com/toccoag/tocco-client/blob/master/.eslintrc
To show current linting errors and warnings:
yarn lint
To try auto-fix them:
yarn lint:fix
Note
ESLint command will run as a git pre commit hook. It isn’t possible to commit anything as long as there are linting errors. Lint will also be executed automatically on our CI.
Setup Linting with IntelliJ
Install ESLint Plugin
Settings (Preferences on OS X) | Languages & Frameworks | JavaScript | Code Quality Tools –enable
Settings (Preferences on OS X) | Editor | Inspections | Code Style Issues | Unterminated statement – disable
Setup Linting with Visual Studio Code
Install ESLint Plugin
Prettier¶
Prettier is used as a code formatter tool.
To format the project with prettier:
yarn format
Setup Formatting with IntelliJ
Install Prettier Plugin
Settings (Preferences on OS X) | Languages & Frameworks | JavaScript | Prettier -> set package
Settings (Preferences on OS X) | Languages & Frameworks | JavaScript | Prettier -> enable for reformat code
Setup Formatting with Visual Studio Code
Install Prettier Plugin
Set Prettier as Default Formatter
Note
Prettier command will run as a git pre commit hook. It isn’t possible to commit anything as long as there are formatting errors. Prettier will also be executed automatically on our CI.
Folders and structure¶
Naming conventions for folders¶
What |
Case |
Example |
---|---|---|
Packages |
Kebab |
entity-browser |
Components |
Pascal |
SearchField |
Module |
Camel |
searchForm |
Any other |
Kebab |
test-data |
Tocco variable naming¶
To be consistent trough all apps following variable names should be chosen when dealing with the nice backend:
Name |
Alternative name |
Description |
---|---|---|
entityName |
name |
Technical entity name e.g. User or Education_schedule |
entityLabel |
label |
Localized entity label e.g. Person or Lehrplan |
entityModel |
model |
Object containing the whole model including the name, label and fields |
entityKey |
key |
Primary key of entity. Avoid “id” or “pk” as substitute |
entityId |
id |
Object containing entityName and entityKey eg. {entityName: ‘User, entityKey: “33”} |
formName |
Form name including the scope e.g. User_list |
|
formBase |
Only the form base without the scope e.g. UserSearch |
|
form |
Form object containing name and fields |
Javascript¶
React components¶
Use arrow functions
Use functional components whenever possible
Destruct props
Use
props
parameter for spreading props on child components but destruct needed values
// Good
const Comp({a, b}) => {}
// Good
const Comp(props) => {
const {a, b} = props
const foo = a + b
return <Child {...props} />
}
// Not so good
const Comp(props) => {
const foo = props.a + props.b
return <Child {...props} />
}
Use
()
for better JSX-alignment
// Good
return (
<Comp>
{children}
</Comp>
)
// Not so good
return <Comp>
{children}
</Comp>
Functions¶
Use arrow functions
// Good
const calculateAnything = () => {}
// Not so good
function calculateAnything () {}
Variables¶
Use variables for better reading/understanding
// Good
const hasFilterApplied = Boolean(filter) && filter.length > 2
return hasFilterApplied ? searchResults : []
// Not so good
return Boolean(filter) && filter.length > 2 ? searchResults : []
// Good
const entityBaseUrl = getBaseUrl(entity.id)
navigateTo(`${entityBaseUrl}/${relationName}`)
// Not so good
navigateTo(`${getBaseUrl(entity.id)}/${relationName}`)
Omit unnecessary variables
// Good
doSomething(history.location)
// Not so good
const location = history.location
doSomething(location)
Actions¶
Wrap arguments in payload attribute
Use arrow functions
Returning object literals (no return statement used)
// Good
export const setPending = (pending = false) => ({
type: SET_PENDING,
payload: {
pending
}
})
// Not so good
export function setPending(pending = false) {
return {
type: SET_PENDING,
pending: pending
}
}
Reducers¶
Use arrow functions
Use destructuring assignment
// Good
const updateOldPassword = (state, {payload}) => ({
...state,
oldPassword: payload.oldPassword
})
// Not so good
function updateOldPassword(state, args) {
return Object.assign({}, state, {
oldPassword: args.payload.oldPassword
})
}
Tests¶
Group tests hierarchically according to directory structure starting with the package-name
test description should always start with
should
// Good
describe('package-name', () => {
describe('components', () => {
describe('Image component', () => {
test('should render an image', () => {
//...
// Bad
describe('Image component', () => {
test('renders an image', () => {
//...
Use Chai to.be.true instead of equal(true)
// Good
expect(withTitle.find(LoginFormContainer).prop('showTitle')).to.be.true
// Not so good
expect(withTitle.find(LoginFormContainer).prop('showTitle')).to.equal(true)
Export / Import¶
Use
index.js
for exporting files from a folderOnly import files in app via
main.js
// Good
import {SearchBox} from 'tocco-ui'
import {chooseDocument} from 'tocco-docs-browser/src/main'
// Not so good
import SearchBox from 'tocco-ui/src/SearchBox'
import chooseDocument from 'tocco-docs-browser/src/modules/chooseDocument'