aboutsummaryrefslogtreecommitdiff
path: root/src/client/documents/Documents.ts
diff options
context:
space:
mode:
authorStanley Yip <stanley_yip@brown.edu>2020-02-09 14:58:57 -0500
committerStanley Yip <stanley_yip@brown.edu>2020-02-09 14:58:57 -0500
commitf6179334d6f2942631caa17b7c8ae2531d87c7c4 (patch)
tree091da0ef7bedb900c958c28cebe4058fade644cf /src/client/documents/Documents.ts
parent07141291bee793955d7061f4e479942d7aceda67 (diff)
parent87167fd126e161b29d8d798a5f04e3cf159aae16 (diff)
recommender system works
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r--src/client/documents/Documents.ts306
1 files changed, 208 insertions, 98 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 97f7f8bf0..4b5152224 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -19,7 +19,7 @@ import { AggregateFunction } from "../northstar/model/idea/idea";
import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss";
import { IconBox } from "../views/nodes/IconBox";
import { OmitKeys, JSONUtils } from "../../Utils";
-import { Field, Doc, Opt, DocListCastAsync } from "../../new_fields/Doc";
+import { Field, Doc, Opt, DocListCastAsync, FieldResult, DocListCast } from "../../new_fields/Doc";
import { ImageField, VideoField, AudioField, PdfField, WebField, YoutubeField } from "../../new_fields/URLField";
import { HtmlField } from "../../new_fields/HtmlField";
import { List } from "../../new_fields/List";
@@ -29,16 +29,16 @@ import { listSpec } from "../../new_fields/Schema";
import { DocServer } from "../DocServer";
import { dropActionType } from "../util/DragManager";
import { DateField } from "../../new_fields/DateField";
-import { UndoManager } from "../util/UndoManager";
+import { UndoManager, undoBatch } from "../util/UndoManager";
import { YoutubeBox } from "../apis/youtube/YoutubeBox";
import { CollectionDockingView } from "../views/collections/CollectionDockingView";
import { LinkManager } from "../util/LinkManager";
import { DocumentManager } from "../util/DocumentManager";
import DirectoryImportBox from "../util/Import & Export/DirectoryImportBox";
-import { Scripting, CompileScript } from "../util/Scripting";
+import { Scripting } from "../util/Scripting";
import { ButtonBox } from "../views/nodes/ButtonBox";
import { FontIconBox } from "../views/nodes/FontIconBox";
-import { SchemaHeaderField, RandomPastel } from "../../new_fields/SchemaHeaderField";
+import { SchemaHeaderField } from "../../new_fields/SchemaHeaderField";
import { PresBox } from "../views/nodes/PresBox";
import { ComputedField, ScriptField } from "../../new_fields/ScriptField";
import { ProxyField } from "../../new_fields/Proxy";
@@ -51,40 +51,56 @@ import { PresElementBox } from "../views/presentationview/PresElementBox";
import { QueryBox } from "../views/nodes/QueryBox";
import { ColorBox } from "../views/nodes/ColorBox";
import { DocuLinkBox } from "../views/nodes/DocuLinkBox";
-var requestImageSize = require('../util/request-image-size');
-var path = require('path');
+import { DocumentBox } from "../views/nodes/DocumentBox";
+import { InkingStroke } from "../views/InkingStroke";
+import { InkField } from "../../new_fields/InkField";
+import { InkingControl } from "../views/InkingControl";
+import { RichTextField } from "../../new_fields/RichTextField";
+const requestImageSize = require('../util/request-image-size');
+const path = require('path');
export interface DocumentOptions {
+ _autoHeight?: boolean;
+ _panX?: number;
+ _panY?: number;
+ _width?: number;
+ _height?: number;
+ _nativeWidth?: number;
+ _nativeHeight?: number;
+ _fitWidth?: boolean;
+ _fitToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents
+ _LODdisable?: boolean;
+ _dropAction?: dropActionType;
+ _chromeStatus?: string;
+ _viewType?: number;
+ _gridGap?: number; // gap between items in masonry view
+ _xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts
+ _yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts
+ _textTemplate?: RichTextField; // template used by a formattedTextBox to create a text box to render
+ _itemIndex?: number; // which item index the carousel viewer is showing
+ _hideSidebar?: boolean; //whether an annotationsidebar should be displayed for text docuemnts
x?: number;
y?: number;
z?: number;
+ layoutKey?: string;
type?: string;
- width?: number;
- height?: number;
- nativeWidth?: number;
- nativeHeight?: number;
title?: string;
- panX?: number;
- panY?: number;
page?: number;
scale?: number;
- fitWidth?: boolean;
+ isDisplayPanel?: boolean; // whether the panel functions as GoldenLayout "stack" used to display documents
forceActive?: boolean;
preventTreeViewOpen?: boolean; // ignores the treeViewOpen Doc flag which allows a treeViewItem's expande/collapse state to be independent of other views of the same document in the tree view
layout?: string | Doc;
hideHeadings?: boolean; // whether stacking view column headings should be hidden
- isTemplateField?: boolean;
+ isTemplateForField?: string; // the field key for which the containing document is a rendering template
isTemplateDoc?: boolean;
templates?: List<string>;
- viewType?: number;
- backgroundColor?: string;
+ backgroundColor?: string | ScriptField;
ignoreClick?: boolean;
lockedPosition?: boolean; // lock the x,y coordinates of the document so that it can't be dragged
lockedTransform?: boolean; // lock the panx,pany and scale parameters of the document so that it be panned/zoomed
opacity?: number;
defaultBackgroundColor?: string;
- dropAction?: dropActionType;
- chromeStatus?: string;
columnWidth?: number;
fontSize?: number;
curPage?: number;
@@ -96,22 +112,37 @@ export interface DocumentOptions {
sectionFilter?: string; // field key used to determine headings for sections in stacking and masonry views
schemaColumns?: List<SchemaHeaderField>;
dockingConfig?: string;
- autoHeight?: boolean;
+ annotationOn?: Doc;
removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document
dbDoc?: Doc;
- unchecked?: ScriptField; // returns whether a check box is unchecked
+ ischecked?: ScriptField; // returns whether a font icon box is checked
activePen?: Doc; // which pen document is currently active (used as the radio button state for the 'unhecked' pen tool scripts)
onClick?: ScriptField;
+ onChildClick?: ScriptField; // script given to children of a collection to execute when they are clicked
+ onPointerDown?: ScriptField;
+ onPointerUp?: ScriptField;
dragFactory?: Doc; // document to create when dragging with a suitable onDragStart script
onDragStart?: ScriptField; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop
+ clipboard?: Doc; //script to execute at start of drag operation -- e.g., when a "creator" button is dragged this script generates a different document to drop
icon?: string;
- gridGap?: number; // gap between items in masonry view
- xMargin?: number; // gap between left edge of document and start of masonry/stacking layouts
- yMargin?: number; // gap between top edge of dcoument and start of masonry/stacking layouts
sourcePanel?: Doc; // panel to display in 'targetContainer' as the result of a button onClick script
targetContainer?: Doc; // document whose proto will be set to 'panel' as the result of a onClick click script
dropConverter?: ScriptField; // script to run when documents are dropped on this Document.
+ strokeWidth?: number;
+ color?: string;
+ treeViewHideTitle?: boolean; // whether to hide the title of a tree view
+ treeViewOpen?: boolean; // whether this document is expanded in a tree view
+ treeViewChecked?: ScriptField; // script to call when a tree view checkbox is checked
+ isFacetFilter?: boolean; // whether document functions as a facet filter in a tree view
+ limitHeight?: number; // maximum height for newly created (eg, from pasting) text documents
// [key: string]: Opt<Field>;
+ pointerHack?: boolean; // for buttons, allows onClick handler to fire onPointerDown
+ isExpanded?: boolean; // is linear view expanded
+ textTransform?: string; // is linear view expanded
+ letterSpacing?: string; // is linear view expanded
+ flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
+ selectedIndex?: number;
+ syntaxColor?: string; // can be applied to text for syntax highlighting all matches in the text
}
class EmptyBox {
@@ -139,19 +170,19 @@ export namespace Docs {
const TemplateMap: TemplateMap = new Map([
[DocumentType.TEXT, {
layout: { view: FormattedTextBox, dataField: data },
- options: { height: 150, backgroundColor: "#f1efeb", defaultBackgroundColor: "#f1efeb" }
+ options: { _height: 150, backgroundColor: "#f1efeb", defaultBackgroundColor: "#f1efeb" }
}],
[DocumentType.HIST, {
layout: { view: HistogramBox, dataField: data },
- options: { height: 300, backgroundColor: "black" }
+ options: { _height: 300, backgroundColor: "black" }
}],
[DocumentType.QUERY, {
layout: { view: QueryBox, dataField: data },
- options: { width: 400 }
+ options: { _width: 400 }
}],
[DocumentType.COLOR, {
layout: { view: ColorBox, dataField: data },
- options: { nativeWidth: 220, nativeHeight: 300 }
+ options: { _nativeWidth: 220, _nativeHeight: 300 }
}],
[DocumentType.IMG, {
layout: { view: ImageBox, dataField: data },
@@ -159,15 +190,19 @@ export namespace Docs {
}],
[DocumentType.WEB, {
layout: { view: WebBox, dataField: data },
- options: { height: 300 }
+ options: { _height: 300 }
}],
[DocumentType.COL, {
layout: { view: CollectionView, dataField: data },
- options: { panX: 0, panY: 0, scale: 1, width: 500, height: 500 }
+ options: { _panX: 0, _panY: 0, scale: 1, _width: 500, _height: 500 }
}],
[DocumentType.KVP, {
layout: { view: KeyValueBox, dataField: data },
- options: { height: 150 }
+ options: { _height: 150 }
+ }],
+ [DocumentType.DOCUMENT, {
+ layout: { view: DocumentBox, dataField: data },
+ options: { _height: 250 }
}],
[DocumentType.VID, {
layout: { view: VideoBox, dataField: data },
@@ -175,19 +210,19 @@ export namespace Docs {
}],
[DocumentType.AUDIO, {
layout: { view: AudioBox, dataField: data },
- options: { height: 35, backgroundColor: "lightGray" }
+ options: { _height: 35, backgroundColor: "lightGray" }
}],
[DocumentType.PDF, {
layout: { view: PDFBox, dataField: data },
- options: { nativeWidth: 1200, curPage: 1 }
+ options: { curPage: 1 }
}],
[DocumentType.ICON, {
layout: { view: IconBox, dataField: data },
- options: { width: Number(MINIMIZED_ICON_SIZE), height: Number(MINIMIZED_ICON_SIZE) },
+ options: { _width: Number(MINIMIZED_ICON_SIZE), _height: Number(MINIMIZED_ICON_SIZE) },
}],
[DocumentType.IMPORT, {
layout: { view: DirectoryImportBox, dataField: data },
- options: { height: 150 }
+ options: { _height: 150 }
}],
[DocumentType.LINKDOC, {
data: new List<Doc>(),
@@ -205,7 +240,7 @@ export namespace Docs {
}],
[DocumentType.FONTICON, {
layout: { view: FontIconBox, dataField: data },
- options: { width: 40, height: 40, borderRounding: "100%" },
+ options: { _width: 40, _height: 40, borderRounding: "100%" },
}],
[DocumentType.RECOMMENDATION, {
layout: { view: RecommendationsBox },
@@ -217,10 +252,14 @@ export namespace Docs {
[DocumentType.PRESELEMENT, {
layout: { view: PresElementBox, dataField: data }
}],
+ [DocumentType.INK, {
+ layout: { view: InkingStroke, dataField: data },
+ options: { backgroundColor: "transparent" }
+ }]
]);
// All document prototypes are initialized with at least these values
- const defaultOptions: DocumentOptions = { x: 0, y: 0, width: 300 };
+ const defaultOptions: DocumentOptions = { x: 0, y: 0, _width: 300 };
const suffix = "Proto";
/**
@@ -238,16 +277,16 @@ export namespace Docs {
ProxyField.initPlugin();
ComputedField.initPlugin();
// non-guid string ids for each document prototype
- let prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix);
+ const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix);
// fetch the actual prototype documents from the server
- let actualProtos = await DocServer.GetRefFields(prototypeIds);
+ const actualProtos = await DocServer.GetRefFields(prototypeIds);
// update this object to include any default values: DocumentOptions for all prototypes
prototypeIds.map(id => {
- let existing = actualProtos[id] as Doc;
- let type = id.replace(suffix, "") as DocumentType;
+ const existing = actualProtos[id] as Doc;
+ const type = id.replace(suffix, "") as DocumentType;
// get or create prototype of the specified type...
- let target = existing || buildPrototype(type, id);
+ const target = existing || buildPrototype(type, id);
// ...and set it if not undefined (can be undefined only if TemplateMap does not contain
// an entry dedicated to the given DocumentType)
target && PrototypeMap.set(type, target);
@@ -286,19 +325,20 @@ export namespace Docs {
*/
function buildPrototype(type: DocumentType, prototypeId: string): Opt<Doc> {
// load template from type
- let template = TemplateMap.get(type);
+ const template = TemplateMap.get(type);
if (!template) {
return undefined;
}
- let layout = template.layout;
+ const layout = template.layout;
// create title
- let upper = suffix.toUpperCase();
- let title = prototypeId.toUpperCase().replace(upper, `_${upper}`);
+ const upper = suffix.toUpperCase();
+ const title = prototypeId.toUpperCase().replace(upper, `_${upper}`);
// synthesize the default options, the type and title from computed values and
// whatever options pertain to this specific prototype
- let options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
+ const options = { title, type, baseProto: true, ...defaultOptions, ...(template.options || {}) };
options.layout = layout.view.LayoutString(layout.dataField);
- return Doc.assign(new Doc(prototypeId, true), { ...options, baseLayout: options.layout });
+ const doc = Doc.assign(new Doc(prototypeId, true), { layoutKey: "layout", ...options });
+ return doc;
}
}
@@ -309,7 +349,8 @@ export namespace Docs {
*/
export namespace Create {
- const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "nativeWidth", "nativeHeight", "dropAction", "forceActive", "fitWidth"];
+ const delegateKeys = ["x", "y", "layoutKey", "_width", "_height", "_panX", "_panY", "_viewType", "_nativeWidth", "_nativeHeight", "_dropAction", "_annotationOn",
+ "_chromeStatus", "_forceActive", "_autoHeight", "_fitWidth", "_LODdisable", "_itemIndex", "_hideSidebar"];
/**
* This function receives the relevant document prototype and uses
@@ -342,12 +383,12 @@ export namespace Docs {
protoProps.isPrototype = true;
- let dataDoc = MakeDataDelegate(proto, protoProps, data);
- let viewDoc = Doc.MakeDelegate(dataDoc, delegId);
+ const dataDoc = MakeDataDelegate(proto, protoProps, data);
+ const viewDoc = Doc.MakeDelegate(dataDoc, delegId);
AudioBox.ActiveRecordings.map(d => DocUtils.MakeLink({ doc: viewDoc }, { doc: d }, "audio link", "link to audio: " + d.title));
- return Doc.assign(viewDoc, delegateProps);
+ return Doc.assign(viewDoc, delegateProps, true);
}
/**
@@ -369,22 +410,21 @@ export namespace Docs {
}
export function ImageDocument(url: string, options: DocumentOptions = {}) {
- let imgField = new ImageField(new URL(url));
- let inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options });
+ const imgField = new ImageField(new URL(url));
+ const inst = InstanceFromProto(Prototypes.get(DocumentType.IMG), imgField, { title: path.basename(url), ...options });
let target = imgField.url.href;
if (new RegExp(window.location.origin).test(target)) {
- let extension = path.extname(target);
+ const extension = path.extname(target);
target = `${target.substring(0, target.length - extension.length)}_o${extension}`;
}
- // if (target !== "http://www.cs.brown.edu/") {
requestImageSize(target)
.then((size: any) => {
- let aspect = size.height / size.width;
- if (!inst.nativeWidth) {
- inst.nativeWidth = size.width;
+ const aspect = size.height / size.width;
+ if (!inst._nativeWidth) {
+ inst._nativeWidth = size.width;
}
- inst.nativeHeight = NumCast(inst.nativeWidth) * aspect;
- inst.height = NumCast(inst.width) * aspect;
+ inst._nativeHeight = NumCast(inst._nativeWidth) * aspect;
+ inst._height = NumCast(inst._width) * aspect;
})
.catch((err: any) => console.log(err));
// }
@@ -418,8 +458,16 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.COLOR), "", options);
}
- export function TextDocument(options: DocumentOptions = {}) {
- return InstanceFromProto(Prototypes.get(DocumentType.TEXT), "", options);
+ export function TextDocument(text: string, options: DocumentOptions = {}) {
+ return InstanceFromProto(Prototypes.get(DocumentType.TEXT), text, options);
+ }
+
+ export function InkDocument(color: string, tool: number, strokeWidth: number, points: { X: number, Y: number }[], options: DocumentOptions = {}) {
+ const doc = InstanceFromProto(Prototypes.get(DocumentType.INK), new InkField(points), options);
+ doc.color = color;
+ doc.strokeWidth = strokeWidth;
+ doc.tool = tool;
+ return doc;
}
export function IconDocument(icon: string, options: DocumentOptions = {}) {
@@ -431,12 +479,12 @@ export namespace Docs {
}
export async function DBDocument(url: string, options: DocumentOptions = {}, columnOptions: DocumentOptions = {}) {
- let schemaName = options.title ? options.title : "-no schema-";
- let ctlog = await Gateway.Instance.GetSchema(url, schemaName);
+ const schemaName = options.title ? options.title : "-no schema-";
+ const ctlog = await Gateway.Instance.GetSchema(url, schemaName);
if (ctlog && ctlog.schemas) {
- let schema = ctlog.schemas[0];
- let schemaDoc = Docs.Create.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! });
- let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []);
+ const schema = ctlog.schemas[0];
+ const schemaDoc = Docs.Create.TreeDocument([], { ...options, _nativeWidth: undefined, _nativeHeight: undefined, _width: 150, _height: 100, title: schema.displayName! });
+ const schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []);
if (!schemaDocuments) {
return;
}
@@ -447,18 +495,18 @@ export namespace Docs {
if (field instanceof Doc) {
docs.push(field);
} else {
- var atmod = new ColumnAttributeModel(attr);
- let histoOp = new HistogramOperation(schema.displayName!,
+ const atmod = new ColumnAttributeModel(attr);
+ const histoOp = new HistogramOperation(schema.displayName!,
new AttributeTransformationModel(atmod, AggregateFunction.None),
new AttributeTransformationModel(atmod, AggregateFunction.Count),
new AttributeTransformationModel(atmod, AggregateFunction.Count));
- docs.push(Docs.Create.HistogramDocument(histoOp, { ...columnOptions, width: 200, height: 200, title: attr.displayName! }));
+ docs.push(Docs.Create.HistogramDocument(histoOp, { ...columnOptions, _width: 200, _height: 200, title: attr.displayName! }));
}
}));
});
return schemaDoc;
}
- return Docs.Create.TreeDocument([], { width: 50, height: 100, title: schemaName });
+ return Docs.Create.TreeDocument([], { _width: 50, _height: 100, title: schemaName });
}
export function WebDocument(url: string, options: DocumentOptions = {}) {
@@ -473,28 +521,40 @@ 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);
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Freeform }, id);
}
export function LinearDocument(documents: Array<Doc>, options: DocumentOptions, id?: string) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Linear }, id);
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", backgroundColor: "black", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Linear }, id);
+ }
+
+ export function CarouselDocument(documents: Array<Doc>, options: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel });
}
export function SchemaDocument(schemaColumns: SchemaHeaderField[], documents: Array<Doc>, options: DocumentOptions) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema });
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List(schemaColumns), ...options, _viewType: CollectionViewType.Schema });
}
export function TreeDocument(documents: Array<Doc>, options: DocumentOptions) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Tree });
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Tree });
}
export function StackingDocument(documents: Array<Doc>, options: DocumentOptions) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Stacking });
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Stacking });
+ }
+
+ export function MulticolumnDocument(documents: Array<Doc>, options: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Multicolumn });
}
export function MasonryDocument(documents: Array<Doc>, options: DocumentOptions) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, viewType: CollectionViewType.Masonry });
+ return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Masonry });
}
export function ButtonDocument(options?: DocumentOptions) {
@@ -515,7 +575,9 @@ export namespace Docs {
}
export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) {
- return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+ const inst = InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id);
+ Doc.GetProto(inst).data = new List<Doc>(documents);
+ return inst;
}
export function DirectoryImportDocument(options: DocumentOptions = {}) {
@@ -528,16 +590,17 @@ export namespace Docs {
export type DocConfig = {
doc: Doc,
- initialWidth?: number
+ initialWidth?: number,
+ path?: Doc[]
};
export function StandardCollectionDockingDocument(configs: Array<DocConfig>, options: DocumentOptions, id?: string, type: string = "row") {
- let layoutConfig = {
+ const layoutConfig = {
content: [
{
type: type,
content: [
- ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth))
+ ...configs.map(config => CollectionDockingView.makeDocumentConfig(config.doc, undefined, config.initialWidth, config.path))
]
}
]
@@ -597,7 +660,8 @@ export namespace Docs {
* might involve arbitrary recursion (since toField might itself call convertObject)
*/
const convertObject = (object: any, title?: string): Doc => {
- let target = new Doc(), result: Opt<Field>;
+ const target = new Doc();
+ let result: Opt<Field>;
Object.keys(object).map(key => (result = toField(object[key], key)) && (target[key] = result));
title && !target.title && (target.title = title);
return target;
@@ -611,7 +675,8 @@ export namespace Docs {
* might involve arbitrary recursion (since toField might itself call convertList)
*/
const convertList = (list: Array<any>): List<Field> => {
- let target = new List(), result: Opt<Field>;
+ const target = new List();
+ let result: Opt<Field>;
list.map(item => (result = toField(item)) && target.push(result));
return target;
};
@@ -630,44 +695,89 @@ export namespace Docs {
throw new Error(`How did ${data} of type ${typeof data} end up in JSON?`);
};
+ export function DocumentFromField(target: Doc, fieldKey: string, proto?: Doc, options?: DocumentOptions): Doc | undefined {
+ let created: Doc | undefined;
+ let layout: ((fieldKey: string) => string) | undefined;
+ const field = target[fieldKey];
+ const resolved = options || {};
+ if (field instanceof ImageField) {
+ created = Docs.Create.ImageDocument((field).url.href, resolved);
+ layout = ImageBox.LayoutString;
+ } else if (field instanceof Doc) {
+ created = field;
+ } else if (field instanceof VideoField) {
+ created = Docs.Create.VideoDocument((field).url.href, resolved);
+ layout = VideoBox.LayoutString;
+ } else if (field instanceof PdfField) {
+ created = Docs.Create.PdfDocument((field).url.href, resolved);
+ layout = PDFBox.LayoutString;
+ } else if (field instanceof IconField) {
+ created = Docs.Create.IconDocument((field).icon, resolved);
+ layout = IconBox.LayoutString;
+ } else if (field instanceof AudioField) {
+ created = Docs.Create.AudioDocument((field).url.href, resolved);
+ layout = AudioBox.LayoutString;
+ } else if (field instanceof HistogramField) {
+ created = Docs.Create.HistogramDocument((field).HistoOp, resolved);
+ layout = HistogramBox.LayoutString;
+ } else if (field instanceof InkField) {
+ const { selectedColor, selectedWidth, selectedTool } = InkingControl.Instance;
+ created = Docs.Create.InkDocument(selectedColor, selectedTool, Number(selectedWidth), (field).inkData, resolved);
+ layout = InkingStroke.LayoutString;
+ } else if (field instanceof List && field[0] instanceof Doc) {
+ created = Docs.Create.StackingDocument(DocListCast(field), resolved);
+ layout = CollectionView.LayoutString;
+ } else {
+ created = Docs.Create.TextDocument("", { ...{ _width: 200, _height: 25, _autoHeight: true }, ...resolved });
+ layout = FormattedTextBox.LayoutString;
+ }
+ created.layout = layout?.(fieldKey);
+ created.title = fieldKey;
+ proto && (created.proto = Doc.GetProto(proto));
+ return created;
+ }
+
export async function DocumentFromType(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.Create.ImageDocument;
+ if (!options._width) options._width = 300;
}
if (type.indexOf("video") !== -1) {
ctor = Docs.Create.VideoDocument;
+ if (!options._width) options._width = 600;
+ if (!options._height) options._height = options._width * 2 / 3;
}
if (type.indexOf("audio") !== -1) {
ctor = Docs.Create.AudioDocument;
}
if (type.indexOf("pdf") !== -1) {
ctor = Docs.Create.PdfDocument;
- options.nativeWidth = 1200;
- options.nativeHeight = 1200;
+ if (!options._width) options._width = 400;
+ if (!options._height) options._height = options._width * 1200 / 927;
}
if (type.indexOf("excel") !== -1) {
ctor = Docs.Create.DBDocument;
- options.dropAction = "copy";
+ options._dropAction = "copy";
}
if (type.indexOf("html") !== -1) {
if (path.includes(window.location.hostname)) {
- let s = path.split('/');
- let id = s[s.length - 1];
+ const s = path.split('/');
+ const id = s[s.length - 1];
return DocServer.GetRefField(id).then(field => {
if (field instanceof Doc) {
- let alias = Doc.MakeAlias(field);
+ const alias = Doc.MakeAlias(field);
alias.x = options.x || 0;
alias.y = options.y || 0;
- alias.width = options.width || 300;
- alias.height = options.height || options.width || 300;
+ alias._width = options._width || 300;
+ alias._height = options._height || options._width || 300;
return alias;
}
return undefined;
});
}
ctor = Docs.Create.WebDocument;
- options = { height: options.width, ...options, title: path, nativeWidth: undefined };
+ options = { _height: options._width, ...options, title: path, _nativeWidth: undefined };
}
return ctor ? ctor(path, options) : undefined;
}
@@ -693,9 +803,9 @@ export namespace DocUtils {
DocListCastAsync(promoteDoc.links).then(links => {
links && links.map(async link => {
if (link) {
- let a1 = await Cast(link.anchor1, Doc);
+ const a1 = await Cast(link.anchor1, Doc);
if (a1 && Doc.AreProtosEqual(a1, promoteDoc)) link.anchor1 = copy;
- let a2 = await Cast(link.anchor2, Doc);
+ const a2 = await Cast(link.anchor2, Doc);
if (a2 && Doc.AreProtosEqual(a2, promoteDoc)) link.anchor2 = copy;
LinkManager.Instance.deleteLink(link);
LinkManager.Instance.addLink(link);
@@ -708,11 +818,11 @@ export namespace DocUtils {
}
export function MakeLink(source: { doc: Doc, ctx?: Doc }, target: { doc: Doc, ctx?: Doc }, title: string = "", description: string = "", id?: string) {
- let sv = DocumentManager.Instance.getDocumentView(source.doc);
+ const sv = DocumentManager.Instance.getDocumentView(source.doc);
if (sv && sv.props.ContainingCollectionDoc === target.doc) return;
if (target.doc === CurrentUserUtils.UserDocument) return undefined;
- let linkDocProto = new Doc(id, true);
+ const linkDocProto = new Doc(id, true);
UndoManager.RunInBatch(() => {
linkDocProto.type = DocumentType.LINK;
@@ -728,8 +838,8 @@ export namespace DocUtils {
linkDocProto.anchor2Groups = new List<Doc>([]);
linkDocProto.anchor1Timecode = source.doc.currentTimecode;
linkDocProto.anchor2Timecode = target.doc.currentTimecode;
- linkDocProto.layoutKey1 = DocuLinkBox.LayoutString("anchor1");
- linkDocProto.layoutKey2 = DocuLinkBox.LayoutString("anchor2");
+ linkDocProto.layout_key1 = DocuLinkBox.LayoutString("anchor1");
+ linkDocProto.layout_key2 = DocuLinkBox.LayoutString("anchor2");
linkDocProto.width = linkDocProto.height = 0;
linkDocProto.isBackground = true;
linkDocProto.isButton = true;