From ef94ad7df2a087141ddb8d347d3e3c484ff7609b Mon Sep 17 00:00:00 2001
From: Sam Wilkins <samwilkins333@gmail.com>
Date: Tue, 3 Dec 2019 01:46:36 -0500
Subject: const linter rule and restored google docs push, fixed routing

---
 src/client/views/nodes/DocumentContentsView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index b9b84d5ce..13fd3cde1 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -83,7 +83,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     }
 
     CreateBindings(): JsxBindings {
-        let list = {
+        const list = {
             ...OmitKeys(this.props, ['parentActive'], (obj: any) => obj.active = this.props.parentActive).omit,
             Document: this.layoutDoc,
             DataDoc: this.dataDoc,
-- 
cgit v1.2.3-70-g09d2


From 600d06a162b4489fd52d5809eb9f5a69f28618fc Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Fri, 6 Dec 2019 23:11:51 -0500
Subject: performance tuning for sidebar

---
 src/Utils.ts                                         |  2 ++
 src/client/views/MainView.tsx                        | 11 +++++------
 .../views/collections/CollectionStackingView.tsx     | 20 +++++++++++++-------
 .../CollectionStackingViewFieldColumn.tsx            |  6 +++---
 src/client/views/collections/CollectionView.tsx      |  2 ++
 src/client/views/nodes/DocumentContentsView.tsx      |  3 +++
 6 files changed, 28 insertions(+), 16 deletions(-)

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/Utils.ts b/src/Utils.ts
index 7401ef981..2b15ad0f2 100644
--- a/src/Utils.ts
+++ b/src/Utils.ts
@@ -362,6 +362,8 @@ export function returnZero() { return 0; }
 
 export function returnEmptyString() { return ""; }
 
+export let emptyPath = [];
+
 export function emptyFunction() { }
 
 export function unimplementedFunction() { throw new Error("This function is not implemented, but should be."); }
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 175af1abc..dacc9226e 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -15,7 +15,7 @@ import { List } from '../../new_fields/List';
 import { listSpec } from '../../new_fields/Schema';
 import { Cast, FieldValue, StrCast } from '../../new_fields/Types';
 import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils';
-import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils } from '../../Utils';
+import { emptyFunction, returnEmptyString, returnFalse, returnOne, returnTrue, Utils, emptyPath } from '../../Utils';
 import GoogleAuthenticationManager from '../apis/GoogleAuthenticationManager';
 import { DocServer } from '../DocServer';
 import { Docs, DocumentOptions } from '../documents/Documents';
@@ -261,11 +261,10 @@ export class MainView extends React.Component {
     getPHeight = () => this._panelHeight;
     getContentsHeight = () => this._panelHeight - this._buttonBarHeight;
 
-    _emptyPath = [];
     @computed get mainDocView() {
         return <DocumentView Document={this.mainContainer!}
             DataDoc={undefined}
-            LibraryPath={this._emptyPath}
+            LibraryPath={emptyPath}
             addDocument={undefined}
             addDocTab={this.addDocTabFunc}
             pinToPres={emptyFunction}
@@ -367,7 +366,7 @@ export class MainView extends React.Component {
                 <DocumentView
                     Document={sidebarButtonsDoc}
                     DataDoc={undefined}
-                    LibraryPath={[]}
+                    LibraryPath={emptyPath}
                     addDocument={undefined}
                     addDocTab={this.addDocTabFunc}
                     pinToPres={emptyFunction}
@@ -394,7 +393,7 @@ export class MainView extends React.Component {
                 <DocumentView
                     Document={sidebarContent}
                     DataDoc={undefined}
-                    LibraryPath={[]}
+                    LibraryPath={emptyPath}
                     addDocument={undefined}
                     addDocTab={this.addDocTabFunc}
                     pinToPres={emptyFunction}
@@ -478,7 +477,7 @@ export class MainView extends React.Component {
                 <CollectionLinearView
                     Document={CurrentUserUtils.UserDocument.expandingButtons}
                     DataDoc={undefined}
-                    LibraryPath={[]}
+                    LibraryPath={emptyPath}
                     fieldKey={"data"}
                     annotationsKey={""}
                     select={emptyFunction}
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 9f01de08b..ff3417b77 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -24,6 +24,7 @@ import { ContextMenu } from "../ContextMenu";
 import { ContextMenuProps } from "../ContextMenuItem";
 import { ScriptBox } from "../ScriptBox";
 import { CollectionMasonryViewFieldRow } from "./CollectionMasonryViewFieldRow";
+import { TraceMobx } from "../../../new_fields/util";
 
 @observer
 export class CollectionStackingView extends CollectionSubView(doc => doc) {
@@ -383,17 +384,22 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
         }
     }
 
+    @computed get renderedSections() {
+        TraceMobx();
+        let sections = [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]];
+        if (this.sectionFilter) {
+            const entries = Array.from(this.Sections.entries());
+            sections = entries.sort(this.sortFunc);
+        }
+        return sections.map(section => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1]));
+    }
     render() {
+        TraceMobx();
         const editableViewProps = {
             GetValue: () => "",
             SetValue: this.addGroup,
             contents: "+ ADD A GROUP"
         };
-        let sections = [[undefined, this.filteredChildren] as [SchemaHeaderField | undefined, Doc[]]];
-        if (this.sectionFilter) {
-            const entries = Array.from(this.Sections.entries());
-            sections = entries.sort(this.sortFunc);
-        }
         return (
             <div className="collectionStackingMasonry-cont" >
                 <div className={this.isStackingView ? "collectionStackingView" : "collectionMasonryView"}
@@ -401,8 +407,8 @@ export class CollectionStackingView extends CollectionSubView(doc => doc) {
                     onScroll={action((e: React.UIEvent<HTMLDivElement>) => this._scroll = e.currentTarget.scrollTop)}
                     onDrop={this.onDrop.bind(this)}
                     onContextMenu={this.onContextMenu}
-                    onWheel={(e: React.WheelEvent) => e.stopPropagation()} >
-                    {sections.map(section => this.isStackingView ? this.sectionStacking(section[0], section[1]) : this.sectionMasonry(section[0], section[1]))}
+                    onWheel={e => e.stopPropagation()} >
+                    {this.renderedSections}
                     {!this.showAddAGroup ? (null) :
                         <div key={`${this.props.Document[Id]}-addGroup`} className="collectionStackingView-addGroupButton"
                             style={{ width: !this.isStackingView ? "100%" : this.columnWidth / this.numGroupColumns - 10, marginTop: 10 }}>
diff --git a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
index 80dc482af..ca3b93bf8 100644
--- a/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
+++ b/src/client/views/collections/CollectionStackingViewFieldColumn.tsx
@@ -17,6 +17,7 @@ import { anchorPoints, Flyout } from "../DocumentDecorations";
 import { EditableView } from "../EditableView";
 import { CollectionStackingView } from "./CollectionStackingView";
 import "./CollectionStackingView.scss";
+import { TraceMobx } from "../../../new_fields/util";
 
 library.add(faPalette);
 
@@ -252,13 +253,12 @@ export class CollectionStackingViewFieldColumn extends React.Component<CSVFieldC
 
     @observable private collapsed: boolean = false;
 
-    private toggleVisibility = action(() => {
-        this.collapsed = !this.collapsed;
-    });
+    private toggleVisibility = action(() => this.collapsed = !this.collapsed);
 
     @observable _headingsHack: number = 1;
 
     render() {
+        TraceMobx();
         const cols = this.props.cols();
         const key = StrCast(this.props.parent.props.Document.sectionFilter);
         let templatecols = "";
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index cd546696f..411040332 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -32,6 +32,7 @@ import { SelectionManager } from '../../util/SelectionManager';
 import './CollectionView.scss';
 import { FieldViewProps, FieldView } from '../nodes/FieldView';
 import { Touchable } from '../Touchable';
+import { TraceMobx } from '../../../new_fields/util';
 const path = require('path');
 library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy);
 
@@ -251,6 +252,7 @@ export class CollectionView extends Touchable<FieldViewProps> {
             onMoveNextRequest={action(() => this._curLightboxImg = (this._curLightboxImg + 1) % images.length)} />);
     }
     render() {
+        TraceMobx();
         const props: CollectionRenderProps = {
             addDocument: this.addDocument,
             removeDocument: this.removeDocument,
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 13fd3cde1..1bbc82119 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -32,6 +32,7 @@ import { VideoBox } from "./VideoBox";
 import { WebBox } from "./WebBox";
 import { InkingStroke } from "../InkingStroke";
 import React = require("react");
+import { TraceMobx } from "../../../new_fields/util";
 const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
 
 type BindingProps = Without<FieldViewProps, 'fieldKey'>;
@@ -57,6 +58,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     hideOnLeave?: boolean
 }> {
     @computed get layout(): string {
+        TraceMobx();
         if (!this.layoutDoc) return "<p>awaiting layout</p>";
         const layout = Cast(this.layoutDoc[this.props.layoutKey], "string");
         if (layout === undefined) {
@@ -92,6 +94,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
     }
 
     render() {
+        TraceMobx();
         return (this.props.renderDepth > 7 || !this.layout) ? (null) :
             <ObserverJsxParser
                 blacklistedAttrs={[]}
-- 
cgit v1.2.3-70-g09d2


From 55823d0cc300f5cdd90ee34013bfdee93b5709e6 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sun, 15 Dec 2019 20:11:58 -0500
Subject: added a DocumentBox as a contentfitting container for another
 document.  added a menu item for showing selected document.

---
 src/client/documents/DocumentTypes.ts              |  3 +-
 src/client/documents/Documents.ts                  |  9 ++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 .../views/nodes/ContentFittingDocumentView.tsx     |  6 +--
 src/client/views/nodes/DocumentBox.scss            |  6 +++
 src/client/views/nodes/DocumentBox.tsx             | 55 ++++++++++++++++++++++
 src/client/views/nodes/DocumentContentsView.tsx    |  3 +-
 src/client/views/nodes/ImageBox.tsx                |  1 -
 src/new_fields/ScriptField.ts                      |  2 +-
 .../authentication/models/current_user_utils.ts    |  1 +
 10 files changed, 80 insertions(+), 8 deletions(-)
 create mode 100644 src/client/views/nodes/DocumentBox.scss
 create mode 100644 src/client/views/nodes/DocumentBox.tsx

(limited to 'src/client/views/nodes/DocumentContentsView.tsx')

diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index f6dd0c346..8f96b2fa6 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -25,5 +25,6 @@ export enum DocumentType {
     COLOR = "color",
     DOCULINK = "doculink",
     PDFANNO = "pdfanno",
-    INK = "ink"
+    INK = "ink",
+    DOCUMENT = "document"
 }
\ No newline at end of file
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 4ba45ac30..50c51ace1 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -48,6 +48,7 @@ import { PresElementBox } from "../views/presentationview/PresElementBox";
 import { QueryBox } from "../views/nodes/QueryBox";
 import { ColorBox } from "../views/nodes/ColorBox";
 import { DocuLinkBox } from "../views/nodes/DocuLinkBox";
+import { DocumentBox } from "../views/nodes/DocumentBox";
 import { InkingStroke } from "../views/InkingStroke";
 import { InkField } from "../../new_fields/InkField";
 const requestImageSize = require('../util/request-image-size');
@@ -171,6 +172,10 @@ export namespace Docs {
                 layout: { view: KeyValueBox, dataField: data },
                 options: { height: 150 }
             }],
+            [DocumentType.DOCUMENT, {
+                layout: { view: DocumentBox, dataField: data },
+                options: { height: 250 }
+            }],
             [DocumentType.VID, {
                 layout: { view: VideoBox, dataField: data },
                 options: { currentTimecode: 0 },
@@ -482,6 +487,10 @@ export namespace Docs {
             return InstanceFromProto(Prototypes.get(DocumentType.KVP), document, { title: document.title + ".kvp", ...options });
         }
 
+        export function DocumentDocument(document?: Doc, options: DocumentOptions = {}) {
+            return InstanceFromProto(Prototypes.get(DocumentType.DOCUMENT), document, { title: document ? document.title + "" : "container", ...options });
+        }
+
         export function FreeformDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
             return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Freeform }, id);
         }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9bb6fa97e..0b18e9f25 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -908,7 +908,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
             <div className={"collectionfreeformview-container"} ref={this.createDropTarget} onWheel={this.onPointerWheel}//pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined,
                 style={{ pointerEvents: SelectionManager.GetIsDragging() ? "all" : undefined, height: this.isAnnotationOverlay ? (this.props.Document.scrollHeight ? this.Document.scrollHeight : "100%") : this.props.PanelHeight() }}
                 onPointerDown={this.onPointerDown} onPointerMove={this.onCursorMove} onDrop={this.onDrop.bind(this)} onContextMenu={this.onContextMenu} onTouchStart={this.onTouchStart}>
-                {!BoolCast(this.Document.LODdisable) && this.props.renderDepth > 0 && this.Document[WidthSym]() * this.Document[HeightSym]() / this.props.ScreenToLocalTransform().Scale < NumCast(this.Document.LODarea, 100000) ? this.placeholder : this.marqueeView}
+                {!BoolCast(this.Document.LODdisable) && !this.props.isAnnotationOverlay && this.props.renderDepth > 0 && this.Document[WidthSym]() * this.Document[HeightSym]() / this.props.ScreenToLocalTransform().Scale < NumCast(this.Document.LODarea, 100000) ? this.placeholder : this.marqueeView}
                 <CollectionFreeFormOverlayView elements={this.elementFunc} />
             </div>;
     }
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 5e3306a11..2565fd932 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -31,9 +31,9 @@ interface ContentFittingDocumentViewProps {
     CollectionDoc?: Doc;
     onClick?: ScriptField;
     getTransform: () => Transform;
-    addDocument: (document: Doc) => boolean;
-    moveDocument: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean;
-    removeDocument: (document: Doc) => boolean;
+    addDocument?: (document: Doc) => boolean;
+    moveDocument?: (document: Doc, target: Doc | undefined, addDoc: ((doc: Doc) => boolean)) => boolean;
+    removeDocument?: (document: Doc) => boolean;
     active: (outsideReaction: boolean) => boolean;
     whenActiveChanged: (isActive: boolean) => void;
     addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
diff --git a/src/client/views/nodes/DocumentBox.scss b/src/client/views/nodes/DocumentBox.scss
new file mode 100644
index 000000000..6a2f98166
--- /dev/null
+++ b/src/client/views/nodes/DocumentBox.scss
@@ -0,0 +1,6 @@
+.documentBox-container {
+    width: 100%;
+    height: 100%;
+    pointer-events: all;
+    background: gray;
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/DocumentBox.tsx b/src/client/views/nodes/DocumentBox.tsx
new file mode 100644
index 000000000..2f2cba485
--- /dev/null
+++ b/src/client/views/nodes/DocumentBox.tsx
@@ -0,0 +1,55 @@
+import { observer } from "mobx-react";
+import { Doc } from "../../../new_fields/Doc";
+import { documentSchema } from "../../../new_fields/documentSchemas";
+import { makeInterface } from "../../../new_fields/Schema";
+import { ComputedField } from "../../../new_fields/ScriptField";
+import { emptyFunction, emptyPath } from "../../../Utils";
+import { ContextMenu } from "../ContextMenu";
+import { ContextMenuProps } from "../ContextMenuItem";
+import { DocComponent } from "../DocComponent";
+import { ContentFittingDocumentView } from "./ContentFittingDocumentView";
+import "./DocumentBox.scss";
+import { FieldView, FieldViewProps } from "./FieldView";
+import React = require("react");
+
+type DocBoxSchema = makeInterface<[typeof documentSchema]>;
+const DocBoxDocument = makeInterface(documentSchema);
+
+@observer
+export class DocumentBox extends DocComponent<FieldViewProps, DocBoxSchema>(DocBoxDocument) {
+    public static LayoutString(fieldKey: string) { return FieldView.LayoutString(DocumentBox, fieldKey); }
+
+
+    specificContextMenu = (e: React.MouseEvent): void => {
+        const funcs: ContextMenuProps[] = [];
+        funcs.push({ description: "Auto Show Selected", event: () => Doc.GetProto(this.props.Document).data = ComputedField.MakeFunction("selectedDocs(this,true,_last_)?.[0]"), icon: "expand-arrows-alt" });
+
+        ContextMenu.Instance.addItem({ description: "DocumentBox Funcs...", subitems: funcs, icon: "asterisk" });
+    }
+    render() {
+        const containedDoc = this.props.Document[this.props.fieldKey] as Doc;
+        return <div className="documentBox-container" onContextMenu={this.specificContextMenu}>
+            {!containedDoc ? (null) : <ContentFittingDocumentView
+                Document={containedDoc}
+                DataDocument={undefined}
+                LibraryPath={emptyPath}
+                fitToBox={this.props.fitToBox}
+                addDocument={this.props.addDocument}
+                moveDocument={this.props.moveDocument}
+                removeDocument={this.props.removeDocument}
+                ruleProvider={this.props.ruleProvider}
+                addDocTab={this.props.addDocTab}
+                pinToPres={this.props.pinToPres}
+                getTransform={this.props.ScreenToLocalTransform}
+                renderDepth={this.props.renderDepth - 1}
+                PanelWidth={this.props.PanelWidth}
+                PanelHeight={this.props.PanelHeight}
+                focus={this.props.focus}
+                active={this.props.active}
+                whenActiveChanged={this.props.whenActiveChanged}
+                setPreviewScript={emptyFunction}
+                previewScript={undefined}
+            />}
+        </div>;
+    }
+}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 1bbc82119..8f6bfc8e1 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -14,6 +14,7 @@ import { LinkFollowBox } from "../linking/LinkFollowBox";
 import { YoutubeBox } from "./../../apis/youtube/YoutubeBox";
 import { AudioBox } from "./AudioBox";
 import { ButtonBox } from "./ButtonBox";
+import { DocumentBox } from "./DocumentBox";
 import { DocumentViewProps } from "./DocumentView";
 import "./DocumentView.scss";
 import { FontIconBox } from "./FontIconBox";
@@ -102,7 +103,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & {
                     FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, FontIconBox: FontIconBox, ButtonBox, FieldView,
                     CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
                     PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox, LinkFollowBox, PresElementBox, QueryBox,
-                    ColorBox, DocuLinkBox, InkingStroke
+                    ColorBox, DocuLinkBox, InkingStroke, DocumentBox
                 }}
                 bindings={this.CreateBindings()}
                 jsx={this.layout}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index f6aa47f15..09e627078 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -18,7 +18,6 @@ import { undoBatch } from '../../util/UndoManager';
 import { ContextMenu } from "../../views/ContextMenu";
 import { ContextMenuProps } from '../ContextMenuItem';
 import { DocAnnotatableComponent } from '../DocComponent';
-import { InkingControl } from '../InkingControl';
 import FaceRectangles from './FaceRectangles';
 import { FieldView, FieldViewProps } from './FieldView';
 import "./ImageBox.scss";
diff --git a/src/new_fields/ScriptField.ts b/src/new_fields/ScriptField.ts
index 0cadb60ed..b5ad4a7f6 100644
--- a/src/new_fields/ScriptField.ts
+++ b/src/new_fields/ScriptField.ts
@@ -103,7 +103,7 @@ export class ScriptField extends ObjectField {
     }
     public static CompileScript(script: string, params: object = {}, addReturn = false) {
         const compiled = CompileScript(script, {
-            params: { this: Doc.name, ...params },
+            params: { this: Doc.name, _last_: "any", ...params },
             typecheck: false,
             editable: true,
             addReturn: addReturn
diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts
index 50bfb4832..fd01a291d 100644
--- a/src/server/authentication/models/current_user_utils.ts
+++ b/src/server/authentication/models/current_user_utils.ts
@@ -47,6 +47,7 @@ export class CurrentUserUtils {
         doc.activePen = doc;
         const docProtoData: { title: string, icon: string, drag?: string, ignoreClick?: boolean, click?: string, ischecked?: string, activePen?: Doc, backgroundColor?: string, dragFactory?: Doc }[] = [
             { title: "collection", icon: "folder", ignoreClick: true, drag: 'Docs.Create.FreeformDocument([], { nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: "freeform" })' },
+            { title: "preview", icon: "expand", ignoreClick: true, drag: 'Docs.Create.DocumentDocument(undefined, { width: 250, height: 250, title: "container" })' },
             { title: "todo item", icon: "check", ignoreClick: true, drag: 'getCopy(this.dragFactory, true)', dragFactory: notes[notes.length - 1] },
             { title: "web page", icon: "globe-asia", ignoreClick: true, drag: 'Docs.Create.WebDocument("https://en.wikipedia.org/wiki/Hedgehog", { width: 300, height: 300, title: "New Webpage" })' },
             { title: "cat image", icon: "cat", ignoreClick: true, drag: 'Docs.Create.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { width: 200, title: "an image of a cat" })' },
-- 
cgit v1.2.3-70-g09d2

