2.3.0-rc.6 • Published 5 years ago

ezbob v2.3.0-rc.6

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

Installation

Create an npm user and contact Ezbob support and ask for privileges. On your root app, run in command line:

npm login //Enter your credentials
npm install
npm start

//In another terminal - open a node.js server to retrieve the app token
cd server
npm start

Then your app should run on localhost:3000.

This project was bootstrapped with Create React App.

Available Scripts

In the project directory, you can run:

npm start

Runs the app in the development mode. Open http://localhost:3000 to view it in the browser.

The page will reload if you make edits. You will also see any lint errors in the console.

npm test

Launches the test runner in the interactive watch mode. See the section about running tests for more information.

npm run storybook

Runs the Storybook development environment. Presents an isolated view of the widgets library

npm run build

Builds the app for production in the build folder. Bundles React in production mode and optimizes the build for the best performance.

The build is minified and the filenames include hashes. Your app is ready to be deployed!

See the section about deployment for more information.

Configuration

App

Path: src/App.js

This is the staring point of the App. here you'll find the structure of the program. This is a regular React JSX file. Inside the render function you should wrap everything with UIFramework component.

The UIFramework will get a config object (defined below) and render its children. The structure should be:

<Flow>
    <Header>
        <ProgressBar>
            <ProgressBarStep id={1} label={'label'} title="title"><div>Your icon here</div></ProgressBarStep>
            <ProgressBarStep id={2} label={'label'} title="title"><div>Your icon here</div></ProgressBarStep>
            <ProgressBarStep id={3} label={'label'} title="title"><div>Your icon here</div></ProgressBarStep>
            <ProgressBarStep id={4} label={'label'} title="title"><div>Your icon here</div></ProgressBarStep>
        </ProgressBar>
    </Header>
    <Body>
        <Modal modalName='ModalName1'>
            <ModalClass1/>
        </Modal>
         <Modal modalName='ModalName2'>
            <ModalClass2/>
        </Modal>
        <Page routePath="routePath">
            <Step stepName="stepName1">
                <Widget1 name="widget1"/>
                <Widget2 name="widget2"/>
                <Widget3 name="widget3"/>
            </Step>
        </Page>
    </Body>
    <Footer name="footer"/>
</Flow>

widget's name

Most widgets have a "name" prop. This "name" prop is used to bind widgets with respective entries in config and translations.

For example:

<Input name="applicant.email"/>

When using this widget, "applicant.email" is the path in config.js's "widgetsConfig" property. It's also the path in the translations file:

config.js (src/config/config.js):

widgetsConfig: {
    applicant: {
        email: {
            validationRules: 'required|min:3|email',
            customErrorMessage: {
                email: 'VALID_EMAIL',
                required: 'REQUIRED',
                min: 'MIN'
            }
        }
    }
}

translations file (src/config/languages/en-US.json):

"applicant": {
    "email": {
        "label": "Email address",
        "tooltip": {
            "content": "We will use your email address to get in touch with you regarding your application or with important information about your Esme account.\nYour email address will also be your username when logging in to your account in future."
        }
    }
}        

Translations

