diff options
| author | Sophie Zhang <sophie_zhang@brown.edu> | 2024-01-25 11:35:26 -0500 |
|---|---|---|
| committer | Sophie Zhang <sophie_zhang@brown.edu> | 2024-01-25 11:35:26 -0500 |
| commit | f3dab2a56db5e4a6a3dca58185d94e1ff7d1dc32 (patch) | |
| tree | a7bc895266b53bb620dbd2dd71bad2e83b555446 /src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx | |
| parent | b5c5410b4af5d2c68d2107d3f064f6e3ec4ac3f2 (diff) | |
| parent | 136f3d9f349d54e8bdd73b6380ea47c19e5edebf (diff) | |
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx')
| -rw-r--r-- | src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx | 114 |
1 files changed, 114 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..58f6b1593 --- /dev/null +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx @@ -0,0 +1,114 @@ +import { IconButton, Size, Type } from 'browndash-components'; +import { IReactionDisposer, action, makeObservable, observable, reaction } from 'mobx'; +import { observer } from 'mobx-react'; +import * as React from 'react'; +import { SettingsManager } from '../../../util/SettingsManager'; +import { ObservableReactComponent } from '../../ObservableReactComponent'; +import './CollectionFreeFormView.scss'; +// import assets from './assets/link.png'; + +/** + * 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 const StateMessageGIF = Symbol('StateMessageGIF'); +export class infoState { + [StateMessage]: string = ''; + [StateEntryFunc]?: () => any; + [StateMessageGIF]?: string = ''; + [key: string]: infoArc; + constructor(message: string, arcs: { [key: string]: infoArc }, entryFunc?: () => any, messageGif?: string) { + this[StateMessage] = message; + Object.assign(this, arcs); + this[StateEntryFunc] = entryFunc; + this[StateMessageGIF] = messageGif; + } +} + +/** + * 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, + gif?: string +) { + return new infoState(msg, arcs, entryFunc, gif); +} + +export interface CollectionFreeFormInfoStateProps { + infoState: infoState; + next: (state: infoState) => any; + close: () => void; +} + +@observer +export class CollectionFreeFormInfoState extends ObservableReactComponent<CollectionFreeFormInfoStateProps> { + _disposers: IReactionDisposer[] = []; + @observable _hide = false; + + constructor(props: any) { + super(props); + makeObservable(this); + } + + 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(prevProps: Readonly<CollectionFreeFormInfoStateProps>) { + super.componentDidUpdate(prevProps); + this.clearState(); + this.initState(); + } + componentWillUnmount(): void { + this.clearState(); + } + render() { + return ( + <div className="collectionFreeform-infoUI" style={{ display: this._hide ? 'none' : undefined }}> + <div className="msg">{this.State?.[StateMessage]}</div> + <div className="gif-container" style={{ display: this.State?.[StateMessageGIF] ? undefined : 'none' }}> + <img className="gif" src={this.State?.[StateMessageGIF]} alt="state message gif"></img> + </div> + <div style={{ position: 'absolute', top: -10, left: -10 }}> + <IconButton icon="x" color={SettingsManager.userColor} size={Size.XSMALL} type={Type.TERT} background={SettingsManager.userBackgroundColor} onClick={action(e => this.props.close())} /> + </div> + </div> + ); + } +} |
