npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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.textEstatemay 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 and StageOne. 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

  1. We use CSS modules and preprocessor Sass with extension scss. 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
  2. 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)

  1. Create a file .env.development with following content: export TOKEN=access-key
  2. To generate token, it is necessary to create an access key in Flowfact system (CRM): profile / settings / API access / create access
  3. From the root of the project run the script publishForDevLocal.sh

Development (globally)

  1. Create a file .env.development with following content: export TOKEN=access-key
  2. To generate token, it is necessary to create an access key in Flowfact system (CRM): profile / settings / API access / create access
  3. From the root of the project run the script publishForDevGlobal.sh

Production (locally)

  1. Create a file .env.production with following content: export TOKEN=access-key
  2. To generate token, it is necessary to create an access key in Flowfact system (CRM): profile / settings / API access / create access
  3. From the root of the project run the script publishForProdLocal.sh

Production (globally)

  1. Create a file .env.production with following content: export TOKEN=access-key
  2. To generate token, it is necessary to create an access key in Flowfact system (CRM): profile / settings / API access / create access
  3. From the root of the project run the script publishForProdGlobal.sh

Staging (globally)

  1. Create a file .env.staging with following content: export TOKEN=access-key
  2. To generate token, it is necessary to create an access key in Flowfact system (CRM): profile / settings / API access / create access
  3. 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:

  1. Setup environment with REACT_APP_STAGE command
  2. Setup your token with TOKEN command
  3. Setup start point of the app with PUBLIC_URL command
  4. Build and publish the app with yarn build && yarn expose -- publish --template-id={TEMPLATE-ID-NUM} --name={TEMPLATE-NAME}
  5. 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:

  1. Setup environment with REACT_APP_STAGE command
  2. Setup your token with TOKEN command
  3. Setup start point of the app with PUBLIC_URL command
  4. 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:

  1. Setup environment with REACT_APP_STAGE command
  2. Setup your token with TOKEN command
  3. Setup start point of the app with PUBLIC_URL command
  4. 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