evercheck-utils
v0.1.3
Published
contains all sort of util functions used on evercheck products
Downloads
551
Readme
EverCheck Utils
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
- EverCheck Utils
- Overview
- Installation
- usage
- Available Functions
buildExportUrl
capitalize
convertObjectToQueryString
convertQueryStringToAnObject
countFilters
createEntityTypes
downloadExportFile
evercheckDate
fetchReducerFactory
formatAsCurrency
formatDate
getCurrentPage
getItemsByPage
hasRequestFail
isFetching
replaceEspecialCharacter
startCase
getStatusByPage
getSize
handleUrlChange
paginationReducerFactory
combineReducers
repeat
debounce
- Constants
- Authors
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
andcontent-type
headers in the response otherwise file corrupt or will be downloaded with a name likeExport_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.
- See moment.js docs
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 propertypayload
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
- Miguel Blanco - Initial work - Mikews93
See also the list of contributors who participated in this project.