External mashup support

How to add layout component from an external mashup

Layout renderer exposes client-side API for registration of React components implemented in external mashups and client-side integrations.
The first API is tau/api/layout-renderer/v1/registerReactComponent. It exposes a function that should be called to register an external component. The function accepts component descriptor that consists of two fields: type property is a unique component id, component is a class, or functional React component. Both properties are mandatory.
Component of registered type should be specified in Detailed Views settings for some entity and process.
A config object related to an external component will be passed as config prop to registered React component.

Example:

tau.mashups
  .addDependency('react')
  .addDependency('tau/api/layout-renderer/v1/registerReactComponent')
  .addMashup(function(React, registerReactComponent) {
    const TestComponent = ({config: {type, componentId}}) => <div>Test component</div>;

    registerReactComponent({
      type: 'test-component',
      component: TestComponent
    });
  });

If React component has to know entity which detailed view is opened for or should interact with backend using store or store2 services, it can consume tau/api/layout-renderer/v1/LayoutContextConsumer that allows accessing context passed from Targetprocess monolith:

tau.mashups
  .addDependency('react')
  .addDependency('tau/api/layout-renderer/v1/registerReactComponent')
  .addDependency('tau/api/layout-renderer/v1/LayoutContextConsumer')
  .addMashup(function(React, registerReactComponent, LayoutContextConsumer) {
    class StatefullComponent extends React.Component {
      constructor(props) {
        super(props);

        this.state = {
          isLoading: true,
          entity: null
        };
      }

      componentDidMount() {
        this.props.store
          .getDef(this.props.entityTypeName, {id: this.props.entityId})
          .then(entity => this.setState({isLoading: false, entity}));
      }
      
      render() {
        ...
      }
    }

    const TestComponent = () => (
      <LayoutContextConsumer>
        {({context}) => (
          <StatefullComponent
            store={context.configurator.getStore()}
            entityId={context.entity.id}
            entityTypeName={context.entity.entityType.name.toLowerCase()}
          />
        )}
      </LayoutContextConsumer>
    );

    registerReactComponent({
      type: 'test-component',
      component: TestComponent
    });
  });