From e4b22138e39244728144fbdd4c06e439be1b519a Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 10 Apr 2020 13:24:07 -0400 Subject: more cleanup for layoutDoc/dataDoc/rootDoc updates. fix to doc filtering checkboxes getting filtered. fix to template captions. fixes to generalize LabelDoc's buttonParms --- src/new_fields/Doc.ts | 9 +++++---- src/new_fields/RichTextField.ts | 4 ++++ 2 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src/new_fields') diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index a9c97fc19..934ba0f60 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -645,11 +645,12 @@ export namespace Doc { Cast(templateFieldValue, listSpec(Doc), [])?.map(d => d instanceof Doc && MakeMetadataFieldTemplate(d, templateDoc)); (Doc.GetProto(templateField)[metadataFieldKey] = ObjectField.MakeCopy(templateFieldValue)); } - if (templateCaptionValue instanceof RichTextField && (templateCaptionValue.Text || templateCaptionValue.Data.toString().includes("dashField"))) { - templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`, { this: Doc.name }); + // copy the textTemplates from 'this' (not 'self') because the layout contains the template info, not the original doc + if (templateCaptionValue instanceof RichTextField && !templateCaptionValue.Empty()) { + templateField["caption-textTemplate"] = ComputedField.MakeFunction(`copyField(this.caption)`); } - if (templateFieldValue instanceof RichTextField && (templateFieldValue.Text || templateFieldValue.Data.toString().includes("dashField"))) { - templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`, { this: Doc.name }); + if (templateFieldValue instanceof RichTextField && !templateFieldValue.Empty()) { + templateField[metadataFieldKey + "-textTemplate"] = ComputedField.MakeFunction(`copyField(this.${metadataFieldKey})`); } // get the layout string that the template uses to specify its layout diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index a5a81f4a4..5cf0e0cc3 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -19,6 +19,10 @@ export class RichTextField extends ObjectField { this.Text = text; } + Empty() { + return !(this.Text || this.Data.toString().includes("dashField")); + } + [Copy]() { return new RichTextField(this.Data, this.Text); } -- cgit v1.2.3-70-g09d2 From 7afce5c0ba803b66f3b8c6722f25604290abc1c1 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sat, 11 Apr 2020 15:59:14 -0400 Subject: fixed deiconifying things. fixed interactions with backgrounds to allow their content to be active. added overflow flag for collection freeforms. --- src/client/views/DocComponent.tsx | 2 +- src/client/views/collections/CollectionDockingView.tsx | 2 +- .../collections/collectionFreeForm/CollectionFreeFormView.tsx | 6 +++--- .../views/collections/collectionFreeForm/MarqueeView.tsx | 10 ++++++++-- src/new_fields/documentSchemas.ts | 1 + src/server/authentication/models/current_user_utils.ts | 4 ++-- 6 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index c97e46f91..b1bd4191c 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -115,7 +115,7 @@ export function ViewBoxAnnotatableComponent

