aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
authorandrewdkim <adkim414@gmail.com>2019-09-21 14:24:05 -0400
committerandrewdkim <adkim414@gmail.com>2019-09-21 14:24:05 -0400
commitc0dc4928c29e043ae897f4f7c58168831c3d8fd5 (patch)
tree214173886faf8a7bcd47fd384e3341c2f8158658 /src/client/views/nodes
parent53c4f6ddad5534101d7a7482332cddb02ba99c21 (diff)
parent1d5dc3eb4095cea017412de9519b8eaee979c16c (diff)
merge from master
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/ButtonBox.tsx6
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx37
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx9
-rw-r--r--src/client/views/nodes/DocumentView.tsx720
-rw-r--r--src/client/views/nodes/DragBox.tsx10
-rw-r--r--src/client/views/nodes/FieldView.tsx3
-rw-r--r--src/client/views/nodes/FormattedTextBox.tsx42
-rw-r--r--src/client/views/nodes/IconBox.tsx5
-rw-r--r--src/client/views/nodes/ImageBox.tsx45
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx4
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx8
-rw-r--r--src/client/views/nodes/PDFBox.tsx106
-rw-r--r--src/client/views/nodes/VideoBox.tsx22
13 files changed, 383 insertions, 634 deletions
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx
index 68d3b8ae1..f08ea4891 100644
--- a/src/client/views/nodes/ButtonBox.tsx
+++ b/src/client/views/nodes/ButtonBox.tsx
@@ -3,7 +3,7 @@ import { faEdit } from '@fortawesome/free-regular-svg-icons';
import { action, computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { Doc, DocListCastAsync } from '../../../new_fields/Doc';
+import { Doc, DocListCastAsync, DocListCast } from '../../../new_fields/Doc';
import { List } from '../../../new_fields/List';
import { createSchema, makeInterface, listSpec } from '../../../new_fields/Schema';
import { ScriptField } from '../../../new_fields/ScriptField';
@@ -49,7 +49,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
funcs.push({
description: "Clear Script Params", event: () => {
let params = Cast(this.props.Document.buttonParams, listSpec("string"));
- params && params.map(p => this.props.Document[p] = undefined)
+ params && params.map(p => this.props.Document[p] = undefined);
}, icon: "trash"
});
@@ -68,7 +68,7 @@ export class ButtonBox extends DocComponent<FieldViewProps, ButtonDocument>(Butt
render() {
let params = Cast(this.props.Document.buttonParams, listSpec("string"));
let missingParams = params && params.filter(p => this.props.Document[p] === undefined);
- params && params.map(async p => await DocListCastAsync(this.props.Document[p])); // bcz: really hacky form of prefetching ...
+ params && params.map(p => DocListCast(this.props.Document[p])); // bcz: really hacky form of prefetching ...
return (
<div className="buttonBox-outerDiv" ref={this.createDropTarget} onContextMenu={this.specificContextMenu}>
<div className="buttonBox-mainButton" style={{ background: StrCast(this.props.Document.backgroundColor), color: StrCast(this.props.Document.color, "black") }} >
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 19d4a6784..9685f9bca 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,10 +1,10 @@
-import { computed, action, observable, reaction, IReactionDisposer } from "mobx";
+import { computed, action, observable, reaction, IReactionDisposer, trace } from "mobx";
import { observer } from "mobx-react";
import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema";
import { FieldValue, NumCast, StrCast, Cast } from "../../../new_fields/Types";
import { Transform } from "../../util/Transform";
import { DocComponent } from "../DocComponent";
-import { percent2frac } from "../../../Utils"
+import { percent2frac } from "../../../Utils";
import { DocumentView, DocumentViewProps, documentSchema } from "./DocumentView";
import "./CollectionFreeFormDocumentView.scss";
import React = require("react");
@@ -17,8 +17,9 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
width?: number;
height?: number;
jitterRotation: number;
+ transition?: string;
}
-const positionSchema = createSchema({
+export const positionSchema = createSchema({
zIndex: "number",
x: "number",
y: "number",
@@ -32,8 +33,8 @@ export const PositionDocument = makeInterface(documentSchema, positionSchema);
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, PositionDocument>(PositionDocument) {
_disposer: IReactionDisposer | undefined = undefined;
@computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg)`; }
- @computed get X() { return this._animx !== undefined ? this._animx : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
- @computed get Y() { return this._animy !== undefined ? this._animy : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
+ @computed get X() { return this._animPos !== undefined ? this._animPos[0] : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
+ @computed get Y() { return this._animPos !== undefined ? this._animPos[1] : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
@computed get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.Document[WidthSym](); }
@computed get height() { return this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.Document[HeightSym](); }
@computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); }
@@ -59,22 +60,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
this._disposer && this._disposer();
}
componentDidMount() {
- this._disposer = reaction(() => this.props.Document.iconTarget,
+ this._disposer = reaction(() => [this.props.Document.animateToPos, this.props.Document.isAnimating],
() => {
- const icon = this.props.Document.iconTarget ? Array.from(Cast(this.props.Document.iconTarget, listSpec("number"))!) : undefined;
- if (icon) {
- let target = this.props.ScreenToLocalTransform().transformPoint(icon[0], icon[1]);
- if (icon[2] === 1) {
- this._animx = target[0];
- this._animy = target[1];
- }
- setTimeout(action(() => {
- this._animx = icon[2] === 1 ? this.Document.x : target[0];
- this._animy = icon[2] === 1 ? this.Document.y : target[1];
- }), 25);
- } else {
- this._animx = this._animy = undefined;
- }
+ const target = this.props.Document.animateToPos ? Array.from(Cast(this.props.Document.animateToPos, listSpec("number"))!) : undefined;
+ this._animPos = !target ? undefined : target[2] ? [this.Document.x || 0, this.Document.y || 0] : this.props.ScreenToLocalTransform().transformPoint(target[0], target[1]);
}, { fireImmediately: true });
}
@@ -83,7 +72,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
panelHeight = () => this.props.PanelHeight();
getTransform = (): Transform => this.props.ScreenToLocalTransform()
.translate(-this.X, -this.Y)
- .scale(1 / this.contentScaling()).scale(1 / this.scaleToOverridingWidth);
+ .scale(1 / this.contentScaling()).scale(1 / this.scaleToOverridingWidth)
borderRounding = () => {
let ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined;
@@ -107,11 +96,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document;
}
- @observable _animx: number | undefined = undefined;
- @observable _animy: number | undefined = undefined;
+ @observable _animPos: number[] | undefined = undefined;
render() {
- const hasPosition = this.props.x !== undefined || this.props.y !== undefined;
return (
<div className="collectionFreeFormDocumentView-container"
style={{
@@ -123,7 +110,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
StrCast(this.layoutDoc.boxShadow, ""),
borderRadius: this.borderRounding(),
transform: this.transform,
- transition: this.props.Document.isIconAnimating ? "transform .5s" : hasPosition ? "transform 1s" : StrCast(this.layoutDoc.transition),
+ transition: this.Document.isAnimating !== undefined ? ".5s ease-in" : this.props.transition ? this.props.transition : StrCast(this.layoutDoc.transition),
width: this.width,
height: this.height,
zIndex: this.Document.zIndex || 0,
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index d0e117fe4..3c3cc0d91 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -93,13 +93,6 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
return { props: list };
}
- @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() {
return this.props.layoutKey === "overlayLayout" ? "<div/>" : this.layout;
}
@@ -107,7 +100,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
render() {
let self = this;
if (this.props.renderDepth > 7) return (null);
- if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null);
+ if (!this.layout && this.props.layoutKey !== "overlayLayout") return (null);
return <ObserverJsxParser
blacklistedAttrs={[]}
components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox }}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 65a8a4234..014067d06 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,9 +1,9 @@
import { library } from '@fortawesome/fontawesome-svg-core';
import * as fa from '@fortawesome/free-solid-svg-icons';
-import { action, computed, IReactionDisposer, reaction, runInAction } from "mobx";
+import { action, computed, runInAction } from "mobx";
import { observer } from "mobx-react";
import * as rp from "request-promise";
-import { Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc";
+import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../new_fields/Doc";
import { Copy, Id } from '../../../new_fields/FieldSymbols';
import { List } from "../../../new_fields/List";
import { ObjectField } from "../../../new_fields/ObjectField";
@@ -40,7 +40,7 @@ import { DocumentContentsView } from "./DocumentContentsView";
import "./DocumentView.scss";
import { FormattedTextBox } from './FormattedTextBox';
import React = require("react");
-import { CompileScript, Scripting } from '../../util/Scripting';
+import { Scripting } from '../../util/Scripting';
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
library.add(fa.faTrash);
@@ -65,19 +65,9 @@ library.add(fa.faUnlock);
library.add(fa.faLock);
library.add(fa.faLaptopCode, fa.faMale, fa.faCopy, fa.faHandPointRight, fa.faCompass, fa.faSnowflake, fa.faMicrophone);
-// const linkSchema = createSchema({
-// title: "string",
-// linkDescription: "string",
-// linkTags: "string",
-// linkedTo: Doc,
-// linkedFrom: Doc
-// });
-
-// type LinkDoc = makeInterface<[typeof linkSchema]>;
-// const LinkDoc = makeInterface(linkSchema);
-
export interface DocumentViewProps {
ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+ ContainingCollectionDoc: Opt<Doc>;
Document: Doc;
DataDoc?: Doc;
fitToBox?: boolean;
@@ -92,13 +82,12 @@ export interface DocumentViewProps {
ruleProvider: Doc | undefined;
PanelWidth: () => number;
PanelHeight: () => number;
- focus: (doc: Doc, willZoom: boolean, scale?: number) => void;
+ focus: (doc: Doc, willZoom: boolean, scale?: number, afterFocus?: () => boolean) => void;
parentActive: () => boolean;
whenActiveChanged: (isActive: boolean) => void;
bringToFront: (doc: Doc, sendToBack?: boolean) => void;
- addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void;
+ addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => boolean;
pinToPres: (document: Doc) => void;
- collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
zoomToScale: (scale: number) => void;
backgroundColor: (doc: Doc) => string | undefined;
getScale: () => number;
@@ -108,33 +97,35 @@ export interface DocumentViewProps {
export const documentSchema = createSchema({
layout: "string", // should also allow Doc but that can't be expressed in the schema
- title: "string",
- nativeWidth: "number",
- nativeHeight: "number",
- backgroundColor: "string",
- opacity: "number",
hidden: "boolean",
- onClick: ScriptField,
- ignoreAspect: "boolean",
- autoHeight: "boolean",
- isTemplate: "boolean",
- isButton: "boolean",
- isBackground: "boolean",
- ignoreClick: "boolean",
- type: "string",
- maximizeLocation: "string",
- lockedPosition: "boolean",
excludeFromLibrary: "boolean",
- width: "number",
- height: "number",
- borderRounding: "string",
fitToBox: "boolean",
- searchFields: "string",
- heading: "number",
- showCaption: "string",
- showTitle: "string"
+ // layout: "string", // this should be a "string" or Doc, but can't do that in schemas, so best to leave it out
+ title: "string", // document title (can be on either data document or layout)
+ nativeWidth: "number", // native width of document which determines how much document contents are scaled when the document's width is set
+ nativeHeight: "number", // "
+ width: "number", // width of document in its container's coordinate system
+ height: "number", // "
+ backgroundColor: "string", // background color of document
+ opacity: "number", // opacity of document
+ onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop)
+ ignoreAspect: "boolean", // whether aspect ratio should be ignored when laying out or manipulating the document
+ autoHeight: "boolean", // whether the height of the document should be computed automatically based on its contents
+ isTemplate: "boolean", // whether this document acts as a template layout for describing how other documents should be displayed
+ isBackground: "boolean", // whether document is a background element and ignores input events (can only selet with marquee)
+ type: "string", // enumerated type of document
+ maximizeLocation: "string", // flag for where to place content when following a click interaction (e.g., onRight, inPlace, inTab)
+ lockedPosition: "boolean", // whether the document can be spatially manipulated
+ borderRounding: "string", // border radius rounding of document
+ searchFields: "string", // the search fields to display when this document matches a search in its metadata
+ heading: "number", // the logical layout 'heading' of this document (used by rule provider to stylize h1 header elements, from h2, etc)
+ showCaption: "string", // whether editable caption text is overlayed at the bottom of the document
+ showTitle: "string", // whether an editable title banner is displayed at tht top of the document
+ isButton: "boolean", // whether document functions as a button (overiding native interactions of its content)
+ ignoreClick: "boolean", // whether documents ignores input clicks (but does not ignore manipulation and other events)
});
+
type Document = makeInterface<[typeof documentSchema]>;
const Document = makeInterface(documentSchema);
@@ -149,52 +140,36 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
private _dropDisposer?: DragManager.DragDropDisposer;
public get ContentDiv() { return this._mainCont.current; }
- @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
- @computed get topMost(): boolean { return this.props.renderDepth === 0; }
+ @computed get active() { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
+ @computed get topMost() { return this.props.renderDepth === 0; }
+ @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
+ @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
+ @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; }
@action
componentDidMount() {
- if (this._mainCont.current) {
- this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, {
- handlers: { drop: this.drop.bind(this) }
- });
- }
+ this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }));
DocumentManager.Instance.DocumentViews.push(this);
}
@action
componentDidUpdate() {
this._dropDisposer && this._dropDisposer();
- if (this._mainCont.current) {
- this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, {
- handlers: { drop: this.drop.bind(this) }
- });
- }
+ this._mainCont.current && (this._dropDisposer = DragManager.MakeDropTarget(this._mainCont.current, { handlers: { drop: this.drop.bind(this) } }));
}
+
@action
componentWillUnmount() {
this._dropDisposer && this._dropDisposer();
DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
}
- get dataDoc() {
- // bcz: don't think we need this, but left it in in case strange behavior pops up. DocumentContentsView has this functionality
- // if (this.props.DataDoc === undefined && (this.props.Document.layout instanceof Doc || this.props.Document instanceof Promise)) {
- // // 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 !== this.props.Document ? this.props.DataDoc : undefined;
- }
startDragging(x: number, y: number, dropAction: dropActionType, applyAsTemplate?: boolean) {
if (this._mainCont.current) {
- const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
let dragData = new DragManager.DocumentDragData([this.props.Document]);
- const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
+ const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0);
+ dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
dragData.dropAction = dropAction;
- dragData.xOffset = xoff;
- dragData.yOffset = yoff;
dragData.moveDocument = this.props.moveDocument;
dragData.applyAsTemplate = applyAsTemplate;
DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, {
@@ -206,151 +181,78 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
}
- @action
- public collapseTargetsToPoint = (scrpt: number[], expandedDocs: Doc[] | undefined): void => {
- SelectionManager.DeselectAll();
- if (expandedDocs) {
- let isMinimized: boolean | undefined;
- expandedDocs.map(maximizedDoc => {
- if (isMinimized === undefined) {
- isMinimized = BoolCast(maximizedDoc.isMinimized);
- }
- let w = NumCast(maximizedDoc.width);
- let h = NumCast(maximizedDoc.height);
- let iconAnimating = maximizedDoc.isIconAnimating ? Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!) : undefined;
- if (isMinimized || (iconAnimating && iconAnimating.length && iconAnimating[0] === 0)) {
- // MAXIMIZE DOC
- if (maximizedDoc.isMinimized) {
- maximizedDoc.isIconAnimating = new List<number>([0, 0]);
- maximizedDoc.isMinimized = false;
- }
- maximizedDoc.iconTarget = new List<number>([...scrpt, 1]);
- setTimeout(() => {
- maximizedDoc.isIconAnimating = new List<number>([w, h]);
- setTimeout(() => {
- if (maximizedDoc.isIconAnimating && Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!)[0] !== 0) {
- maximizedDoc.isIconAnimating = undefined;
- }
- }, 750);
- }, 0);
- } else {
- maximizedDoc.iconTarget = new List<number>([...scrpt, 0]);
- // MINIMIZE DOC
- maximizedDoc.isIconAnimating = new List<number>([0, 0]);
- setTimeout(() => {
- if (maximizedDoc.isIconAnimating && Array.from(Cast(maximizedDoc.isIconAnimating, listSpec("number"))!)[0] === 0) {
- maximizedDoc.isMinimized = true;
- maximizedDoc.isIconAnimating = undefined;
- }
- }, 750);
- }
- });
- }
- }
-
onClick = async (e: React.MouseEvent) => {
- if (e.nativeEvent.cancelBubble) return; // || SelectionManager.IsSelected(this)) -- bcz: needed because EditableView may stopPropagation which won't apparently stop this event from firing.
- if (this.onClickHandler && this.onClickHandler.script) {
+ if (!e.nativeEvent.cancelBubble && !this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
+ (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
e.stopPropagation();
- this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document });
e.preventDefault();
- return;
+ if (this._doubleTap && this.props.renderDepth) {
+ let fullScreenAlias = Doc.MakeAlias(this.props.Document);
+ let layoutNative = await PromiseValue(Cast(this.props.Document.layoutNative, Doc));
+ if (layoutNative && fullScreenAlias.layout === layoutNative.layout) {
+ await swapViews(fullScreenAlias, "layoutCustom", "layoutNative");
+ }
+ this.props.addDocTab(fullScreenAlias, undefined, "inTab");
+ SelectionManager.DeselectAll();
+ Doc.UnBrushDoc(this.props.Document);
+ } else if (this.onClickHandler && this.onClickHandler.script) {
+ this.onClickHandler.script.run({ this: this.Document.isTemplate && this.props.DataDoc ? this.props.DataDoc : this.props.Document }, console.log);
+ } else if (this.Document.isButton) {
+ SelectionManager.SelectDoc(this, e.ctrlKey); // don't think this should happen if a button action is actually triggered.
+ this.buttonClick(e.altKey, e.ctrlKey);
+ } else SelectionManager.SelectDoc(this, e.ctrlKey);
}
- let altKey = e.altKey;
- let ctrlKey = e.ctrlKey;
- if (this._doubleTap && this.props.renderDepth) {
- e.stopPropagation();
- let fullScreenAlias = Doc.MakeAlias(this.props.Document);
- Doc.UseDetailLayout(fullScreenAlias);
- fullScreenAlias.showCaption = "caption";
- this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab");
+ }
+
+ buttonClick = async (altKey: boolean, ctrlKey: boolean) => {
+ let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
+ let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
+ let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
+ let expandedDocs: Doc[] = [];
+ expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
+ expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs;
+ // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
+ if (expandedDocs.length) {
SelectionManager.DeselectAll();
- Doc.UnBrushDoc(this.props.Document);
+ let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace");
+ maxLocation = this.Document.maximizeLocation = (!ctrlKey ? !altKey ? maxLocation : (maxLocation !== "inPlace" ? "inPlace" : "onRight") : (maxLocation !== "inPlace" ? "inPlace" : "inTab"));
+ if (maxLocation === "inPlace") {
+ expandedDocs.forEach(maxDoc => this.props.addDocument && this.props.addDocument(maxDoc, false));
+ let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2);
+ DocumentManager.Instance.animateBetweenPoint(scrpt, expandedDocs);
+ } else {
+ expandedDocs.forEach(maxDoc => (!this.props.addDocTab(maxDoc, undefined, "close") && this.props.addDocTab(maxDoc, undefined, maxLocation)));
+ }
}
- else if (!this.Document.ignoreClick && CurrentUserUtils.MainDocId !== this.props.Document[Id] &&
- (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD &&
- Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
- e.stopPropagation();
- SelectionManager.SelectDoc(this, e.ctrlKey);
- if (this.Document.isButton || this.Document.type === DocumentType.BUTTON) {
- let maximizedDocs = await DocListCastAsync(this.props.Document.maximizedDocs);
- let summarizedDocs = await DocListCastAsync(this.props.Document.summarizedDocs);
- let linkedDocs = LinkManager.Instance.getAllRelatedLinks(this.props.Document);
- let expandedDocs: Doc[] = [];
- expandedDocs = maximizedDocs ? [...maximizedDocs, ...expandedDocs] : expandedDocs;
- expandedDocs = summarizedDocs ? [...summarizedDocs, ...expandedDocs] : expandedDocs;
- // let expandedDocs = [ ...(maximizedDocs ? maximizedDocs : []), ...(summarizedDocs ? summarizedDocs : []),];
- if (expandedDocs.length) {
- SelectionManager.DeselectAll();
- let maxLocation = StrCast(this.Document.maximizeLocation, "inPlace");
- let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target);
- if (altKey || ctrlKey) {
- maxLocation = this.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"));
- if (!maxLocation || maxLocation === "inPlace") {
- let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
- let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !d.isMinimized, false);
- expandedDocs.forEach(maxDoc => Doc.GetProto(maxDoc).isMinimized = false);
- let hasView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedDocs[0], this.props.ContainingCollectionView);
- if (!hasView) {
- this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(getDispDoc(maxDoc), false));
- }
- expandedDocs.forEach(maxDoc => maxDoc.isMinimized = wasMinimized);
- }
- }
- if (maxLocation && maxLocation !== "inPlace" && CollectionDockingView.Instance) {
- let dataDocs = DocListCast(CollectionDockingView.Instance.props.Document.data);
- if (dataDocs) {
- expandedDocs.forEach(maxDoc =>
- (!CollectionDockingView.Instance.CloseRightSplit(Doc.GetProto(maxDoc)) &&
- this.props.addDocTab(getDispDoc(maxDoc), undefined, maxLocation)));
- }
- } else {
- let scrpt = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(NumCast(this.Document.width) / 2, NumCast(this.Document.height) / 2);
- this.collapseTargetsToPoint(scrpt, expandedDocs);
- }
- }
- else if (linkedDocs.length) {
- SelectionManager.DeselectAll();
- let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored);
- let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0);
- if (firstUnshown.length) first = [firstUnshown[0]];
- let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]];
-
- // @TODO: shouldn't always follow target context
- let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined];
-
- let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined];
-
- if (!linkedFwdDocs.some(l => l instanceof Promise)) {
- let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab");
- let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
- DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false,
- document => { // open up target if it's not already in view ...
- let cv = this.props.ContainingCollectionView; // bcz: ugh --- maybe need to have a props.unfocus() method so that we leave things in the state we found them??
- let px = cv && cv.props.Document.panX;
- let py = cv && cv.props.Document.panY;
- let s = cv && cv.props.Document.scale;
- this.props.focus(this.props.Document, true, 1); // by zooming into the button document first
- setTimeout(() => {
- this.props.addDocTab(document, undefined, maxLocation);
- cv && (cv.props.Document.panX = px);
- cv && (cv.props.Document.panY = py);
- cv && (cv.props.Document.scale = s);
- }, 1000); // then after the 1sec animation, open up the target in a new tab
- },
- linkedFwdPage[altKey ? 1 : 0], targetContext);
- }
- }
+ else if (linkedDocs.length) {
+ SelectionManager.DeselectAll();
+ let first = linkedDocs.filter(d => Doc.AreProtosEqual(d.anchor1 as Doc, this.props.Document) && !d.anchor1anchored);
+ let firstUnshown = first.filter(d => DocumentManager.Instance.getDocumentViews(d.anchor2 as Doc).length === 0);
+ if (firstUnshown.length) first = [firstUnshown[0]];
+ let linkedFwdDocs = first.length ? [first[0].anchor2 as Doc, first[0].anchor1 as Doc] : [expandedDocs[0], expandedDocs[0]];
+
+ // @TODO: shouldn't always follow target context
+ let linkedFwdContextDocs = [first.length ? await (first[0].targetContext) as Doc : undefined, undefined];
+ let linkedFwdPage = [first.length ? NumCast(first[0].anchor2Page, undefined) : undefined, undefined];
+
+ if (!linkedFwdDocs.some(l => l instanceof Promise)) {
+ let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab");
+ let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionDoc) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined;
+ DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false,
+ // open up target if it's not already in view ... by zooming into the button document first and setting flag to reset zoom afterwards
+ doc => this.props.focus(this.props.Document, true, 1, () => this.props.addDocTab(doc, undefined, maxLocation)),
+ linkedFwdPage[altKey ? 1 : 0], targetContext);
}
}
}
-
onPointerDown = (e: React.PointerEvent): void => {
if (e.nativeEvent.cancelBubble) return;
this._downX = e.clientX;
this._downY = e.clientY;
this._hitTemplateDrag = false;
+ // this whole section needs to move somewhere else. We're trying to initiate a special "template" drag where
+ // this document is the template and we apply it to whatever we drop it on.
for (let element = (e.target as any); element && !this._hitTemplateDrag; element = element.parentElement) {
if (element.className && element.className.toString() === "collectionViewBaseChrome-collapse") {
this._hitTemplateDrag = true;
@@ -367,7 +269,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
document.removeEventListener("pointermove", this.onPointerMove);
}
else if (!e.cancelBubble && this.active) {
- if (!this.Document.excludeFromLibrary && (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3)) {
+ if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
if (!e.altKey && !this.topMost && e.buttons === 1 && !BoolCast(this.Document.lockedPosition)) {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
@@ -389,66 +291,41 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); }
@undoBatch
- makeNativeViewClicked = (): void => {
- makeNativeView(this.props.Document);
- }
+ makeNativeViewClicked = (): void => { swapViews(this.props.Document, "layoutNative", "layoutCustom"); }
+
@undoBatch
- makeCustomViewClicked = (): void => {
- this.props.Document.nativeLayout = this.Document.layout;
- this.props.Document.nativeType = this.Document.type;
- this.props.Document.nonCustomAutoHeight = this.Document.autoHeight;
- this.props.Document.nonCustomWidth = this.Document.width;
- this.props.Document.nonCustomHeight = this.Document.height;
- this.props.Document.nonCustomNativeWidth = this.Document.nativeWidth;
- this.props.Document.nonCustomNativeHeight = this.Document.nativeHeight;
- this.props.Document.nonCustomIgnoreAspect = this.Document.ignoreAspect;
- PromiseValue(Cast(this.props.Document.customLayout, Doc)).then(custom => {
- if (custom) {
- this.Document.type = DocumentType.TEMPLATE;
- this.props.Document.layout = custom;
- !custom.nativeWidth && (this.Document.nativeWidth = 0);
- !custom.nativeHeight && (this.Document.nativeHeight = 0);
- !custom.nativeWidth && (this.Document.ignoreAspect = true);
- this.Document.autoHeight = BoolCast(this.Document.customAutoHeight);
- this.Document.width = NumCast(this.props.Document.customWidth);
- this.Document.height = NumCast(this.props.Document.customHeight);
- this.Document.nativeWidth = NumCast(this.props.Document.customNativeWidth);
- this.Document.nativeHeight = NumCast(this.props.Document.customNativeHeight);
- this.Document.ignoreAspect = BoolCast(this.Document.customIgnoreAspect);
- this.props.Document.customAutoHeight = undefined;
- this.props.Document.customWidth = undefined;
- this.props.Document.customHeight = undefined;
- this.props.Document.customNativeWidth = undefined;
- this.props.Document.customNativeHeight = undefined;
- this.props.Document.customIgnoreAspect = undefined;
- } else {
- let options = { title: "data", width: (this.Document.width || 0), x: -(this.Document.width || 0) / 2, y: - (this.Document.height || 0) / 2, };
- let fieldTemplate = this.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) :
- this.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) :
- Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
+ makeCustomViewClicked = async () => {
+ if (this.props.Document.layoutCustom === undefined) {
+ Doc.GetProto(this.props.DataDoc || this.props.Document).layoutNative = Doc.MakeTitled("layoutNative");
+ await swapViews(this.props.Document, "", "layoutNative");
- fieldTemplate.backgroundColor = this.Document.backgroundColor;
- fieldTemplate.heading = 1;
- fieldTemplate.autoHeight = true;
+ let options = { title: "data", width: (this.Document.width || 0), x: -(this.Document.width || 0) / 2, y: - (this.Document.height || 0) / 2, };
+ let fieldTemplate = this.Document.type === DocumentType.TEXT ? Docs.Create.TextDocument(options) :
+ this.Document.type === DocumentType.VID ? Docs.Create.VideoDocument("http://www.cs.brown.edu", options) :
+ Docs.Create.ImageDocument("http://www.cs.brown.edu", options);
- let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: this.Document.title + "layout", width: (this.Document.width || 0) + 20, height: Math.max(100, (this.Document.height || 0) + 45) });
- let proto = Doc.GetProto(docTemplate);
- Doc.MakeMetadataFieldTemplate(fieldTemplate, proto, true);
+ fieldTemplate.backgroundColor = this.Document.backgroundColor;
+ fieldTemplate.heading = 1;
+ fieldTemplate.autoHeight = true;
- Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined, false);
- Doc.GetProto(this.dataDoc || this.props.Document).customLayout = this.Document.layout;
- }
- });
+ let docTemplate = Docs.Create.FreeformDocument([fieldTemplate], { title: this.Document.title + "_layout", width: (this.Document.width || 0) + 20, height: Math.max(100, (this.Document.height || 0) + 45) });
+
+ Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate), true);
+ Doc.ApplyTemplateTo(docTemplate, this.props.Document, undefined);
+ Doc.GetProto(this.props.DataDoc || this.props.Document).layoutCustom = Doc.MakeTitled("layoutCustom");
+ } else {
+ swapViews(this.props.Document, "layoutCustom", "layoutNative");
+ }
}
@undoBatch
makeBtnClicked = (): void => {
- let doc = Doc.GetProto(this.props.Document);
- if (doc.isButton || doc.onClick) {
- doc.isButton = false;
- doc.onClick = undefined;
+ if (this.Document.isButton || this.Document.onClick || this.Document.ignoreClick) {
+ this.Document.isButton = false;
+ this.Document.ignoreClick = false;
+ this.Document.onClick = undefined;
} else {
- doc.isButton = true;
+ this.Document.isButton = true;
}
}
@@ -456,42 +333,28 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@action
drop = async (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.AnnotationDragData) {
+ /// this whole section for handling PDF annotations looks weird. Need to rethink this to make it cleaner
e.stopPropagation();
- let annotationDoc = de.data.annotationDocument;
- annotationDoc.linkedToDoc = true;
- de.data.targetContext = this.props.ContainingCollectionView!.props.Document;
+ let sourceDoc = de.data.annotationDocument;
let targetDoc = this.props.Document;
+ let annotations = await DocListCastAsync(sourceDoc.annotations);
+ sourceDoc.linkedToDoc = true;
+ de.data.targetContext = this.props.ContainingCollectionDoc;
targetDoc.targetContext = de.data.targetContext;
- let annotations = await DocListCastAsync(annotationDoc.annotations);
annotations && annotations.forEach(anno => anno.target = targetDoc);
- DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(annotationDoc.title)}`);
+ DocUtils.MakeLink(sourceDoc, targetDoc, this.props.ContainingCollectionDoc, `Link from ${StrCast(sourceDoc.title)}`);
}
if (de.data instanceof DragManager.DocumentDragData && de.data.applyAsTemplate) {
- Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document, this.props.DataDoc);
+ Doc.ApplyTemplateTo(de.data.draggedDocuments[0], this.props.Document);
e.stopPropagation();
}
if (de.data instanceof DragManager.LinkDragData) {
- let sourceDoc = de.data.linkSourceDocument;
- let destDoc = this.props.Document;
-
e.stopPropagation();
- if (de.mods === "AltKey") {
- const protoDest = destDoc.proto;
- const protoSrc = sourceDoc.proto;
- let src = protoSrc ? protoSrc : sourceDoc;
- let dst = protoDest ? protoDest : destDoc;
- dst.data = (src.data! as ObjectField)[Copy]();
- dst.nativeWidth = src.nativeWidth;
- dst.nativeHeight = src.nativeHeight;
- }
- else {
- // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
- // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
- let linkDoc = DocUtils.MakeLink(sourceDoc, destDoc, this.props.ContainingCollectionView ? this.props.ContainingCollectionView.props.Document : undefined);
- de.data.droppedDocuments.push(destDoc);
- de.data.linkDocument = linkDoc;
- }
+ // const docs = await SearchUtil.Search(`data_l:"${destDoc[Id]}"`, true);
+ // const views = docs.map(d => DocumentManager.Instance.getDocumentView(d)).filter(d => d).map(d => d as DocumentView);
+ de.data.linkSourceDocument !== this.props.Document &&
+ (de.data.linkDocument = DocUtils.MakeLink(de.data.linkSourceDocument, this.props.Document, this.props.ContainingCollectionDoc));
}
}
@@ -499,9 +362,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
onDrop = (e: React.DragEvent) => {
let text = e.dataTransfer.getData("text/plain");
if (!e.isDefaultPrevented() && text && text.startsWith("<div")) {
- let oldLayout = FieldValue(this.Document.layout) || "";
+ let oldLayout = StrCast(this.props.Document.layout);
let layout = text.replace("{layout}", oldLayout);
- this.Document.layout = layout;
+ this.props.Document.layout = layout;
e.stopPropagation();
e.preventDefault();
}
@@ -518,46 +381,42 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
proto.nativeHeight = this.props.PanelHeight();
}
}
+
@undoBatch
@action
- makeIntoPortal = (): void => {
- if (!DocListCast(this.props.Document.links).find(doc => {
- if (Cast(doc.anchor2, Doc) instanceof Doc && (Cast(doc.anchor2, Doc) as Doc)!.title === this.Document.title + ".portal") return true;
- return false;
- })) {
+ makeIntoPortal = async () => {
+ let anchors = await Promise.all(DocListCast(this.props.Document.links).map(async (d: Doc) => Cast(d.anchor2, Doc)));
+ if (!anchors.find(anchor2 => anchor2 && anchor2.title === this.Document.title + ".portal" ? true : false)) {
let portalID = (this.Document.title + ".portal").replace(/^-/, "").replace(/\([0-9]*\)$/, "");
DocServer.GetRefField(portalID).then(existingPortal => {
let portal = existingPortal instanceof Doc ? existingPortal : Docs.Create.FreeformDocument([], { width: (this.Document.width || 0) + 10, height: this.Document.height || 0, title: portalID });
DocUtils.MakeLink(this.props.Document, portal, undefined, portalID);
- Doc.GetProto(this.props.Document).isButton = true;
- })
+ this.Document.isButton = true;
+ });
}
}
+
@undoBatch
@action
- toggleCustomView = (): void => {
+ setCustomView = (custom: boolean): void => {
if (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.DataDoc) {
- Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.DataDoc)
- } else {
- if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) {
- this.makeCustomViewClicked();
- } else if (this.Document.nativeLayout) {
- this.makeNativeViewClicked();
- }
+ Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.ContainingCollectionView.props.DataDoc);
+ } else { // bcz: not robust -- for now documents with string layout are native documents, and those with Doc layouts are customized
+ custom ? this.makeCustomViewClicked() : this.makeNativeViewClicked();
}
}
@undoBatch
@action
makeBackground = (): void => {
- this.layoutDoc.isBackground = !this.layoutDoc.isBackground;
- this.layoutDoc.isBackground && this.props.bringToFront(this.layoutDoc, true);
+ this.Document.isBackground = !this.Document.isBackground;
+ this.Document.isBackground && this.props.bringToFront(this.Document, true);
}
@undoBatch
@action
toggleLockPosition = (): void => {
- this.layoutDoc.lockedPosition = BoolCast(this.layoutDoc.lockedPosition) ? undefined : true;
+ this.Document.lockedPosition = this.Document.lockedPosition ? undefined : true;
}
listen = async () => {
@@ -586,34 +445,23 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const cm = ContextMenu.Instance;
let subitems: ContextMenuProps[] = [];
subitems.push({ description: "Open Full Screen", event: () => CollectionDockingView.Instance && CollectionDockingView.Instance.OpenFullScreen(this), icon: "desktop" });
- subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.dataDoc, "inTab"), icon: "folder" });
- subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.dataDoc, "onRight"), icon: "caret-square-right" });
- subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "inTab"), icon: "folder" });
- subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.dataDoc, "onRight"), icon: "caret-square-right" });
+ subitems.push({ description: "Open Tab ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "inTab"), icon: "folder" });
+ subitems.push({ description: "Open Right ", event: () => this.props.addDocTab(this.props.Document, this.props.DataDoc, "onRight"), icon: "caret-square-right" });
+ subitems.push({ description: "Open Alias Tab ", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "inTab"), icon: "folder" });
+ subitems.push({ description: "Open Alias Right", event: () => this.props.addDocTab(Doc.MakeAlias(this.props.Document), this.props.DataDoc, "onRight"), icon: "caret-square-right" });
subitems.push({ description: "Open Fields ", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" });
cm.addItem({ description: "Open...", subitems: subitems, icon: "external-link-alt" });
let existingOnClick = ContextMenu.Instance.findByDescription("OnClick...");
let onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
- onClicks.push({
- description: "Toggle Detail", event: () => {
- let compiled = CompileScript("toggleDetail(this)", {
- params: { this: "Doc" },
- typecheck: false,
- editable: true,
- });
- if (compiled.compiled) {
- this.Document.onClick = new ScriptField(compiled);
- }
- }, icon: "window-restore"
- });
- onClicks.push({ description: this.layoutDoc.ignoreClick ? "Select" : "Do Nothing", event: () => this.layoutDoc.ignoreClick = !this.layoutDoc.ignoreClick, icon: this.layoutDoc.ignoreClick ? "unlock" : "lock" });
+ onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript("toggleDetail(this)"), icon: "window-restore" });
+ onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
onClicks.push({ description: this.Document.isButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.makeBtnClicked, icon: "concierge-bell" });
onClicks.push({ description: "Edit onClick Script", icon: "edit", event: (obj: any) => ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", obj.x, obj.y) });
onClicks.push({
description: "Edit onClick Foreach Doc Script", icon: "edit", event: (obj: any) => {
- this.props.Document.collectionContext = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document;
+ this.props.Document.collectionContext = this.props.ContainingCollectionDoc;
ScriptBox.EditButtonScript("Foreach Collection Doc (d) => ", this.props.Document, "onClick", obj.x, obj.y, "docList(this.collectionContext.data).map(d => {", "});\n");
}
});
@@ -623,20 +471,17 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
let layoutItems: ContextMenuProps[] = existing && "subitems" in existing ? existing.subitems : [];
layoutItems.push({ description: this.Document.isBackground ? "As Foreground" : "As Background", event: this.makeBackground, icon: this.Document.lockedPosition ? "unlock" : "lock" });
if (this.props.DataDoc) {
- layoutItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc!), icon: "concierge-bell" })
+ layoutItems.push({ description: "Make View of Metadata Field", event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc!), icon: "concierge-bell" });
}
- layoutItems.push({ description: `${this.layoutDoc.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.layoutDoc.chromeStatus = (this.layoutDoc.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
- layoutItems.push({ description: `${this.layoutDoc.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc.autoHeight = !this.layoutDoc.autoHeight, icon: "plus" });
+ layoutItems.push({ description: `${this.Document.chromeStatus !== "disabled" ? "Hide" : "Show"} Chrome`, event: () => this.Document.chromeStatus = (this.Document.chromeStatus !== "disabled" ? "disabled" : "enabled"), icon: "project-diagram" });
+ layoutItems.push({ description: `${this.Document.autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.Document.autoHeight = !this.Document.autoHeight, icon: "plus" });
layoutItems.push({ description: this.Document.ignoreAspect || !this.Document.nativeWidth || !this.Document.nativeHeight ? "Freeze" : "Unfreeze", event: this.freezeNativeDimensions, icon: "snowflake" });
- layoutItems.push({ description: this.layoutDoc.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.layoutDoc.lockedPosition) ? "unlock" : "lock" });
+ layoutItems.push({ description: this.Document.lockedPosition ? "Unlock Position" : "Lock Position", event: this.toggleLockPosition, icon: BoolCast(this.Document.lockedPosition) ? "unlock" : "lock" });
layoutItems.push({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
layoutItems.push({ description: "Zoom to Document", event: () => this.props.focus(this.props.Document, true), icon: "search" });
- if (this.props.Document.detailedLayout && !this.Document.isTemplate) {
- layoutItems.push({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" });
- }
if (this.Document.type !== DocumentType.COL && this.Document.type !== DocumentType.TEMPLATE) {
layoutItems.push({ description: "Use Custom Layout", event: this.makeCustomViewClicked, icon: "concierge-bell" });
- } else if (this.props.Document.nativeLayout) {
+ } else if (this.props.Document.layoutNative) {
layoutItems.push({ description: "Use Native Layout", event: this.makeNativeViewClicked, icon: "concierge-bell" });
}
!existing && cm.addItem({ description: "Layout...", subitems: layoutItems, icon: "compass" });
@@ -653,49 +498,46 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
cm.addItem({ description: "Pin to Presentation", event: () => this.props.pinToPres(this.props.Document), icon: "map-pin" }); //I think this should work... and it does! A miracle!
cm.addItem({ description: "Add Repl", icon: "laptop-code", event: () => OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: "Scripting REPL" }) });
cm.addItem({
- description: "Download document", icon: "download", event: async () => {
- let y = JSON.parse(await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), {
+ description: "Download document", icon: "download", event: async () =>
+ console.log(JSON.parse(await rp.get(Utils.CorsProxy("http://localhost:8983/solr/dash/select"), {
qs: { q: 'world', fq: 'NOT baseProto_b:true AND NOT deleted:true', start: '0', rows: '100', hl: true, 'hl.fl': '*' }
- }));
- console.log(y);
- // const a = document.createElement("a");
- // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
- // a.href = url;
- // a.download = `DocExport-${this.props.Document[Id]}.zip`;
- // a.click();
- }
+ })))
+ // const a = document.createElement("a");
+ // const url = Utils.prepend(`/downloadId/${this.props.Document[Id]}`);
+ // a.href = url;
+ // a.download = `DocExport-${this.props.Document[Id]}.zip`;
+ // a.click();
});
cm.addItem({ description: "Publish", event: () => DocUtils.Publish(this.props.Document, this.Document.title || "", this.props.addDocument, this.props.removeDocument), icon: "file" });
cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
- type User = { email: string, userDocumentId: string };
- let usersMenu: ContextMenuProps[] = [];
try {
- let stuff = await rp.get(Utils.prepend(RouteStore.getUsers));
- const users: User[] = JSON.parse(stuff);
- usersMenu = users.filter(({ email }) => email !== Doc.CurrentUserEmail).map(({ email, userDocumentId }) => ({
- description: email, event: async () => {
+ type User = { email: string, userDocumentId: string };
+ const users: User[] = JSON.parse(await rp.get(Utils.prepend(RouteStore.getUsers)));
+ let usersMenu = users.filter(({ email }) => email !== Doc.CurrentUserEmail).map(({ email, userDocumentId }) => ({
+ description: email,
+ event: async () => {
const userDocument = await Cast(DocServer.GetRefField(userDocumentId), Doc);
- if (!userDocument) {
- throw new Error(`Couldn't get user document of user ${email}`);
- }
- const notifDoc = await Cast(userDocument.optionalRightCollection, Doc);
- if (notifDoc instanceof Doc) {
- const data = await Cast(notifDoc.data, listSpec(Doc));
- const sharedDoc = Doc.MakeAlias(this.props.Document);
- if (data) {
- data.push(sharedDoc);
- } else {
- notifDoc.data = new List([sharedDoc]);
+ if (userDocument) {
+ const notifDoc = await Cast(userDocument.optionalRightCollection, Doc);
+ if (notifDoc) {
+ const data = await Cast(notifDoc.data, listSpec(Doc));
+ const sharedDoc = Doc.MakeAlias(this.props.Document);
+ if (data) {
+ data.push(sharedDoc);
+ } else {
+ notifDoc.data = new List([sharedDoc]);
+ }
}
}
- }, icon: "male"
- }));
+ },
+ icon: "male"
+ } as ContextMenuProps));
+ cm.addItem({ description: "Share...", subitems: usersMenu, icon: "share" });
} catch {
}
runInAction(() => {
- cm.addItem({ description: "Share...", subitems: usersMenu, icon: "share" });
if (!ClientUtils.RELEASE) {
let setWriteMode = (mode: DocServer.WriteMode) => {
DocServer.AclsMode = mode;
@@ -731,62 +573,46 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
});
}
- onPointerEnter = (e: React.PointerEvent): void => { Doc.BrushDoc(this.props.Document); };
- onPointerLeave = (e: React.PointerEvent): void => { Doc.UnBrushDoc(this.props.Document); };
- isSelected = () => SelectionManager.IsSelected(this);
- @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
- @computed get nativeWidth() { return this.Document.nativeWidth || 0; }
- @computed get nativeHeight() { return this.Document.nativeHeight || 0; }
- @computed get onClickHandler() { return this.props.onClick ? this.props.onClick : this.Document.onClick; }
- @computed get contents() {
- return (<DocumentContentsView {...this.props}
- ChromeHeight={this.chromeHeight}
- isSelected={this.isSelected}
- select={this.select}
- onClick={this.onClickHandler}
- layoutKey={"layout"}
- fitToBox={this.Document.fitToBox ? true : this.props.fitToBox}
- DataDoc={this.dataDoc} />);
+ // the document containing the view layout information - will be the Document itself unless the Document has
+ // a layout field. In that case, all layout information comes from there unless overriden by Document
+ get layoutDoc(): Document {
+ return Document(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document);
}
- chromeHeight = () => {
- let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined;
- let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.layoutDoc.showTitle);
- let templates = Cast(this.layoutDoc.templates, listSpec("string"));
- if (!showOverlays && templates instanceof List) {
- templates.map(str => {
- if (!showTitle && str.indexOf("{props.Document.title}") !== -1) showTitle = "title";
- });
- }
- return (showTitle ? 25 : 0) + 1;// bcz: why 8??
- }
+ // does Document set a layout prop
+ setsLayoutProp = (prop: string) => this.props.Document[prop] !== this.props.Document["default" + prop[0].toUpperCase() + prop.slice(1)];
+ // get the a layout prop by first choosing the prop from Document, then falling back to the layout doc otherwise.
+ getLayoutPropStr = (prop: string) => StrCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : this.layoutDoc[prop]);
+ getLayoutPropNum = (prop: string) => NumCast(this.setsLayoutProp(prop) ? this.props.Document[prop] : this.layoutDoc[prop]);
- get layoutDoc(): Document {
- // 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 Document(this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document);
+ isSelected = () => SelectionManager.IsSelected(this);
+ select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); };
+
+ chromeHeight = () => {
+ let showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined;
+ let showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : StrCast(this.Document.showTitle);
+ return (showTitle ? 25 : 0) + 1;
}
render() {
const ruleColor = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleColor_" + this.Document.heading]) : undefined;
const ruleRounding = this.props.ruleProvider ? StrCast(this.props.ruleProvider["ruleRounding_" + this.Document.heading]) : undefined;
- const colorSet = this.layoutDoc.backgroundColor !== this.layoutDoc.defaultBackgroundColor;
- const clusterCol = this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground;
- const backgroundColor = this.layoutDoc.isBackground || (clusterCol && !colorSet) ?
- this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) :
- ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc);
+ const colorSet = this.setsLayoutProp("backgroundColor");
+ const clusterCol = this.props.ContainingCollectionDoc && this.props.ContainingCollectionDoc.clusterOverridesDefaultBackground;
+ const backgroundColor = this.Document.isBackground || (clusterCol && !colorSet) ?
+ this.props.backgroundColor(this.Document) || StrCast(this.layoutDoc.backgroundColor) :
+ ruleColor && !colorSet ? ruleColor : StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.Document);
const nativeWidth = this.nativeWidth > 0 && !this.Document.ignoreAspect ? `${this.nativeWidth}px` : "100%";
const nativeHeight = this.Document.ignoreAspect ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%";
- const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.layoutDoc) : undefined;
- const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.layoutDoc.showTitle;
- const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.layoutDoc.showCaption;
- const showTextTitle = showTitle && StrCast(this.layoutDoc.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined;
+ const showOverlays = this.props.showOverlays ? this.props.showOverlays(this.Document) : undefined;
+ const showTitle = showOverlays && "title" in showOverlays ? showOverlays.title : this.getLayoutPropStr("showTitle");
+ const showCaption = showOverlays && "caption" in showOverlays ? showOverlays.caption : this.getLayoutPropStr("showCaption");
+ const showTextTitle = showTitle && StrCast(this.Document.layout).indexOf("FormattedTextBox") !== -1 ? showTitle : undefined;
const fullDegree = Doc.isBrushedHighlightedDegree(this.props.Document);
- const borderRounding = this.Document.borderRounding || ruleRounding;
+ const borderRounding = this.getLayoutPropStr("borderRounding") || ruleRounding;
const localScale = this.props.ScreenToLocalTransform().Scale * fullDegree;
- const iconAnimating = this.Document.isIconAnimating ? Array.from(Cast(this.Document.isIconAnimating, listSpec("number"))!) : undefined;
const searchHighlight = (!this.Document.searchFields ? (null) :
<div className="documentView-searchHighlight" style={{ width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
{this.Document.searchFields}
@@ -794,7 +620,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const captionView = (!showCaption ? (null) :
<div className="documentView-captionWrapper" style={{ width: `${100 * this.props.ContentScaling()}%`, transform: `scale(${1 / this.props.ContentScaling()})` }}>
<FormattedTextBox {...this.props}
- onClick={this.onClickHandler} DataDoc={this.dataDoc} active={returnTrue}
+ onClick={this.onClickHandler} DataDoc={this.props.DataDoc} active={returnTrue}
isSelected={this.isSelected} focus={emptyFunction} select={this.select}
fieldExt={""} hideOnLeave={true} fieldKey={showCaption}
/>
@@ -807,19 +633,26 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
transform: `scale(${1 / this.props.ContentScaling()})`
}}>
<EditableView
- contents={(this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle]}
+ contents={this.Document[showTitle]}
display={"block"} height={72} fontSize={12}
- GetValue={() => StrCast((this.layoutDoc.isTemplate || !this.dataDoc ? this.layoutDoc : this.dataDoc)[showTitle])}
- SetValue={(value: string) => ((this.layoutDoc.isTemplate ? this.layoutDoc : Doc.GetProto(this.layoutDoc))[showTitle] = value) ? true : true}
+ GetValue={() => StrCast(this.Document[showTitle])}
+ SetValue={(value: string) => (Doc.GetProto(this.Document)[showTitle] = value) ? true : true}
/>
</div>);
+ const contents = (<DocumentContentsView {...this.props}
+ ChromeHeight={this.chromeHeight}
+ isSelected={this.isSelected}
+ select={this.select}
+ onClick={this.onClickHandler}
+ layoutKey={"layout"}
+ DataDoc={this.props.DataDoc} />);
return (
<div className={`documentView-node${this.topMost ? "-topmost" : ""}`}
ref={this._mainCont}
style={{
- transition: iconAnimating ? "transform .5s" : StrCast(this.layoutDoc.transition),
- pointerEvents: this.layoutDoc.isBackground && !this.isSelected() ? "none" : "all",
- color: StrCast(this.layoutDoc.color),
+ transition: this.props.Document.isAnimating !== undefined ? ".5s linear" : StrCast(this.Document.transition),
+ pointerEvents: this.Document.isBackground && !this.isSelected() ? "none" : "all",
+ color: StrCast(this.Document.color),
outlineColor: ["transparent", "maroon", "maroon", "yellow"][fullDegree],
outlineStyle: ["none", "dashed", "solid", "solid"][fullDegree],
outlineWidth: fullDegree && !borderRounding ? `${localScale}px` : "0px",
@@ -831,20 +664,20 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
opacity: this.Document.opacity
}}
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
- onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave}
+ onPointerEnter={() => Doc.BrushDoc(this.props.Document)} onPointerLeave={() => Doc.UnBrushDoc(this.props.Document)}
>
{!showTitle && !showCaption ?
this.Document.searchFields ?
(<div className="documentView-searchWrapper">
- {this.contents}
+ {contents}
{searchHighlight}
</div>)
:
- this.contents
+ contents
:
<div className="documentView-styleWrapper" >
<div className="documentView-styleContentWrapper" style={{ height: showTextTitle ? "calc(100% - 29px)" : "100%", top: showTextTitle ? "29px" : undefined }}>
- {this.contents}
+ {contents}
</div>
{titleView}
{captionView}
@@ -856,66 +689,35 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
}
+export async function swapViews(doc: Doc, newLayoutField: string, oldLayoutField: string, oldLayout?: Doc) {
+ let oldLayoutExt = oldLayout || await Cast(doc[oldLayoutField], Doc);
+ if (oldLayoutExt) {
+ oldLayoutExt.autoHeight = doc.autoHeight;
+ oldLayoutExt.width = doc.width;
+ oldLayoutExt.height = doc.height;
+ oldLayoutExt.nativeWidth = doc.nativeWidth;
+ oldLayoutExt.nativeHeight = doc.nativeHeight;
+ oldLayoutExt.ignoreAspect = doc.ignoreAspect;
+ oldLayoutExt.backgroundLayout = doc.backgroundLayout;
+ oldLayoutExt.type = doc.type;
+ oldLayoutExt.layout = doc.layout;
+ }
-let makeNativeView = (doc: any): void => {
- doc.layout = doc.nativeLayout;
- doc.nativeLayout = undefined;
- doc.type = doc.nativeType;
-
- doc.customAutoHeight = doc.autoHeight;
- doc.customWidth = doc.width;
- doc.customHeight = doc.height;
- doc.customNativeWidth = doc.nativeWidth;
- doc.customNativeHeight = doc.nativeHeight;
- doc.customIgnoreAspect = doc.ignoreAspect;
-
- doc.autoHeight = doc.nonCustomAutoHeight;
- doc.width = doc.nonCustomWidth;
- doc.height = doc.nonCustomHeight;
- doc.nativeWidth = doc.nonCustomNativeWidth;
- doc.nativeHeight = doc.nonCustomNativeHeight;
- doc.ignoreAspect = doc.nonCustomIgnoreAspect;
- doc.nonCustomAutoHeight = undefined;
- doc.nonCustomWidth = undefined;
- doc.nonCustomHeight = undefined;
- doc.nonCustomNativeWidth = undefined;
- doc.nonCustomNativeHeight = undefined;
- doc.nonCustomIgnoreAspect = undefined;
-}
-let makeCustomView = (doc: any): void => {
- doc.nativeLayout = doc.layout;
- doc.nativeType = doc.type;
- doc.nonCustomAutoHeight = doc.autoHeight;
- doc.nonCustomWidth = doc.nativeWidth;
- doc.nonCustomHeight = doc.nativeHeight;
- doc.nonCustomNativeWidth = doc.nativeWidth;
- doc.nonCustomNativeHeight = doc.nativeHeight;
- doc.nonCustomIgnoreAspect = doc.ignoreAspect;
- let custom = doc.customLayout as Doc;
- if (custom instanceof Doc) {
- doc.type = DocumentType.TEMPLATE;
- doc.layout = custom;
- !custom.nativeWidth && (doc.nativeWidth = 0);
- !custom.nativeHeight && (doc.nativeHeight = 0);
- !custom.nativeWidth && (doc.ignoreAspect = true);
- doc.autoHeight = doc.autoHeight;
- doc.width = doc.customWidth;
- doc.height = doc.customHeight;
- doc.nativeWidth = doc.customNativeWidth;
- doc.nativeHeight = doc.customNativeHeight;
- doc.ignoreAspect = doc.ignoreAspect;
- doc.customAutoHeight = undefined;
- doc.customWidth = undefined;
- doc.customHeight = undefined;
- doc.customNativeWidth = undefined;
- doc.customNativeHeight = undefined;
- doc.customIgnoreAspect = undefined;
+ let newLayoutExt = newLayoutField && await Cast(doc[newLayoutField], Doc);
+ if (newLayoutExt) {
+ doc.autoHeight = newLayoutExt.autoHeight;
+ doc.width = newLayoutExt.width;
+ doc.height = newLayoutExt.height;
+ doc.nativeWidth = newLayoutExt.nativeWidth;
+ doc.nativeHeight = newLayoutExt.nativeHeight;
+ doc.ignoreAspect = newLayoutExt.ignoreAspect;
+ doc.backgroundLayout = newLayoutExt.backgroundLayout;
+ doc.type = newLayoutExt.type;
+ doc.layout = await newLayoutExt.layout;
}
}
+
Scripting.addGlobal(function toggleDetail(doc: any) {
- if (doc.type !== DocumentType.COL && doc.type !== DocumentType.TEMPLATE) {
- makeCustomView(doc);
- } else if (doc.nativeLayout) {
- makeNativeView(doc);
- }
+ let native = typeof doc.layout === "string";
+ swapViews(doc, native ? "layoutCustom" : "layoutNative", native ? "layoutNative" : "layoutCustom");
}); \ No newline at end of file
diff --git a/src/client/views/nodes/DragBox.tsx b/src/client/views/nodes/DragBox.tsx
index 067d47de4..6c3db18c4 100644
--- a/src/client/views/nodes/DragBox.tsx
+++ b/src/client/views/nodes/DragBox.tsx
@@ -45,17 +45,15 @@ export class DragBox extends DocComponent<FieldViewProps, DragDocument>(DragDocu
}
onDragMove = (e: MouseEvent) => {
- if (!e.cancelBubble && !this.props.Document.excludeFromLibrary && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) {
+ if (!e.cancelBubble && (Math.abs(this._downX - e.clientX) > 5 || Math.abs(this._downY - e.clientY) > 5)) {
document.removeEventListener("pointermove", this.onDragMove);
document.removeEventListener("pointerup", this.onDragUp);
const onDragStart = this.Document.onDragStart;
e.stopPropagation();
e.preventDefault();
- let res = onDragStart ? onDragStart.script.run({ this: this.props.Document }) : undefined;
- let doc = res !== undefined && res.success ?
- res.result as Doc :
- Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" });
- doc && DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY);
+ let res = onDragStart && onDragStart.script.run({ this: this.props.Document }).result;
+ let doc = (res as Doc) || Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" });
+ DragManager.StartDocumentDrag([this._mainCont.current!], new DragManager.DocumentDragData([doc]), e.clientX, e.clientY);
}
e.stopPropagation();
e.preventDefault();
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 943d181d6..49fc2263d 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -30,6 +30,7 @@ export interface FieldViewProps {
leaveNativeSize?: boolean;
fitToBox?: boolean;
ContainingCollectionView: Opt<CollectionView | CollectionPDFView | CollectionVideoView>;
+ ContainingCollectionDoc: Opt<Doc>;
ruleProvider: Doc | undefined;
Document: Doc;
DataDoc?: Doc;
@@ -38,7 +39,7 @@ export interface FieldViewProps {
select: (isCtrlPressed: boolean) => void;
renderDepth: number;
addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean;
- addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => void;
+ addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
pinToPres: (document: Doc) => void;
removeDocument?: (document: Doc) => boolean;
moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean;
diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx
index 77e29632e..eb4718581 100644
--- a/src/client/views/nodes/FormattedTextBox.tsx
+++ b/src/client/views/nodes/FormattedTextBox.tsx
@@ -39,6 +39,7 @@ import { ReplaceStep } from 'prosemirror-transform';
import { DocumentType } from '../../documents/DocumentTypes';
import { formattedTextBoxCommentPlugin, FormattedTextBoxComment } from './FormattedTextBoxComment';
import { inputRules } from 'prosemirror-inputrules';
+import { DocumentButtonBar } from '../DocumentButtonBar';
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -141,10 +142,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
public get CurrentDiv(): HTMLDivElement { return this._ref.current!; }
- @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "dummy"); }
-
- @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+ @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); }
+ @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
// this should be internal to prosemirror, but is needed
// here to make sure that footnote view nodes in the overlay editor
@@ -182,9 +182,9 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
DocUtils.Publish(this.dataDoc[key] as Doc, value, this.props.addDocument, this.props.removeDocument);
if (linkDoc) { (linkDoc as Doc).anchor2 = this.dataDoc[key] as Doc; }
else DocUtils.MakeLink(this.dataDoc, this.dataDoc[key] as Doc, undefined, "Ref:" + value, undefined, undefined, id, true);
- })
+ });
});
- })
+ });
this.linkOnDeselect.clear();
}
@@ -195,7 +195,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
let range = tx.selection.$from.blockRange(tx.selection.$to);
let text = range ? tx.doc.textBetween(range.start, range.end) : "";
let textEndSelection = tx.selection.to;
- for (; textEndSelection < range!.end && text[textEndSelection - range!.start] != " "; textEndSelection++) { }
+ for (; textEndSelection < range!.end && text[textEndSelection - range!.start] !== " "; textEndSelection++) { }
text = text.substr(0, textEndSelection - range!.start);
text = text.split(" ")[text.split(" ").length - 1];
let split = text.split("::");
@@ -297,8 +297,13 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
e.stopPropagation();
} else if (de.data instanceof DragManager.DocumentDragData) {
const draggedDoc = de.data.draggedDocuments.length && de.data.draggedDocuments[0];
- if (draggedDoc && draggedDoc.type === DocumentType.TEXT) {
- if (!Doc.AreProtosEqual(draggedDoc, this.props.Document)) {
+ if (draggedDoc && draggedDoc.type === DocumentType.TEXT && !Doc.AreProtosEqual(draggedDoc, this.props.Document)) {
+ if (de.mods === "AltKey") {
+ if (draggedDoc.data instanceof RichTextField) {
+ Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(draggedDoc.data.Data);
+ e.stopPropagation();
+ }
+ } else {
draggedDoc.isTemplate = true;
if (typeof (draggedDoc.layout) === "string") {
let layoutDelegateToOverrideFieldKey = Doc.MakeDelegate(draggedDoc);
@@ -424,8 +429,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._pullReactionDisposer = reaction(
() => this.props.Document[Pulls],
() => {
- if (!DocumentDecorations.hasPulledHack) {
- DocumentDecorations.hasPulledHack = true;
+ if (!DocumentButtonBar.hasPulledHack) {
+ DocumentButtonBar.hasPulledHack = true;
let unchanged = this.dataDoc.unchanged;
this.pullFromGoogleDoc(unchanged ? this.checkState : this.updateState);
}
@@ -435,8 +440,8 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
this._pushReactionDisposer = reaction(
() => this.props.Document[Pushes],
() => {
- if (!DocumentDecorations.hasPushedHack) {
- DocumentDecorations.hasPushedHack = true;
+ if (!DocumentButtonBar.hasPushedHack) {
+ DocumentButtonBar.hasPushedHack = true;
this.pushToGoogleDoc();
}
}
@@ -529,7 +534,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
response && (this.dataDoc[GoogleRef] = response.documentId);
let pushSuccess = response !== undefined && !("errors" in response);
dataDoc.unchanged = pushSuccess;
- DocumentDecorations.Instance.startPushOutcome(pushSuccess);
+ DocumentButtonBar.Instance.startPushOutcome(pushSuccess);
}
};
let undo = () => {
@@ -574,7 +579,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
} else {
delete dataDoc[GoogleRef];
}
- DocumentDecorations.Instance.startPullOutcome(pullSuccess);
+ DocumentButtonBar.Instance.startPullOutcome(pullSuccess);
}
checkState = (exportState: GoogleApiClientUtils.ReadResult, dataDoc: Doc) => {
@@ -587,7 +592,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
let receivedTitle = exportState.title;
let unchanged = storedPlainText === receivedPlainText && storedTitle === receivedTitle;
dataDoc.unchanged = unchanged;
- DocumentDecorations.Instance.setPullState(unchanged);
+ DocumentButtonBar.Instance.setPullState(unchanged);
}
}
}
@@ -635,7 +640,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
let annotations = DocListCast(region.annotations);
annotations.forEach(anno => anno.target = this.props.Document);
- let fieldExtDoc = Doc.resolvedFieldDataDoc(doc, "data", "true");
+ let fieldExtDoc = Doc.fieldExtensionDoc(doc, "data");
let targetAnnotations = DocListCast(fieldExtDoc.annotations);
if (targetAnnotations) {
targetAnnotations.push(region);
@@ -909,7 +914,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
tryUpdateHeight() {
const ChromeHeight = this.props.ChromeHeight;
let sh = this._ref.current ? this._ref.current.scrollHeight : 0;
- if (!this.props.isOverlay && this.props.Document.autoHeight && sh !== 0) {
+ if (!this.props.isOverlay && !this.props.Document.isAnimating && this.props.Document.autoHeight && sh !== 0) {
let nh = this.props.Document.isTemplate ? 0 : NumCast(this.dataDoc.nativeHeight, 0);
let dh = NumCast(this.props.Document.height, 0);
this.props.Document.height = Math.max(10, (nh ? dh / nh * sh : sh) + (ChromeHeight ? ChromeHeight() : 0));
@@ -921,7 +926,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
let style = this.props.isOverlay ? "scroll" : "hidden";
let rounded = StrCast(this.props.Document.borderRounding) === "100%" ? "-rounded" : "";
let interactive: "all" | "none" = InkingControl.Instance.selectedTool || this.props.Document.isBackground
- //|| (this.props.Document.isButton && !this.props.isSelected())
? "none" : "all";
Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey);
return (
@@ -947,7 +951,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe
onPointerEnter={action(() => this._entered = true)}
onPointerLeave={action(() => this._entered = false)}
>
- <div className={`formattedTextBox-inner${rounded}`} style={{ whiteSpace: "pre-wrap", pointerEvents: (this.props.Document.isButton && !this.props.isSelected()) ? "none" : undefined }} ref={this.createDropTarget} />
+ <div className={`formattedTextBox-inner${rounded}`} style={{ whiteSpace: "pre-wrap", pointerEvents: ((this.props.Document.isButton || this.props.onClick) && !this.props.isSelected()) ? "none" : undefined }} ref={this.createDropTarget} />
</div>
);
}
diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx
index 92cb5a9c9..63a504d1a 100644
--- a/src/client/views/nodes/IconBox.tsx
+++ b/src/client/views/nodes/IconBox.tsx
@@ -12,7 +12,7 @@ import { IconField } from "../../../new_fields/IconField";
import { ContextMenu } from "../ContextMenu";
import Measure from "react-measure";
import { MINIMIZED_ICON_SIZE } from "../../views/globalCssVariables.scss";
-import { Scripting, CompileScript } from "../../util/Scripting";
+import { Scripting } from "../../util/Scripting";
import { ComputedField } from "../../../new_fields/ScriptField";
@@ -45,8 +45,7 @@ export class IconBox extends React.Component<FieldViewProps> {
}
public static AutomaticTitle(doc: Doc) {
- let computed = CompileScript(`return iconTitle(this);`, { params: { this: "Doc" }, typecheck: false });
- computed.compiled && (Doc.GetProto(doc).title = new ComputedField(computed));
+ Doc.GetProto(doc).title = ComputedField.MakeFunction('iconTitle(this);');
}
public static DocumentIcon(layout: string) {
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index beccce9dd..624593245 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -17,13 +17,12 @@ import { Utils } from '../../../Utils';
import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices';
import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
-import { CompileScript } from '../../util/Scripting';
import { undoBatch } from '../../util/UndoManager';
import { ContextMenu } from "../../views/ContextMenu";
import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from '../DocComponent';
import { InkingControl } from '../InkingControl';
-import { positionSchema } from './DocumentView';
+import { documentSchema } from './DocumentView';
import FaceRectangles from './FaceRectangles';
import { FieldView, FieldViewProps } from './FieldView';
import "./ImageBox.scss";
@@ -50,8 +49,8 @@ declare class MediaRecorder {
constructor(e: any);
}
-type ImageDocument = makeInterface<[typeof pageSchema, typeof positionSchema]>;
-const ImageDocument = makeInterface(pageSchema, positionSchema);
+type ImageDocument = makeInterface<[typeof pageSchema, typeof documentSchema]>;
+const ImageDocument = makeInterface(pageSchema, documentSchema);
@observer
export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageDocument) {
@@ -64,9 +63,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
@observable private _isOpen: boolean = false;
private dropDisposer?: DragManager.DragDropDisposer;
+ @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); }
- @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
-
+ @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
protected createDropTarget = (ele: HTMLDivElement) => {
if (this.dropDisposer) {
@@ -82,32 +81,18 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
console.log("IMPLEMENT ME PLEASE");
}
- @computed get extensionDoc() { return Doc.resolvedFieldDataDoc(this.dataDoc, this.props.fieldKey, "Alternates"); }
-
@undoBatch
@action
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.data instanceof DragManager.DocumentDragData) {
- de.data.droppedDocuments.forEach(action((drop: Doc) => {
- if (de.mods === "AltKey" && /*this.dataDoc !== this.props.Document &&*/ drop.data instanceof ImageField) {
- Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(drop.data.url);
- e.stopPropagation();
- } else if (de.mods === "MetaKey") {
- if (this.extensionDoc !== this.dataDoc) {
- let layout = StrCast(drop.backgroundLayout);
- if (layout.indexOf(ImageBox.name) !== -1) {
- let imgData = this.extensionDoc.Alternates;
- if (!imgData) {
- Doc.GetProto(this.extensionDoc).Alternates = new List([]);
- }
- let imgList = Cast(this.extensionDoc.Alternates, listSpec(Doc), [] as any[]);
- imgList && imgList.push(drop);
- e.stopPropagation();
- }
- }
- }
+ if (de.mods === "AltKey" && de.data.draggedDocuments.length && de.data.draggedDocuments[0].data instanceof ImageField) {
+ Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new ImageField(de.data.draggedDocuments[0].data.url);
+ e.stopPropagation();
+ }
+ de.mods === "MetaKey" && de.data.droppedDocuments.forEach(action((drop: Doc) => {
+ Doc.AddDocToList(Doc.GetProto(this.extensionDoc), "Alternates", drop);
+ e.stopPropagation();
}));
- // de.data.removeDocument() bcz: need to implement
}
}
@@ -220,7 +205,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
let modes: ContextMenuProps[] = existingAnalyze && "subitems" in existingAnalyze ? existingAnalyze.subitems : [];
modes.push({ description: "Generate Tags", event: this.generateMetadata, icon: "tag" });
modes.push({ description: "Find Faces", event: this.extractFaces, icon: "camera" });
- !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: modes, icon: "hand-point-right" })
+ !existingAnalyze && ContextMenu.Instance.addItem({ description: "Analyzers...", subitems: modes, icon: "hand-point-right" });
ContextMenu.Instance.addItem({ description: "Image Funcs...", subitems: funcs, icon: "asterisk" });
}
@@ -244,9 +229,7 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD
results.tags.map((tag: Tag) => {
tagsList.push(tag.name);
let sanitized = tag.name.replace(" ", "_");
- let script = `return (${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`;
- let computed = CompileScript(script, { params: { this: "Doc" } });
- computed.compiled && (tagDoc[sanitized] = new ComputedField(computed));
+ tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`);
});
this.extensionDoc.generatedTags = tagsList;
tagDoc.title = "Generated Tags Doc";
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index ee70942de..3a9318469 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -76,7 +76,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
} else if (type === "script") {
field = new ScriptField(script);
} else {
- let res = script.run({ this: target });
+ let res = script.run({ this: target }, console.log);
if (!res.success) return false;
field = res.result;
}
@@ -124,7 +124,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
let i = 0;
const self = this;
for (let key of Object.keys(ids).slice().sort()) {
- rows.push(<KeyValuePair doc={realDoc} ref={(function () {
+ rows.push(<KeyValuePair doc={realDoc} addDocTab={this.props.addDocTab} ref={(function () {
let oldEl: KeyValuePair | undefined;
return (el: KeyValuePair) => {
if (oldEl) self.rows.splice(self.rows.indexOf(oldEl), 1);
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 7e0f3735d..1fed4c8bb 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,7 +1,7 @@
import { action, observable } from 'mobx';
import { observer } from "mobx-react";
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import { Doc, Field } from '../../../new_fields/Doc';
+import { Doc, Field, Opt } from '../../../new_fields/Doc';
import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils';
import { Docs } from '../../documents/Documents';
import { Transform } from '../../util/Transform';
@@ -22,6 +22,7 @@ export interface KeyValuePairProps {
keyName: string;
doc: Doc;
keyWidth: number;
+ addDocTab: (doc: Doc, data: Opt<Doc>, where: string) => boolean;
}
@observer
export class KeyValuePair extends React.Component<KeyValuePairProps> {
@@ -45,7 +46,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
if (value instanceof Doc) {
e.stopPropagation();
e.preventDefault();
- ContextMenu.Instance.addItem({ description: "Open Fields", event: () => { let kvp = Docs.Create.KVPDocument(value, { width: 300, height: 300 }); CollectionDockingView.Instance.AddRightSplit(kvp, undefined); }, icon: "layer-group" });
+ ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { width: 300, height: 300 }), undefined, "onRight"), icon: "layer-group" });
ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
}
}
@@ -55,6 +56,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
Document: this.props.doc,
DataDoc: this.props.doc,
ContainingCollectionView: undefined,
+ ContainingCollectionDoc: undefined,
ruleProvider: undefined,
fieldKey: this.props.keyName,
fieldExt: "",
@@ -67,7 +69,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
focus: emptyFunction,
PanelWidth: returnZero,
PanelHeight: returnZero,
- addDocTab: returnZero,
+ addDocTab: returnFalse,
pinToPres: returnZero,
ContentScaling: returnOne
};
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index df35b603c..764051d62 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -4,40 +4,28 @@ import { observer } from "mobx-react";
import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
import 'react-image-lightbox/style.css';
-import { Doc, WidthSym, Opt } from "../../../new_fields/Doc";
+import { Doc, Opt, WidthSym } from "../../../new_fields/Doc";
import { makeInterface } from "../../../new_fields/Schema";
-import { ScriptField } from '../../../new_fields/ScriptField';
-import { BoolCast, Cast, NumCast } from "../../../new_fields/Types";
+import { ComputedField, ScriptField } from '../../../new_fields/ScriptField';
+import { Cast, NumCast } from "../../../new_fields/Types";
import { PdfField } from "../../../new_fields/URLField";
import { KeyCodes } from '../../northstar/utils/KeyCodes';
-import { CompileScript } from '../../util/Scripting';
+import { panZoomSchema } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { DocComponent } from "../DocComponent";
import { InkingControl } from "../InkingControl";
import { PDFViewer } from "../pdf/PDFViewer";
-import { positionSchema } from "./DocumentView";
+import { documentSchema } from "./DocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./PDFBox.scss";
import React = require("react");
-type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
-const PdfDocument = makeInterface(positionSchema, pageSchema);
-export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === KeyCodes.BACKSPACE) e.stopPropagation(); };
+type PdfDocument = makeInterface<[typeof documentSchema, typeof panZoomSchema, typeof pageSchema]>;
+const PdfDocument = makeInterface(documentSchema, panZoomSchema, pageSchema);
@observer
export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) {
public static LayoutString() { return FieldView.LayoutString(PDFBox); }
-
- @observable private _flyout: boolean = false;
- @observable private _alt = false;
- @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
-
- @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; }
- @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
-
-
- @computed get fieldExtensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); }
-
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _reactionDisposer?: IReactionDisposer;
private _keyValue: string = "";
@@ -47,16 +35,26 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
private _valueRef: React.RefObject<HTMLInputElement> = React.createRef();
private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef();
+ @observable private _flyout: boolean = false;
+ @observable private _alt = false;
+ @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>;
+
+ @computed get extensionDoc() { return Doc.fieldExtensionDoc(this.dataDoc, this.props.fieldKey); }
+
+ @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+
componentDidMount() {
this.props.setPdfBox && this.props.setPdfBox(this);
+ this.props.Document.curPage = ComputedField.MakeFunction("Math.floor(Number(this.panY) / Number(this.nativeHeight) + 1)");
+
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
if (pdfUrl instanceof PdfField) {
Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf));
}
this._reactionDisposer = reaction(
- () => this.props.Document.panY,
- () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.panY), behavior: "auto" })
+ () => this.Document.panY,
+ () => this._mainCont.current && this._mainCont.current.scrollTo({ top: this.Document.panY || 0, behavior: "auto" })
);
}
@@ -65,24 +63,22 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
public GetPage() {
- return Math.floor(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1;
+ return Math.floor((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
}
@action
public BackPage() {
- let cp = Math.ceil(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1;
+ let cp = Math.ceil((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
cp = cp - 1;
if (cp > 0) {
- this.props.Document.curPage = cp;
- this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
+ this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
}
}
@action
- public GotoPage(p: number) {
+ public GotoPage = (p: number) => {
if (p > 0 && p <= NumCast(this.dataDoc.numPages)) {
- this.props.Document.curPage = p;
- this.props.Document.panY = (p - 1) * NumCast(this.dataDoc.nativeHeight);
+ this.Document.panY = (p - 1) * (this.Document.nativeHeight || 0);
}
}
@@ -90,23 +86,20 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
public ForwardPage() {
let cp = this.GetPage() + 1;
if (cp <= NumCast(this.dataDoc.numPages)) {
- this.props.Document.curPage = cp;
- this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight);
+ this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
}
}
@action
setPanY = (y: number) => {
- this.containingCollectionDocument && (this.containingCollectionDocument.panY = y);
+ this.Document.panY = y;
}
@action
private applyFilter = () => {
- let scriptText = this._scriptValue.length > 0 ? this._scriptValue :
- this._keyValue.length > 0 && this._valueValue.length > 0 ?
- `return this.${this._keyValue} === ${this._valueValue}` : "return true";
- let script = CompileScript(scriptText, { params: { this: Doc.name } });
- script.compiled && (this.props.Document.filterScript = new ScriptField(script));
+ let scriptText = this._scriptValue ? this._scriptValue :
+ this._keyValue && this._valueValue ? `this.${this._keyValue} === ${this._valueValue}` : "true";
+ this.props.Document.filterScript = ScriptField.MakeFunction(scriptText);
}
scrollTo = (y: number) => {
@@ -114,8 +107,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
private resetFilters = () => {
- this._keyValue = this._valueValue = "";
- this._scriptValue = "return true";
+ this._keyValue = this._valueValue = this._scriptValue = "";
this._keyRef.current && (this._keyRef.current.value = "");
this._valueRef.current && (this._valueRef.current.value = "");
this._scriptRef.current && (this._scriptRef.current.value = "");
@@ -129,7 +121,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
return !this.props.active() ? (null) :
(<div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}>
<button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings"
- style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}>
+ style={{ marginTop: `${this.Document.panY || 0}px` }}>
<div className="pdfBox-settingsButton-arrow"
style={{
borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
@@ -146,13 +138,13 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
Annotation View Settings
</div>
<div className="pdfBox-settingsFlyout-kvpInput">
- <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange}
+ <input placeholder="Key" className="pdfBox-settingsFlyout-input" onChange={this.newKeyChange}
style={{ gridColumn: 1 }} ref={this._keyRef} />
- <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange}
+ <input placeholder="Value" className="pdfBox-settingsFlyout-input" onChange={this.newValueChange}
style={{ gridColumn: 3 }} ref={this._valueRef} />
</div>
<div className="pdfBox-settingsFlyout-kvpInput">
- <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} />
+ <input placeholder="Custom Script" onChange={this.newScriptChange} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} />
</div>
<div className="pdfBox-settingsFlyout-kvpInput">
<button style={{ gridColumn: 1 }} onClick={this.resetFilters}>
@@ -170,20 +162,20 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
loaded = (nw: number, nh: number, np: number) => {
this.dataDoc.numPages = np;
- if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight || !this.dataDoc.scrollHeight) {
- let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1);
- this.dataDoc.nativeWidth = nw;
- this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh;
- this.dataDoc.height = this.dataDoc[WidthSym]() * (nh / nw);
- this.dataDoc.scrollHeight = np * this.dataDoc.nativeHeight;
+ if (!this.Document.nativeWidth || !this.Document.nativeHeight || !this.Document.scrollHeight) {
+ let oldaspect = (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1);
+ this.Document.nativeWidth = nw;
+ this.Document.nativeHeight = this.Document.nativeHeight ? nw * oldaspect : nh;
+ this.Document.height = this.Document[WidthSym]() * (nh / nw);
+ this.Document.scrollHeight = np * this.Document.nativeHeight;
}
}
@action
onScroll = (e: React.UIEvent<HTMLDivElement>) => {
- if (e.currentTarget && this.containingCollectionDocument) {
- this.containingCollectionDocument.panTransformType = "None";
- this.containingCollectionDocument.panY = e.currentTarget.scrollTop;
+ if (e.currentTarget && this.props.ContainingCollectionDoc) {
+ this.props.Document.panTransformType = "None";
+ this.Document.panY = e.currentTarget.scrollTop;
}
}
@@ -195,14 +187,14 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
<div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> :
<div className={classname}
onScroll={this.onScroll}
- style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}
+ style={{ marginTop: `${(this.Document.panY || 0)}px` }}
ref={this._mainCont}>
- <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale, 1)), width: "100%" }} />
- <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={NumCast(this.props.Document.panY)}
- Document={this.props.Document} DataDoc={this.props.DataDoc}
- addDocTab={this.props.addDocTab} setPanY={this.setPanY}
+ <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + ((this.Document.nativeHeight || 0) - (this.Document.nativeHeight || 0) / (this.Document.scale || 1)) }} />
+ <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={this.Document.panY || 0}
+ Document={this.props.Document} DataDoc={this.dataDoc}
+ addDocTab={this.props.addDocTab} setPanY={this.setPanY} GoToPage={this.GotoPage}
pinToPres={this.props.pinToPres} addDocument={this.props.addDocument}
- fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} />
+ fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} />
{this.settingsPanel()}
</div>);
}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1ac2fae39..9469a2a0f 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -14,19 +14,18 @@ import { ContextMenuProps } from "../ContextMenuItem";
import { DocComponent } from "../DocComponent";
import { DocumentDecorations } from "../DocumentDecorations";
import { InkingControl } from "../InkingControl";
-import { positionSchema } from "./DocumentView";
+import { documentSchema } from "./DocumentView";
import { FieldView, FieldViewProps } from './FieldView';
import { pageSchema } from "./ImageBox";
import "./VideoBox.scss";
import { library } from "@fortawesome/fontawesome-svg-core";
import { faVideo } from "@fortawesome/free-solid-svg-icons";
-import { CompileScript } from "../../util/Scripting";
import { Doc } from "../../../new_fields/Doc";
import { ScriptField } from "../../../new_fields/ScriptField";
var path = require('path');
-type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
-const VideoDocument = makeInterface(positionSchema, pageSchema);
+type VideoDocument = makeInterface<[typeof documentSchema, typeof pageSchema]>;
+const VideoDocument = makeInterface(documentSchema, pageSchema);
library.add(faVideo);
@@ -116,18 +115,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
width: 150, height: 50, title: NumCast(this.props.Document.curPage).toString()
});
- const script = CompileScript(`(self as any).curPage = ${NumCast(this.props.Document.curPage)}`, {
- params: { this: Doc.name },
- capturedVariables: { self: this.props.Document },
- typecheck: false,
- editable: true,
- });
- if (script.compiled) {
- b.onClick = new ScriptField(script);
- this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.addDocument && this.props.ContainingCollectionView.props.addDocument(b, false);
- } else {
- console.log(script.errors.map(error => error.messageText).join("\n"));
- }
+ b.onClick = ScriptField.MakeScript(`this.curPage = ${NumCast(this.props.Document.curPage)}`);
} else {
//convert to desired file format
var dataUrl = canvas.toDataURL('image/png'); // can also use 'image/png'
@@ -271,7 +259,7 @@ export class VideoBox extends DocComponent<FieldViewProps, VideoDocument>(VideoD
}
- @computed get dataDoc() { return this.props.DataDoc && (BoolCast(this.props.Document.isTemplate) || BoolCast(this.props.DataDoc.isTemplate) || this.props.DataDoc.layout === this.props.Document) ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
+ @computed get dataDoc() { return this.props.DataDoc && this.props.Document.isTemplate ? this.props.DataDoc : Doc.GetProto(this.props.Document); }
@computed get youtubeContent() {
this._youtubeIframeId = VideoBox._youtubeIframeCounter++;