1.2.2 • Published 3 years ago

inriver-html-react-components v1.2.2

Weekly downloads
8
License
MIT
Repository
github
Last release
3 years ago

inriver-html-react-components

This is a React Library containing React Components and other functionality made spesifically for inRiver templates. This project includes:

  • Generic and customizable fields that handle every inRiver fieldType. (See Known Issues for exceptions)
  • A field change detector and updater: Edits made to fields can be detected and updated in inRiver
  • A visual, color-coded and readable message system that gives feedback to the user on failed or successful field updates
  • Uses the Geta package inriverjs-geta, making inRiver API requests easier

Install

Run ONE of the below lines in a dedicated folder:

# Run this:
npx create-react-app my-app --template typescript
# or this:
yarn create react-app my-app --template typescript

Now install the packages:

cd my-app
npm i inriver-html-react-components
npm install --save-dev gulp gulp-inline-source gulp-replace
npm i

We will now setup environment variables. Create two files in the my-app root folder called .env and .env.local. .env is used both when debugging and building, and will be comitted along with the source code. .env.local is only visible locally, and the variables are also used when debugging. Think of these files as the settings.json and local.settings.json that are used in Azure Functions.

Add the following to the .env file:

REACT_APP_INRIVER_APIKEY=123
INLINE_RUNTIME_CHUNK=false
GENERATE_SOURCEMAP=false
SKIP_PREFLIGHT_CHECK=true

Replace 123 for REACT_APP_INRIVER_APIKEY with the actual REST API key. The rest of the settings are for setting up gulp, which we implement soon.

Add the following to the .env.local file:

REACT_APP_INRIVER_TEST_ENTITY=123

Replace 123 with the id of the entity you want to use when debugging locally.

We will now make the project produce a single html file on build, which simplifies uploading the template. Add a file called gulpfile.js in the my-app root folder with the following:

const gulp = require('gulp')
const inlinesource = require('gulp-inline-source')
const replace = require('gulp-replace')

gulp.task('default', () => {
    return gulp.src('./build/*.html')
        .pipe(replace('.js"></script>', '.js" inline></script>'))
        .pipe(replace('rel="stylesheet">', 'rel="stylesheet" inline>'))
        .pipe(inlinesource({
            compress: false,
            ignore: ['png']
        }))
        .pipe(gulp.dest('./build'))
});

Finally, append && npx gulp to the end of your build command in my-app\package.json. Example:

# replace this:
"build": "react-scripts build"
# with this:
"build": "react-scripts build && npx gulp"

Running npm run build will now package everything into a single file at my-app\build\index.html.

NOTE: If you are getting CORS errors when running locally, add this as a setting in control center: REST_API_ALLOWED_ORIGINS=*. NOTE: The reason it's not set by default, is because inRiver considers it a possible security issue.

Usage

Below is an example usage. Replace MyComponent with an actual component.

import React, { Component } from 'react'

import MyComponent from 'inriver-html-react-components'
import 'inriver-html-react-components/dist/index.css'

class Example extends Component {
  render() {
    return <MyComponent />
  }
}

For full working examples, check out the below example, or any of the examples here: https://github.com/Geta/Geta.inRiver.IPMC.HtmlTemplates/tree/boilerplate-react-project/inriver-html-react-components/examples.

import { useEffect, useState } from 'react';
import './App.css';
import 'inriver-html-react-components/dist/index.css';
import InRiverAPIClient from 'inriverjs-geta/lib';
import { IFieldSummaryModel } from 'inriverjs-geta/lib/types';
import { functions, constants } from 'inriver-html-react-components';
import { FieldData } from 'inriver-html-react-components/dist/types';
import { EntityField } from 'inriver-html-react-components';

function App() {
  const entityId = functions.getEntityId() ?? parseInt(process.env.REACT_APP_INRIVER_TEST_ENTITY!);
  const inRiverApi = new InRiverAPIClient(process.env.REACT_APP_INRIVER_APIKEY!)
  const [data, setData] = useState<FieldData[]>([]);

  useEffect(() => {
    inRiverApi.Entities.FetchData({
      entityIds: [entityId],
      objects: functions.getReturnType(constants.ReturnType.EntitySummary | constants.ReturnType.FieldsSummary),
    })
      .then(result => setData(result.data[0].fields!
        .slice(0, 5)
        .map(f => convertToFieldData(f))))
  }, []);

  return <div>
    {data.map((field, idx) =>
      <EntityField
        key={idx}
        inRiverApi={inRiverApi}
        field={field}
        addPendingChange={(value: any) => console.log('logging pending change', value)}
      />
    )}
  </div>

}

function convertToFieldData(fieldSummary: IFieldSummaryModel): FieldData {
  return {
    fieldTypeId: fieldSummary.fieldTypeId!,
    entityId: fieldSummary.entityId!,
    fieldTypeDisplayName: fieldSummary.fieldTypeDisplayName!,
    fieldDataType: constants.DataType[fieldSummary.fieldDataType! as any] as any,
    value: fieldSummary.value! as unknown as any,
    isMultiValue: fieldSummary.isMultiValue!,
    cvlId: fieldSummary.cvlId,
    parentCvlId: fieldSummary.parentCvlId
  }
}

export default App;

Fields:

Generate a field by using the Component EntityField. The component accepts the following mandatory props: | Prop | DataType | Description | | --------------------- | ------------------- | ----------------------------------------------------------------- | | inRiverApi | InRiverAPIClient | inRiver client, used by CvlField to fetch cvl values | | field | IFieldSummaryModel | the Field data | | addPendingChange | (value: any) => void | triggered when a field is changed. value contains the new value |

As well as the following optional props: | Prop | DataType | Description | | --------------------- | ------------------- | ----------------------------------------------------------------- | | isChanged | boolean | used to mark if a field has been edited | | fieldLabel | string | overrides default label field.fieldTypeDisplayName | | style | React.CSSProperties | override element style | | labelStyle | React.CSSProperties | override element style of label element | | fieldWidth string | string | override field width | | parentCvlSelectedKeys | string[] | the parent cvl field's selected value(s). Used for filtering |

NOTE: The Field property can be fetched from inRiver or created manually. The field properties currently in use are: value, fieldTypeDisplayName, fieldDataType, isMultiValue and cvlId.

Known issues

  • FieldSet not implemented
  • When changing a parent cvl field to another value then back, and also doing the same for the child cvl field right after, the child might not switch back to it's original value (visually). Ignored for now since it is extremely unlikely a user will do this.

Resources

  • create-react-library NPM
  • inriverjs-geta NPM

License

MIT © RabaGhast