diff options
author | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-04-24 00:43:56 +0530 |
---|---|---|
committer | usodhi <61431818+usodhi@users.noreply.github.com> | 2020-04-24 00:43:56 +0530 |
commit | 847f01833d3a078f76432e2e9d903e5804093b0a (patch) | |
tree | b5d1a9227c1a90ea8e62567a3aa2ec87ed933c73 /src/client/views/nodes/DocumentContentsView.tsx | |
parent | 36eefd94f5f5d3bc08f1f1dea31d0b752a2070c3 (diff) | |
parent | 8a8f2c8848fe76e26188666790accaf236267e78 (diff) |
Merge branch 'master' of https://github.com/browngraphicslab/Dash-Web into grid_view_secondary
Diffstat (limited to 'src/client/views/nodes/DocumentContentsView.tsx')
-rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index 7522af3a3..a022f2e02 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -1,8 +1,8 @@ import { computed } from "mobx"; import { observer } from "mobx-react"; -import { Doc, Opt } from "../../../new_fields/Doc"; -import { Cast, StrCast } from "../../../new_fields/Types"; -import { OmitKeys, Without } from "../../../Utils"; +import { Doc, Opt, Field } from "../../../new_fields/Doc"; +import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; +import { OmitKeys, Without, emptyPath } from "../../../Utils"; import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox"; import { CollectionDockingView } from "../collections/CollectionDockingView"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; @@ -35,8 +35,10 @@ import { WebBox } from "./WebBox"; import { InkingStroke } from "../InkingStroke"; import React = require("react"); import { RecommendationsBox } from "../RecommendationsBox"; - import { TraceMobx } from "../../../new_fields/util"; +import { ScriptField } from "../../../new_fields/ScriptField"; +import XRegExp = require("xregexp"); + const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? type BindingProps = Without<FieldViewProps, 'fieldKey'>; @@ -53,6 +55,43 @@ class ObserverJsxParser1 extends JsxParser { const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any; + +interface HTMLtagProps { + Document: Doc; + htmltag: string; + onClick?: ScriptField; +} +//"<HTMLdiv borderRadius='100px' onClick={this.bannerColor=this.bannerColor==='red'?'green':'red'} width='100%' height='100%' transform='rotate({2*this.x+this.y}deg)'><ImageBox {...props} fieldKey={'data'}/><HTMLspan width='100%' marginTop='50%' height='10%' position='absolute' backgroundColor='{this.bannerColor===`green`?`dark`:`light`}grey'>{this.title}</HTMLspan></HTMLdiv>"@observer +@observer +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 }); + } + render() { + const style: { [key: string]: any } = {}; + const divKeys = OmitKeys(this.props, ["children", "htmltag", "Document", "key", "onClick", "__proto__"]).omit; + Object.keys(divKeys).map((prop: string) => { + let p = (this.props as any)[prop] as string; + const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: extend this to support expression -- is this really a script? + return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ this: this.props.Document }).result as string || ""; + }; + p = p?.replace(/{([^.'][^}']+)}/g, replacer); + + const replacer2 = (match: any, key: string, offset: any, string: any) => { // bcz: extend this to support expression -- is this really a script? + const n = Cast(this.props.Document[key], "number", null); + return n ? n.toString() : StrCast(this.props.Document[key], p); + }; + style[prop] = p?.replace(/@([a-zA-Z0-9-_]+)/g, replacer2); + + }); + const Tag = this.props.htmltag as keyof JSX.IntrinsicElements; + return <Tag style={style} onClick={this.click}> + {this.props.children} + </Tag>; + } +} + @observer export class DocumentContentsView extends React.Component<DocumentViewProps & { isSelected: (outsideReaction: boolean) => boolean, @@ -91,32 +130,67 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & { return Doc.expandTemplateLayout(template, this.props.Document, params ? "(" + params + ")" : this.props.layoutKey); } - CreateBindings(): JsxBindings { + CreateBindings(onClick: Opt<ScriptField>): JsxBindings { const list = { ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, Document: this.layoutDoc, DataDoc: this.dataDoc, + onClick: onClick }; return { props: list }; } render() { TraceMobx(); - return (this.props.renderDepth > 12 || !this.layout || !this.layoutDoc) ? (null) : + let layoutFrame = this.layout; + + // 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; + }; + 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 Document={props.Document} htmltag='${p1}'`; + }; + layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2); + + // replace /HTML<tag> with </HTMLdiv> as in: </HTMLdiv> becomes </HTMLtag> + const replacer3 = (match: any, p1: string, offset: any, string: any) => { + return `</HTMLtag`; + }; + layoutFrame = layoutFrame.replace(/<\/HTML([a-zA-Z0-9_-]+)/g, replacer3); + + // add onClick function to props + const splits = layoutFrame.split("onClick="); + let onClick: Opt<ScriptField>; + if (splits.length > 1) { + const code = XRegExp.matchRecursive(splits[1], "{", "}", "", { valueNames: ["between", "left", "match", "right", "between"] }); + layoutFrame = splits[0] + " onClick={props.onClick} " + splits[1].substring(code[1].end + 1); + onClick = ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name }); + } + + const bindings = this.CreateBindings(onClick); + // layoutFrame = splits.length > 1 ? splits[0] + splits[1].replace(/{([^{}]|(?R))*}/, replacer4) : ""; // might have been more elegant if javascript supported recursive patterns + + return (this.props.renderDepth > 12 || !layoutFrame || !this.layoutDoc) ? (null) : this.props.forceLayout === "FormattedTextBox" && this.props.forceFieldKey ? - <FormattedTextBox {...this.CreateBindings().props} fieldKey={this.props.forceFieldKey} /> + <FormattedTextBox {...bindings.props} fieldKey={this.props.forceFieldKey} /> : <ObserverJsxParser + key={42} blacklistedAttrs={[]} + renderInWrapper={false} components={{ FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, SliderBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, QueryBox, ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox, - RecommendationsBox, ScreenshotBox + RecommendationsBox, ScreenshotBox, HTMLtag }} - bindings={this.CreateBindings()} - jsx={this.layout} + bindings={bindings} + jsx={layoutFrame} showWarnings={true} onError={(test: any) => { console.log(test); }} |