0.0.1 • Published 4 years ago

shaman-online-meeting v0.0.1

Weekly downloads
5
License
-
Repository
-
Last release
4 years ago

#Install

  • Copy src/config.json.dist to src/config.json
  • Run npm install

#Production

  • Copy src/config.json.dist to src/config.json
  • Run npm run clean && npm run build

#Development

  • Configure IDE * If you use IDE by JetBrains, you can import settings for auto formatting code. File to import docs/IDEA_JS_airbnb.xml
  • To start development: Use npm start, it run webpack dev server in watch mode. Webpack in watch mode will recompile project whenever one of files changes. Wait until webpack compile project. Project been available at localhost:YOUR_PORT Default port for development server is 3000, if you want change it use npm start -- --port YOUR_PORT

#Npm scripts To run script use npm run SCRIPT_NAME.

Available scripts:

  • clean - remove all files from dist folder
  • start - run webpack dev server
  • test - run karma tests
  • build - build project for production
  • js-lint - run ESLint
  • js-lint-fix - run ESLint in fix mode
  • sort-styles - sort styles
  • style-lint - run Stylelint
  • all-lint - run all linters
  • all-test - run tests and all linters

#Redux

Actions

  • We use redux-actions for create actions, it create actions in accordance FSA
  • We use helpers for create AJAX and CRUD actions see actions/helpers file for details

Middlewares

List of used middlewares:

  • stringifyQueryParams - use for stringify queryParam q
  • tokens - add token from state (app.token) to API_CALL actions

##Services

  • url - service for generate full url`s
  • api - service for send AJAX requests
  • schemas - schemas description for normalize data via normalizr

##AJAX API

###Ajax api data flow AJAX flow

###How send AJAX request and process response

  • Create action with API_CALL key
#!javascript

import { API_READ, API_CALL } from 'services/api';
import { SCHEMA } from 'services/schemas'

const actionsTypes = {
	'SUCCESS':'MY_TEST_ACTION_SUCCESS', // with this action type will called if request ok
	'FAILURE':'MY_TEST_ACTION_FAILURE', // with this action type will called if request failure
};
//in general you should use action creators for that, but we consider clear action
const action = {
	type:'MY_TEST_ACTION_REQUEST'
	payload:{
	  [API_CALL]: { // you should use API_CALL imported from services/api
	    method: API_READ, // for more methods see services/api
	    endpoint: '/test_url',
	    actions: actionsTypes,
	    schema: SCHEMA, //data from success response will normalized in accordance this schema
	    // you can use queryParams, body and etc
	  },
	}
}
  • Call store.dispatch(action)
  • Action pass through reducers, if you want, you can create reducer which will change state in accordance action(for example isInProgress flag)
  • Action will processing sagas/api saga will create request to server via services/api services/api send request to server(if action has schema key, response data will be normalized) * if response ok - saga dispatch action MY_TEST_ACTION_SUCCESS, else MY_TEST_ACTION_FAILURE
  • If you want, you can create reducers for MY_TEST_ACTION_SUCCESS or MY_TEST_ACTION_FAILURE, response from server will be available in payload.response

Normalize data

We use Normalizr for normalize data from server. This will make it easier to follow Redux principle "Single source of truth" See normalizr docs for details

##Notify API TODO

#JS

  • We use Airbnb JavaScript Style Guide with some exceptions (see .eslintrc.json for details)
  • Check your code with ESlint, to run ESLint use npm run js-lint. ESLint can fix some problems, for do this run npm run js-lint-fix
  • We comment code with JSDoc. Use @typedef for comment reusable types, if your type - global, store it in docs/types

#CSS

  • Use kebab-case for selectors names
  • We use SCSS preprocessor
  • We use React CSS Modules to isolate components class names from each other.

    This means what all selectors in your CSS(SCSS) will transform with hash, for example: my-cool-selector -> my_cool-selector_jhsd_3. To work with that selectors use CSSModules decorator, and styleName attribute instead className Prefers class based selector instead tag name based selectors. Why? You may rewrite styles in child components, because tag name based selectors is not transformed.

  • We use Autoprefixer to automatic add vendor prefixes to CSS rules. Forget about display: -ms-flexbox write just display: flex and Autoprefixer will all work done for you
  • We use PostCSS Sorting to sort rules content with specified order. Run npm run sort-styles to sort styles before push commits to server
  • Check your styles with Stylelint, to run Stylelint use npm run style-lint.

#Tests

  • We use Karma as test runner, this allows testing app in different environments
  • We use Power-assert as assertion library, it makes errors output much more convenient
  • We use SinonJs for mocks, spyes, stubs and etc.
  • For start test use npm test, this run run Karma in watch mode, Karma executing the tests whenever one of files changes. Set NODE_ENV=CI if you want run tests in CI
  • All tests files: must have the ending .test.js. for example myFirstTest.test.js must be in directory __tests__ * __tests__ directory must be on the same level with the test file
  • To tests Redux middlewares use helpers middlewares/__tests__/helpers to dispatch your actions with fake store

Best practices )))

UI Components

Sometimes we need reusable UI components which:

  • Stores data in global store during lifetime
  • Clean up store when destroy
  • Can dispatch actions, specified for this UI component

For example consider create LoginForm component. It should be able:

  • Send data to API server
  • Show spinner until request finished
  • Show error message if auth failed

###Actions Actions for ui components store in actions/ui.

Create two actions in actions/ui/loginForm

  • UI_LOGIN_FORM_ACTIVATE - will fire when component mount to DOM
  • UI_LOGIN_FORM_DEACTIVATE - will fire when component unmount from DOM

Reducer

Reduces for ui components store in reducers/ui.

Create reducer in reducers/ui/loginForm, It will do:

  • Fill init state when UI_LOGIN_FORM_ACTIVATE
  • Clean state when UI_LOGIN_FORM_DEACTIVATE
  • Set isInProgress when LOGIN_START_REQUEST
  • Unset isInProgress when LOGIN_START_SUCCESS
  • Unset isInProgress and fill errorMessage when LOGIN_START_FAILED

###Containers Create container component in containers. Connect it to state with following options:

  • actionCreators: uiActivate uiDeactivate * startLogin(this action send ajax request to server)
  • slice from state ui.loginForm

###Result As result we will have component which incapsulate all the functionality in one place, and does not pollute global state