0.1.3 • Published 5 years ago

evercheck-utils v0.1.3

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

EverCheck Utils

Build Status

Overview

To have a centralized place to share, to document and to use common functions and constants build for condorlabs products.

Installation

npm install evercheck-utils

// or

yarn add evercheck-utils

usage

const evercheck-utils = require('evercheck-utils');

// ES6

import evercheck-utils from 'evercheck-utils';

The hole library can be imported as well as the individual functions, in case you want to import just and specific function, you can do it like the following (replace <FunctionName> with function name to import):

import <FunctionName> from 'evercheck-utils/lib/<FunctionName>';

//or

import { <FunctionName> }from 'evercheck-utils';

Available Functions

buildExportUrl

Returns a url that points to the related endpoint to export data

import buildExportURL from 'evercheck-utils/lib/buildExportURL'

...

const entity = 'testEntity';
const urlParams = { active: true };
const apiUrl = 'http://test.test.com';
const tokenName = 'testToken';

const result = buildExportURL(entity, urlParams, apiUrl, tokenName);
console.log(result);

// output
'http://test.test.com/testEntity/export?active=true'

capitalize

Returns the first letter in uppercase, lowers the rest and replaces underscores by space.

import capitalize from 'evercheck-utils/lib/capitalize'
...
console.log(capitalize('SAMPLE STRING'));

// output
'Sample string'

convertObjectToQueryString

Converts an object to a query string

import convertObjectToQueryString from 'evercheck-utils/lib/convertObjectToQueryString'

...

console.log(convertObjectToQueryString({ active: true, offset: 0, limit: 10 }));

// output
'?active=true&offset=0&limit=10'

This is useful when to change location in the browser based on a filters object.

In case you do not want the question character to be retrieved, add a second parameter with false value, for instance:

...
const withQuestionCharacter = false;
convertObjectToQueryString({ active: true, offset: 0, limit: 10 }, withQuestionCharacter )

// output
'active=true&offset=0&limit=10'

convertQueryStringToAnObject

Converts a query string to an object

const params = convertQueryStringToAnObject('?active=true&offset=0&limit=10');
console.log(params);

//output
{ active: true, offset: 0, limit: 10 }

This is useful to manage browser url query string

countFilters

Returns the of number properties inside an Object, this is commonly used to display amount of filters applied to a given list on a table.

console.log( countFilters({ active: true,  status: 'done' }) );

// output
 -> 2

createEntityTypes

Creates actionTypes according to the name supplied in entityName property, is commonly used to generate ActionsTypes in order to work with redux and new architecture base on hooks.

const entityName = 'employees';
const fetchingTypes = createEntityTypes({ entityName });
console.log(fetchingTypes)[
  // output
  (FETCHING_EMPLOYEES,
  FETCH_EMPLOYEES_SUCCESS,
  FETCH_EMPLOYEES_ERROR,
  CLEAR_EMPLOYEES_PAGINATION)
];

The actionTypes can also be return as an object, to do so send asObject: true along with entityName, for instance:

const entityName = 'employees';
console.log(createEntityTypes({ entityName, asObject: true }));

// output
{
  fetchingType: 'FETCHING_EMPLOYEES',
  successType: 'FETCH_EMPLOYEES_SUCCESS',
  errorType: 'FETCH_EMPLOYEES_ERROR',
  clearType: 'CLEAR_EMPLOYEES_PAGINATION'
}

downloadExportFile

Makes a request to downloads files on the specified url, this function brings support for older versions of IE 9+

const entity = 'courses';
const queryParams = { active: true };
const urlBase = 'http://test.test.com';

const jwtToken =
  'eyAJJHAS7ASBjf8ASF.ASjsfa78asfkjkjasfksafASKjkAS78aSjk.SJskasDjk89';

await downloadExportFile(entity, queryParams, urlBase, jwtToken);

Considerations

  • In case urlBase is not specified the request will be made to localhost.

  • The endpoint that returns the file must provide content-disposition and content-type headers in the response otherwise file corrupt or will be downloaded with a name like Export_20/03/2019.

evercheckDate

This is a wrapper for moment and contains the same functionalities as last version, use it to not import moment on your projects and low down the bundle size of the website.

fetchReducerFactory

Returns a reducing function to manage global state data base on request status, this is useful when working with redux and the new hooks architecture, the reducing function will have the following definition

return (state = initialState, action) => {
  const payload = action.payload ? action.payload : omit(action, 'type');
  switch (action.type) {
    case FETCHING:
      return onFetching ? onFetching(payload) : payload;
    case SUCCESS:
      return onSuccess ? onSuccess(payload) : payload;
    case ERROR:
      return onError ? onError(payload) : payload;
    default:
      return state;
  }
};

