aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/DocumentDecorations.tsx2
-rw-r--r--src/client/views/Main.tsx2
-rw-r--r--src/client/views/MainView.tsx24
-rw-r--r--src/client/views/SearchBox.tsx2
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx386
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx2
-rw-r--r--src/client/views/collections/CollectionSubView.tsx16
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx2
-rw-r--r--src/client/views/collections/CollectionVideoView.tsx2
-rw-r--r--src/client/views/collections/DockedFrameRenderer.tsx116
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx18
-rw-r--r--src/client/views/nodes/DocumentView.tsx4
12 files changed, 298 insertions, 278 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index da9b1253e..787033455 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -274,7 +274,7 @@ export class DocumentDecorations extends React.Component<{}, { value: string }>
@undoBatch
@action createIcon = (selected: DocumentView[], layoutString: string): Doc => {
let doc = selected[0].props.Document;
- let iconDoc = Docs.IconDocument(layoutString);
+ let iconDoc = Docs.Create.IconDocument(layoutString);
iconDoc.isButton = true;
iconDoc.proto!.title = selected.length > 1 ? "-multiple-.icon" : StrCast(doc.title) + ".icon";
iconDoc.labelField = selected.length > 1 ? undefined : this._fieldKey;
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 3d9750a85..98b14f9c8 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -5,7 +5,7 @@ import * as ReactDOM from 'react-dom';
import * as React from 'react';
(async () => {
- await Docs.initProtos();
+ await Docs.Prototypes.initialize();
await CurrentUserUtils.loadCurrentUser();
ReactDOM.render(<MainView />, document.getElementById('root'));
})();
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 426e2440a..984db0426 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -55,7 +55,7 @@ export class MainView extends React.Component {
private set mainContainer(doc: Opt<Doc>) {
if (doc) {
if (!("presentationView" in doc)) {
- doc.presentationView = Docs.TreeDocument([], { title: "Presentation" });
+ doc.presentationView = Docs.Create.TreeDocument([], { title: "Presentation" });
}
CurrentUserUtils.UserDocument.activeWorkspace = doc;
}
@@ -151,12 +151,12 @@ export class MainView extends React.Component {
createNewWorkspace = async (id?: string) => {
const list = Cast(CurrentUserUtils.UserDocument.data, listSpec(Doc));
if (list) {
- let freeformDoc = Docs.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` });
+ let freeformDoc = Docs.Create.FreeformDocument([], { x: 0, y: 400, width: this.pwidth * .7, height: this.pheight, title: `WS collection ${list.length + 1}` });
let configs = [
{ doc: CurrentUserUtils.UserDocument, initialWidth: 150 },
{ doc: freeformDoc, initialWidth: 600 }
]
- let mainDoc = Docs.StandardCollectionDockingDocument(configs, { title: `Workspace ${list.length + 1}` }, id);
+ let mainDoc = Docs.Create.StandardCollectionDockingDocument(configs, { title: `Workspace ${list.length + 1}` }, id);
list.push(mainDoc);
// bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container)
setTimeout(() => {
@@ -242,18 +242,18 @@ export class MainView extends React.Component {
let audiourl = "http://techslides.com/demos/samples/sample.mp3";
let videourl = "http://techslides.com/demos/sample-videos/small.mp4";
- let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" }));
- let addColNode = action(() => Docs.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
- let addDockingNode = action(() => Docs.StandardCollectionDockingDocument([{ doc: addColNode(), initialWidth: 200 }], { width: 200, height: 200, title: "a nested docking freeform collection" }));
- let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" }));
+ let addTextNode = action(() => Docs.Create.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" }));
+ let addColNode = action(() => Docs.Create.FreeformDocument([], { width: this.pwidth * .7, height: this.pheight, title: "a freeform collection" }));
+ let addDockingNode = action(() => Docs.Create.StandardCollectionDockingDocument([{ doc: addColNode(), initialWidth: 200 }], { width: 200, height: 200, title: "a nested docking freeform collection" }));
+ let addSchemaNode = action(() => Docs.Create.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" }));
let addTreeNode = action(() => CurrentUserUtils.UserDocument);
//let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" }));
// let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" }));
- let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" }));
- let addPDFNode = action(() => Docs.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" }));
- let addImageNode = action(() => Docs.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
- let addWebNode = action(() => Docs.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
- let addAudioNode = action(() => Docs.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }));
+ let addVideoNode = action(() => Docs.Create.VideoDocument(videourl, { width: 200, title: "video node" }));
+ let addPDFNode = action(() => Docs.Create.PdfDocument(pdfurl, { width: 200, height: 200, title: "a pdf doc" }));
+ let addImageNode = action(() => Docs.Create.ImageDocument(imgurl, { width: 200, title: "an image of a cat" }));
+ let addWebNode = action(() => Docs.Create.WebDocument(weburl, { width: 200, height: 200, title: "a sample web page" }));
+ let addAudioNode = action(() => Docs.Create.AudioDocument(audiourl, { width: 200, height: 200, title: "audio node" }));
let btns: [React.RefObject<HTMLDivElement>, IconName, string, () => Doc][] = [
[React.createRef<HTMLDivElement>(), "font", "Add Textbox", addTextNode],
diff --git a/src/client/views/SearchBox.tsx b/src/client/views/SearchBox.tsx
index 63d2065e2..7164d98a4 100644
--- a/src/client/views/SearchBox.tsx
+++ b/src/client/views/SearchBox.tsx
@@ -166,7 +166,7 @@ export class SearchBox extends React.Component {
y += 300;
}
}
- return Docs.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this.searchString}"` });
+ return Docs.Create.FreeformDocument(docs, { width: 400, height: 400, panX: 175, panY: 175, backgroundColor: "grey", title: `Search Docs: "${this.searchString}"` });
}
// Useful queries:
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index dfb8fac35..e2bcb10ec 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -6,50 +6,32 @@ import * as ReactDOM from 'react-dom';
import Measure, { ContentRect } from "react-measure";
import * as GoldenLayout from "../../../client/goldenLayout";
import { Doc, Field, Opt, DocListCast } from "../../../new_fields/Doc";
-import { FieldId } from "../../../new_fields/RefField";
import { listSpec } from "../../../new_fields/Schema";
import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
import { emptyFunction, returnTrue, Utils } from "../../../Utils";
import { DocServer } from "../../DocServer";
import { DragLinksAsDocuments, DragManager } from "../../util/DragManager";
-import { Transform } from '../../util/Transform';
import { undoBatch, UndoManager } from "../../util/UndoManager";
-import { DocumentView } from "../nodes/DocumentView";
import "./CollectionDockingView.scss";
import { SubCollectionViewProps } from "./CollectionSubView";
import React = require("react");
import { ParentDocSelector } from './ParentDocumentSelector';
import { DocumentManager } from '../../util/DocumentManager';
-import { CollectionViewType } from './CollectionBaseView';
import { Id } from '../../../new_fields/FieldSymbols';
-import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils';
+import { DockedFrameRenderer } from './DockedFrameRenderer';
@observer
export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
public static TopLevel: CollectionDockingView;
- public static makeDocumentConfig(document: Doc, width?: number) {
- return {
- type: 'react-component',
- component: 'DocumentFrameRenderer',
- title: document.title,
- width: width,
- props: {
- documentId: document[Id],
- }
- };
- }
-
- private makeDocConfig = (document: Doc, width?: number) => {
- const config = CollectionDockingView.makeDocumentConfig(document, width);
- (config.props as any).parent = this;
- return config;
- }
-
private _goldenLayout: any = null;
private _containerRef = React.createRef<HTMLDivElement>();
+ reactionDisposer?: IReactionDisposer;
+ _removedDocs: Doc[] = [];
private _flush: boolean = false;
private _ignoreStateChange = "";
private _isPointerDown = false;
+ hack: boolean = false;
+ undohack: any = null;
constructor(props: SubCollectionViewProps) {
super(props);
@@ -57,32 +39,93 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
(window as any).React = React;
(window as any).ReactDOM = ReactDOM;
}
- hack: boolean = false;
- undohack: any = null;
- public StartOtherDrag(dragDocs: Doc[], e: any) {
- this.hack = true;
- this.undohack = UndoManager.StartBatch("goldenDrag");
- dragDocs.map(dragDoc =>
- CollectionDockingView.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
- onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }));
+
+ componentDidMount: () => void = () => {
+ if (this._containerRef.current) {
+ this.reactionDisposer = reaction(
+ () => StrCast(this.props.Document.dockingConfig),
+ () => {
+ if (!this._goldenLayout || this._ignoreStateChange !== this.retrieveConfiguration()) {
+ // Because this is in a set timeout, if this component unmounts right after mounting,
+ // we will leak a GoldenLayout, because we try to destroy it before we ever create it
+ setTimeout(() => this.setupGoldenLayout(), 1);
+ }
+ this._ignoreStateChange = "";
+ }, { fireImmediately: true });
+
+ // window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
+ }
}
- private openFullScreen = (document: Doc) => {
- let newItemStackConfig = {
- type: 'stack',
- content: [this.makeDocConfig(document)]
- };
- var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
- this._goldenLayout.root.contentItems[0].addChild(docconfig);
- docconfig.callDownwards('_$init');
- this._goldenLayout._$maximiseItem(docconfig);
- this._ignoreStateChange = this.retrieveConfiguration();
- this.stateChanged();
+ componentWillUnmount: () => void = () => {
+ try {
+ this._goldenLayout.unbind('itemDropped', this.itemDropped);
+ this._goldenLayout.unbind('tabCreated', this.tabCreated);
+ this._goldenLayout.unbind('stackCreated', this.stackCreated);
+ this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
+ } catch (e) {
+ console.log("Unable to unbind Golden Layout event listener...", e);
+ }
+ if (this._goldenLayout) this._goldenLayout.destroy();
+ this._goldenLayout = null;
+
+ if (this.reactionDisposer) {
+ this.reactionDisposer();
+ }
}
- @action
- public static OpenFullScreen(document: Doc, dockingView: CollectionDockingView = CollectionDockingView.TopLevel) {
- dockingView.openFullScreen(document);
+ setupGoldenLayout() {
+ var config = StrCast(this.props.Document.dockingConfig);
+ if (config) {
+ if (!this._goldenLayout) {
+ this.initializeConfiguration(config);
+ }
+ else {
+ if (config === this.retrieveConfiguration()) {
+ return;
+ }
+ try {
+ this._goldenLayout.unbind('itemDropped', this.itemDropped);
+ this._goldenLayout.unbind('tabCreated', this.tabCreated);
+ this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
+ this._goldenLayout.unbind('stackCreated', this.stackCreated);
+ } catch (e) { }
+ this._goldenLayout.destroy();
+ this.initializeConfiguration(config);
+ }
+ this._goldenLayout.on('itemDropped', this.itemDropped);
+ this._goldenLayout.on('tabCreated', this.tabCreated);
+ this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
+ this._goldenLayout.on('stackCreated', this.stackCreated);
+ this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
+ this._goldenLayout.container = this._containerRef.current;
+ if (this._goldenLayout.config.maximisedItemId === '__glMaximised') {
+ try {
+ this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise();
+ } catch (e) {
+ this._goldenLayout.config.maximisedItemId = null;
+ }
+ }
+ this._goldenLayout.init();
+ }
+ }
+
+ private makeDocConfig = (document: Doc, width?: number) => {
+ const config = CollectionDockingView.makeDocumentConfig(document, width);
+ (config.props as any).parent = this;
+ return config;
+ }
+
+ public static makeDocumentConfig(document: Doc, width?: number) {
+ return {
+ type: 'react-component',
+ component: 'DocumentFrameRenderer',
+ title: document.title,
+ width: width,
+ props: {
+ documentId: document[Id],
+ }
+ };
}
initializeConfiguration = (configText: string) => {
@@ -109,44 +152,29 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
});
}
- @undoBatch
- @action
- public static CloseRightSplit = (document: Doc, dockingView: CollectionDockingView = CollectionDockingView.TopLevel): boolean => {
- let retVal = false;
- if (dockingView._goldenLayout.root.contentItems[0].isRow) {
- retVal = Array.from(dockingView._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
- if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
- Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)!.Document, document)) {
- child.contentItems[0].remove();
- dockingView.layoutChanged(document);
- return true;
- } else {
- Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
- if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) {
- child.contentItems[j].remove();
- child.config.activeItemIndex = Math.max(child.contentItems.length - 1, 0);
- let docs = Cast(dockingView.props.Document.data, listSpec(Doc));
- docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1);
- return true;
- }
- return false;
- });
- }
- return false;
- });
- }
- if (retVal) {
- dockingView.stateChanged();
- }
- return retVal;
+ public StartOtherDrag(dragDocs: Doc[], e: any) {
+ this.hack = true;
+ this.undohack = UndoManager.StartBatch("goldenDrag");
+ dragDocs.map(dragDoc =>
+ CollectionDockingView.AddRightSplit(dragDoc, true).contentItems[0].tab._dragListener.
+ onMouseDown({ pageX: e.pageX, pageY: e.pageY, preventDefault: emptyFunction, button: 0 }));
}
@action
- layoutChanged(removed?: Doc) {
- this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
- this._goldenLayout.emit('stateChanged');
+ public static OpenFullScreen(document: Doc, dockingView: CollectionDockingView = CollectionDockingView.TopLevel) {
+ dockingView.openFullScreen(document);
+ }
+
+ private openFullScreen = (document: Doc) => {
+ let newItemStackConfig = {
+ type: 'stack',
+ content: [this.makeDocConfig(document)]
+ };
+ var docconfig = this._goldenLayout.root.layoutManager.createContentItem(newItemStackConfig, this._goldenLayout);
+ this._goldenLayout.root.contentItems[0].addChild(docconfig);
+ docconfig.callDownwards('_$init');
+ this._goldenLayout._$maximiseItem(docconfig);
this._ignoreStateChange = this.retrieveConfiguration();
- if (removed) CollectionDockingView.TopLevel._removedDocs.push(removed);
this.stateChanged();
}
@@ -209,75 +237,47 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
this.layoutChanged();
}
- setupGoldenLayout() {
- var config = StrCast(this.props.Document.dockingConfig);
- if (config) {
- if (!this._goldenLayout) {
- this.initializeConfiguration(config);
- }
- else {
- if (config === this.retrieveConfiguration()) {
- return;
- }
- try {
- this._goldenLayout.unbind('itemDropped', this.itemDropped);
- this._goldenLayout.unbind('tabCreated', this.tabCreated);
- this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- this._goldenLayout.unbind('stackCreated', this.stackCreated);
- } catch (e) { }
- this._goldenLayout.destroy();
- this.initializeConfiguration(config);
- }
- this._goldenLayout.on('itemDropped', this.itemDropped);
- this._goldenLayout.on('tabCreated', this.tabCreated);
- this._goldenLayout.on('tabDestroyed', this.tabDestroyed);
- this._goldenLayout.on('stackCreated', this.stackCreated);
- this._goldenLayout.registerComponent('DocumentFrameRenderer', DockedFrameRenderer);
- this._goldenLayout.container = this._containerRef.current;
- if (this._goldenLayout.config.maximisedItemId === '__glMaximised') {
- try {
- this._goldenLayout.config.root.getItemsById(this._goldenLayout.config.maximisedItemId)[0].toggleMaximise();
- } catch (e) {
- this._goldenLayout.config.maximisedItemId = null;
+ @undoBatch
+ @action
+ public static CloseRightSplit = (document: Doc, dockingView: CollectionDockingView = CollectionDockingView.TopLevel): boolean => {
+ let retVal = false;
+ if (dockingView._goldenLayout.root.contentItems[0].isRow) {
+ retVal = Array.from(dockingView._goldenLayout.root.contentItems[0].contentItems).some((child: any) => {
+ if (child.contentItems.length === 1 && child.contentItems[0].config.component === "DocumentFrameRenderer" &&
+ Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(child.contentItems[0].config.props.documentId)!.Document, document)) {
+ child.contentItems[0].remove();
+ dockingView.layoutChanged(document);
+ return true;
+ } else {
+ Array.from(child.contentItems).filter((tab: any) => tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => {
+ if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) {
+ child.contentItems[j].remove();
+ child.config.activeItemIndex = Math.max(child.contentItems.length - 1, 0);
+ let docs = Cast(dockingView.props.Document.data, listSpec(Doc));
+ docs && docs.indexOf(document) !== -1 && docs.splice(docs.indexOf(document), 1);
+ return true;
+ }
+ return false;
+ });
}
- }
- this._goldenLayout.init();
+ return false;
+ });
}
- }
- reactionDisposer?: IReactionDisposer;
- componentDidMount: () => void = () => {
- if (this._containerRef.current) {
- this.reactionDisposer = reaction(
- () => StrCast(this.props.Document.dockingConfig),
- () => {
- if (!this._goldenLayout || this._ignoreStateChange !== this.retrieveConfiguration()) {
- // Because this is in a set timeout, if this component unmounts right after mounting,
- // we will leak a GoldenLayout, because we try to destroy it before we ever create it
- setTimeout(() => this.setupGoldenLayout(), 1);
- }
- this._ignoreStateChange = "";
- }, { fireImmediately: true });
-
- // window.addEventListener('resize', this.onResize); // bcz: would rather add this event to the parent node, but resize events only come from Window
+ if (retVal) {
+ dockingView.stateChanged();
}
+ return retVal;
}
- componentWillUnmount: () => void = () => {
- try {
- this._goldenLayout.unbind('itemDropped', this.itemDropped);
- this._goldenLayout.unbind('tabCreated', this.tabCreated);
- this._goldenLayout.unbind('stackCreated', this.stackCreated);
- this._goldenLayout.unbind('tabDestroyed', this.tabDestroyed);
- } catch (e) {
- }
- if (this._goldenLayout) this._goldenLayout.destroy();
- this._goldenLayout = null;
- // window.removeEventListener('resize', this.onResize);
-
- if (this.reactionDisposer) {
- this.reactionDisposer();
- }
+ @action
+ layoutChanged(removed?: Doc) {
+ this._goldenLayout.root.callDownwards('setSize', [this._goldenLayout.width, this._goldenLayout.height]);
+ this._goldenLayout.emit('stateChanged');
+ this._ignoreStateChange = this.retrieveConfiguration();
+ if (removed) CollectionDockingView.TopLevel._removedDocs.push(removed);
+ this.stateChanged();
}
+
@action
onResize = (size: ContentRect) => {
// bcz: since GoldenLayout isn't a React component itself, we need to notify it to resize when its document container's size has changed
@@ -387,6 +387,9 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
}
tab.setActive(true);
}
+ tab.header.element[0].ondrop = (e: any) => {
+ console.log("DROPPPP THE BASS!", e);
+ }
ReactDOM.render(<ParentDocSelector Document={doc} addDocTab={(doc, location) => CollectionDockingView.AddTab(stack, doc)} />, upDiv);
tab.reactComponents = [upDiv];
tab.element.append(upDiv);
@@ -422,7 +425,6 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
}
}
}
- _removedDocs: Doc[] = [];
private stackCreated = (stack: any) => {
//stack.header.controlsContainer.find('.lm_popout').hide();
@@ -462,102 +464,4 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
);
}
-}
-
-interface DockedFrameProps {
- documentId: FieldId;
- glContainer: any;
- glEventHub: any;
- parent: CollectionDockingView;
-}
-
-@observer
-export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
- _mainCont = React.createRef<HTMLDivElement>();
- @observable private _panelWidth = 0;
- @observable private _panelHeight = 0;
- @observable private _document: Opt<Doc>;
- private get parentProps(): SubCollectionViewProps {
- return this.props.parent.props;
- }
-
- get _stack(): any {
- let parent = this.props.glContainer.parent.parent;
- if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1)
- return parent.parent.contentItems[1];
- return parent;
- }
- constructor(props: any) {
- super(props);
- DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
- }
-
- nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth);
- nativeHeight = () => NumCast(this._document!.nativeHeight, this._panelHeight);
- contentScaling = () => {
- const nativeH = this.nativeHeight();
- const nativeW = this.nativeWidth();
- let wscale = this._panelWidth / nativeW;
- return wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale;
- }
-
- ScreenToLocalTransform = () => {
- if (this._mainCont.current && this._mainCont.current.children) {
- let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement);
- scale = Utils.GetScreenTransform(this._mainCont.current).scale;
- return this.parentProps.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
- }
- return Transform.Identity();
- }
- get scaleToFitMultiplier() {
- let docWidth = NumCast(this._document!.width);
- let docHeight = NumCast(this._document!.height);
- if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1;
- if (StrCast(this._document!.layout).indexOf("Collection") === -1 ||
- NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1;
- let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ?
- this._panelHeight / docHeight : this._panelWidth / docWidth);
- return scaling;
- }
- get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; }
-
- addDocTab = (doc: Doc, location: string) => {
- if (location === "onRight") {
- CollectionDockingView.AddRightSplit(doc);
- } else {
- CollectionDockingView.AddTab(this._stack, doc);
- }
- }
- get content() {
- if (!this._document) {
- return (null);
- }
- return (
- <div className="collectionDockingView-content" ref={this._mainCont}
- style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px) scale(${this.scaleToFitMultiplier}, ${this.scaleToFitMultiplier})` }}>
- <DocumentView key={this._document[Id]} Document={this._document}
- bringToFront={emptyFunction}
- addDocument={undefined}
- removeDocument={undefined}
- ContentScaling={this.contentScaling}
- PanelWidth={this.nativeWidth}
- PanelHeight={this.nativeHeight}
- ScreenToLocalTransform={this.ScreenToLocalTransform}
- isTopMost={true}
- selectOnLoad={false}
- parentActive={returnTrue}
- whenActiveChanged={emptyFunction}
- focus={emptyFunction}
- addDocTab={this.addDocTab}
- ContainingCollectionView={undefined} />
- </div >);
- }
-
- render() {
- let theContent = this.content;
- return !this._document ? (null) :
- <Measure offset onResize={action((r: any) => { this._panelWidth = r.offset.width; this._panelHeight = r.offset.height; })}>
- {({ measureRef }) => <div ref={measureRef}> {theContent} </div>}
- </Measure>;
- }
} \ No newline at end of file
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 11d71d023..477879b79 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -261,7 +261,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) {
let dbName = StrCast(this.props.Document.title);
let res = await Gateway.Instance.PostSchema(csv, dbName);
if (self.props.CollectionView.props.addDocument) {
- let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document });
+ let schemaDoc = await Docs.Create.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }, { dbDoc: self.props.Document });
if (schemaDoc) {
//self.props.CollectionView.props.addDocument(schemaDoc, false);
self.props.Document.schemaDoc = schemaDoc;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index be37efd3d..440a2410b 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -113,20 +113,20 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
protected async getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise<Opt<Doc>> {
let ctor: ((path: string, options: DocumentOptions) => (Doc | Promise<Doc | undefined>)) | undefined = undefined;
if (type.indexOf("image") !== -1) {
- ctor = Docs.ImageDocument;
+ ctor = Docs.Create.ImageDocument;
}
if (type.indexOf("video") !== -1) {
- ctor = Docs.VideoDocument;
+ ctor = Docs.Create.VideoDocument;
}
if (type.indexOf("audio") !== -1) {
- ctor = Docs.AudioDocument;
+ ctor = Docs.Create.AudioDocument;
}
if (type.indexOf("pdf") !== -1) {
- ctor = Docs.PdfDocument;
+ ctor = Docs.Create.PdfDocument;
options.nativeWidth = 1200;
}
if (type.indexOf("excel") !== -1) {
- ctor = Docs.DBDocument;
+ ctor = Docs.Create.DBDocument;
options.dropAction = "copy";
}
if (type.indexOf("html") !== -1) {
@@ -145,7 +145,7 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
});
return undefined;
}
- ctor = Docs.WebDocument;
+ ctor = Docs.Create.WebDocument;
options = { height: options.width, ...options, title: path, nativeWidth: undefined };
}
return ctor ? ctor(path, options) : undefined;
@@ -175,13 +175,13 @@ export function CollectionSubView<T>(schemaCtor: (doc: Doc) => T) {
return;
}
if (html && html.indexOf("<img") !== 0 && !html.startsWith("<a")) {
- let htmlDoc = Docs.HtmlDocument(html, { ...options, width: 300, height: 300, documentText: text });
+ let htmlDoc = Docs.Create.HtmlDocument(html, { ...options, width: 300, height: 300, documentText: text });
this.props.addDocument(htmlDoc, false);
return;
}
if (text && text.indexOf("www.youtube.com/watch") !== -1) {
const url = text.replace("youtube.com/watch?v=", "youtube.com/embed/");
- this.props.addDocument(Docs.WebDocument(url, { ...options, width: 300, height: 300 }));
+ this.props.addDocument(Docs.Create.WebDocument(url, { ...options, width: 300, height: 300 }));
return;
}
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index b0a310ec1..424042fee 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -142,7 +142,7 @@ class TreeView extends React.Component<TreeViewProps> {
onWorkspaceContextMenu = (e: React.MouseEvent): void => {
if (!e.isPropagationStopped()) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7
ContextMenu.Instance.addItem({ description: "Open as Workspace", event: undoBatch(() => MainView.Instance.openWorkspace(this.props.document)) });
- ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight"), icon: "layer-group" });
+ ContextMenu.Instance.addItem({ description: "Open Fields", event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.document, { width: 300, height: 300 }), "onRight"), icon: "layer-group" });
if (NumCast(this.props.document.viewType) !== CollectionViewType.Docking) {
ContextMenu.Instance.addItem({ description: "Open Tab", event: () => this.props.addDocTab(this.props.document, "inTab"), icon: "folder" });
ContextMenu.Instance.addItem({ description: "Open Right", event: () => this.props.addDocTab(this.props.document, "onRight"), icon: "caret-square-right" });
diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx
index 7853544d5..bd5cd5450 100644
--- a/src/client/views/collections/CollectionVideoView.tsx
+++ b/src/client/views/collections/CollectionVideoView.tsx
@@ -98,7 +98,7 @@ export class CollectionVideoView extends React.Component<FieldViewProps> {
SearchBox.convertDataUri(dataUrl, filename).then((returnedFilename) => {
if (returnedFilename) {
let url = DocServer.prepend(returnedFilename);
- let imageSummary = Docs.ImageDocument(url, {
+ let imageSummary = Docs.Create.ImageDocument(url, {
x: NumCast(this.props.Document.x) + width, y: NumCast(this.props.Document.y),
width: 150, height: height / width * 150, title: "--snapshot" + NumCast(this.props.Document.curPage) + " image-"
});
diff --git a/src/client/views/collections/DockedFrameRenderer.tsx b/src/client/views/collections/DockedFrameRenderer.tsx
new file mode 100644
index 000000000..25d4b2a49
--- /dev/null
+++ b/src/client/views/collections/DockedFrameRenderer.tsx
@@ -0,0 +1,116 @@
+import 'golden-layout/src/css/goldenlayout-base.css';
+import 'golden-layout/src/css/goldenlayout-dark-theme.css';
+import { action, observable, reaction, Lambda, IReactionDisposer } from "mobx";
+import { observer } from "mobx-react";
+import Measure, { ContentRect } from "react-measure";
+import { Doc, Field, Opt, DocListCast } from "../../../new_fields/Doc";
+import { FieldId } from "../../../new_fields/RefField";
+import { Cast, NumCast, StrCast } from "../../../new_fields/Types";
+import { emptyFunction, returnTrue, Utils } from "../../../Utils";
+import { DocServer } from "../../DocServer";
+import { Transform } from '../../util/Transform';
+import { DocumentView } from "../nodes/DocumentView";
+import "./CollectionDockingView.scss";
+import { SubCollectionViewProps } from "./CollectionSubView";
+import React = require("react");
+import { CollectionViewType } from './CollectionBaseView';
+import { Id } from '../../../new_fields/FieldSymbols';
+import { CollectionDockingView } from './CollectionDockingView';
+
+interface DockedFrameProps {
+ documentId: FieldId;
+ glContainer: any;
+ glEventHub: any;
+ parent: CollectionDockingView;
+}
+
+@observer
+export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
+ _mainCont = React.createRef<HTMLDivElement>();
+ @observable private _panelWidth = 0;
+ @observable private _panelHeight = 0;
+ @observable private _document: Opt<Doc>;
+ private get parentProps(): SubCollectionViewProps {
+ return this.props.parent.props;
+ }
+
+ get _stack(): any {
+ let parent = this.props.glContainer.parent.parent;
+ if (this._document && this._document.excludeFromLibrary && parent.parent && parent.parent.contentItems.length > 1)
+ return parent.parent.contentItems[1];
+ return parent;
+ }
+ constructor(props: any) {
+ super(props);
+ DocServer.GetRefField(this.props.documentId).then(action((f: Opt<Field>) => this._document = f as Doc));
+ }
+
+ nativeWidth = () => NumCast(this._document!.nativeWidth, this._panelWidth);
+ nativeHeight = () => NumCast(this._document!.nativeHeight, this._panelHeight);
+ contentScaling = () => {
+ const nativeH = this.nativeHeight();
+ const nativeW = this.nativeWidth();
+ let wscale = this._panelWidth / nativeW;
+ return wscale * nativeH > this._panelHeight ? this._panelHeight / nativeH : wscale;
+ }
+
+ ScreenToLocalTransform = () => {
+ if (this._mainCont.current && this._mainCont.current.children) {
+ let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement);
+ scale = Utils.GetScreenTransform(this._mainCont.current).scale;
+ return this.parentProps.ScreenToLocalTransform().translate(-translateX, -translateY).scale(1 / this.contentScaling() / scale);
+ }
+ return Transform.Identity();
+ }
+ get scaleToFitMultiplier() {
+ let docWidth = NumCast(this._document!.width);
+ let docHeight = NumCast(this._document!.height);
+ if (NumCast(this._document!.nativeWidth) || !docWidth || !this._panelWidth || !this._panelHeight) return 1;
+ if (StrCast(this._document!.layout).indexOf("Collection") === -1 ||
+ NumCast(this._document!.viewType) !== CollectionViewType.Freeform) return 1;
+ let scaling = Math.max(1, this._panelWidth / docWidth * docHeight > this._panelHeight ?
+ this._panelHeight / docHeight : this._panelWidth / docWidth);
+ return scaling;
+ }
+ get previewPanelCenteringOffset() { return (this._panelWidth - this.nativeWidth() * this.contentScaling()) / 2; }
+
+ addDocTab = (doc: Doc, location: string) => {
+ if (location === "onRight") {
+ CollectionDockingView.AddRightSplit(doc);
+ } else {
+ CollectionDockingView.AddTab(this._stack, doc);
+ }
+ }
+ get content() {
+ if (!this._document) {
+ return (null);
+ }
+ return (
+ <div className="collectionDockingView-content" ref={this._mainCont}
+ style={{ transform: `translate(${this.previewPanelCenteringOffset}px, 0px) scale(${this.scaleToFitMultiplier}, ${this.scaleToFitMultiplier})` }}>
+ <DocumentView key={this._document[Id]} Document={this._document}
+ bringToFront={emptyFunction}
+ addDocument={undefined}
+ removeDocument={undefined}
+ ContentScaling={this.contentScaling}
+ PanelWidth={this.nativeWidth}
+ PanelHeight={this.nativeHeight}
+ ScreenToLocalTransform={this.ScreenToLocalTransform}
+ isTopMost={true}
+ selectOnLoad={false}
+ parentActive={returnTrue}
+ whenActiveChanged={emptyFunction}
+ focus={emptyFunction}
+ addDocTab={this.addDocTab}
+ ContainingCollectionView={undefined} />
+ </div >);
+ }
+
+ render() {
+ let theContent = this.content;
+ return !this._document ? (null) :
+ <Measure offset onResize={action((r: any) => { this._panelWidth = r.offset.width; this._panelHeight = r.offset.height; })}>
+ {({ measureRef }) => <div ref={measureRef}> {theContent} </div>}
+ </Measure>;
+ }
+} \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 29734fa19..cd386abfa 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -79,7 +79,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
ns.map(line => {
let indent = line.search(/\S|$/);
- let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line });
+ let newBox = Docs.Create.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line });
this.props.addDocument(newBox, false);
y += 40 * this.props.getTransform().Scale;
});
@@ -89,13 +89,13 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
navigator.clipboard.readText().then(text => {
let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== "");
if (ns.length === 1 && text.startsWith("http")) {
- this.props.addDocument(Docs.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer
+ this.props.addDocument(Docs.Create.ImageDocument(text, { nativeWidth: 300, width: 300, x: x, y: y }), false);// paste an image from its URL in the paste buffer
} else {
this.pasteTable(ns, x, y);
}
});
} else {
- let newBox = Docs.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
+ let newBox = Docs.Create.TextDocument({ width: 200, height: 100, x: x, y: y, title: "-typed text-" });
this.props.addLiveTextDocument(newBox);
}
e.stopPropagation();
@@ -136,7 +136,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
doc.width = 200;
docList.push(doc);
}
- let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
+ let newCol = Docs.Create.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 });
this.props.addDocument(newCol, false);
}
@@ -259,7 +259,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
let ink = Cast(this.props.container.props.Document.ink, InkField);
let inkData = ink ? ink.inkData : undefined;
let zoomBasis = NumCast(this.props.container.props.Document.scale, 1);
- let newCollection = Docs.FreeformDocument(selected, {
+ let newCollection = Docs.Create.FreeformDocument(selected, {
x: bounds.left,
y: bounds.top,
panX: 0,
@@ -283,14 +283,14 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
d.page = -1;
return d;
});
- let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+ let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
newCollection.proto!.summaryDoc = summary;
selected = [newCollection];
newCollection.x = bounds.left + bounds.width;
summary.proto!.subBulletDocs = new List<Doc>(selected);
//summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight"
summary.templates = new List<string>([Templates.Bullet.Layout]);
- let container = Docs.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, title: "-summary-" });
+ let container = Docs.Create.FreeformDocument([summary, newCollection], { x: bounds.left, y: bounds.top, width: 300, height: 200, title: "-summary-" });
container.viewType = CollectionViewType.Stacking;
this.props.addLiveTextDocument(container);
// });
@@ -303,11 +303,11 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
d.page = -1;
return d;
});
- let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
+ let summary = Docs.Create.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "#e2ad32" /* yellow */, title: "-summary-" });
SearchBox.convertDataUri(dataUrl, "icon" + summary[Id] + "_image").then((returnedFilename) => {
if (returnedFilename) {
let url = DocServer.prepend(returnedFilename);
- let imageSummary = Docs.ImageDocument(url, {
+ let imageSummary = Docs.Create.ImageDocument(url, {
x: bounds.left, y: bounds.top + 100 / zoomBasis,
width: 150, height: bounds.height / bounds.width * 150, title: "-summary image-"
});
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index efba26c2c..16e40000d 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -302,7 +302,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
deleteClicked = (): void => { this.props.removeDocument && this.props.removeDocument(this.props.Document); }
- fieldsClicked = (): void => { this.props.addDocTab(Docs.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") };
+ fieldsClicked = (): void => { this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }), "onRight") };
makeBtnClicked = (): void => {
let doc = Doc.GetProto(this.props.Document);
doc.isButton = !BoolCast(doc.isButton, false);
@@ -418,7 +418,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
cm.addItem({
description: "Find aliases", event: async () => {
const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document);
- this.props.addDocTab && this.props.addDocTab(Docs.SchemaDocument(["title"], aliases, {}), "onRight");
+ this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), "onRight");
}, icon: "search"
});
cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" });