1.0.99 • Published 4 months ago

fcmlib v1.0.99

Weekly downloads
-
License
MIT
Repository
github
Last release
4 months ago

��# FCM

This library allows you to build flow custom components which target both the default and default-legacy players simultaneously.

It works on the concept that there is a base abstract class definition called FCMCore that defines all the methods & properties.

There are then 2 extension classes to this (FCMLegacy & FCMNew) which handle the interactions with the flow player API's

FCMLegacy converts the legacy manywho javascript library into the FCMCore model.

FCMNew converts the new default player library to the FCMCore model.

To make this all work we implement our actual component in a single TSX file exposing a React.Component<any,any>.

We implement our flow component in 2 files for Core & Legacy.

I use ESBuild to transpile, host and package.

e.g.

'''

package.json File

An example of a package.json file

{
  "name": "mycomp",
  "version": "1.0.0",
  "description": "My Component",
  "scripts": {
    "start": "esbuild ./src/MyClassNew.tsx --outfile=./build/myclass_ng.js --sourcemap=both --serve=8080 --servedir=build --bundle --format=esm --watch",
    "build": "esbuild ./src/MyClassNew.tsx --outfile=./build/myclass_ng.js --minify --bundle  --format=esm --target=chrome58,firefox57,safari11,edge16",
    "startLegacy": "esbuild ./src/MyClassNewLegacy.tsx --outfile=./build/myclass_leg.js --sourcemap=both --serve=8080 --servedir=build --bundle --format=esm --watch",
    "buildLegacy": "esbuild ./src/MyClassNewLegacy.tsx --outfile=./build/myclass_leg.js --minify --bundle  --format=esm --target=chrome58,firefox57,safari11,edge16",
    "buildAll": "npm run build & npm run buildLegacy"
  },
  "author": "Boomi",
  "license": "MIT",
  "dependencies": {
    "fcmlib": "^1.0.38",
    "react": "18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.28",
    "esbuild": "0.19.4"
  }
}

tsconfig.json

An example of a package.json file

{
  "compilerOptions": {
    "outDir": "./build",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "jsx": "react",
    "downlevelIteration": true,
    "lib": [
      "es2015",
      "dom"
    ],
    "skipLibCheck": false,
    "esModuleInterop": true
  },
  "include": [
    "./src/**/*"
  ]
}

Legacy Component Definition (MyClassLegacy.tsx)

import { FCMLegacy } from "fcmlib/lib/FCMLegacy";
import * as React from 'react';
import { _MyClass } from "./MyClass";
declare const manywho: any;

class MyClass extends FCMLegacy {

    //FCMCore will trigger this if we should update
    redraw() {
        // call something on the real component to trigger a redraw
        this.childComponent.buildCoreTable();
    }

    render() {
        return(
            <_MyClass 
                parent={this}
                ref={(element: any) => {this.childComponent = element}} // here we are giving FCMCore a ref to our component
            />
        );
    }
}
manywho.component.register('MyClass', MyClass);

New Component Definition (MyClassNew.tsx)

import { FCMNew } from "fcmlib/lib/FCMNew";
import * as React from 'react';
import { _MyClass } from "./MyClass";

export default class CascadingCombos extends FCMNew {

    //FCMCore will trigger this if we should update
    redraw() {
        // call something on the real component to trigger a redraw
        this.childComponent.buildCoreTable();
    }

    render() {
        return(
            <_MyClass 
                parent={this}
                ref={(element: any) => {this.childComponent = element}} // here we are giving FCMCore a ref to our component
            />
        );
    }
}

Actual component implementation (MyClass.tsx)

export class _MyClass extends React.Component<any,any> {
    component: FCMCore;

    constructor(props.any) {
        super(props);
        this.component = props.props.parent;
    }

    render() {

        let classes: string = 'myclass ' + this.component.getAttribute('classes', '');
        const style: CSSProperties = {};
        style.width = 'fit-content';
        style.height = 'fit-content';

        if (this.component.isVisible === false) {
            style.display = 'none';
        }
        if (this.component.getAttribute("width")) {
            style.width = this.component.getAttribute("width");
        }
        if (this.component.getAttribute("height")) {
            style.height = this.component.getAttribute("height");
        }
        return (
            <div
                className={classes}
                style={style}
            >
                "Hello World"
            </div>
        );
    }
}

Interface

We now have the ability, in the actual component file (MyClass.tsx) to use this.component.xxx to interact with the data delivered to us by Flow and the Flow server side state directly.

Core Properties

id

The component's guid as created by Flow.

label

The component's label string.

contentType

An eContentType enumeration of the state's content type.

contentValue

The component's string state value if the state is a simple type (string, number, dateTime, boolean etc.).

objectData

The component's dataSource as an objectDataArray if the model is an objectData or objectDataArray.

getOriginalStateValue() : string | boolean | number | Date | FlowObjectData | FlowObjectDataArray | undefined

Gets the component's initial state vale as a real converted type.

setStateValue(value: string | boolean | number | Date | FlowObjectData | FlowObjectDataArray)

Sets the component's state value.

stateValue : string | boolean | number | Date | FlowObjectData | FlowObjectDataArray

Gets the current value of the component's state.

The one you last set with setStateValue().

outcomes : Object

An object with each outcome attached to the component keyed on its developer name.

e.g.

let oc: FlowOutcome = this.component.outcomes["OutcomeName"]

or

Object.keys(this.component.outcomes).forEach((key: string) => {
    let oc: FlowOutcome = this.component.outcomes[key]
});

async triggerOutcome(outcomeName: string) : Promise

This will trigger the outcome specified by its developerName.

It is await-able.

async getValue(name: string) : Promise

This will make an await-able call to directly get any named value from the current Flow's state.

It directly calls the Flow REST api.

If the value (Named on it's developerName) is not in the state it will throw a silent console error and return a null.

If successful it will return a FlowValue object.

async setValue(FlowValue | FlowValue[])

This will make an await-able call to directly update the FlowValue into the current Flow's state.

It directly calls the Flow REST api.

e.g.

let val: FlowValue = await this.component.getValue("MyValue");
if(val) {
    val.value = "Hello World";
    //or
    val.value = someObjectDataOrArray;
    await this.component.setValue(val);
}

async inflateValue(value: string) : Promise

This awaitable function will attempt to extract a part of a Flow value.

We pass it {{MyValue}} or {{MyValue->Property}} or {{MyValue->Property->property}} etc.

It will retrieve the FlowValue "MyValue" if not previously retrieved then iterate down through it's properies to get the indicated one.

Great if you want to pass a complex value in an attribute.

getAttribute(AttributeName, defaultValue) : string;

This will get the value of the named attribute from the component.

If it is not defined then the defaultValue will be returned or null if no default is specified.

e.g.

let myBool: boolean = this.component.getAttribute("myBool","false") === "true";

Others

There are various other component configuration attributes exposed like visibility, developerName, authenticationToken, currentMapElementId and more.

Other Classes

Various other classes are exposed as helpers and Enums.

FlowObjectData

FlowObjectDataArray

FlowDisplayColumn

FlowOutcome

FlowAttribute

FlowValue

eContentType

1.0.99

4 months ago

1.0.98

4 months ago

1.0.95

5 months ago

1.0.97

5 months ago

1.0.96

5 months ago

1.0.94

5 months ago

1.0.93

6 months ago

1.0.91

7 months ago

1.0.90

7 months ago

1.0.92

7 months ago

1.0.88

7 months ago

1.0.89

7 months ago

1.0.87

8 months ago

1.0.86

8 months ago

1.0.84

9 months ago

1.0.85

9 months ago

1.0.83

11 months ago

1.0.82

11 months ago

1.0.77

1 year ago

1.0.79

1 year ago

1.0.78

1 year ago

1.0.80

1 year ago

1.0.81

1 year ago

1.0.73

1 year ago

1.0.76

1 year ago

1.0.75

1 year ago

1.0.74

1 year ago

1.0.66

1 year ago

1.0.65

1 year ago

1.0.68

1 year ago

1.0.67

1 year ago

1.0.72

1 year ago

1.0.71

1 year ago

1.0.70

1 year ago

1.0.62

1 year ago

1.0.64

1 year ago

1.0.63

1 year ago

1.0.61

1 year ago

1.0.60

1 year ago

1.0.59

1 year ago

1.0.58

1 year ago

1.0.57

1 year ago

1.0.56

1 year ago

1.0.51

1 year ago

1.0.50

1 year ago

1.0.55

1 year ago

1.0.54

1 year ago

1.0.53

1 year ago

1.0.52

1 year ago

1.0.42

1 year ago

1.0.39

1 year ago

1.0.40

1 year ago

1.0.41

1 year ago

1.0.38

1 year ago

1.0.37

1 year ago

1.0.36

1 year ago

1.0.35

1 year ago

1.0.29

1 year ago

1.0.33

1 year ago

1.0.32

1 year ago

1.0.31

1 year ago

1.0.30

1 year ago

1.0.34

1 year ago

1.0.26

1 year ago

1.0.25

1 year ago

1.0.28

1 year ago

1.0.27

1 year ago

1.0.24

1 year ago

1.0.19

2 years ago

1.0.22

2 years ago

1.0.21

2 years ago

1.0.20

2 years ago

1.0.23

2 years ago

1.0.18

2 years ago

1.0.17

2 years ago

1.0.16

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago

1.0.15

2 years ago

1.0.14

2 years ago

1.0.12

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago