@aappddeevv/dynamics-client-ui
Version:
## What is it? A library to help you create great dynamics applications.
121 lines (104 loc) • 3.57 kB
text/typescript
import * as React from "react"
import * as PropTypes from "prop-types"
import {getContext, InferableComponentEnhancerWithProps} from "recompose"
import * as Utils from "./Utils"
import { NotificationManager, Notifier} from "./NotificationManager"
import { ConsoleErrorHandler, ErrorHandler } from "./ErrorHandler"
import { XRM } from "./xrm"
export * from "./NotificationManager"
export interface DynamicsContext {
xrm: XRM | null
notifier: Notifier
errorHandler: ErrorHandler
}
export interface DynamicsProps {
xrm?: XRM | null
notifier?: Notifier
errorHandler?: ErrorHandler
}
/** Not used yet. */
export const dynamicsShape = PropTypes.shape({
notifier: PropTypes.object,
xrm: PropTypes.object,
errorHandler: PropTypes.object
})
/**
* Render the first child only. Places Xrm and a NotificationManager into the context.
* Declare a child's use of the context:
* ```
* class Foo extends React.Component {
* public static contextTypes = {
* Xrm: PropTypes.object, // can use isRequired
* notifier: PropTypes.instanceOf(Object) // can use isRequired
* }
* constructor(props, context) {
* super(props, context);
* ...
* }
* ...
* ```
* You can access the context using `this.context.notifier.add(..)`. Instead of retyping
* the contextTypes in the child, you can use `public static contextTypes { ...Dynamics.childContextTypes }`.
*
* The component is stateless as only the children define the render.
*
* TODO: Notifier only works on forms, make more general so it works in non-forms.
*/
export class Dynamics<P extends DynamicsProps=DynamicsProps, S={}> extends React.Component<P, S> {
constructor(props: P, context: any) {
super(props, context)
}
private defaultErrorHandler: ErrorHandler = new ConsoleErrorHandler()
private defaultNotifier: Notifier = new NotificationManager(() => this.getXrm())
public getChildContext(): DynamicsContext {
return {
notifier: this.notifier,
xrm: this.getXrm(),
errorHandler: this.errorHandler,
}
}
/** Get Xrm from the props or the global environment window.parent. */
protected getXrm = (): XRM | null => {
//console.log("Dyanmics.getXrm()", this)
if(this.props &&
typeof this.props.xrm !== "undefined" && this.props.xrm !== null)
return this.props.xrm!
return Utils.getXrm()
}
get notifier(): Notifier {
return (this.props && this.props.notifier) ?
this.props.notifier! as Notifier:
this.defaultNotifier
}
get errorHandler(): ErrorHandler {
return this.props.errorHandler ?
(this.props.errorHandler as ErrorHandler):
this.defaultErrorHandler
}
public static childContextTypes = {
notifier: PropTypes.object,
xrm: PropTypes.object,
errorHandler: PropTypes.object
}
render() {
const { children } = this.props;
return React.Children.only(children)
}
}
/** Use this to compose your component with Xrm and NotificationManager
* in the props.
*
* const YourComponent = ({notificationManager, Xrm, ...rest}) => {
* console.log(notifier, Xrm); // to prove that it is there.
* }
* export default withDynamics(YourComponent)
* ```
*/
export const withDynamics = getContext(
{
notifier: PropTypes.instanceOf(NotificationManager),
xrm: PropTypes.object,
errorHandler: PropTypes.object
}
)
export default Dynamics