aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-12-21 14:55:48 -0500
committerbobzel <zzzman@gmail.com>2023-12-21 14:55:48 -0500
commit1caba64ee0f32ee8af79263cd4ef2a8bc5d5146e (patch)
tree0fa0e957d1f342fdc6ed4a4b43f5dddfddb1298a /src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
parent02eb7da95df283606d4275a22d9451cef371c3b5 (diff)
parent2691b951d96f2ce7652acbea9e340b61737b3b57 (diff)
Merge branch 'moreUpgrading' into dataViz-annotations
Diffstat (limited to 'src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx113
1 files changed, 113 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..d9f7ca6ea
--- /dev/null
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
@@ -0,0 +1,113 @@
+import { IconButton, Size, Type } from 'browndash-components';
+import { action, IReactionDisposer, 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;
+}
+
+@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._hide = true)} />
+ </div>
+ </div>
+ );
+ }
+}