1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
import { computed, trace } from "mobx";
import { observer } from "mobx-react";
import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
import { CollectionPDFView } from "../collections/CollectionPDFView";
import { CollectionSchemaView } from "../collections/CollectionSchemaView";
import { CollectionVideoView } from "../collections/CollectionVideoView";
import { CollectionView } from "../collections/CollectionView";
import { AudioBox } from "./AudioBox";
import { DocumentViewProps } from "./DocumentView";
import "./DocumentView.scss";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
import { IconBox } from "./IconBox";
import { KeyValueBox } from "./KeyValueBox";
import { PDFBox } from "./PDFBox";
import { VideoBox } from "./VideoBox";
import { FieldView } from "./FieldView";
import { WebBox } from "./WebBox";
import { HistogramBox } from "../../northstar/dash-nodes/HistogramBox";
import React = require("react");
import { FieldViewProps } from "./FieldView";
import { Without, OmitKeys } from "../../../Utils";
import { Cast, StrCast, NumCast } from "../../../new_fields/Types";
import { List } from "../../../new_fields/List";
import { Doc } from "../../../new_fields/Doc";
import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox";
import { CollectionViewType } from "../collections/CollectionBaseView";
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
type BindingProps = Without<FieldViewProps, 'fieldKey'>;
export interface JsxBindings {
props: BindingProps;
}
class ObserverJsxParser1 extends JsxParser {
constructor(props: any) {
super(props);
observer(this as any);
}
}
const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
@observer
export class DocumentContentsView extends React.Component<DocumentViewProps & {
isSelected: () => boolean,
select: (ctrl: boolean) => void,
layoutKey: string,
hideOnLeave?: boolean
}> {
@computed get layout(): string {
const layout = Cast(this.layoutDoc[this.props.layoutKey], "string");
if (layout === undefined) {
return this.props.Document.data ?
"<FieldView {...props} fieldKey='data' />" :
KeyValueBox.LayoutString(this.layoutDoc.proto ? "proto" : "");
} else if (typeof layout === "string") {
return layout;
} else {
return "<p>Loading layout</p>";
}
}
get dataDoc() {
if (this.props.DataDoc === undefined && this.props.Document.layout instanceof Doc) {
// if there is no dataDoc (ie, we're not rendering a temlplate layout), but this document
// has a template layout document, then we will render the template layout but use
// this document as the data document for the layout.
return this.props.Document;
}
return this.props.DataDoc;
}
get layoutDoc() {
// if this document's layout field contains a document (ie, a rendering template), then we will use that
// to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string.
return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
}
CreateBindings(): JsxBindings {
return { props: { ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit, Document: this.layoutDoc, DataDoc: this.dataDoc } };
}
@computed get templates(): List<string> {
let field = this.props.Document.templates;
if (field && field instanceof List) {
return field;
}
return new List<string>();
}
@computed get finalLayout() {
const baseLayout = this.props.layoutKey === "overlayLayout" ? "<div/>" : this.layout;
let base = baseLayout;
let layout = baseLayout;
// bcz: templates are intended only for a document's primary layout or overlay (not background). However,
// a DocumentContentsView is used to render annotation overlays, so we detect that here
// by checking the layoutKey. This should probably be moved into
// a prop so that the overlay can explicitly turn off templates.
if ((this.props.layoutKey === "overlayLayout" && StrCast(this.props.Document.layout).indexOf("CollectionView") !== -1) ||
(this.props.layoutKey === "layout" && StrCast(this.props.Document.layout).indexOf("CollectionView") === -1) ||
(this.props.layoutKey === "layout" && NumCast(this.props.Document.viewType)) !== CollectionViewType.Freeform) {
this.templates.forEach(template => {
let self = this;
// this scales constants in the markup by the scaling applied to the document, but caps the constants to be smaller
// than the width/height of the containing document
function convertConstantsToNative(match: string, offset: number, x: string) {
let px = Number(match.replace("px", ""));
return `${Math.min(NumCast(self.props.Document.height, 0),
Math.min(NumCast(self.props.Document.width, 0),
px * self.props.ScreenToLocalTransform().Scale))}px`;
}
// let nativizedTemplate = template.replace(/([0-9]+)px/g, convertConstantsToNative);
// layout = nativizedTemplate.replace("{layout}", base);
layout = template.replace("{layout}", base);
base = layout;
});
}
return layout;
}
render() {
let self = this;
if (this.props.renderDepth > 7) return (null);
if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
return <ObserverJsxParser
components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }}
bindings={this.CreateBindings()}
jsx={this.finalLayout}
showWarnings={true}
onError={(test: any) => { console.log(test); }}
/>;
}
}
|