aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DocumentContentsView.tsx
diff options
context:
space:
mode:
authorSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
committerSophie Zhang <sophie_zhang@brown.edu>2024-01-25 11:35:26 -0500
commitf3dab2a56db5e4a6a3dca58185d94e1ff7d1dc32 (patch)
treea7bc895266b53bb620dbd2dd71bad2e83b555446 /src/client/views/nodes/DocumentContentsView.tsx
parentb5c5410b4af5d2c68d2107d3f064f6e3ec4ac3f2 (diff)
parent136f3d9f349d54e8bdd73b6380ea47c19e5edebf (diff)
Merge branch 'master' into sophie-ai-images
Diffstat (limited to 'src/client/views/nodes/DocumentContentsView.tsx')
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx127
1 files changed, 62 insertions, 65 deletions
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e1de2fa76..07e179246 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -1,54 +1,52 @@
-import { computed } from 'mobx';
+import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
+import JsxParser from 'react-jsx-parser';
+import * as XRegExp from 'xregexp';
+import { OmitKeys, Without, emptyPath } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
-import { AclPrivate } from '../../../fields/DocSymbols';
+import { AclPrivate, DocData } from '../../../fields/DocSymbols';
import { ScriptField } from '../../../fields/ScriptField';
import { Cast, StrCast } from '../../../fields/Types';
import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
-import { emptyPath, OmitKeys, Without } from '../../../Utils';
-import { DirectoryImportBox } from '../../util/Import & Export/DirectoryImportBox';
+import { InkingStroke } from '../InkingStroke';
+import { ObservableReactComponent } from '../ObservableReactComponent';
+import { CollectionCalendarView } from '../collections/CollectionCalendarView';
import { CollectionDockingView } from '../collections/CollectionDockingView';
+import { CollectionView } from '../collections/CollectionView';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { CollectionSchemaView } from '../collections/collectionSchema/CollectionSchemaView';
import { SchemaRowBox } from '../collections/collectionSchema/SchemaRowBox';
-import { CollectionView } from '../collections/CollectionView';
-import { InkingStroke } from '../InkingStroke';
import { PresElementBox } from '../nodes/trails/PresElementBox';
import { SearchBox } from '../search/SearchBox';
import { DashWebRTCVideo } from '../webcam/DashWebRTCVideo';
import { YoutubeBox } from './../../apis/youtube/YoutubeBox';
import { AudioBox } from './AudioBox';
-import { ColorBox } from './ColorBox';
import { ComparisonBox } from './ComparisonBox';
import { DataVizBox } from './DataVizBox/DataVizBox';
-import { DocumentViewProps } from './DocumentView';
import './DocumentView.scss';
import { EquationBox } from './EquationBox';
import { FieldView, FieldViewProps } from './FieldView';
import { FontIconBox } from './FontIconBox/FontIconBox';
-import { FormattedTextBox } from './formattedText/FormattedTextBox';
import { FunctionPlotBox } from './FunctionPlotBox';
import { ImageBox } from './ImageBox';
-import { ImportElementBox } from './importBox/ImportElementBox';
import { KeyValueBox } from './KeyValueBox';
import { LabelBox } from './LabelBox';
import { LinkAnchorBox } from './LinkAnchorBox';
import { LinkBox } from './LinkBox';
import { LoadingBox } from './LoadingBox';
import { MapBox } from './MapBox/MapBox';
+import { MapPushpinBox } from './MapBox/MapPushpinBox';
import { PDFBox } from './PDFBox';
import { PhysicsSimulationBox } from './PhysicsBox/PhysicsSimulationBox';
import { RecordingBox } from './RecordingBox';
import { ScreenshotBox } from './ScreenshotBox';
import { ScriptingBox } from './ScriptingBox';
-import { PresBox } from './trails/PresBox';
import { VideoBox } from './VideoBox';
import { WebBox } from './WebBox';
-import React = require('react');
-import XRegExp = require('xregexp');
-import { MapPushpinBox } from './MapBox/MapPushpinBox';
-
-const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
+import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import { ImportElementBox } from './importBox/ImportElementBox';
+import { PresBox } from './trails/PresBox';
type BindingProps = Without<FieldViewProps, 'fieldKey'>;
export interface JsxBindings {
@@ -66,7 +64,6 @@ export const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
interface HTMLtagProps {
Document: Doc;
- RootDoc: Doc;
htmltag: string;
onClick?: ScriptField;
onInput?: ScriptField;
@@ -90,18 +87,18 @@ interface HTMLtagProps {
export class HTMLtag extends React.Component<HTMLtagProps> {
click = (e: React.MouseEvent) => {
const clickScript = (this.props as any).onClick as Opt<ScriptField>;
- clickScript?.script.run({ this: this.props.Document, self: this.props.RootDoc, scale: this.props.scaling });
+ clickScript?.script.run({ this: this.props.Document, self: this.props.Document, scale: this.props.scaling });
};
onInput = (e: React.FormEvent<HTMLDivElement>) => {
const onInputScript = (this.props as any).onInput as Opt<ScriptField>;
- onInputScript?.script.run({ this: this.props.Document, self: this.props.RootDoc, value: (e.target as any).textContent });
+ onInputScript?.script.run({ this: this.props.Document, self: this.props.Document, value: (e.target as any).textContent });
};
render() {
const style: { [key: string]: any } = {};
- const divKeys = OmitKeys(this.props, ['children', 'htmltag', 'RootDoc', 'scaling', 'Document', 'key', 'onInput', 'onClick', '__proto__']).omit;
+ const divKeys = OmitKeys(this.props, ['children', 'dragStarting', 'dragEnding', 'htmltag', 'scaling', 'Document', 'key', 'onInput', 'onClick', '__proto__']).omit;
const replacer = (match: any, expr: string, offset: any, string: any) => {
- // bcz: this executes a script to convert a propery expression string: { script } into a value
- return (ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ self: this.props.RootDoc, this: this.props.Document, scale: this.props.scaling }).result as string) || '';
+ // bcz: this executes a script to convert a property expression string: { script } into a value
+ return (ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: 'number' })?.script.run({ self: this.props.Document, this: this.props.Document, scale: this.props.scaling }).result as string) || '';
};
Object.keys(divKeys).map((prop: string) => {
const p = (this.props as any)[prop] as string;
@@ -116,71 +113,72 @@ export class HTMLtag extends React.Component<HTMLtagProps> {
}
}
+export interface DocumentContentsViewProps extends FieldViewProps {
+ layoutFieldKey: string;
+}
@observer
-export class DocumentContentsView extends React.Component<
- DocumentViewProps & {
- isSelected: (outsideReaction: boolean) => boolean;
- select: (ctrl: boolean) => void;
- NativeDimScaling?: () => number;
- setHeight?: (height: number) => void;
- layout_fieldKey: string;
+export class DocumentContentsView extends ObservableReactComponent<DocumentContentsViewProps> {
+ constructor(props: any) {
+ super(props);
+ makeObservable(this);
}
-> {
+
@computed get layout(): string {
TraceMobx();
- if (this.props.LayoutTemplateString) return this.props.LayoutTemplateString;
+ if (this._props.LayoutTemplateString) return this._props.LayoutTemplateString;
if (!this.layoutDoc) return '<p>awaiting layout</p>';
- if (this.props.layout_fieldKey === 'layout_keyValue') return StrCast(this.props.Document.layout_keyValue, KeyValueBox.LayoutString());
- const layout = Cast(this.layoutDoc[this.layoutDoc === this.props.Document && this.props.layout_fieldKey ? this.props.layout_fieldKey : StrCast(this.layoutDoc.layout_fieldKey, 'layout')], 'string');
- if (layout === undefined) return this.props.Document.data ? "<FieldView {...props} fieldKey='data' />" : KeyValueBox.LayoutString();
+ if (this._props.layoutFieldKey === 'layout_keyValue') return StrCast(this._props.Document.layout_keyValue, KeyValueBox.LayoutString());
+ const layout = Cast(this.layoutDoc[this.layoutDoc === this._props.Document && this._props.layoutFieldKey ? this._props.layoutFieldKey : StrCast(this.layoutDoc.layout_fieldKey, 'layout')], 'string');
+ if (layout === undefined) return this._props.Document.data ? "<FieldView {...props} fieldKey='data' />" : KeyValueBox.LayoutString();
if (typeof layout === 'string') return layout;
return '<p>Loading layout</p>';
}
- get dataDoc() {
- const proto = this.props.DataDoc || Doc.GetProto(this.props.Document);
- return proto instanceof Promise ? undefined : proto;
- }
get layoutDoc() {
// bcz: replaced this with below : is it correct? change was made to accommodate passing fieldKey's from a layout script
- // const template: Doc = this.props.LayoutTemplate?.() || Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined);
+ // const template: Doc = this._props.LayoutTemplate?.() || Doc.Layout(this._props.Document, this._props.fieldKey ? Cast(this._props.Document[this._props.fieldKey], Doc, null) : undefined);
const template: Doc =
- this.props.LayoutTemplate?.() ||
- (this.props.LayoutTemplateString && this.props.Document) ||
- (this.props.layout_fieldKey && StrCast(this.props.Document[this.props.layout_fieldKey]) && this.props.Document) ||
- Doc.Layout(this.props.Document, this.props.layout_fieldKey ? Cast(this.props.Document[this.props.layout_fieldKey], Doc, null) : undefined);
- return Doc.expandTemplateLayout(template, this.props.Document);
+ this._props.LayoutTemplate?.() ||
+ (this._props.LayoutTemplateString && this._props.Document) ||
+ (this._props.layoutFieldKey && StrCast(this._props.Document[this._props.layoutFieldKey]) && this._props.Document) ||
+ Doc.Layout(this._props.Document, this._props.layoutFieldKey ? Cast(this._props.Document[this._props.layoutFieldKey], Doc, null) : undefined);
+ return Doc.expandTemplateLayout(template, this._props.Document);
}
CreateBindings(onClick: Opt<ScriptField>, onInput: Opt<ScriptField>): JsxBindings {
const docOnlyProps = [
- // these are the properties in DocumentViewProps that need to be removed to pass on only DocumentSharedViewProps to the FieldViews
+ // these are the properties in DocumentViewProps that need to be removed to pass on only DocumentSharedViewProps to the FieldViews
'hideResizeHandles',
'hideTitle',
- 'contentPointerEvents',
- 'radialMenu',
+ 'bringToFront',
+ 'childContentPointerEvents',
'LayoutTemplateString',
'LayoutTemplate',
+ 'layoutFieldKey',
'dontCenter',
'contextMenuItems',
- 'onClick',
- 'onDoubleClick',
- 'onPointerDown',
- 'onPointerUp',
+ //'onClick', // don't need to omit this since it will be set
+ 'onDoubleClickScript',
+ 'onPointerDownScript',
+ 'onPointerUpScript',
];
- const list = {
- ...OmitKeys(this.props, [...docOnlyProps], '').omit,
- RootDoc: Cast(this.layoutDoc?.rootDocument, Doc, null) || this.layoutDoc,
- Document: this.layoutDoc,
- DataDoc: this.dataDoc,
- onClick: onClick,
- onInput: onInput,
+ const templateDataDoc = this._props.TemplateDataDocument ?? (this.layoutDoc !== this._props.Document ? this._props.Document[DocData] : undefined);
+ const list: BindingProps & React.DetailedHTMLProps<React.HtmlHTMLAttributes<HTMLDivElement>, HTMLDivElement> = {
+ ...this._props,
+ Document: this.layoutDoc ?? this._props.Document,
+ TemplateDataDocument: templateDataDoc instanceof Promise ? undefined : templateDataDoc,
+ onClick: onClick as any as React.MouseEventHandler, // pass onClick script as if it were a real function -- it will be interpreted properly in the HTMLtag
+ onInput: onInput as any as React.FormEventHandler,
+ };
+ return {
+ props: {
+ ...OmitKeys(list, [...docOnlyProps], '').omit,
+ },
};
- return { props: list };
}
// componentWillUpdate(oldProps: any, newState: any) {
- // // console.log("willupdate", oldProps, this.props); // bcz: if you get a message saying something invalidated because reactive props changed, then this method allows you to figure out which prop changed
+ // // console.log("willupdate", oldProps, this._props); // bcz: if you get a message saying something invalidated because reactive props changed, then this method allows you to figure out which prop changed
// }
@computed get renderData() {
@@ -189,13 +187,13 @@ export class DocumentContentsView extends React.Component<
// replace code content with a script >{content}< as in <HTMLdiv>{this.title}</HTMLdiv>
const replacer = (match: any, prefix: string, expr: string, postfix: string, offset: any, string: any) => {
- return prefix + ((ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this.props.Document }).result as string) || '') + postfix;
+ return prefix + ((ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix;
};
layoutFrame = layoutFrame.replace(/(>[^{]*)[^=]\{([^.'][^<}]+)\}([^}]*<)/g, replacer);
// replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'>
const replacer2 = (match: any, p1: string, offset: any, string: any) => {
- return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} scaling='${this.props.NativeDimScaling?.() || 1}' htmltag='${p1}'`;
+ return `<HTMLtag Document={props.Document} scaling='${this._props.NativeDimScaling?.() || 1}' htmltag='${p1}'`;
};
layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2);
@@ -227,7 +225,7 @@ export class DocumentContentsView extends React.Component<
TraceMobx();
const { bindings, layoutFrame } = this.renderData;
- return this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || GetEffectiveAcl(this.layoutDoc) === AclPrivate ? null : (
+ return this._props.renderDepth > 12 || !layoutFrame || !this.layoutDoc || GetEffectiveAcl(this.layoutDoc) === AclPrivate ? null : (
<ObserverJsxParser
key={42}
blacklistedAttrs={emptyPath}
@@ -235,7 +233,6 @@ export class DocumentContentsView extends React.Component<
components={{
FormattedTextBox,
ImageBox,
- DirectoryImportBox,
FontIconBox,
LabelBox,
EquationBox,
@@ -243,6 +240,7 @@ export class DocumentContentsView extends React.Component<
CollectionFreeFormView,
CollectionDockingView,
CollectionSchemaView,
+ CollectionCalendarView,
CollectionView,
WebBox,
KeyValueBox,
@@ -255,7 +253,6 @@ export class DocumentContentsView extends React.Component<
PresElementBox,
SearchBox,
FunctionPlotBox,
- ColorBox,
DashWebRTCVideo,
LinkAnchorBox,
InkingStroke,