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 folder

  • Only 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'