diff options
| author | bobzel <zzzman@gmail.com> | 2023-12-07 10:13:20 -0500 |
|---|---|---|
| committer | bobzel <zzzman@gmail.com> | 2023-12-07 10:13:20 -0500 |
| commit | 0d4c4ba17f90cf80403e6c65d2402125537cbd6b (patch) | |
| tree | 0096af1c8ce92837028723ebf29d42796e22dad6 /src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx | |
| parent | dd1db35513257abc6f36da5f8608afdde1bc4dd8 (diff) | |
| parent | 3d3878f721c0c86d59e2d1201990d9336b6283ed (diff) | |
merged infoUI
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx new file mode 100644 index 000000000..3ba7aedef --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -0,0 +1,88 @@ +import { IReactionDisposer, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import './CollectionFreeFormView.scss'; + +/** + * An Fsa Arc. The first array element is a test condition function that will be observed. + * The second array element is a function that will be invoked when the first test function + * returns a truthy value + */ +export type infoArc = [() => any, (res?: any) => infoState]; + +export const StateMessage = Symbol('StateMessage'); +export const StateEntryFunc = Symbol('StateEntryFunc'); +export class infoState { + [StateMessage]: string = ''; + [StateEntryFunc]?: () => any; + [key: string]: infoArc; + constructor(message: string, arcs: { [key: string]: infoArc }, entryFunc?: () => any) { + this[StateMessage] = message; + Object.assign(this, arcs); + this[StateEntryFunc] = entryFunc; + } +} + +/** + * Create an FSA state. + * @param msg the message displayed when in this state + * @param arcs an object with fields containing @infoArcs (an object with field names indicating the arc transition and + * field values being a tuple of an arc transition trigger function (that returns a truthy value when the arc should fire), + * and an arc transition action function (that sets the next state) + * @param entryFunc a function to call when entering the state + * @returns an FSA state + */ +export function InfoState( + msg: string, // + arcs: { [key: string]: infoArc }, + entryFunc?: () => any +) { + return new infoState(msg, arcs, entryFunc); +} + +export interface CollectionFreeFormInfoStateProps { + infoState: infoState; + next: (state: infoState) => any; +} + +@observer +export class CollectionFreeFormInfoState extends React.Component<CollectionFreeFormInfoStateProps> { + _disposers: IReactionDisposer[] = []; + + get State() { + return this.props.infoState; + } + get Arcs() { + return Object.keys(this.State).map(key => this.State[key]); + } + + clearState = () => this._disposers.map(disposer => disposer()); + initState = () => + (this._disposers = this.Arcs.map(arc => ({ test: arc[0], act: arc[1] })).map(arc => { + return reaction( + // + arc.test, + res => { + if (res) { + const next = arc.act(res); + this.props.next(next); + } + }, + { fireImmediately: true } + ); + })); + + componentDidMount(): void { + this.initState(); + } + componentDidUpdate() { + this.clearState(); + this.initState(); + } + componentWillUnmount(): void { + this.clearState(); + } + render() { + return <div className="infoUI">{this.State[StateMessage]}</div>; + } +} |
