diff options
Diffstat (limited to 'src/client/documents/Documents.ts')
-rw-r--r-- | src/client/documents/Documents.ts | 184 |
1 files changed, 79 insertions, 105 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 7f82280c5..84e6258ac 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -1,7 +1,8 @@ +import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { action, runInAction } from "mobx"; import { basename } from "path"; import { DateField } from "../../fields/DateField"; -import { Doc, DocListCast, DocListCastAsync, Field, HeightSym, Initializing, Opt, updateCachedAcls, WidthSym } from "../../fields/Doc"; +import { Doc, DocListCast, DocListCastAsync, Field, Initializing, Opt, updateCachedAcls } from "../../fields/Doc"; import { Id } from "../../fields/FieldSymbols"; import { HtmlField } from "../../fields/HtmlField"; import { InkField, PointData } from "../../fields/InkField"; @@ -14,7 +15,7 @@ import { Cast, NumCast, StrCast } from "../../fields/Types"; import { AudioField, ImageField, MapField, PdfField, RecordingField, VideoField, WebField, YoutubeField } from "../../fields/URLField"; import { SharingPermissions } from "../../fields/util"; import { Upload } from "../../server/SharedMediaTypes"; -import { OmitKeys, Utils, aggregateBounds } from "../../Utils"; +import { aggregateBounds, OmitKeys, Utils } from "../../Utils"; import { YoutubeBox } from "../apis/youtube/YoutubeBox"; import { DocServer } from "../DocServer"; import { Networking } from "../Network"; @@ -33,13 +34,14 @@ import { ContextMenuProps } from "../views/ContextMenuItem"; import { DFLT_IMAGE_NATIVE_DIM } from "../views/global/globalCssVariables.scss"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke } from "../views/InkingStroke"; import { AudioBox } from "../views/nodes/AudioBox"; +import { FontIconBox } from "../views/nodes/button/FontIconBox"; import { ColorBox } from "../views/nodes/ColorBox"; import { ComparisonBox } from "../views/nodes/ComparisonBox"; +import { DataVizBox } from "../views/nodes/DataViz"; import { DocFocusOptions } from "../views/nodes/DocumentView"; import { EquationBox } from "../views/nodes/EquationBox"; import { FieldViewProps } from "../views/nodes/FieldView"; import { FilterBox } from "../views/nodes/FilterBox"; -import { FontIconBox } from "../views/nodes/button/FontIconBox"; import { FormattedTextBox } from "../views/nodes/formattedText/FormattedTextBox"; import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox"; import { ImageBox } from "../views/nodes/ImageBox"; @@ -47,7 +49,9 @@ import { KeyValueBox } from "../views/nodes/KeyValueBox"; import { LabelBox } from "../views/nodes/LabelBox"; import { LinkBox } from "../views/nodes/LinkBox"; import { LinkDescriptionPopup } from "../views/nodes/LinkDescriptionPopup"; +import { MapBox } from "../views/nodes/MapBox/MapBox"; import { PDFBox } from "../views/nodes/PDFBox"; +import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; import { ScreenshotBox } from "../views/nodes/ScreenshotBox"; import { ScriptingBox } from "../views/nodes/ScriptingBox"; import { SliderBox } from "../views/nodes/SliderBox"; @@ -57,11 +61,7 @@ import { PresElementBox } from "../views/nodes/trails/PresElementBox"; import { VideoBox } from "../views/nodes/VideoBox"; import { WebBox } from "../views/nodes/WebBox"; import { SearchBox } from "../views/search/SearchBox"; -import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo"; import { DocumentType } from "./DocumentTypes"; -import { IconProp } from "@fortawesome/fontawesome-svg-core"; -import { MapBox } from "../views/nodes/MapBox/MapBox"; -import { RecordingBox } from "../views/nodes/RecordingBox/RecordingBox"; const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", "")); class EmptyBox { @@ -69,53 +69,57 @@ class EmptyBox { return ""; } } -abstract class FInfo { +export abstract class FInfo { description: string = ""; - type?: string; + fieldType?: string; values?: Field[]; - layoutField?: boolean; // is this field a layout (or datadoc) field // format?: string; // format to display values (e.g, decimal places, $, etc) // parse?: ScriptField; // parse a value from a string - constructor(d: string, l: boolean = false) { this.description = d; this.layoutField = l; } + constructor(d: string) { this.description = d; } } -class BoolInfo extends FInfo { type?= "boolean"; values?: boolean[] = [true, false]; } -class NumInfo extends FInfo { type?= "number"; values?: number[] = []; } -class StrInfo extends FInfo { type?= "string"; values?: string[] = []; } -class DocInfo extends FInfo { type?= "Doc"; values?: Doc[] = []; } -class DimInfo extends FInfo { type?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; } -class PEInfo extends FInfo { type?= "pointerEvents"; values?= ["all", "none"]; } -class DAInfo extends FInfo { type?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; } +class BoolInfo extends FInfo { fieldType?= "boolean"; values?: boolean[] = [true, false]; } +class NumInfo extends FInfo { fieldType?= "number"; values?: number[] = []; constructor(d:string, values?:number[]) { super(d); this.values = values; }} +class StrInfo extends FInfo { fieldType?= "string"; values?: string[] = []; constructor(d:string, values?:string[]) { super(d); this.values = values; }} +class DocInfo extends FInfo { fieldType?= "Doc"; values?: Doc[] = []; constructor(d:string, values?:Doc[]) { super(d); this.values = values; }} +class DimInfo extends FInfo { fieldType?= "DimUnit"; values?= [DimUnit.Pixel, DimUnit.Ratio]; } +class PEInfo extends FInfo { fieldType?= "pointerEvents"; values?= ["all", "none"]; } +class DAInfo extends FInfo { fieldType?= "dropActionType"; values?= ["alias", "copy", "move", "same", "proto", "none"]; } type BOOLt = BoolInfo | boolean; -type NUMt = NumInfo | number; -type STRt = StrInfo | string; -type DOCt = DocInfo | Doc; -type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio; -type PEVt = PEInfo | "none" | "all"; +type NUMt = NumInfo | number; +type STRt = StrInfo | string; +type DOCt = DocInfo | Doc; +type DIMt = DimInfo | typeof DimUnit.Pixel | typeof DimUnit.Ratio; +type PEVt = PEInfo | "none" | "all"; type DROPt = DAInfo | dropActionType; export class DocumentOptions { + x?: NUMt = new NumInfo("x coordinate of document in a freeform view"); + y?: NUMt = new NumInfo("y coordinage of document in a freeform view"); + z?: NUMt = new NumInfo("whether document is in overlay (1) or not (0)", [1,0]); system?: BOOLt = new BoolInfo("is this a system created/owned doc"); + type?: STRt = new StrInfo("type of document", Array.from(Object.keys(DocumentType))); + title?: string; _dropAction?: DROPt = new DAInfo("what should happen to this document when it's dropped somewhere else"); allowOverlayDrop?: BOOLt = new BoolInfo("can documents be dropped onto this document without using dragging title bar or holding down embed key (ctrl)?"); childDropAction?: DROPt = new DAInfo("what should happen to the source document when it's dropped onto a child of a collection "); targetDropAction?: DROPt = new DAInfo("what should happen to the source document when ??? "); - userColor?: string; // color associated with a Dash user (seen in header fields of shared documents) - color?: string; // foreground color data doc + userColor?: STRt = new StrInfo("color associated with a Dash user (seen in header fields of shared documents)"); + color?: STRt = new StrInfo("foreground color data doc"); backgroundColor?: STRt = new StrInfo("background color for data doc"); - _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)", true); - _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents", true); - _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title", true); - _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes", true); - _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume", true); - _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view", true); - _panY?: NUMt = new NumInfo("vertical pan location of a freeform view", true); - _width?: NUMt = new NumInfo("displayed width of a document", true); - _height?: NUMt = new NumInfo("displayed height of document", true); - _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)", true); - _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)", true); - _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height", true); - _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units", true); - _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)", true); - _fitContentsToBox?: boolean; // whether a freeformview should zoom/scale to create a shrinkwrapped view of its contents + _backgroundColor?: STRt = new StrInfo("background color for each template layout doc (overrides backgroundColor)"); + _autoHeight?: BOOLt = new BoolInfo("whether document automatically resizes vertically to display contents"); + _headerHeight?: NUMt = new NumInfo("height of document header used for displaying title"); + _headerFontSize?: NUMt = new NumInfo("font size of header of custom notes"); + _headerPointerEvents?: PEVt = new PEInfo("types of events the header of a custom text document can consume"); + _panX?: NUMt = new NumInfo("horizontal pan location of a freeform view"); + _panY?: NUMt = new NumInfo("vertical pan location of a freeform view"); + _width?: NUMt = new NumInfo("displayed width of a document"); + _height?: NUMt = new NumInfo("displayed height of document"); + _nativeWidth?: NUMt = new NumInfo("native width of document contents (e.g., the pixel width of an image)"); + _nativeHeight?: NUMt = new NumInfo("native height of document contents (e.g., the pixel height of an image)"); + _dimMagnitude?: NUMt = new NumInfo("magnitude of collectionMulti{row,col} element's width or height"); + _dimUnit?: DIMt = new DimInfo("units of collectionMulti{row,col} element's width or height - 'px' or '*' for pixels or relative units"); + _fitWidth?: BOOLt = new BoolInfo("whether document should scale its contents to fit its rendered width or not (e.g., for PDFviews)"); + _fitContentsToBox?: BOOLt = new BoolInfo("whether a freeformview should zoom/scale to create a shrinkwrapped view of its content"); _contentBounds?: List<number>; // the (forced) bounds of the document to display. format is: [left, top, right, bottom] _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 @@ -155,23 +159,20 @@ export class DocumentOptions { _timecodeToShow?: number; // the time that a document should be displayed (e.g., when an annotation shows up as a video plays) _timecodeToHide?: number; // the time that a document should be hidden _timelineLabel?: boolean; // whether the document exists on a timeline - "_carousel-caption-xMargin"?: number; - "_carousel-caption-yMargin"?: number; - "icon-nativeWidth"?: number; - "icon-nativeHeight"?: number; - "dragFactory-count"?: number; // number of items created from a drag button (used for setting title with incrementing index) - x?: number; - y?: number; - z?: number; // whether document is in overlay (1) or not (0 or undefined) + "_carousel-caption-xMargin"?: NUMt = new NumInfo("x margin of caption inside of a carouself collection"); + "_carousel-caption-yMargin"?: NUMt = new NumInfo("y margin of caption inside of a carouself collection"); + "icon-nativeWidth"?: NUMt = new NumInfo("native width of icon view"); + "icon-nativeHeight"?: NUMt = new NumInfo("native height of icon view"); + "dragFactory-count"?: NUMt = new NumInfo("number of items created from a drag button (used for setting title with incrementing index)"); lat?: number; lng?: number; infoWindowOpen?: boolean; author?: string; _layoutKey?: string; + fieldValues?: List<any>; // possible field values used by fieldInfos + fieldType?: string; // type of afield used by fieldInfos unrendered?: boolean; // denotes an annotation that is not rendered with a DocumentView (e.g, rtf/pdf text selections and links to scroll locations in web/pdf) - type?: string; - title?: string; - "acl-Public"?: string; // public permissions + "acl-Public"?: string; // public permissions "_acl-Public"?: string; // public permissions version?: string; // version identifier for a document label?: string; @@ -194,6 +195,7 @@ export class DocumentOptions { childLimitHeight?: number; // whether to limit the height of collection children. 0 - means height can be no bigger than width childLayoutTemplate?: Doc; // template for collection to use to render its children (see PresBox layout in tree view) childLayoutString?: string; // template string for collection to use to render its children + childDocumentsActive?: boolean; // whether child documents are active when parent is document active childDontRegisterViews?: boolean; childHideLinkButton?: boolean; // hide link buttons on all children childContextMenuFilters?: List<ScriptField>; @@ -338,33 +340,6 @@ export class DocumentOptions { } export namespace Docs { - const _docOptions = new DocumentOptions(); - - export async function setupFieldInfos() { - return await DocServer.GetRefField("FieldInfos8") as Doc ?? - runInAction(() => { - const infos = new Doc("FieldInfos8", true); - const keys = Object.keys(new DocumentOptions()); - for (const key of keys) { - const options = (_docOptions as any)[key] as FInfo; - const finfo = new Doc(); - finfo.name = key; - switch (options.type) { - case "boolean": finfo.options = new List<boolean>(options.values as any as boolean[]); break; - case "number": finfo.options = new List<number>(options.values as any as number[]); break; - case "Doc": finfo.options = new List<Doc>(options.values as any as Doc[]); break; - default: // string, pointerEvents, dimUnit, dropActionType - finfo.options = new List<string>(options.values as any as string[]); break; - } - finfo.layoutField = options.layoutField; - finfo.description = options.description; - finfo.type = options.type; - infos[key] = finfo; - } - return infos; - }); - } - export let newAccount: boolean = false; export namespace Prototypes { @@ -386,8 +361,8 @@ export namespace Docs { [DocumentType.RTF, { layout: { view: FormattedTextBox, dataField: "text" }, options: { - _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, nativeHeightUnfrozen: true, treeViewGrowsHorizontally: true, - links: "@links(self)" + _height: 35, _xMargin: 10, _yMargin: 10, nativeDimModifiable: true, treeViewGrowsHorizontally: true, + forceReflow: true, links: "@links(self)" } }], [DocumentType.SEARCH, { @@ -424,7 +399,7 @@ export namespace Docs { }], [DocumentType.AUDIO, { layout: { view: AudioBox, dataField: defaultDataKey }, - options: { _height: 100, backgroundColor: "lightGray", links: "@links(self)" } + options: { _height: 100, backgroundColor: "lightGray", forceReflow: true, nativeDimModifiable: true, links: "@links(self)" } }], [DocumentType.REC, { layout: { view: VideoBox, dataField: defaultDataKey }, @@ -436,7 +411,7 @@ export namespace Docs { }], [DocumentType.MAP, { layout: { view: MapBox, dataField: defaultDataKey }, - options: { _height: 600, _width: 800, links: "@links(self)" } + options: { _height: 600, _width: 800, nativeDimModifiable: true, links: "@links(self)" } }], [DocumentType.IMPORT, { layout: { view: DirectoryImportBox, dataField: defaultDataKey }, @@ -474,11 +449,11 @@ export namespace Docs { }], [DocumentType.EQUATION, { layout: { view: EquationBox, dataField: defaultDataKey }, - options: { links: "@links(self)", hideResizeHandles: true, hideDecorationTitle: true } + options: { links: "@links(self)", nativeDimModifiable: true, hideResizeHandles: true, hideDecorationTitle: true } }], [DocumentType.FUNCPLOT, { layout: { view: FunctionPlotBox, dataField: defaultDataKey }, - options: { links: "@links(self)" } + options: { nativeDimModifiable: true, links: "@links(self)" } }], [DocumentType.BUTTON, { layout: { view: LabelBox, dataField: "onClick" }, @@ -517,7 +492,7 @@ export namespace Docs { }], [DocumentType.COMPARISON, { layout: { view: ComparisonBox, dataField: defaultDataKey }, - options: { clipWidth: 50, backgroundColor: "gray", targetDropAction: "alias", links: "@links(self)" } + options: { clipWidth: 50, nativeDimModifiable: true, backgroundColor: "gray", targetDropAction: "alias", links: "@links(self)" } }], [DocumentType.GROUPDB, { data: new List<Doc>(), @@ -528,6 +503,10 @@ export namespace Docs { layout: { view: EmptyBox, dataField: defaultDataKey }, options: { links: "@links(self)" } }], + [DocumentType.DATAVIZ, { + layout: { view: DataVizBox, dataField: defaultDataKey }, + options: { _fitWidth: true, nativeDimModifiable: true, links: "@links(self)" } + }] ]); const suffix = "Proto"; @@ -550,15 +529,6 @@ export namespace Docs { const prototypeIds = Object.values(DocumentType).filter(type => type !== DocumentType.NONE).map(type => type + suffix); // fetch the actual prototype documents from the server const actualProtos = Docs.newAccount ? {} : await DocServer.GetRefFields(prototypeIds); - if (!Docs.newAccount) { - Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeHeightUnfrozen = true; // to avoid having to recreate the DB - Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeHeightUnfrozen = true; - Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeHeightUnfrozen = true; - Cast(actualProtos[DocumentType.WEB + suffix], Doc, null).nativeDimModifiable = true; // to avoid having to recreate the DB - Cast(actualProtos[DocumentType.PDF + suffix], Doc, null).nativeDimModifiable = true; - Cast(actualProtos[DocumentType.RTF + suffix], Doc, null).nativeDimModifiable = true; - } - // update this object to include any default values: DocumentOptions for all prototypes prototypeIds.map(id => { const existing = actualProtos[id] as Doc; @@ -661,7 +631,7 @@ export namespace Docs { const { omit: dataProps, extract: viewProps } = OmitKeys(options, viewKeys, "^_"); dataProps["acl-Override"] = "None"; - dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; + dataProps["acl-Public"] = options["acl-Public"] ? options["acl-Public"] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; dataProps.system = viewProps.system; dataProps.isPrototype = true; @@ -678,7 +648,7 @@ export namespace Docs { const dataDoc = Doc.assign(Doc.MakeDelegate(proto, protoId), dataProps, undefined, true); const viewFirstProps: { [id: string]: any } = {}; - viewFirstProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.UserDoc()?.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; + viewFirstProps["acl-Public"] = options["_acl-Public"] ? options["_acl-Public"] : Doc.defaultAclPrivate ? SharingPermissions.None : SharingPermissions.Augment; viewFirstProps["acl-Override"] = "None"; viewFirstProps.author = Doc.CurrentUserEmail; const viewDoc = Doc.assign(Doc.MakeDelegate(dataDoc, delegId), viewFirstProps, true, true); @@ -702,8 +672,8 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRES), new List<Doc>(), options); } - export function ScriptingDocument(script: Opt<ScriptField>, options: DocumentOptions = {}, fieldKey?: string) { - return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script, + export function ScriptingDocument(script: Opt<ScriptField>|null, options: DocumentOptions = {}, fieldKey?: string) { + return InstanceFromProto(Prototypes.get(DocumentType.SCRIPTING), script ? script: undefined, { ...options, layout: fieldKey ? ScriptingBox.LayoutString(fieldKey) : undefined }); } @@ -792,8 +762,8 @@ export namespace Docs { I.tool = tool; I["text-align"] = "center"; I.title = "ink"; - I.x = options.x; - I.y = options.y; + I.x = options.x as number; + I.y = options.y as number; I._width = options._width as number; I._height = options._height as number; I._fontFamily = "cursive"; @@ -823,7 +793,7 @@ export namespace Docs { const nwid = options._nativeWidth || undefined; const nhght = options._nativeHeight || undefined; if (!nhght && width && height && nwid) options._nativeHeight = Number(nwid) * Number(height) / Number(width); - return InstanceFromProto(Prototypes.get(DocumentType.WEB), url ? new WebField(url) : undefined, options); + return InstanceFromProto(Prototypes.get(DocumentType.WEB), new WebField(url ? url : "http://www.bing.com/"), options); } export function HtmlDocument(html: string, options: DocumentOptions = {}) { @@ -934,6 +904,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.PRESELEMENT), undefined, { ...(options || {}) }); } + export function DataVizDocument(options?: DocumentOptions) { + return InstanceFromProto(Prototypes.get(DocumentType.DATAVIZ), undefined, { title: "Data Viz", ...options }); + } + export function DockDocument(documents: Array<Doc>, config: string, options: DocumentOptions, id?: string) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { freezeChildren: "remove|add", ...options, _viewType: CollectionViewType.Docking, dockingConfig: config }, id); } @@ -1256,8 +1230,8 @@ export namespace DocUtils { return DocServer.GetRefField(id).then(field => { if (field instanceof Doc) { const alias = Doc.MakeAlias(field); - alias.x = options.x || 0; - alias.y = options.y || 0; + alias.x = options.x as number || 0; + alias.y = options.y as number || 0; alias._width = (options._width as number) || 300; alias._height = (options._height as number) || (options._width as number) || 300; return alias; @@ -1289,8 +1263,8 @@ export namespace DocUtils { })) as ContextMenuProps[], icon: "sticky-note" }); - const documentList: ContextMenuProps[] = DocListCast(DocListCast(CurrentUserUtils.MyTools?.data).lastElement()?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ - description: ":" + StrCast(dragDoc.title), + const documentList: ContextMenuProps[] = DocListCast(DocListCast(CurrentUserUtils.MyTools?.data)[0]?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({ + description: ":" + StrCast(dragDoc.title).replace("Untitled ",""), event: undoBatch((args: { x: number, y: number }) => { const newDoc = Doc.copyDragFactory(dragDoc); if (newDoc) { |