this.props.whenActiveChanged(this._isChildActive = isActive)); active = (outsideReaction?: boolean) => ((InkingControl.Instance.selectedTool === InkTool.None && !this.props.Document.isBackground) && ((this.props.Document.forceActive && this.props.rootSelected(outsideReaction)) || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) - annotationsActive = (outsideReaction?: boolean) => (InkingControl.Instance.selectedTool !== InkTool.None || + annotationsActive = (outsideReaction?: boolean) => (InkingControl.Instance.selectedTool !== InkTool.None || (this.props.Document.isBackground && this.props.active()) || (this.props.Document.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) } return Component; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 28aaf0c57..d77ef812f 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -773,7 +773,7 @@ export class DockedFrameRenderer extends React.Component { return CollectionDockingView.AddRightSplit(doc, libraryPath); } else if (location === "close") { return CollectionDockingView.CloseRightSplit(doc); - } else { + } else {// if (location === "inPlace") { return CollectionDockingView.Instance.AddTab(this._stack, doc, libraryPath); } } diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index b5bcc0cc2..e4e1a543a 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -67,7 +67,7 @@ export const panZoomSchema = createSchema({ type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof documentSchema, typeof positionSchema, typeof pageSchema]>; const PanZoomDocument = makeInterface(panZoomSchema, documentSchema, positionSchema, pageSchema); export type collectionFreeformViewProps = { - forceScaling?:boolean; // whether to force scaling of content (needed by ImageBox) + forceScaling?: boolean; // whether to force scaling of content (needed by ImageBox) }; @observer @@ -138,7 +138,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u @undoBatch @action onInternalDrop = (e: Event, de: DragManager.DropEvent) => { - if (this.props.Document.isBackground) return false; + // if (this.props.Document.isBackground) return false; const xf = this.getTransform(); const xfo = this.getTransformOverlay(); const [xp, yp] = xf.transformPoint(de.x, de.y); @@ -164,7 +164,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument, u const nh = NumCast(layoutDoc._nativeHeight); layoutDoc._height = nw && nh ? nh / nw * NumCast(layoutDoc._width) : 300; } - this.bringToFront(d); + d.isBackground === undefined && this.bringToFront(d); })); (de.complete.docDragData.droppedDocuments.length === 1 || de.shiftKey) && this.updateClusterDocs(de.complete.docDragData.droppedDocuments); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index ec2b2749c..96a7c4fc0 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -586,13 +586,19 @@ export class MarqueeView extends React.Component + return

{/* */}
; } render() { - return
e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> + return
e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}> {this._visible ? this.marqueeDiv : null} {this.props.children}
; diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index a640862f3..b11941f40 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -33,6 +33,7 @@ export const documentSchema = createSchema({ color: "string", // foreground color of document backgroundColor: "string", // background color of document opacity: "number", // opacity of document + overflow: "string", // sets overflow behvavior for CollectionFreeForm views creationDate: DateField, // when the document was created links: listSpec(Doc), // computed (readonly) list of links associated with this document onClick: ScriptField, // script to run when document is clicked (can be overriden by an onClick prop) diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index b4dc17178..5e0e9ad67 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -57,9 +57,9 @@ export class CurrentUserUtils { doc.iconView = new PrefetchProxy(Docs.Create.TextDocument("", { title: "icon", _width: 150, _height: 30, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") })); Doc.GetProto(doc.iconView as any as Doc).icon = new RichTextField('{"doc":{"type":"doc","content":[{"type":"paragraph","attrs":{"align":null,"color":null,"id":null,"indent":null,"inset":null,"lineSpacing":null,"paddingBottom":null,"paddingTop":null},"content":[{"type":"dashField","attrs":{"fieldKey":"title","docid":""}}]}]},"selection":{"type":"text","anchor":2,"head":2},"storedMarks":[]}', ""); doc.isTemplateDoc = makeTemplate(doc.iconView as any as Doc); - doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") })); + doc.iconImageView = new PrefetchProxy(Docs.Create.ImageDocument("http://www.cs.brown.edu/~bcz/face.gif", { title: "data", _width: 50, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") })); doc.isTemplateDoc = makeTemplate(doc.iconImageView as any as Doc, true, "image_icon"); - doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(this)") })); + doc.iconColView = new PrefetchProxy(Docs.Create.TreeDocument([], { title: "data", _width: 180, _height: 80, isTemplateDoc: true, onClick: ScriptField.MakeScript("deiconifyView(self)") })); doc.isTemplateDoc = makeTemplate(doc.iconColView as any as Doc, true, "collection_icon"); doc.iconViews = Docs.Create.TreeDocument([doc.iconView as any as Doc, doc.iconImageView as any as Doc, doc.iconColView as any as Doc], { title: "icon types", _height: 75 }); } -- cgit v1.2.3-70-g09d2 From 09793f930a79e9d07a2060578a851ac617e94bc7 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Sun, 12 Apr 2020 11:26:07 -0400 Subject: changes to treeView titles - show alias/proto. setInPlace --- src/client/views/collections/CollectionTreeView.tsx | 16 ++++++++++------ src/new_fields/Doc.ts | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index fd84c6498..23fb259fc 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -182,14 +182,17 @@ class TreeView extends React.Component { GetValue={() => StrCast(this.props.document[key])} SetValue={undoBatch((value: string) => { Doc.SetInPlace(this.props.document, key, value, false) || true; - this.props.document.editTitle = undefined; + Doc.SetInPlace(this.props.document, "editTitle", undefined, false); + //this.props.document.editTitle = undefined; })} OnFillDown={undoBatch((value: string) => { Doc.SetInPlace(this.props.document, key, value, false); const doc = Docs.Create.FreeformDocument([], { title: "-", x: 0, y: 0, _width: 100, _height: 25, templates: new List([Templates.Title.Layout]) }); //EditableView.loadId = doc[Id]; - this.props.document.editTitle = undefined; - doc.editTitle = true; + Doc.SetInPlace(this.props.document, "editTitle", undefined, false); + // this.props.document.editTitle = undefined; + Doc.SetInPlace(this.props.document, "editTitle", true, false); + //doc.editTitle = true; return this.props.addDocument(doc); })} onClick={() => { @@ -306,7 +309,7 @@ class TreeView extends React.Component { const rows: JSX.Element[] = []; for (const key of Object.keys(ids).slice().sort()) { - if (this.props.ignoreFields?.includes(key)) continue; + if (this.props.ignoreFields?.includes(key) || key === "title" || key === "treeViewOpen") continue; const contents = doc[key]; let contentElement: (JSX.Element | null)[] | JSX.Element = []; @@ -423,7 +426,7 @@ class TreeView extends React.Component { @computed get renderTitle() { const onItemDown = SetupDrag(this._tref, () => this.dataDoc, this.move, this.props.dropAction, this.props.treeViewId[Id], true); - const editTitle = ScriptField.MakeFunction("this.editTitle=true", { this: Doc.name }); + const editTitle = ScriptField.MakeFunction("setInPlace(this, 'editTitle', true)"); const headerElements = ( { style={{ background: Doc.IsHighlighted(this.props.document) ? "orange" : Doc.IsBrushed(this.props.document) ? "#06121212" : "0", fontWeight: this.props.document.searchMatch ? "bold" : undefined, + textDecoration: Doc.GetT(this.props.document, "title", "string", true) ? "underline" : undefined, outline: BoolCast(this.props.document.workspaceBrush) ? "dashed 1px #06123232" : undefined, pointerEvents: this.props.active() || SelectionManager.GetIsDragging() ? "all" : "none" }} > - {this.props.document.editTitle ? + {Doc.GetT(this.props.document, "editTitle", "boolean", true) ? this.editableView("title") : Date: Sun, 12 Apr 2020 21:36:26 -0700 Subject: rough pass at collection map view --- package-lock.json | 68 +++++++++++++++----- package.json | 6 +- src/client/Network.ts | 13 ++++ src/client/cognitive_services/CognitiveServices.ts | 1 - src/client/documents/Documents.ts | 9 ++- src/client/views/Main.tsx | 1 - .../views/collections/CollectionMapView.scss | 4 ++ src/client/views/collections/CollectionMapView.tsx | 72 ++++++++++++++++++++++ src/client/views/collections/CollectionView.tsx | 10 ++- src/new_fields/Types.ts | 1 + webpack.config.js | 55 ++++++++++------- 11 files changed, 195 insertions(+), 45 deletions(-) create mode 100644 src/client/views/collections/CollectionMapView.scss create mode 100644 src/client/views/collections/CollectionMapView.tsx (limited to 'src/new_fields') diff --git a/package-lock.json b/package-lock.json index 1949a8a5c..f40dc7b0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -584,6 +584,20 @@ "@types/node": "*" } }, + "@types/google-maps-react": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/google-maps-react/-/google-maps-react-2.0.4.tgz", + "integrity": "sha512-8EGr84L6ozODnfjWN9xVUFIxFedBbZinuDe5lBEJ757yh/lZqoKkqxrYLqvrLksDRVVwQYwWdFvfEASujmk36A==", + "requires": { + "@types/googlemaps": "*", + "@types/react": "*" + } + }, + "@types/googlemaps": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/@types/googlemaps/-/googlemaps-3.39.3.tgz", + "integrity": "sha512-L8O9HAVFZj0TuiS8h5ORthiMsrrhjxTC8XUusp5k47oXCst4VTm+qWKvrAvmYMybZVokbp4Udco1mNwJrTNZPQ==" + }, "@types/isstream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/@types/isstream/-/isstream-0.1.0.tgz", @@ -750,7 +764,7 @@ }, "@types/passport": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.2.tgz", "integrity": "sha512-Pf39AYKf8q+YoONym3150cEwfUD66dtwHJWvbeOzKxnA0GZZ/vAXhNWv9vMhKyRQBQZiQyWQnhYBEBlKW6G8wg==", "requires": { "@types/express": "*" @@ -5615,7 +5629,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -5633,11 +5648,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5650,15 +5667,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -5761,7 +5781,8 @@ }, "inherits": { "version": "2.0.4", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -5771,6 +5792,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5783,17 +5805,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.9.0", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5810,6 +5835,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -5890,7 +5916,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -5900,6 +5927,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -5975,7 +6003,8 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -6005,6 +6034,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -6022,6 +6052,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -6060,11 +6091,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.1.1", - "bundled": true + "bundled": true, + "optional": true } } }, @@ -6344,6 +6377,11 @@ } } }, + "google-maps-react": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/google-maps-react/-/google-maps-react-2.0.2.tgz", + "integrity": "sha512-6cYauGwt22haDUrWxKQ6yoNOqjiuxHo8YYcmb+aBvNICokdXmZOUB6Ah4vD5VexMVlrwP2PFqA/D8sHpEB52KA==" + }, "google-p12-pem": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-2.0.1.tgz", @@ -14376,7 +14414,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -15990,7 +16028,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { "ansi-regex": "^2.0.0" @@ -18303,7 +18341,7 @@ }, "wrap-ansi": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "requires": { "string-width": "^1.0.1", diff --git a/package.json b/package.json index 440646c48..c742857ad 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "scripts": { "start-release": "cross-env RELEASE=true NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", - "start": "cross-env HANDWRITING='61088486d76c4b12ba578775a5f55422' NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", + "start": "cross-env NODE_OPTIONS=--max_old_space_size=4096 ts-node-dev -- src/server/index.ts", "debug": "cross-env NODE_OPTIONS=--max_old_space_size=8192 ts-node-dev --inspect -- src/server/index.ts", "build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 webpack --env production", "test": "mocha -r ts-node/register test/**/*.ts", @@ -83,6 +83,7 @@ "@types/express-validator": "^3.0.0", "@types/formidable": "^1.0.31", "@types/gapi": "0.0.39", + "@types/google-maps-react": "^2.0.4", "@types/jquery": "^3.3.31", "@types/jquery-awesome-cursor": "^0.3.0", "@types/jsonwebtoken": "^8.3.7", @@ -162,6 +163,7 @@ "formidable": "^1.2.1", "golden-layout": "^1.5.9", "google-auth-library": "^4.2.4", + "google-maps-react": "^2.0.2", "googleapis": "^40.0.0", "googlephotos": "^0.2.5", "howler": "^2.1.3", @@ -258,4 +260,4 @@ "xoauth2": "^1.2.0", "youtube": "^0.1.0" } -} +} \ No newline at end of file diff --git a/src/client/Network.ts b/src/client/Network.ts index 6982ecf19..bd0e6e61a 100644 --- a/src/client/Network.ts +++ b/src/client/Network.ts @@ -4,10 +4,23 @@ import { Upload } from "../server/SharedMediaTypes"; export namespace Networking { + const EnvVarCache = new Map(); + export async function FetchFromServer(relativeRoute: string) { return (await fetch(relativeRoute)).text(); } + export async function FetchEnvironmentVariable(varNameLiteral: string) { + let resolved = EnvVarCache.get(varNameLiteral); + if (!resolved) { + resolved = await FetchFromServer(`/environment/${varNameLiteral}`); + if (resolved !== undefined) { + EnvVarCache.set(varNameLiteral, resolved); + } + } + return resolved; + } + export async function PostToServer(relativeRoute: string, body?: any) { const options = { uri: Utils.prepend(relativeRoute), diff --git a/src/client/cognitive_services/CognitiveServices.ts b/src/client/cognitive_services/CognitiveServices.ts index 5d83de233..3133bf4b1 100644 --- a/src/client/cognitive_services/CognitiveServices.ts +++ b/src/client/cognitive_services/CognitiveServices.ts @@ -8,7 +8,6 @@ import { UndoManager } from "../util/UndoManager"; import requestPromise = require("request-promise"); import { List } from "../../new_fields/List"; import { ClientRecommender } from "../ClientRecommender"; -import { ImageBox } from "../views/nodes/ImageBox"; type APIManager = { converter: BodyConverter, requester: RequestExecutor }; type RequestExecutor = (apiKey: string, body: string, service: Service) => Promise; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 703c049cd..43e379125 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -49,6 +49,8 @@ import { ContextMenuProps } from "../views/ContextMenuItem"; import { ContextMenu } from "../views/ContextMenu"; import { LinkBox } from "../views/nodes/LinkBox"; import { ScreenshotBox } from "../views/nodes/ScreenshotBox"; +import CollectionMapView from "../views/collections/CollectionMapView"; +import LocationField, { LocationData } from "../../new_fields/LocationField"; const requestImageSize = require('../util/request-image-size'); const path = require('path'); @@ -277,8 +279,7 @@ export namespace Docs { }], [DocumentType.SCREENSHOT, { layout: { view: ScreenshotBox, dataField: data }, - options: {} - }] + }], ]); // All document prototypes are initialized with at least these values @@ -624,6 +625,10 @@ export namespace Docs { 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 MapDocument(documents: Array, options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), options); + } + export function CarouselDocument(documents: Array, options: DocumentOptions) { return InstanceFromProto(Prototypes.get(DocumentType.COL), new List(documents), { _chromeStatus: "collapsed", schemaColumns: new List([new SchemaHeaderField("title", "#f1efeb")]), ...options, _viewType: CollectionViewType.Carousel }); } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 6d705aa44..b21eb9c8f 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -5,7 +5,6 @@ import * as ReactDOM from 'react-dom'; import * as React from 'react'; import { DocServer } from "../DocServer"; import { AssignAllExtensions } from "../../extensions/General/Extensions"; -process.env.HANDWRITING = "61088486d76c4b12ba578775a5f55422"; AssignAllExtensions(); diff --git a/src/client/views/collections/CollectionMapView.scss b/src/client/views/collections/CollectionMapView.scss new file mode 100644 index 000000000..c74433902 --- /dev/null +++ b/src/client/views/collections/CollectionMapView.scss @@ -0,0 +1,4 @@ +.collectionMapView-contents { + width: 100%; + height: 100%; +} \ No newline at end of file diff --git a/src/client/views/collections/CollectionMapView.tsx b/src/client/views/collections/CollectionMapView.tsx new file mode 100644 index 000000000..49411f61b --- /dev/null +++ b/src/client/views/collections/CollectionMapView.tsx @@ -0,0 +1,72 @@ +import { observer } from "mobx-react"; +import { makeInterface } from "../../../new_fields/Schema"; +import { documentSchema } from "../../../new_fields/documentSchemas"; +import React = require("react"); +import { Map, Marker, MapProps, GoogleApiWrapper } from "google-maps-react"; +import { NumCast, StrCast } from "../../../new_fields/Types"; +import { CollectionSubView } from "./CollectionSubView"; +import { Utils } from "../../../Utils"; + +type MapDocument = makeInterface<[typeof documentSchema]>; +const MapDocument = makeInterface(documentSchema); + +export type LocationData = google.maps.LatLngLiteral & { address?: string }; + +@observer +class CollectionMapView extends CollectionSubView & { google: any }>(MapDocument) { + + render() { + const { childLayoutPairs, props } = this; + const { Document } = props; + const center: LocationData = { lat: NumCast(Document.mapCenterLat), lng: NumCast(Document.mapCenterLng) }; + if (!center.lat) { + center.lat = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLat, 0) : 0; + center.lng = childLayoutPairs.length ? NumCast(childLayoutPairs[0].layout.locationLng, 0) : 0; + } + return ( +
+ + {childLayoutPairs.map(({ layout }) => { + const location: LocationData = { + lat: NumCast(childLayoutPairs[0].layout.locationLat, 0), + lng: NumCast(childLayoutPairs[0].layout.locationLng, 0) + }; + const iconSize = new google.maps.Size(NumCast(layout.mapIconWidth, 45), NumCast(layout.mapIconHeight, 45)); + return ( + { + Document.mapCenterLat = location.lat; + Document.mapCenterLng = location.lng; + }} + icon={{ + size: iconSize, + scaledSize: iconSize, + url: StrCast(Document.mapIconUrl, "https://www.pinclipart.com/picdir/middle/359-3598915_map-marker-icon-location-icon-png-clipart.png") + }} + /> + ); + })} + +
+ ); + } + +} + +declare var process: { + env: { + GOOGLE_MAPS_API_KEY: string; + } +}; + +export default GoogleApiWrapper({ apiKey: process.env.GOOGLE_MAPS_API_KEY })(CollectionMapView) as any; \ No newline at end of file diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 821840e0b..d1dc32829 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -1,7 +1,7 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faEye, faEdit } from '@fortawesome/free-regular-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { faColumns, faCopy, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree } from '@fortawesome/free-solid-svg-icons'; +import { faColumns, faCopy, faEllipsisV, faFingerprint, faImage, faProjectDiagram, faSignature, faSquare, faTh, faThList, faTree, faGlobeAmericas } from '@fortawesome/free-solid-svg-icons'; import { action, observable, computed } from 'mobx'; import { observer } from "mobx-react"; import * as React from 'react'; @@ -44,12 +44,15 @@ import { Docs } from '../../documents/Documents'; import { ScriptField, ComputedField } from '../../../new_fields/ScriptField'; import { InteractionUtils } from '../../util/InteractionUtils'; import { ObjectField } from '../../../new_fields/ObjectField'; +import CollectionMapView from './CollectionMapView'; +import { ClientUtils } from '../../util/ClientUtils'; +import { GoogleApiWrapper } from 'google-maps-react'; const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; export const COLLECTION_BORDER_WIDTH = 2; const path = require('path'); -library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faEllipsisV, faImage, faEye as any, faCopy); +library.add(faTh, faTree, faSquare, faProjectDiagram, faSignature, faThList, faFingerprint, faColumns, faGlobeAmericas, faEllipsisV, faImage, faEye as any, faCopy); export enum CollectionViewType { Invalid = "invalid", @@ -65,6 +68,7 @@ export enum CollectionViewType { Carousel = "carousel", Linear = "linear", Staff = "staff", + Map = "map" } export interface CollectionRenderProps { @@ -170,6 +174,7 @@ export class CollectionView extends Touchable { case CollectionViewType.Stacking: { this.props.Document.singleColumn = true; return (); } case CollectionViewType.Masonry: { this.props.Document.singleColumn = false; return (); } case CollectionViewType.Time: { return (); } + case CollectionViewType.Map: return (); case CollectionViewType.Freeform: default: { this.props.Document._freeformLayoutEngine = undefined; return (); } } @@ -211,6 +216,7 @@ export class CollectionView extends Touchable { subItems.push({ description: "Masonry", event: () => this.props.Document._viewType = CollectionViewType.Masonry, icon: "columns" }); subItems.push({ description: "Carousel", event: () => this.props.Document._viewType = CollectionViewType.Carousel, icon: "columns" }); subItems.push({ description: "Pivot/Time", event: () => this.props.Document._viewType = CollectionViewType.Time, icon: "columns" }); + subItems.push({ description: "Map", event: () => this.props.Document._viewType = CollectionViewType.Map, icon: "globe-americas" }); switch (this.props.Document._viewType) { case CollectionViewType.Freeform: { subItems.push({ description: "Custom", icon: "fingerprint", event: AddCustomFreeFormLayout(this.props.Document, this.props.fieldKey) }); diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 0ca35fab2..aa44cefa0 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -87,6 +87,7 @@ export function BoolCast(field: FieldResult, defaultVal: boolean | null = false) export function DateCast(field: FieldResult) { return Cast(field, DateField, null); } + export function ScriptCast(field: FieldResult) { return Cast(field, ScriptField, null); } diff --git a/webpack.config.js b/webpack.config.js index 6a14dfcda..655334ef2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,6 +2,14 @@ var path = require('path'); var webpack = require('webpack'); const CopyWebpackPlugin = require("copy-webpack-plugin"); const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin"); +const env = require('dotenv').config().parsed; +const envKeys = Object.keys(env).reduce((prev, next) => { + if (next.startsWith("DASH_")) { + const resolved = next.replace("DASH_", ""); + prev[`process.env.${resolved}`] = JSON.stringify(env[next]); + } + return prev; +}, {}); module.exports = { mode: 'development', @@ -33,17 +41,18 @@ module.exports = { extensions: ['.js', '.ts', '.tsx'] }, module: { - rules: [ - { + rules: [{ test: [/\.tsx?$/], - use: [ - { loader: 'ts-loader', options: { transpileOnly: true } } - ] + use: [{ + loader: 'ts-loader', + options: { + transpileOnly: true + } + }] }, { test: /\.scss|css$/, - use: [ - { + use: [{ loader: "style-loader" }, { @@ -56,28 +65,30 @@ module.exports = { }, { test: /\.(jpg|png|pdf)$/, - use: [ - { - loader: 'file-loader' - } - ] + use: [{ + loader: 'file-loader' + }] }, { test: /\.(png|jpg|gif)$/i, - use: [ - { - loader: 'url-loader', - options: { - limit: 8192 - } + use: [{ + loader: 'url-loader', + options: { + limit: 8192 } - ] - }] + }] + } + ] }, plugins: [ - new CopyWebpackPlugin([{ from: "deploy", to: path.join(__dirname, "build") }]), + new CopyWebpackPlugin([{ + from: "deploy", + to: path.join(__dirname, "build") + }]), + new webpack.DefinePlugin(envKeys), new ForkTsCheckerWebpackPlugin({ - tslint: true, useTypescriptIncrementalApi: true + tslint: true, + useTypescriptIncrementalApi: true }), new webpack.optimize.OccurrenceOrderPlugin(), new webpack.HotModuleReplacementPlugin(), -- cgit v1.2.3-70-g09d2 From 130e26103461f23a2d8b57ea2eef6b17eefb8f8e Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 13 Apr 2020 21:46:20 -0400 Subject: updated childDetailedView stuff for pivot view --- src/client/views/TemplateMenu.tsx | 4 ++-- src/client/views/collections/CollectionTimeView.tsx | 10 ++++++---- src/client/views/collections/CollectionTreeView.tsx | 2 +- src/client/views/collections/CollectionView.tsx | 4 ++-- src/client/views/collections/CollectionViewChromes.tsx | 4 ++-- src/client/views/nodes/DocumentView.tsx | 8 ++++---- src/new_fields/Doc.ts | 8 -------- src/new_fields/documentSchemas.ts | 2 +- 8 files changed, 18 insertions(+), 24 deletions(-) (limited to 'src/new_fields') diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 4d7f1e443..b76137f06 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -167,8 +167,8 @@ export class TemplateMenu extends React.Component { } } -Scripting.addGlobal(function switchView(doc: Doc, template: Doc) { - if (template.dragFactory) { +Scripting.addGlobal(function switchView(doc: Doc, template: Doc | undefined) { + if (template?.dragFactory) { template = Cast(template.dragFactory, Doc, null); } const templateTitle = StrCast(template?.title); diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx index 53de2fbbe..31b720b81 100644 --- a/src/client/views/collections/CollectionTimeView.tsx +++ b/src/client/views/collections/CollectionTimeView.tsx @@ -5,7 +5,7 @@ import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; import { RichTextField } from "../../../new_fields/RichTextField"; import { ComputedField, ScriptField } from "../../../new_fields/ScriptField"; -import { NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; +import { NumCast, StrCast, BoolCast, Cast } from "../../../new_fields/Types"; import { emptyFunction, returnFalse, setupMoveUpEvents } from "../../../Utils"; import { Scripting } from "../../util/Scripting"; import { ContextMenu } from "../ContextMenu"; @@ -19,6 +19,7 @@ const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; import React = require("react"); +import { DocumentView } from "../nodes/DocumentView"; @observer export class CollectionTimeView extends CollectionSubView(doc => doc) { @@ -28,14 +29,15 @@ export class CollectionTimeView extends CollectionSubView(doc => doc) { componentWillUnmount() { this.props.Document.onChildClick = undefined; } - componentDidMount() { - const childDetailed = this.props.Document.childDetailed; // bcz: needs to be here to make sure the childDetailed layout template has been loaded when the first item is clicked; - const childText = "const alias = getAlias(this); Doc.ApplyTemplateTo(thisContainer.childDetailed, alias, 'layout_detailView'); alias.layoutKey='layout_detailedView'; alias.dropAction='alias'; alias.removeDropProperties=new List(['dropAction']); useRightSplit(alias, shiftKey); "; + async componentDidMount() { + const childText = "const alias = getAlias(this); switchView(alias, thisContainer.childDetailView); alias.dropAction='alias'; alias.removeDropProperties=new List(['dropAction']); useRightSplit(alias, shiftKey); "; this.props.Document.onChildClick = ScriptField.MakeScript(childText, { this: Doc.name, heading: "string", thisContainer: Doc.name, shiftKey: "boolean" }); this.props.Document._fitToBox = true; if (!this.props.Document.onViewDefClick) { this.props.Document.onViewDefDivClick = ScriptField.MakeScript("pivotColumnClick(this,payload)", { payload: "any" }); } + this.props.Document.childDetailView = Cast(this.props.Document.childDetailView, Doc, null) ||// bcz: needs to be here to make sure the childDetailView layout template has been loaded when the first item is clicked; + DocumentView.findTemplate("detailView", StrCast(this.props.Document.type), ""); } layoutEngine = () => this._layoutEngine; diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 23fb259fc..b96ee4bc4 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -754,7 +754,7 @@ export class CollectionTreeView extends CollectionSubView(Document, undefined as })); Document.childLayout = heroView; - Document.childDetailed = detailView; + Document.childDetailView = detailView; Document._viewType = CollectionViewType.Time; Document._forceActive = true; Document._pivotField = "company"; diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index 8cc5146d5..f94277862 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -232,8 +232,8 @@ export class CollectionView extends Touchable { if (this.props.Document.childLayout instanceof Doc) { layoutItems.push({ description: "View Child Layout", event: () => this.props.addDocTab(this.props.Document.childLayout as Doc, "onRight"), icon: "project-diagram" }); } - if (this.props.Document.childDetailed instanceof Doc) { - layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailed as Doc, "onRight"), icon: "project-diagram" }); + if (this.props.Document.childDetailView instanceof Doc) { + layoutItems.push({ description: "View Child Detailed Layout", event: () => this.props.addDocTab(this.props.Document.childDetailView as Doc, "onRight"), icon: "project-diagram" }); } layoutItems.push({ description: `${this.props.Document.isInPlaceContainer ? "Unset" : "Set"} inPlace Container`, event: () => this.props.Document.isInPlaceContainer = !this.props.Document.isInPlaceContainer, icon: "project-diagram" }); diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx index ba95dce00..e494c337a 100644 --- a/src/client/views/collections/CollectionViewChromes.tsx +++ b/src/client/views/collections/CollectionViewChromes.tsx @@ -48,8 +48,8 @@ export class CollectionViewBaseChrome extends React.Component click item view", - script: "this.target.childDetailed = getDocTemplate(this.source?.[0])", - immediate: (source: Doc[]) => this.target.childDetailed = Doc.getDocTemplate(source?.[0]), + script: "this.target.childDetailView = getDocTemplate(this.source?.[0])", + immediate: (source: Doc[]) => this.target.childDetailView = Doc.getDocTemplate(source?.[0]), initialize: emptyFunction, }; _contentCommand = { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cc3c39154..5b6478e66 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -541,7 +541,7 @@ export class DocumentView extends DocComponent(Docu deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); } // applies a custom template to a document. the template is identified by it's short name (e.g, slideView not layout_slideView) - static makeCustomViewClicked = (doc: Doc, creator: (documents: Array, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { + static makeCustomViewClicked = (doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { const batch = UndoManager.StartBatch("makeCustomViewClicked"); runInAction(() => { doc.layoutKey = "layout_" + templateSignature; @@ -563,7 +563,7 @@ export class DocumentView extends DocComponent(Docu !docLayoutTemplate && allTemplates.forEach(tempDoc => StrCast(tempDoc.title) === templateName && (docLayoutTemplate = tempDoc)); return docLayoutTemplate; } - static createCustomView = (doc: Doc, creator: (documents: Array, options: DocumentOptions, id?: string) => Doc, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { + static createCustomView = (doc: Doc, creator: Opt<(documents: Array, options: DocumentOptions, id?: string) => Doc>, templateSignature: string = "custom", docLayoutTemplate?: Doc) => { const templateName = templateSignature.replace(/\(.*\)/, ""); docLayoutTemplate = docLayoutTemplate || DocumentView.findTemplate(templateName, StrCast(doc.type), templateSignature); @@ -584,10 +584,10 @@ export class DocumentView extends DocComponent(Docu } else if (doc.data instanceof ImageField) { fieldTemplate = Docs.Create.ImageDocument("http://www.cs.brown.edu", options); } - const docTemplate = docLayoutTemplate || creator(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); + const docTemplate = docLayoutTemplate || creator?.(fieldTemplate ? [fieldTemplate] : [], { title: customName + "(" + doc.title + ")", isTemplateDoc: true, _width: _width + 20, _height: Math.max(100, _height + 45) }); fieldTemplate && Doc.MakeMetadataFieldTemplate(fieldTemplate, Doc.GetProto(docTemplate)); - Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); + docTemplate && Doc.ApplyTemplateTo(docTemplate, doc, customName, undefined); } @undoBatch diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 92abb7a71..bcf0d1aec 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -603,14 +603,6 @@ export namespace Doc { return undefined; } export function ApplyTemplateTo(templateDoc: Doc, target: Doc, targetKey: string, titleTarget: string | undefined) { - if (!templateDoc) { - target.layout = undefined; - target._nativeWidth = undefined; - target._nativeHeight = undefined; - target.type = undefined; - return; - } - if (!Doc.AreProtosEqual(target[targetKey] as Doc, templateDoc)) { if (target.resolvedDataDoc) { target[targetKey] = new PrefetchProxy(templateDoc); diff --git a/src/new_fields/documentSchemas.ts b/src/new_fields/documentSchemas.ts index b11941f40..bc63e9df8 100644 --- a/src/new_fields/documentSchemas.ts +++ b/src/new_fields/documentSchemas.ts @@ -74,7 +74,7 @@ export const positionSchema = createSchema({ export const collectionSchema = createSchema({ childLayout: Doc, // layout template for children of a collecion - childDetailed: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field) + childDetailView: Doc, // layout template to apply to a child when its clicked on in a collection and opened (requires onChildClick or other script to use this field) onChildClick: ScriptField, // script to run for each child when its clicked onCheckedClick: ScriptField, // script to run when a checkbox is clicked next to a child in a tree view }); -- cgit v1.2.3-70-g09d2