@stacknvault/iex2-core
v3.0.38
Published
Package to manage the IEX2 context
Downloads
25
Readme
IEX2 applications
IEX2 allows developers use the technology they want to generate expose templates to send real estate items to a given contact.
Developers can leverage the IEX2 components and the expose script to develop and publish expose templates.
The iex2-core library
This dependency must be included on the package.json
file:
@stacknvault/iex2-core
Structure of the expose
An expose has stages. They represents the lifecycle that the customer goes through when buying real estate. Some sensitive information may be hidden until certain stage and some sections will be also available after certain stage.
A section is a block that is presented to the user. Examples:
- Provisioning Contract Agreement
- A Hero Banner
- An image carousel
- ...
#Public folder The engine expects two files to exist on the public directory:
assets/context/config.json
assets/context/context.json
How to work with config.json file?
The config.json file has a context block. It fills it with information retrieved from the backend. This is the block that will feed the context.json file with fields named same as the fields under the context section. For example: config.json:
{
"context": {
"foo": {...},
"bar": {...},
"baz": {...}
"config": {...}
"stage": {...}
}
produces the following context.json:
{
"foo": {...},
"bar": {...},
"baz": {...}
"config": {...}
"stage": {...}
}
Types of blocks supported by the config.json file
- string
- integer
- ff-svc
- flowdsl
- literal
- json-expression
- array-map
string
"expose_title": {
"type": "string",
"value": "{{{context.estate.headline}}}"
},
produces:
"expose_title":"Great Villa by the sea"
integer
"stage": {
"type": "integer",
"value": "{{{stage}}}"
},
produces:
"stage": 0
ff-svc
It pulls data from a Flowfact service. Example:
"estate": {
"type": "ff-svc",
"url": "/entity-service/entities/{{{estateId}}}",
"method": "get"
}
produces:
"estate":{
"id":"0f484937-6a1c-4202-81b0-18210179d4df",
"parking":{
"values":[
"4"
]
},
"3_leerstandspreis":{
"values":[
86543
]
},
...
flowdsl
This is a special case to pull data from the search service Example:
"contacts": {
"schema": "estates",
"query": {
"target": "ENTITY",
"fetch": ["headline", "description"],
"conditions": [
{
"type": "HASFIELDWITHVALUE",
"field": "status",
"value": "active"
},
{
"type": "HASFIELDWITHVALUE",
"field": "purchaseprice",
"value": 50000,
"operator": "GREATER"
}
],
"sorts": [
{
"field": "_metadata.createdTimestamp",
"direction": "ASC"
}
]
},
"offset": 1,
"size": 2
}
produces:
{
"entries": [
{
"id": "5afcc1cb-4ce4-4954-8234-105b67e50dc8",
"headline": {
"values": [
"Musterdaten - Großzügig geschnittenenes Haus mitten im Wald"
]
},
"_acps": [
{
"groupId": "3febc943-e718-436c-b717-239bfff76b78",
"accessLevel": 7
}
],
...
{
"id": "d837832a-61a8-4dd3-8de4-823a99b0cfee",
"uri": "companies/companies/d837832a-61a8-4dd3-8de4-823a99b0cfee",
"type": "company",
"relation": "creator"
}
]
},
{
"id": "4658de53-8f34-4f78-b41e-d3b2724157e5",
"headline": {
"values": [
"Musterdaten - Apartments in Berlin "
]
},
{
"id": "d837832a-61a8-4dd3-8de4-823a99b0cfee",
"uri": "companies/companies/d837832a-61a8-4dd3-8de4-823a99b0cfee",
"type": "company",
"relation": "creator"
}
...
"_lock": {
"identifier": false
},
"_optionalConditions": {
"totalCount": 0,
"matchingCount": 0
}
}
],
"totalCount": 7,
"page": 1,
"pageSize": 2,
"offset": 0,
"size": 2
}
literal
It's a literal expression. Example:
"foo": {
"type": "literal",
"obj": {
"bar": "baz"
}
}
produces
"foo": {
"bar": "baz"
}
json-expression
This evaluates a json expression. Example:
"estateContacts": {
"type": "json-expression",
"expression": "context.estate.contact"
}
produces:
"estateContacts":{
"values":[
"ce85ca05-9bab-4094-97e2-e029bb688c22",
"c33ae329-8af3-4a73-b85b-b6ecc1e65697"
]
}
array-map
It iterates within an array and can nest other block inside. The from parameter accepts a json query to produce the element array to map. The to element produces the target mapped array Example:
"estateContacts": {
"type": "array-map",
"from": ".context.estate.contact.values",
"to": {
"type": "ff-svc",
"url": "/entity-service/entities/<%=from=%>",
"method": "get"
}
},
produces:
"estateContact": [
{
"id":"ce85ca05-9bab-4094-97e2-e029bb688c22",
"emails":{
"values":[
"[email protected]"
]
},
...
]
},
{
"id": "dc508439-4016-444e-9311-a52b41841b88",
"lastName": {
"values": [
"Krebs"
]
},
...
}
]
To represent an integer value This file includes the configuration of the fields that are available for the estate at whatever stage. Includes and/or excludes can be used:
including / excluding values
Values can be incuded or excluded depending on the stage An example:
"estate": {
"type": "ff-svc",
"url": "/entity-service/entities/{{{estateId}}}",
"method": "get",
"includes": [
{"name": "flowfact_geolocation", "fromStage": 1},
{"name": "addresses", "fromStage": 1},
{"name": "latitude", "fromStage": 1},
{"name": "longitude", "fromStage": 1},
{"name": "id"},
{"name": "AnnualNetColdRentActualCommercial"},
{"name": "AnnualNetColdRentActualOthers"},
{"name": "AnnualNetColdRentActualResidential"},
...
]
}
- The fields listed for the fromStage 1 won't be available until that stage. The others will be always available. No field outside that list will be available at all.
- If excludes are used, all fields but the axcluded ones are available
- If no includes or excludes are used, all fields will be available Feel free to use includes or excludes to whitelist or blacklist fields.
Field mappings
There are many occassions where data is not standardized on the CRM for the different entities. This results in gaps between different companies / editions when it comes to name the same entity field. For example, estate.textEstate
may be referenced like estate.estateDescription
depending on the edition or the customer.
To aaddress this issue, the expose supports field mappings ike on this example: config.json:
{
...
"fieldMapping": {
"estate": [
["textEstate", "estateDescription"],
["textFree", "freeDescription"],
["textEnvironment", "equipmentDescription"],
["textLocation", "locationDescription"]
]
}
}
Stages
When Stage objects are used, like on the example below, the framework controls when to show them depending on the stage:
...
<Stage level="0">
<ContractAgreement
theme={theme}
contracts={ffmap`company.legislationTexts`}
imgObj={ffmap`estate.mainImage`}/>
</Stage>
<Stage level="1">
<WhateverOtherSection/>
...
</Stage>
Functions like ffmap help access the data from the context.
src folder
assets
- the folder static information that helps to develop the application. For example, e.g. pictures or general
styles
components
- the folder with all components used in the application. It consists of 3 folders: common
, sections
, stages
common
folder contains components that can be reused in different sections, e.g. a component 'ImageCarousel' is used in sections "Gallery" and "FloorPlans".sections
folder contains all sections. Here we call the components frm 'common' and create new components for specific sections.stages
folder consist of 2 folders:StageZero
andStageOne
. Here we list all sections (components) we use for stages 0 and stage 1.
helpers
- the folder with general functions / data that help to develop the app
hooks
- the folder with custom hooks
Expose.jsx
file - start point of the app
Expose.scss
and index.scss
- general styles for the app
multilanguage support
The exposé supports multilanguage by exposing the language and setLanguage items on the context. context.json:
{
"estate": {
...
"textEstate": {
"values": [
"Schönes Anwesen in den Bergen"
]
},
"textEstateEN": {
"values": [
"Nice estate in the mountains"
]
}
}
...
}
Expose source code:
import {ContextStore, ffmap} from '@stacknvault/iex2-core'
...
const {language, setLanguage, iex} = useContext(ContextStore);
setLanguage('en');
...
return (
<div>{ffmap`estate.textEstate`}</div> /* displays it in english*/
);
Multilanguage features can combine with field mappings, so that if for example estate.description
is mapped to estate.my_custom_filed_for_description
and the context contains estate.my_custom_filed_for_descriptionES
, ffmap estate.description
would show the value of estate.my_custom_filed_for_descriptionES
if the language is es
Styles
We use
CSS modules
and preprocessor Sass with extensionscss
. Read more about CSS Module here:- https://github.com/css-modules/css-modules
- https://create-react-app.dev/docs/adding-a-css-modules-stylesheet/
Read mode about Sass here:
- https://sass-lang.com/documentation
Inline styles.
Use it when you need to pass a dynamic value that can be changed depending on the state of the application or company settings. For example, if you want to use a company accent color, you need to get it from getBaseTheme() function (* location: /src/assets/styles/IEXTheme*) Code example:
const theme = getBaseTheme()
<h2 style={{color: theme.brand.colors.primary}}>
Publish a template
Environments:
- production
- staging
- development
Templates that are published locally
are available only to the user to whom the used access key belongs to.
Templates that are published globally
are visible to every Flowfact user in the corresponding environment. You need special rights for that.
Development (locally)
- Create a file
.env.development
with following content:export TOKEN=access-key
- To generate token, it is necessary to create an access key in Flowfact system (CRM):
profile / settings / API access / create access
- From the root of the project run the script
publishForDevLocal.sh
Development (globally)
- Create a file
.env.development
with following content:export TOKEN=access-key
- To generate token, it is necessary to create an access key in Flowfact system (CRM):
profile / settings / API access / create access
- From the root of the project run the script
publishForDevGlobal.sh
Production (locally)
- Create a file
.env.production
with following content: export TOKEN=access-key - To generate token, it is necessary to create an access key in Flowfact system (CRM):
profile / settings / API access / create access
- From the root of the project run the script publishForProdLocal.sh
Production (globally)
- Create a file
.env.production
with following content: export TOKEN=access-key - To generate token, it is necessary to create an access key in Flowfact system (CRM):
profile / settings / API access / create access
- From the root of the project run the script publishForProdGlobal.sh
Staging (globally)
- Create a file
.env.staging
with following content: export TOKEN=access-key - To generate token, it is necessary to create an access key in Flowfact system (CRM):
profile / settings / API access / create access
- From the root of the project run the script publishForStagingGlobal.sh
The expose script
Setting up the environment
The following environment variables need to be set:
- TOKEN: It's taken from Flowfact, from the profile / settings / API access / create access. Example: export TOKEN = your-token-num
- REACT_APP_STAGE: development | staging | production. Example: export REACT_APP_STAGE=development
- PUBLIC_URL: Must be set to "." due to the way the exposes are going to be consumed by the consumer. __ Example__: export PUBLIC_URL=.
Show help menu yarn expose
or yarn expose help
terminal output:
USAGE:
npm run expose <publish|delete|list|render|set-stage|get-context> --<option name>=<option value>
For help, run:
npm run expose help
or
npm run expose <command> help
Publish a template without using prepared scripts
Steps:
- Setup environment with REACT_APP_STAGE command
- Setup your token with TOKEN command
- Setup start point of the app with PUBLIC_URL command
- Build and publish the app with yarn build && yarn expose -- publish --template-id={TEMPLATE-ID-NUM} --name={TEMPLATE-NAME}
- NOTE: if you want to publish a template globally you should to add --global to the command from point 4.
yarn expose publish help
terminal output:
Publishes a template.
USAGE:
npm run expose publish [ --template-id=<your own template id> ] [ --name="<the name of the template>"] [--global]
If no other args are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
Delete a template
Steps:
- Setup environment with REACT_APP_STAGE command
- Setup your token with TOKEN command
- Setup start point of the app with PUBLIC_URL command
- You can delete a template by template-id --template-id={TEMPLTAE-ID} or by name --name={TEMPLATE-NAME}. Example yarn expose delete --template-id={TEMPLATE-ID-NUM}
yarn expose delete help
terminal output:
Deletes a template.
USAGE:
npm run expose delete [ --template-id=<your own template id> ] [--global]
If no other args are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
List all templates
Steps:
- Setup environment with REACT_APP_STAGE command
- Setup your token with TOKEN command
- Setup start point of the app with PUBLIC_URL command
- The command yarn expose list will list all local templates. To list global templates just add --global to the command.
yarn expose list help
terminal output:
Lists templates.
USAGE:
npm run expose list [--global]
If no other args are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
Command yarn run expose render help
terminal output:
Renders a template for a given contact-id, estate-id and optional company-id.
USAGE:
npm run expose render [--render-id=<your own render id> ] --template-id=<template id> --contact-id=<contact id> --estate-id=<estate id> [ --company-id=<company id> ]
If no other args are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
If company id is not specified, it will be taken from the sender
A custom render-id can be used.
Command yarn run expose set-stage help
terminal output:
Sets the stage of a rendered template
USAGE:
npm run expose set-stage --render-id=<render id> --stage=<stage number starting from 0>
If no other args than the stage are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
Command yarn run expose get-context help
terminal output:
Gets the context for a given contact-id, estate-id and optional company-id and it writes it to public/assets/context/context.json.
USAGE:
npm run expose get-context --contact-id=<contact id> --estate-id=<estate id> --stage=<stage number starting from 0> [ --company-id=<company id> ]
If no other args than the stage are specified, they will be taken from .lastRun. The only flag not taken from .lastRun will be --global
If company id is not specified, it will be taken from the sender