Path: src/config/languages/**-**.json Language object is mapped to widgets structure. example:

 "applicant": {
   "fullName": {
       "firstName": {
           "label": "First Name"
       },
       "lastName": {
           "label": "Surname"
       },
       "middleName": {
           "label": "Middle name(s)"
       }
   }
}

The translations also handle messages not bound to a specific widget:
In config.js:

customErrorMessage: {
    required: 'REQUIRED_ADDRESS',
    address: 'ADDRESS'
}

And in translations file:

"clientMessages": {
  "REQUIRED_ADDRESS": "Address is required",
  "ADDRESS": "Address is not valid"
}

#####Accessing config variables: The config file is passed onto the translation function and is available for interpolation:

config.js:

system: {
    vendorName: "Esme"
},
product: {
    loanType: 'business loan'
}

And in translations file:

"translationName": "It's quick to apply for an {{system.vendorName}} {{product.loanType}}. We only need a few details to make a decision.",

#####Advanced usage: referencing config property with formatting options: A widget has the following config:

widgetsConfig:{
    applicant:{
      widgetExample:{
           validationRules: 'required|numeric|min:15000|max:2000000',
           customErrorMessage: {
               required: 'REQUIRED',
               numeric: 'NUMERIC',
               min: 'MIN_AMOUNT',
               max: 'MAX_AMOUNT'
           }  
         }   
    }  
}

To access the validationRules property, use standard formatting:

"translationName": "These are the validation rules: {{widgetsConfig.applicant.widgetExample.validationRules}}",

But to receive a certain value (max) returned from this string, a specific indication must be made:

"translationName": "This is the max amount: {{widgetsConfig.applicant.widgetExample.validationRules, validationRule:max}}",

This would trigger a format() function which takes the value ('validationRules') and formats it according the validationRule key, finding the 'max' value.

Currently we support dedicated formatting only for 'validationRule'

Config.js

Path: src/config/config.js Represents widgets validation rules, input formatting options, default values and general configuration.

Example:

widgetsConfig:{
   loanee: {
       annualDrawings: {
           validationRules: 'required|numeric|max:999999999',
           customErrorMessage: {
               required: 'REQUIRED',
               numeric: 'NUMERIC',
               max: 'MAX_AMOUNT',
           },
           formattingOptions: {
               numeral: true,
               numeralThousandsGroupStyle: 'thousand',
               numeralPositiveOnly: true,
               prefix: locals.currencySign,
               noImmediatePrefix: true,
               numericOnly: true,
               rawValueTrimPrefix: true,
               trailingDecimalOnBlur: true
           },
           inputProps:{
               autoComplete: 'off',
               autoFocus: true
           }
       }
   } 
}

This section outlines the configuration for a widget with the name property of "loanee.annualDrawings".
The 'validationRules' and 'customErrorMessage' properties represent configuration options for validatorjs.
The 'formattingOptions' property represent input options for Cleave.js
The 'inputProps' property represent <input> HTML tag options

formattingOptions and inputProps objects can be overridden by a widget's props:

widgetsConfig:{
    applicant:{
        email:{
            inputProps:{autoComplete:'off'}
        }
    }
}
<Input name="applicant.email" inputProps={{autoComplete:'on'}}/>

In this case, the widget will pass on autoComplete:'on' onto its HTML tag.

loanee: {
    typeOfBusiness: {
        validationRules: 'required',
        customErrorMessage: {
            required: 'REQUIRED',
            alpha: 'ALPHA_BUSINESS_TYPE'
        },
        values: [
            {"value":"LIMITED_COMPANY"},
            {"value":"SOLE_TRADER"}
        ]
    }    
}

Configuration for a Checkbox widget would look like this:

meta: {
    consents: {
        privacyNote: {
            defaultValue: false,
            validationRules: 'accepted',
            customErrorMessage: {
                accepted: 'REQUIRED'
            }
        }
    }
}

Where defaultValue represent the initial value a widget receives when no other value has been set.

Other than validation, input options and drop down values, the config file may contain other configurable properties; Example:

loanee: {
    loanRequest:{
        amount: {
            "LIMITED_COMPANY": {
                defaultValue: 80000,
                min: 10000,
                max: 150000,
                step: 500
            },
            "SOLE_TRADER": {
                defaultValue: 87500,
                min: 25000,
                max: 150000,
                step: 500
            }
        }
    }
}

This is widget-specific data, used only by the Slider widget.

Another example for widget-specific data:

bankAccountStatement: {
    linkAccountDetails: {
        displayIcons: [
            'HSBC', 'sage 50', 'Barclays', 'Lloyds', 'RBS', 'Santander', 'NatWest', 'Dag', 'Halifax', 'NationWide'
        ]
    }
}

Another example is the configuration for the App's Steps:

steps: [
    {stepName: 'registerAccount', label: 'Register', title: 'Register account'},
    {stepName: 'personalInformation', label: 'Personal', title: 'Personal information'},
    {stepName: 'businessInformation', label: 'Business', title: 'Business information'},
    {stepName: 'linkAccounts', label: 'Accounts', title: 'Link accounts'},
]

####Route configuration: Each page has a key defined in this structure that bind to Page component in App.js.

url: the url of the page

title: title of the page

excludeModules: Array of modules to exclude from the view. the list is any widget with "name" props.

customerWizard is the main route and contain logoutURL.

pageRoutes: {
        customerWizard: {
            url: '/customer/wizard'
        },
        customerLogin: {
            url: '/customer/login',
            excludeModules: ['ProgressBar'],
            title: 'pageRoutes.customerLogin'
        },
        forgotPassword: {
            url: '/account/forgot-password',
            excludeModules: ['ProgressBar'],
            title: 'pageRoutes.forgotPassword'
        },
        accountSetPassword: {
            url: '/account/set-password',
            excludeModules: ['ProgressBar'],
            title: 'pageRoutes.accountSetPassword'
        },
        accountVerifyEmail: {
            url: '/account/verify-email',
            excludeModules: ['ProgressBar'],
            title: 'pageRoutes.accountVerifyEmail'
        }
    }

To manage google tag manager please use 'googleTagManager' config.

gtmId - is the GTM-ID from google

allowedTracking - define the events to track

VirtualPageview - fires on every Step/Page move

InputTracking - fires on input/dropdown onFocus/onBlur/checkboxClick events

ButtonTracking - fires on buttons and tooltips

googleTagManager: {
        gtmId: 'GTM-WS8FGWH',
        allowedTracking: {
            VirtualPageview: ['Step', 'Page'],
            InputTracking: ['onFocus', 'onBlur', 'checkboxClick'],
            ButtonTracking: ['onClick', 'tooltipClick']
        }
    }

Lists

Path: src/config/lists/**-**.json

Lists are json files bound to Dropdown widgets by their name. These lists are arrays of object in the following shape:

   [
      {"value":"LIMITED_COMPANY"},
      {"value":"SOLE_TRADER"}
   ]

The translated values

Common Actions

Actions are passed via MainContext and communicate with the framework's state.

CaseActions:

updateInCase

update entry in case with option to validate @param {string |{name, value, validate}} names - widget's name, or an array of {name, value, property} @param {*} value - widget's value @param {boolean} validate - whether or not should call validate on updated property

example:

const newVal = 'some new value';
actions.case.updateInCase('widget.name', newVal);

resetInCase

reset widget case entry, validation will still be applied in nextStep() @param {string|string[]} names - widget's name, or an array of names

example:

resetWidget = () => {
    actions.case.resetInCase('widget.name');   
}

getCaseValue

get value from case by name @param {string} name - widget's name @param {boolean=false} checkStep - if true, return value only if property shares the same step value as getCurrentStep() @returns {* | undefined} found value or undefined example:

const val = actions.case.getCaseValue('widget.name');

CaseValidationActions

getValidationStatus

get validatingStatus ('valid'|'invalid'|'neutral') from case by name @param {string} name - widget's name @returns {string} 'valid' | 'invalid' | 'neutral'

example:

const validationStatus = actions.caseValidation.getValidationStatus('widget.name');

getValidationStatus

get widgetsConfig's validationRules by name, and check if 'required' or 'accepted' is one of them @param {string} name - widget's name @returns {boolean}

example:

const isFieldRequired = actions.caseValidation.isRequired('widget.name');

SettingsActions

getUserConfigProp

get state's config by prop @param {string} prop - path by which to find prop in config @returns {Object} found value in config

example:

const listFromConfig = actions.settings.getUserConfigProp(`widgetsConfig.widget.name`);

ViewActions

toggleModal

set modal view or remove current modal from view @param {{modalName: string, props: object }} modal - modal's name (as defined in App.js) with optional additional props

example:

showModal = () => {
    actions.view.toggleModal(`modalName`, {additionalProps:'additionalProps'});   
}
closeModal = () => {
    actions.view.toggleModal();   
}