NOTE

  • ActionsTypes in each case where generated with createEntityTypes function.
  • onFetching, onSuccess, onError functions will be executed if the where passed on call to fetchReducerFactory.

formatAsCurrency

Formats a number the with currency specified, the Dollar with 2 decimals are the currency by default

Example:

console.log(formatAsCurrency(10));

// output
('$10.00');

formatDate

Formats date using a given format

const date = '2019-02-20':
const outputFormat = 'MMM DD YY':
const inputFormat = 'YYYY-MM-DD';

console.log(formatDate(date, outputFormat, inputFormat));

// output
'Feb 20 19'

getCurrentPage

Calculates the page number of a request based on the offset and limit parameters, this is useful when working with pagination in a table to indicate the page where the user is at

Example

const offset = 0;
const limit = 50;

console.log(getCurrentPage(offset, limit));

// output
('1');

getItemsByPage

Returns the entities inside a normalized object that matches the ids in given page, see the following structure

{
  employees: {
    entities: {
      123: {
        id: 123
      }
    },
    pagination: {
       pages: { 1: [123] },
       size: 1
    }
  }
}

This is useful when working with tables and pagination reducer

Example:

const state =  {
  employees: {
    entities: {
      123: {
        id: 123
      }
    },
    pagination: {
      pages: { 1: [123] },
      size: 1
    }
  }
};

const entityName = 'employees';
const page = 1;

const entities = getItemsByPage(state, entityName, page)
console.log(entities);

// output
{ 123: { id: 123 } }

hasRequestFail

Returns a boolean that indicates if a request has failed. This helper function is useful to determinate whether one or more request has failed. A request is considered as failed when status have been updated to `failed' in the global state

Example, given global state:

{
  employees: {
    requestStatus: 'notFetched'
  },
  courses: {
    requestStatus: 'failed'
  }
}

Usage

const employeesFetchStatus = state.employees.requestStatus;
console.log(hasRequestFailed(employeesFetchStatus));

const coursesFetchStatus = state.courses.requestStatus;
console.log(hasRequestFailed(coursesFetchStatus));

console.log(hasRequestFailed([employeesFetchStatus, coursesFetchStatus]));

// output 1
('false');

// output 2
('true');

// output 3
('true');

NOTE

  • When call with an array of string if one of the strings says failed it will return true

isFetching

Returns a boolean that indicates whether a request is loading. This helper function is useful to determine whether a Spinner should be shown. For the sake of simplicity, both the FETCHING and the NOT_FETCHED statuses mean a request is loading. see REQUEST_STATUSES

Example, given global state:

{
  employees: {
    requestStatus: 'fetching'
  },
  courses: {
    requestStatus: 'successful'
  }
}

Usage

const employeesFetchStatus = state.employees.requestStatus;
console.log(isFetching(employeesFetchStatus));

const coursesFetchStatus = state.courses.requestStatus;
console.log(isFetching(coursesFetchStatus));

// output 1
('true');

// output 2
('false');

replaceEspecialCharacter

Wraps native string replace function and defaults character to replace with empty string space and regExp to /_/g, this values can be change on params

Example:

const text = 'test_with_underscores';
console.log(replaceEspecialCharacter(text));

// output
('test with underscores');

startCase

Returns all words in a text capitalized

Example:

const testString = 'THIS is A test';
console.log(startCase(testString));

// output
('This Is A Test');

getStatusByPage

Function to get request status of given normalized property with pagination reducer in global state.

Example given global state:

const state =  {
  employees: {
    entities: {
      123: {
        id: 123
      }
    },
    pagination: {
      pages: { 1: [123] },
      requestStatus: { 1: 'successful' }
      size: 1
    }
  }
};

Usage

const entityName = 'employees';
const page = 1;
const requestStatus = getStatusByPage(state, entityName, page);

console.log(requestStatus);

// output
('successful');

getSize

Function to get size of given entity list in global state

Example given global state:

const state =  {
  employees: {
    entities: {
      123: {
        id: 123
      }
    },
    pagination: {
      pages: { 1: [123] },
      requestStatus: { 1: 'successful' }
      size: 1
    }
  }
};

Usage

const entityName = 'employees';
const page = 1;
const size = getSize(state, entityName, page);

console.log(size);

// output
1;

handleUrlChange

Watches for changes in browser url in order to update given property inside global state with data received from url specified

parameters

  • dispatch: function to dispatch actions to reducers, see dispatch docs
  • props: object with configuration to make request and store response on state

    • state: global application state
    • url: endpoint who provides the results
    • entityName: property inside of state to be handled
    • search: current query string url
    • nextSearch: changed query string url

NOTE

In order to work properly the endpoint given must response with JSON like:

{ items: [], size: 0 }

Example, given:

  • Response from server:

    {
      items: [ {id: 1 , name: 'Jon' }, {id: 2 , name: 'Arya' }, {id: 2 , name: 'Sansa' }, ],
      size: 3
    }
  • Global State:

    {
      employees: {
        entities: { },
        pagination: {
          pages: {},
          requestStatus: {},
          size: 0
        }
      }
    }

Usage:

const entityName = 'employees':
const url = 'https://yourapi.com/employees';
const search = '';
const nextSearch = '?offset=0&limit=50&active=true'

await handleUrlChange(dispatch, {
  GlobalState,
  url,
  entityName,
  search,
  nextSearch
});

The Global State will end up like the following

  • Updated Global State:

    {
      employees: {
        entities: {
          1: { id: 1, name: 'Jon'},
          2: { id: 2, name: 'Arya'},
          3: { id: 3, name: 'Sansa'}
        },
        pagination: {
          pages: { 1: [1, 2, 3]},
          requestStatus: { 1: 'success'},
          size: 3
        }
      }
    }

Features (Must Read)

  • When navigating between pages without any changes to other filters, if a pages has already being request and was fetched successfully, no request will be made to de endpoint, instead the results will be taken from the global state.

  • Any difference between search and nextSearch params will cause a request to the endpoint, and the entity inside global state will have its initial value until the response is received from the endpoint.

  • All actions dispatch for this function expect for ClearType, will have a property payload where the data from server will be stored. see createEntityTypes.

  • In case an error is received from endpoint, the error will be store in the entity as error

paginationReducerFactory

Creates a combined reducers to handle pagination based on Action Types,

Example:

  const entityName = 'employees';
  const fetchingTypes = createEntityTypes({ entityName });

  const paginationReducer = paginationReducerFactory(
    createEntityTypes({ entityName, asObject: true })
  );

  // function generated receive global state and an Action ( an action is an Object) with a property `type` equal to one of the types in `fetchingTypes` declared above

  const action = { type: fetchingType.onSuccess, size: 0, page: 1, result: [1, 2, 3] }

  console.log(paginationReducer(state, action));

  //output
  pagination: {
    pages: { 1: [1, 2, 3]},
    requestStatus: { 1: 'success'},
    size: 3
  }

Associated Functions

combineReducers

Makes reducing function to listen to the same action types in order to return an object with the result of each reducer

See Compbine reudecer docs

repeat

This can be used to execute a function multiple times, it is useful when trying to repeat dom elements in react

Example:

const times = 5;
const repeatedFunctions = index => ({ id: index });
const result = repeat(times, repeatedFunctions);

console.log(result);

//output
[{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }];

debounce

executes a the target function after debounce function has stopped from being called and the specified delay has passed, it is pretty useful avoid performance issues when calling API function on change event of inputs or component rendering.

Example:

const targetFunction = name=>{ console.log (`Hey! ${name}`) }


for (const param  of ['m', 'mi', 'mik', 'mike', 'mike!']) {
  debounce(targetFunction, param,  600);
}

//output - after for clause finishes and 600 milliseconds 
 'Hey! mike!'

Constants

There are also common constants used many times in the project, below most used are listed

REQUEST_STATUSES

{
  NOT_FETCHED: 'notFetched',
  FETCHING: 'fetching',
  SUCCESSFUL: 'successful',
  FAILED: 'failed'
}

DEFAULT_QUERY_PARAMS

{
  offset: OFFSET,
  limit: LIMIT,
  order: ORDER,
  active: true,
  sort: 'name'
};

LICENSE_COLOR

{
  TAKE_ACTION: 'danger',
  WARNING: 'warning',
  CLEAR: 'success'
};

INVOICE_STATUS

{
  ALL: { color: '#ABBDBD', text: 'All' },
  UNPAID: { color: '#ABBDBD', text: 'unpaid' },
  PAID: { color: '#5BD672', text: 'paid in full' },
  PARTIAL_PAYMENT: { color: '#42A5F5', text: 'partial payment' },
  OVERDUE: { color: '#ABBDBD', text: 'Overdue' },
  OVERDUE30: { color: '#FFAA00', text: 'Overdue 30+' },
  OVERDUE60: { color: '#FFAA00', text: 'Overdue 60+' },
  OVERDUE90: { color: '#FF4E4A', text: 'Overdue 90+' },
  PROCESSED_ERROR: { color: '#B07ED8', text: 'Processing error' }
};

Authors

See also the list of contributors who participated in this project.

0.1.3

5 years ago

0.1.25

5 years ago

0.1.24

5 years ago

0.1.23

5 years ago

0.1.21

5 years ago

0.1.2

5 years ago

0.1.1

5 years ago

0.1.0

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago