From c9f3a1934548169ebe3c2e97968680ff339e304e Mon Sep 17 00:00:00 2001 From: Sam Wilkins Date: Sat, 4 May 2019 18:59:30 -0400 Subject: initial commit - todo: use cursor field rather than generic tuple field --- src/client/northstar/operations/HistogramOperation.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/client/northstar') diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index 5c9c832c0..78b206bdc 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -65,7 +65,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @computed public get FilterString(): string { if (this.OverridingFilters.length > 0) { - return "(" + this.OverridingFilters.filter(fm => fm != null).map(fm => fm.ToPythonString()).join(" || ") + ")"; + return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")"; } let filterModels: FilterModel[] = []; return FilterModel.GetFilterModelsRecursive(this, new Set(), filterModels, true); @@ -89,8 +89,9 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @action public DrillDown(up: boolean) { if (!up) { - if (!this.BarFilterModels.length) + if (!this.BarFilterModels.length) { return; + } this._stackedFilters.push(this.BarFilterModels.map(f => f)); this.OverridingFilters.length = 0; this.OverridingFilters.push(...this._stackedFilters[this._stackedFilters.length - 1]); -- cgit v1.2.3-70-g09d2 From 168cd36282087bbf9e0157352a129d90b20b7394 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 9 May 2019 14:40:03 -0400 Subject: fixed some compile errors --- src/client/northstar/dash-nodes/HistogramBox.tsx | 8 ++++---- src/client/util/DocumentManager.ts | 2 +- src/client/views/DocumentDecorations.tsx | 1 + src/client/views/collections/CollectionBaseView.tsx | 4 ++-- src/client/views/collections/CollectionSchemaView.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 3 ++- src/client/views/nodes/LinkMenu.tsx | 4 ++-- 7 files changed, 13 insertions(+), 11 deletions(-) (limited to 'src/client/northstar') diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index 765ecf8f0..5e7b867b3 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -117,15 +117,15 @@ export class HistogramBox extends React.Component { runInAction(() => { this.HistoOp = histoOp ? histoOp.HistoOp : HistogramOperation.Empty; if (this.HistoOp !== HistogramOperation.Empty) { - reaction(() => Cast(this.props.Document.linkedFromDocs, listSpec(Doc), []), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); + reaction(() => Cast(this.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); reaction(() => Cast(this.props.Document.brushingDocs, listSpec(Doc), []).length, () => { - let brushingDocs = Cast(this.props.Document.brushingDocs, listSpec(Doc), []); + let brushingDocs = Cast(this.props.Document.brushingDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); const proto = this.props.Document.proto; if (proto) { this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => { - brush.bckgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; - let brushed = Cast(brush.brushingDocs, listSpec(Doc), []); + brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; + let brushed = Cast(brush.brushingDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; })); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 69964e2c9..4c264c7ec 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -71,7 +71,7 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { return DocumentManager.Instance.DocumentViews.reduce((pairs, dv) => { - let linksList = Cast(dv.props.Document.linkedToDocs, listSpec(Doc)); + let linksList = Cast(dv.props.Document.linkedToDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 2bde4e0c8..705e7a6d8 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -27,6 +27,7 @@ import { MINIMIZED_ICON_SIZE } from "../views/globalCssVariables.scss"; import { CollectionView } from "./collections/CollectionView"; import { DocumentManager } from "../util/DocumentManager"; import { FormattedTextBox } from "./nodes/FormattedTextBox"; +import { FieldView } from "./nodes/FieldView"; library.add(faLink); diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 14b92af48..2b1f7bb37 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -63,13 +63,13 @@ export class CollectionBaseView extends React.Component { if (!(documentToAdd instanceof Doc)) { return false; } - let data = Cast(documentToAdd.data, listSpec(Doc), []); + let data = Cast(documentToAdd.data, listSpec(Doc), []).filter(d => d).map(d => d as Doc); for (const doc of data.filter(d => d instanceof Document)) { if (this.createsCycle(doc, containerDocument)) { return true; } } - let annots = Cast(documentToAdd.annotations, listSpec(Doc), []); + let annots = Cast(documentToAdd.annotations, listSpec(Doc), []).filter(d => d).map(d => d as Doc); for (const annot of annots) { if (this.createsCycle(annot, containerDocument)) { return true; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 6dd0e5935..ae949b2ed 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -276,7 +276,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } get documentKeysCheckList() { - const docs = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); + const docs = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(d => d).map(d => d as Doc); let keys: { [key: string]: boolean } = {}; // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index cdc1bdc85..8bdf34181 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -99,7 +99,8 @@ export class FieldView extends React.Component { ContainingCollectionView={this.props.ContainingCollectionView} parentActive={this.props.active} toggleMinimized={emptyFunction} - whenActiveChanged={this.props.whenActiveChanged} /> + whenActiveChanged={this.props.whenActiveChanged} + bringToFront={emptyFunction} /> ); } else if (field instanceof List) { diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index e21adebbc..24901913d 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -31,8 +31,8 @@ export class LinkMenu extends React.Component { render() { //get list of links from document - let linkFrom: Doc[] = Cast(this.props.docView.props.Document.linkedFromDocs, listSpec(Doc), []); - let linkTo: Doc[] = Cast(this.props.docView.props.Document.linkedToDocs, listSpec(Doc), []); + let linkFrom = Cast(this.props.docView.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let linkTo = Cast(this.props.docView.props.Document.linkedToDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); if (this._editingLink === undefined) { return (
-- cgit v1.2.3-70-g09d2 From 7da76d2538ebde21d7a878b5096d5a673e5d6375 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Fri, 10 May 2019 23:01:08 -0400 Subject: added summary screen grab icon as a template view of a text document. converted Cast(...ListSpec(Doc)) pattern to DocListCast --- src/client/northstar/dash-nodes/HistogramBox.tsx | 10 +++---- src/client/util/DocumentManager.ts | 6 ++-- src/client/util/DragManager.ts | 6 ++-- src/client/views/PresentationView.tsx | 11 +++++-- src/client/views/Templates.tsx | 35 +++++++++++++++------- .../views/collections/CollectionBaseView.tsx | 8 ++--- .../views/collections/CollectionSchemaView.tsx | 6 ++-- src/client/views/collections/CollectionSubView.tsx | 4 +-- .../views/collections/CollectionTreeView.tsx | 22 +++++++------- .../CollectionFreeFormLinksView.tsx | 12 ++++---- .../collections/collectionFreeForm/MarqueeView.tsx | 24 +++++++++++---- .../views/nodes/CollectionFreeFormDocumentView.tsx | 28 +++++++++-------- src/client/views/nodes/DocumentView.tsx | 23 +++++++------- src/client/views/nodes/IconBox.tsx | 4 +-- src/client/views/nodes/ImageBox.tsx | 14 ++++++--- src/client/views/nodes/LinkMenu.tsx | 6 ++-- src/new_fields/Doc.ts | 10 +++++-- 17 files changed, 137 insertions(+), 92 deletions(-) (limited to 'src/client/northstar') diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index 5e7b867b3..ed556cf45 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -19,7 +19,7 @@ import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives"; import { StyleConstants } from "../utils/StyleContants"; import { NumCast, Cast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/RefField"; @@ -117,15 +117,15 @@ export class HistogramBox extends React.Component { runInAction(() => { this.HistoOp = histoOp ? histoOp.HistoOp : HistogramOperation.Empty; if (this.HistoOp !== HistogramOperation.Empty) { - reaction(() => Cast(this.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); - reaction(() => Cast(this.props.Document.brushingDocs, listSpec(Doc), []).length, + reaction(() => DocListCast(this.props.Document.linkedFromDocs), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); + reaction(() => DocListCast(this.props.Document.brushingDocs).length, () => { - let brushingDocs = Cast(this.props.Document.brushingDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let brushingDocs = DocListCast(this.props.Document.brushingDocs); const proto = this.props.Document.proto; if (proto) { this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; - let brushed = Cast(brush.brushingDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let brushed = DocListCast(brush.brushingDocs); return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; })); } diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index a8b643d4d..9a7a94228 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -1,6 +1,6 @@ import { computed, observable } from 'mobx'; import { DocumentView } from '../views/nodes/DocumentView'; -import { Doc } from '../../new_fields/Doc'; +import { Doc, DocListCast } from '../../new_fields/Doc'; import { FieldValue, Cast, NumCast, BoolCast } from '../../new_fields/Types'; import { listSpec } from '../../new_fields/Schema'; import { undoBatch } from './UndoManager'; @@ -73,7 +73,7 @@ export class DocumentManager { @computed public get LinkedDocumentViews() { return DocumentManager.Instance.DocumentViews.filter(dv => dv.isSelected() || BoolCast(dv.props.Document.libraryBrush, false)).reduce((pairs, dv) => { - let linksList = Cast(dv.props.Document.linkedToDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let linksList = DocListCast(dv.props.Document.linkedToDocs); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { @@ -86,7 +86,7 @@ export class DocumentManager { return pairs; }, [] as { a: DocumentView, b: DocumentView, l: Doc }[])); } - linksList = Cast(dv.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + linksList = DocListCast(dv.props.Document.linkedFromDocs); if (linksList && linksList.length) { pairs.push(...linksList.reduce((pairs, link) => { if (link) { diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index c0402f0c9..2da0d5b51 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -1,5 +1,5 @@ import { action, runInAction } from "mobx"; -import { Doc, DocListCast } from "../../new_fields/Doc"; +import { Doc, DocListCastAsync } from "../../new_fields/Doc"; import { Cast } from "../../new_fields/Types"; import { emptyFunction } from "../../Utils"; import { CollectionDockingView } from "../views/collections/CollectionDockingView"; @@ -43,8 +43,8 @@ export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: n let draggedDocs: Doc[] = []; let draggedFromDocs: Doc[] = [] if (srcTarg) { - let linkToDocs = await DocListCast(srcTarg.linkedToDocs); - let linkFromDocs = await DocListCast(srcTarg.linkedFromDocs); + let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); + let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); if (linkToDocs) draggedDocs = linkToDocs.map(linkDoc => Cast(linkDoc.linkedTo, Doc) as Doc); if (linkFromDocs) draggedFromDocs = linkFromDocs.map(linkDoc => Cast(linkDoc.linkedFrom, Doc) as Doc); } diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 4853eb151..3fb24a339 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -141,8 +141,15 @@ export class PresentationView extends React.Component { (activeW) => { if (activeW && activeW instanceof Doc) { PromiseValue(Cast(activeW.presentationView, Doc)). - then(pv => runInAction(() => - self.Document = pv ? pv : (activeW.presentationView = new Doc()))) + then(pv => runInAction(() => { + if (pv) self.Document = pv; + else { + pv = new Doc(); + pv.title = "Presentation Doc"; + activeW.presentationView = pv; + self.Document = pv; + } + })) } }, { fireImmediately: true }); diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index bbedc95f1..a98870b04 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -5,6 +5,7 @@ export enum TemplatePosition { InnerBottom, InnerRight, InnerLeft, + TopRight, OutterTop, OutterBottom, OutterRight, @@ -39,30 +40,42 @@ export namespace Templates { // export const BasicLayout = new Template("Basic layout", "{layout}"); export const Caption = new Template("Caption", TemplatePosition.OutterBottom, - `
` - ); + `
+ +
` ); + export const TitleOverlay = new Template("TitleOverlay", TemplatePosition.InnerTop, - `
{layout}
-
- {props.Document.title} -
` - ); + `
+
{layout}
+
+ {props.Document.title} +
+
` ); + export const Title = new Template("Title", TemplatePosition.InnerTop, `
{layout}
{props.Document.title} -
` - ); +
` ); export const Bullet = new Template("Bullet", TemplatePosition.InnerTop, `
{layout}
-
- +
` ); + export function ImageOverlay(width: number, height: number, field: string = "thumbnail") { + return (`
+
{layout}
+
+ +
+
`); + } + export const TemplateList: Template[] = [Title, TitleOverlay, Caption, Bullet]; export function sortTemplates(a: Template, b: Template) { diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index 2b1f7bb37..645296d27 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { ContextMenu } from '../ContextMenu'; import { FieldViewProps } from '../nodes/FieldView'; import { Cast, FieldValue, PromiseValue, NumCast } from '../../../new_fields/Types'; -import { Doc, FieldResult, Opt } from '../../../new_fields/Doc'; +import { Doc, FieldResult, Opt, DocListCast } from '../../../new_fields/Doc'; import { listSpec } from '../../../new_fields/Schema'; import { List } from '../../../new_fields/List'; import { Id } from '../../../new_fields/RefField'; @@ -63,13 +63,13 @@ export class CollectionBaseView extends React.Component { if (!(documentToAdd instanceof Doc)) { return false; } - let data = Cast(documentToAdd.data, listSpec(Doc), []).filter(d => d).map(d => d as Doc); - for (const doc of data.filter(d => d instanceof Document)) { + let data = DocListCast(documentToAdd.data); + for (const doc of data) { if (this.createsCycle(doc, containerDocument)) { return true; } } - let annots = Cast(documentToAdd.annotations, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let annots = DocListCast(documentToAdd.annotations); for (const annot of annots) { if (this.createsCycle(annot, containerDocument)) { return true; diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index ae949b2ed..506e60a65 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -19,7 +19,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { Opt, Field, Doc, DocListCast } from "../../../new_fields/Doc"; +import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fields/Doc"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; @@ -118,7 +118,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } const run = script.run; //TODO This should be able to be refactored to compile the script once - const val = await DocListCast(this.props.Document[this.props.fieldKey]) + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]) val && val.forEach(doc => applyToDoc(doc, run)); }}> @@ -276,7 +276,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } get documentKeysCheckList() { - const docs = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(d => d).map(d => d as Doc); + const docs = DocListCast(this.props.Document[this.props.fieldKey]); let keys: { [key: string]: boolean } = {}; // bcz: ugh. this is untracked since otherwise a large collection of documents will blast the server for all their fields. // then as each document's fields come back, we update the documents _proxies. Each time we do this, the whole schema will be diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 0b08e150a..a86d250bd 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -10,7 +10,7 @@ import * as rp from 'request-promise'; import { CollectionView } from "./CollectionView"; import { CollectionPDFView } from "./CollectionPDFView"; import { CollectionVideoView } from "./CollectionVideoView"; -import { Doc, Opt, FieldResult } from "../../../new_fields/Doc"; +import { Doc, Opt, FieldResult, DocListCast } from "../../../new_fields/Doc"; import { DocComponent } from "../DocComponent"; import { listSpec } from "../../../new_fields/Schema"; import { Cast, PromiseValue, FieldValue, ListSpec } from "../../../new_fields/Types"; @@ -49,7 +49,7 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { get children() { //TODO tfs: This might not be what we want? //This linter error can't be fixed because of how js arguments work, so don't switch this to filter(FieldValue) - return Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []).filter(doc => FieldValue(doc)).map(doc => doc as Doc); + return DocListCast(this.props.Document[this.props.fieldKey]); } @action diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 33787f06b..78c84cc89 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -18,9 +18,7 @@ import { Main } from '../Main'; import { CurrentUserUtils } from '../../../server/authentication/models/current_user_utils'; import { CollectionDockingView } from './CollectionDockingView'; import { DocumentManager } from '../../util/DocumentManager'; -import { Utils } from '../../../Utils'; import { List } from '../../../new_fields/List'; -import { indexOf } from 'typescript-collections/dist/lib/arrays'; export interface TreeViewProps { @@ -155,16 +153,21 @@ class TreeView extends React.Component { let keys = Array.from(Object.keys(this.props.document)); if (this.props.document.proto instanceof Doc) { keys.push(...Array.from(Object.keys(this.props.document.proto))); + while (keys.indexOf("proto") !== -1) keys.splice(keys.indexOf("proto"), 1); } keys.map(key => { - let docList = Cast(this.props.document[key], listSpec(Doc)); - if (docList instanceof List && docList.length && docList[0] instanceof Doc) { + let docList = DocListCast(this.props.document[key]); + let doc = Cast(this.props.document[key], Doc); + if (doc instanceof Doc || docList.length) { if (!this._collapsed) { bulletType = BulletType.Collapsible; + let spacing = (key === "data") ? 0 : -10; contentElement.push(
    {(key === "data") ? (null) : - {key}} - {TreeView.GetChildElements(docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)} + {key}} +
    + {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)} +
); } else bulletType = BulletType.Collapsed; @@ -179,7 +182,7 @@ class TreeView extends React.Component { ; } - public static GetChildElements(docs: (Doc | Promise)[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { + public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child => ); } @@ -203,12 +206,11 @@ export class CollectionTreeView extends CollectionSubView(Document) { } } render() { - const children = this.children; let dropAction = StrCast(this.props.Document.dropAction, "alias") as dropActionType; - if (!children) { + if (!this.children) { return (null); } - let childElements = TreeView.GetChildElements(children, false, this.remove, this.props.moveDocument, dropAction); + let childElements = TreeView.GetChildElements(this.children, false, this.remove, this.props.moveDocument, dropAction); return (
{ - let doclist = Cast(this.props.Document[this.props.fieldKey], listSpec(Doc), []); - return { doclist: doclist ? doclist : [], xs: doclist instanceof List ? doclist.map(d => d instanceof Doc && d.x) : [] }; + let doclist = DocListCast(this.props.Document[this.props.fieldKey]); + return { doclist: doclist ? doclist : [], xs: doclist.map(d => d.x) }; }, - async () => { - let doclist = await DocListCast(this.props.Document[this.props.fieldKey]); + () => { + let doclist = DocListCast(this.props.Document[this.props.fieldKey]); let views = doclist ? doclist.filter(doc => StrCast(doc.backgroundLayout).indexOf("istogram") !== -1) : []; views.forEach((dstDoc, i) => { views.forEach((srcDoc, j) => { @@ -84,7 +84,7 @@ export class CollectionFreeFormLinksView extends React.Component d).map(d => d as Doc). + DocListCast(this.props.Document[this.props.fieldKey]). filter(child => child[Id] === collid).map(view => DocumentManager.Instance.getDocumentViews(view).map(view => diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 1bf39e335..9ace0272a 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -1,3 +1,4 @@ +import * as htmlToImage from "html-to-image"; import { action, computed, observable } from "mobx"; import { observer } from "mobx-react"; import { Docs } from "../../../documents/Documents"; @@ -14,6 +15,8 @@ import { Doc } from "../../../../new_fields/Doc"; import { NumCast, Cast } from "../../../../new_fields/Types"; import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; +import { ImageField } from "../../../../new_fields/URLField"; +import { Template, Templates } from "../../Templates"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -30,6 +33,7 @@ interface MarqueeViewProps { @observer export class MarqueeView extends React.Component { + private _mainCont = React.createRef(); @observable _lastX: number = 0; @observable _lastY: number = 0; @observable _downX: number = 0; @@ -166,7 +170,7 @@ export class MarqueeView extends React.Component @undoBatch @action - marqueeCommand = (e: KeyboardEvent) => { + marqueeCommand = async (e: KeyboardEvent) => { if (this._commandExecuted) { return; } @@ -224,13 +228,17 @@ export class MarqueeView extends React.Component let scrpt = this.props.getTransform().inverse().transformPoint(bounds.left, bounds.top); let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + let dataUrl = await htmlToImage.toPng(this._mainCont.current!, { width: bounds.width, height: bounds.height, quality: 1 }); + summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); + + summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); if (e.key === "s" || e.key === "p") { summary.proto!.maximizeOnRight = true; newCollection.proto!.summaryDoc = summary; selected = [newCollection]; } summary.proto!.summarizedDocs = new List(selected); - summary.proto!.isButton = true; + //summary.proto!.isButton = true; selected.map(summarizedDoc => { let maxx = NumCast(summarizedDoc.x, undefined); let maxy = NumCast(summarizedDoc.y, undefined); @@ -313,17 +321,21 @@ export class MarqueeView extends React.Component @computed get marqueeDiv() { - let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); let v = this.props.getContainerTransform().transformDirection(this._lastX - this._downX, this._lastY - this._downY); - return
+ return
; } render() { + let p = this.props.getContainerTransform().transformPoint(this._downX < this._lastX ? this._downX : this._lastX, this._downY < this._lastY ? this._downY : this._lastY); return
- {this.props.children} - {!this._visible ? (null) : this.marqueeDiv} +
+
+ {this.props.children} +
+ {!this._visible ? null : this.marqueeDiv} +
; } } \ No newline at end of file diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index b05f2eea2..39d216da0 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -9,10 +9,10 @@ import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schem import { FieldValue, Cast, NumCast, BoolCast, StrCast } from "../../../new_fields/Types"; import { OmitKeys, Utils } from "../../../Utils"; import { SelectionManager } from "../../util/SelectionManager"; -import { Doc, DocListCast, HeightSym } from "../../../new_fields/Doc"; +import { Doc, DocListCastAsync, DocListCast, } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { CollectionDockingView } from "../collections/CollectionDockingView"; -import { undoBatch, UndoManager } from "../../util/UndoManager"; +import { UndoManager } from "../../util/UndoManager"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { } @@ -65,7 +65,7 @@ export class CollectionFreeFormDocumentView extends DocComponent this.nativeWidth > 0 ? this.width / this.nativeWidth : 1; panelWidth = () => this.props.PanelWidth(); panelHeight = () => this.props.PanelHeight(); - toggleMinimized = async () => this.toggleIcon(await DocListCast(this.props.Document.maximizedDocs)); + toggleMinimized = async () => this.toggleIcon(await DocListCastAsync(this.props.Document.maximizedDocs)); getTransform = (): Transform => this.props.ScreenToLocalTransform() .translate(-this.X, -this.Y) .scale(1 / this.contentScaling()).scale(1 / this.zoom) @@ -132,7 +132,7 @@ export class CollectionFreeFormDocumentView extends DocComponent { + expandedDocs.forEach(maxDoc => { maxDoc.isMinimized = false; if (!dataDocs || dataDocs.indexOf(maxDoc) == -1) { CollectionDockingView.Instance.AddRightSplit(maxDoc); @@ -195,8 +197,8 @@ export class CollectionFreeFormDocumentView extends DocComponent this.props.addDocument!(await maxDoc, false)); - this.toggleIcon(maximizedDocs); + this.props.addDocument && expandedDocs.forEach(async maxDoc => this.props.addDocument!(await maxDoc, false)); + this.toggleIcon(expandedDocs); } } } diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 5aa74c703..90f67db7c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -12,13 +12,13 @@ import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; -import { Template, Templates } from "./../Templates"; +import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); -import { Opt, Doc, WidthSym, HeightSym, DocListCast } from "../../../new_fields/Doc"; +import { Opt, Doc, WidthSym, HeightSym, DocListCastAsync, DocListCast } from "../../../new_fields/Doc"; import { DocComponent } from "../DocComponent"; -import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; import { FieldValue, StrCast, BoolCast, Cast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView"; @@ -109,8 +109,8 @@ export class DocumentView extends DocComponent(Docu } // bcz: kind of ugly .. setup a reaction to update the title of a summary document's target (maximizedDocs) whenver the summary doc's title changes this._reactionDisposer = reaction(() => [this.props.Document.maximizedDocs, this.props.Document.summaryDoc, this.props.Document.summaryDoc instanceof Doc ? this.props.Document.summaryDoc.title : ""], - async () => { - let maxDoc = await DocListCast(this.props.Document.maximizedDocs); + () => { + let maxDoc = DocListCast(this.props.Document.maximizedDocs); if (maxDoc && StrCast(this.props.Document.layout).indexOf("IconBox") !== -1) { this.props.Document.title = (maxDoc && maxDoc.length === 1 ? maxDoc[0].title + ".icon" : ""); } @@ -145,7 +145,7 @@ export class DocumentView extends DocComponent(Docu startDragging(x: number, y: number, dropAction: dropActionType, dragSubBullets: boolean) { if (this._mainCont.current) { - let allConnected = dragSubBullets ? [this.props.Document, ...Cast(this.props.Document.subBulletDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc)] : [this.props.Document]; + let allConnected = [this.props.Document, ...(dragSubBullets ? DocListCast(this.props.Document.subBulletDocs) : [])]; const [left, top] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).inverse().transformPoint(0, 0); let dragData = new DragManager.DocumentDragData(allConnected); const [xoff, yoff] = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top); @@ -169,17 +169,17 @@ export class DocumentView extends DocComponent(Docu SelectionManager.SelectDoc(this, e.ctrlKey); } } - _hitIsBullet = false; + _hitExpander = false; onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; this._downY = e.clientY; if (CollectionFreeFormView.RIGHT_BTN_DRAG && (e.button === 2 || (e.button === 0 && e.altKey)) && !this.isSelected()) { return; } - this._hitIsBullet = (e.target && (e.target as any).id === "isBullet") || Cast(this.props.Document.subBulletDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc).length > 0; + this._hitExpander = DocListCast(this.props.Document.subBulletDocs).length > 0; if (e.shiftKey && e.buttons === 1) { if (this.props.isTopMost) { - this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined, this._hitIsBullet); + this.startDragging(e.pageX, e.pageY, e.altKey || e.ctrlKey ? "alias" : undefined, this._hitExpander); } else if (this.props.Document) { CollectionDockingView.Instance.StartOtherDrag([Doc.MakeAlias(this.props.Document)], e); } @@ -197,7 +197,7 @@ export class DocumentView extends DocComponent(Docu document.removeEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); if (!e.altKey && !this.topMost && (!CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 1) || (CollectionFreeFormView.RIGHT_BTN_DRAG && e.buttons === 2)) { - this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitIsBullet); + this.startDragging(this._downX, this._downY, e.ctrlKey || e.altKey ? "alias" : undefined, this._hitExpander); } } e.stopPropagation(); // doesn't actually stop propagation since all our listeners are listening to events on 'document' however it does mark the event as cancelBubble=true which we test for in the move event handlers @@ -232,6 +232,7 @@ export class DocumentView extends DocComponent(Docu ContextMenu.Instance.clearItems(); SelectionManager.DeselectAll(); } + @undoBatch @action drop = async (e: Event, de: DragManager.DropEvent) => { @@ -259,7 +260,6 @@ export class DocumentView extends DocComponent(Docu } } - @action addTemplate = (template: Template) => { this.templates.push(template.Layout); @@ -307,7 +307,6 @@ export class DocumentView extends DocComponent(Docu } } - isSelected = () => SelectionManager.IsSelected(this); select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); diff --git a/src/client/views/nodes/IconBox.tsx b/src/client/views/nodes/IconBox.tsx index 4bcb4c636..48aecdcd0 100644 --- a/src/client/views/nodes/IconBox.tsx +++ b/src/client/views/nodes/IconBox.tsx @@ -2,12 +2,12 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faCaretUp, faFilePdf, faFilm, faImage, faObjectGroup, faStickyNote } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { computed, observable, runInAction, reaction, IReactionDisposer } from "mobx"; +import { computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { FieldView, FieldViewProps } from './FieldView'; import "./IconBox.scss"; import { Cast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Doc } from "../../../new_fields/Doc"; import { IconField } from "../../../new_fields/IconField"; import { ContextMenu } from "../ContextMenu"; import Measure from "react-measure"; diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 0e9e904a8..f9659a4b2 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,5 +1,5 @@ -import { action, observable } from 'mobx'; +import { action, observable, trace } from 'mobx'; import { observer } from "mobx-react"; import Lightbox from 'react-image-lightbox'; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app @@ -157,15 +157,21 @@ export class ImageBox extends DocComponent(ImageD } render() { + trace(); let field = this.Document[this.props.fieldKey]; let paths: string[] = ["http://www.cs.brown.edu/~bcz/face.gif"]; if (field instanceof ImageField) paths = [field.url.href]; else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); - let nativeWidth = FieldValue(this.Document.nativeWidth, 1); + let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; + let id = this.props.id; return ( -
- Image not found +
+ {paths.length > 1 ? this.dots(paths) : (null)} {this.lightbox(paths)}
); diff --git a/src/client/views/nodes/LinkMenu.tsx b/src/client/views/nodes/LinkMenu.tsx index 24901913d..7bf13d5f9 100644 --- a/src/client/views/nodes/LinkMenu.tsx +++ b/src/client/views/nodes/LinkMenu.tsx @@ -5,7 +5,7 @@ import { LinkBox } from "./LinkBox"; import { LinkEditor } from "./LinkEditor"; import './LinkMenu.scss'; import React = require("react"); -import { Doc } from "../../../new_fields/Doc"; +import { Doc, DocListCast } from "../../../new_fields/Doc"; import { Cast, FieldValue } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { Id } from "../../../new_fields/RefField"; @@ -31,8 +31,8 @@ export class LinkMenu extends React.Component { render() { //get list of links from document - let linkFrom = Cast(this.props.docView.props.Document.linkedFromDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); - let linkTo = Cast(this.props.docView.props.Document.linkedToDocs, listSpec(Doc), []).filter(d => d).map(d => d as Doc); + let linkFrom = DocListCast(this.props.docView.props.Document.linkedFromDocs); + let linkTo = DocListCast(this.props.docView.props.Document.linkedToDoc); if (this._editingLink === undefined) { return (
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 2ab145fa3..46ccb3e90 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -29,13 +29,17 @@ export const SelfProxy = Symbol("SelfProxy"); export const WidthSym = Symbol("Width"); export const HeightSym = Symbol("Height"); -export function DocListCast(field: FieldResult): Promise; -export function DocListCast(field: FieldResult, defaultValue: Doc[]): Promise; -export function DocListCast(field: FieldResult, defaultValue?: Doc[]) { +export function DocListCastAsync(field: FieldResult): Promise; +export function DocListCastAsync(field: FieldResult, defaultValue: Doc[]): Promise; +export function DocListCastAsync(field: FieldResult, defaultValue?: Doc[]) { const list = Cast(field, listSpec(Doc)); return list ? Promise.all(list) : Promise.resolve(defaultValue); } +export function DocListCast(field: FieldResult) { + return Cast(field, listSpec(Doc), []).filter(d => d && d instanceof Doc).map(d => d as Doc) +} + @Deserializable("doc").withFields(["id"]) export class Doc extends RefField { constructor(id?: FieldId, forceSave?: boolean) { -- cgit v1.2.3-70-g09d2 From 281bfa589bd1ca66823003ca91cc11ce895fe5e2 Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 14 May 2019 18:59:32 -0400 Subject: fixes for northstar --- src/client/documents/Documents.ts | 9 ++- src/client/northstar/dash-fields/HistogramField.ts | 11 ++-- .../dash-nodes/HistogramBinPrimitiveCollection.ts | 4 +- src/client/northstar/dash-nodes/HistogramBox.tsx | 16 +++--- .../dash-nodes/HistogramBoxPrimitives.tsx | 3 - src/client/northstar/manager/Gateway.ts | 12 ++++ src/client/northstar/model/ModelHelpers.ts | 10 +++- src/client/northstar/model/idea/idea.ts | 6 ++ src/client/northstar/operations/BaseOperation.ts | 17 ------ .../northstar/operations/HistogramOperation.ts | 12 ++-- src/client/views/Main.tsx | 54 +----------------- .../views/collections/CollectionSchemaView.tsx | 39 ++++++++++++- .../collections/collectionFreeForm/MarqueeView.tsx | 7 ++- src/client/views/nodes/DocumentView.tsx | 2 +- .../authentication/models/current_user_utils.ts | 65 ++++++++++++++++++++-- 15 files changed, 162 insertions(+), 105 deletions(-) (limited to 'src/client/northstar') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 11929455c..ed260d42e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -33,6 +33,7 @@ import { DocServer } from "../DocServer"; import { StrokeData, InkField } from "../../new_fields/InkField"; import { dropActionType } from "../util/DragManager"; import { DateField } from "../../new_fields/DateField"; +import { schema } from "prosemirror-schema-basic"; export interface DocumentOptions { x?: number; @@ -207,16 +208,18 @@ export namespace Docs { export function PdfDocument(url: string, options: DocumentOptions = {}) { return CreateInstance(pdfProto, new PdfField(new URL(url)), options); } + export async function DBDocument(url: string, options: DocumentOptions = {}) { let schemaName = options.title ? options.title : "-no schema-"; let ctlog = await Gateway.Instance.GetSchema(url, schemaName); if (ctlog && ctlog.schemas) { let schema = ctlog.schemas[0]; let schemaDoc = Docs.TreeDocument([], { ...options, nativeWidth: undefined, nativeHeight: undefined, width: 150, height: 100, title: schema.displayName! }); - let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc)); + let schemaDocuments = Cast(schemaDoc.data, listSpec(Doc), []); if (!schemaDocuments) { return; } + CurrentUserUtils.AddNorthstarSchema(schema, schemaDoc); const docs = schemaDocuments; CurrentUserUtils.GetAllNorthstarColumnAttributes(schema).map(attr => { DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt) => { @@ -251,8 +254,8 @@ export namespace Docs { } return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Freeform }); } - export function SchemaDocument(documents: Array, options: DocumentOptions) { - return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Schema }); + export function SchemaDocument(schemaColumns: string[], documents: Array, options: DocumentOptions) { + return CreateInstance(collProto, new List(documents), { schemaColumns: new List(schemaColumns), ...options, viewType: CollectionViewType.Schema }); } export function TreeDocument(documents: Array, options: DocumentOptions) { return CreateInstance(collProto, new List(documents), { schemaColumns: new List(["title"]), ...options, viewType: CollectionViewType.Tree }); diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index f01f08487..aabc77bb2 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -9,7 +9,8 @@ import { OmitKeys } from "../../../Utils"; import { Deserializable } from "../../util/SerializationHelper"; function serialize(field: HistogramField) { - return OmitKeys(field.HistoOp, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; + let obj = OmitKeys(field, ['Links', 'BrushLinks', 'Result', 'BrushColors', 'FilterModels', 'FilterOperand']).omit; + return obj; } function deserialize(jp: any) { @@ -31,10 +32,10 @@ function deserialize(jp: any) { } }); if (X && Y && V) { - return new HistogramField(new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization)); + return new HistogramOperation(jp.SchemaName, X, Y, V, jp.Normalization); } } - return new HistogramField(HistogramOperation.Empty); + return HistogramOperation.Empty; } @Deserializable("histogramField") @@ -50,6 +51,8 @@ export class HistogramField extends ObjectField { } [Copy]() { - return new HistogramField(this.HistoOp.Copy()); + let y = this.HistoOp; + let z = this.HistoOp["Copy"]; + return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts index 6291ec1fc..3e9145a1b 100644 --- a/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts +++ b/src/client/northstar/dash-nodes/HistogramBinPrimitiveCollection.ts @@ -198,8 +198,8 @@ export class HistogramBinPrimitiveCollection { var marginParams = new MarginAggregateParameters(); marginParams.aggregateFunction = axis.AggregateFunction; var marginAggregateKey = ModelHelpers.CreateAggregateKey(this.histoOp.Schema!.distinctAttributeParameters, axis, this.histoResult, brush.brushIndex!, marginParams); - var marginResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey) as MarginAggregateResult; - return !marginResult ? 0 : marginResult.absolutMargin!; + let aggResult = ModelHelpers.GetAggregateResult(bin, marginAggregateKey); + return aggResult instanceof MarginAggregateResult && aggResult.absolutMargin ? aggResult.absolutMargin : 0; } private createBinPrimitive(barAxis: number, brush: Brush, marginRect: PIXIRectangle, diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index ed556cf45..eb1ad69b7 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -17,9 +17,8 @@ import "./HistogramBox.scss"; import { HistogramBoxPrimitives } from './HistogramBoxPrimitives'; import { HistogramLabelPrimitives } from "./HistogramLabelPrimitives"; import { StyleConstants } from "../utils/StyleContants"; -import { NumCast, Cast } from "../../../new_fields/Types"; -import { listSpec } from "../../../new_fields/Schema"; -import { Doc, DocListCast } from "../../../new_fields/Doc"; +import { Cast } from "../../../new_fields/Types"; +import { Doc, DocListCast, DocListCastAsync } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/RefField"; @@ -119,15 +118,16 @@ export class HistogramBox extends React.Component { if (this.HistoOp !== HistogramOperation.Empty) { reaction(() => DocListCast(this.props.Document.linkedFromDocs), (docs) => this.HistoOp.Links.splice(0, this.HistoOp.Links.length, ...docs), { fireImmediately: true }); reaction(() => DocListCast(this.props.Document.brushingDocs).length, - () => { - let brushingDocs = DocListCast(this.props.Document.brushingDocs); + async () => { + let brushingDocs = await DocListCastAsync(this.props.Document.brushingDocs); const proto = this.props.Document.proto; - if (proto) { - this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...brushingDocs.map((brush, i) => { + if (proto && brushingDocs) { + let mapped = brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; let brushed = DocListCast(brush.brushingDocs); return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; - })); + }); + this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped); } }, { fireImmediately: true }); reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true }); diff --git a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx index 721bf6a89..350987695 100644 --- a/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx +++ b/src/client/northstar/dash-nodes/HistogramBoxPrimitives.tsx @@ -11,9 +11,6 @@ import { StyleConstants } from "../../northstar/utils/StyleContants"; import { HistogramBinPrimitiveCollection, HistogramBinPrimitive } from "./HistogramBinPrimitiveCollection"; import { HistogramBox } from "./HistogramBox"; import "./HistogramBoxPrimitives.scss"; -import { JSXElement } from "babel-types"; -import { Utils } from "../utils/Utils"; -import { all } from "bluebird"; export interface HistogramPrimitivesProps { HistoBox: HistogramBox; diff --git a/src/client/northstar/manager/Gateway.ts b/src/client/northstar/manager/Gateway.ts index d26f2724f..c541cce6a 100644 --- a/src/client/northstar/manager/Gateway.ts +++ b/src/client/northstar/manager/Gateway.ts @@ -23,6 +23,18 @@ export class Gateway { } } + public async PostSchema(csvdata: string, schemaname: string): Promise { + try { + const json = await this.MakePostJsonRequest("postSchema", { csv: csvdata, schema: schemaname }); + // const cat = Catalog.fromJS(json); + // return cat; + return json; + } + catch (error) { + throw new Error("can not reach northstar's backend"); + } + } + public async GetSchema(pathname: string, schemaname: string): Promise { try { const json = await this.MakeGetRequest("schema", undefined, { path: pathname, schema: schemaname }); diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index ac807b41f..80bb71224 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -31,7 +31,15 @@ export class ModelHelpers { } public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { - return ArrayUtil.IndexOfWithEqual(histogramResult.aggregateParameters!, aggParameters); + return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) + return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) + return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) + return true; + return false; + }); } public static GetAggregateParameter(distinctAttributeParameters: AttributeParameters | undefined, atm: AttributeTransformationModel): AggregateParameters | undefined { diff --git a/src/client/northstar/model/idea/idea.ts b/src/client/northstar/model/idea/idea.ts index 9d9d60678..c73a822c7 100644 --- a/src/client/northstar/model/idea/idea.ts +++ b/src/client/northstar/model/idea/idea.ts @@ -22,6 +22,9 @@ export abstract class AggregateParameters implements IAggregateParameters { protected _discriminator: string; + public Equals(other: Object): boolean { + return this == other; + } constructor(data?: IAggregateParameters) { if (data) { for (var property in data) { @@ -204,6 +207,9 @@ export interface IAverageAggregateParameters extends ISingleDimensionAggregatePa export abstract class AttributeParameters implements IAttributeParameters { visualizationHints?: VisualizationHint[] | undefined; rawName?: string | undefined; + public Equals(other: Object): boolean { + return this == other; + } protected _discriminator: string; diff --git a/src/client/northstar/operations/BaseOperation.ts b/src/client/northstar/operations/BaseOperation.ts index c6d5f0a15..0d1361ebf 100644 --- a/src/client/northstar/operations/BaseOperation.ts +++ b/src/client/northstar/operations/BaseOperation.ts @@ -25,23 +25,6 @@ export abstract class BaseOperation { @computed public get FilterString(): string { - - // let filterModels: FilterModel[] = []; - // return FilterModel.GetFilterModelsRecursive(this, new Set>(), filterModels, true) - // if (this.OverridingFilters.length > 0) { - // return "(" + this.OverridingFilters.filter(fm => fm !== null).map(fm => fm.ToPythonString()).join(" || ") + ")"; - // } - // let rdg = MainManager.Instance.MainViewModel.FilterReverseDependencyGraph; - // let sliceModel = this.TypedViewModel.IncomingSliceModel; - // if (sliceModel !== null && sliceModel.Source !== null && instanceOfIBaseFilterProvider(sliceModel.Source) && rdg.has(sliceModel.Source)) { - // let filterModels = sliceModel.Source.FilterModels.map(f => f); - // return FilterModel.GetFilterModelsRecursive(rdg.get(sliceModel.Source), new Set>(), filterModels, false); - // } - - // if (rdg.has(this.TypedViewModel)) { - // let filterModels = []; - // return FilterModel.GetFilterModelsRecursive(rdg.get(this.TypedViewModel), new Set>(), filterModels, true) - // } return ""; } diff --git a/src/client/northstar/operations/HistogramOperation.ts b/src/client/northstar/operations/HistogramOperation.ts index 78b206bdc..74e23ea48 100644 --- a/src/client/northstar/operations/HistogramOperation.ts +++ b/src/client/northstar/operations/HistogramOperation.ts @@ -30,7 +30,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons @observable public V: AttributeTransformationModel; @observable public SchemaName: string; @observable public QRange: QuantitativeBinRange | undefined; - @computed public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); } + public get Schema() { return CurrentUserUtils.GetNorthstarSchema(this.SchemaName); } constructor(schemaName: string, x: AttributeTransformationModel, y: AttributeTransformationModel, v: AttributeTransformationModel, normalized?: number) { super(); @@ -41,7 +41,11 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons this.SchemaName = schemaName; } - Copy(): HistogramOperation { + public static Duplicate(op: HistogramOperation) { + + return new HistogramOperation(op.SchemaName, op.X, op.Y, op.V, op.Normalization); + } + public Copy(): HistogramOperation { return new HistogramOperation(this.SchemaName, this.X, this.Y, this.V, this.Normalization); } @@ -50,7 +54,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons } - @computed public get FilterModels() { + public get FilterModels() { return this.BarFilterModels; } @action @@ -71,9 +75,7 @@ export class HistogramOperation extends BaseOperation implements IBaseFilterCons return FilterModel.GetFilterModelsRecursive(this, new Set(), filterModels, true); } - @computed public get BrushString(): string[] { - trace(); let brushes: string[] = []; this.BrushLinks.map(brushLink => { let brushHistogram = Cast(brushLink.b.data, HistogramField); diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 66205f8ca..385fc6ead 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -12,13 +12,6 @@ import { CurrentUserUtils } from '../../server/authentication/models/current_use import { RouteStore } from '../../server/RouteStore'; import { emptyFunction, returnTrue, Utils, returnOne, returnZero } from '../../Utils'; import { Docs } from '../documents/Documents'; -import { ColumnAttributeModel } from '../northstar/core/attribute/AttributeModel'; -import { AttributeTransformationModel } from '../northstar/core/attribute/AttributeTransformationModel'; -import { Gateway, NorthstarSettings } from '../northstar/manager/Gateway'; -import { AggregateFunction, Catalog } from '../northstar/model/idea/idea'; -import '../northstar/model/ModelExtensions'; -import { HistogramOperation } from '../northstar/operations/HistogramOperation'; -import '../northstar/utils/Extensions'; import { SetupDrag, DragManager } from '../util/DragManager'; import { Transform } from '../util/Transform'; import { UndoManager } from '../util/UndoManager'; @@ -70,8 +63,6 @@ export class Main extends React.Component { } } - CurrentUserUtils.loadCurrentUser(); - library.add(faFont); library.add(faImage); library.add(faFilePdf); @@ -84,15 +75,8 @@ export class Main extends React.Component { library.add(faFilm); library.add(faMusic); library.add(faTree); - this.initEventListeners(); this.initAuthenticationRouters(); - - // try { - // this.initializeNorthstar(); - // } catch (e) { - - // } } componentDidMount() { window.onpopstate = this.onHistory; } @@ -155,7 +139,7 @@ export class Main extends React.Component { // bcz: strangely, we need a timeout to prevent exceptions/issues initializing GoldenLayout (the rendering engine for Main Container) setTimeout(() => { this.openWorkspace(mainDoc); - let pendingDocument = Docs.SchemaDocument([], { title: "New Mobile Uploads" }); + let pendingDocument = Docs.SchemaDocument(["title"], [], { title: "New Mobile Uploads" }); mainDoc.optionalRightCollection = pendingDocument; }, 0); } @@ -229,7 +213,7 @@ export class Main extends React.Component { let addTextNode = action(() => Docs.TextDocument({ borderRounding: -1, width: 200, height: 200, title: "a text note" })); let addColNode = action(() => Docs.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Docs.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Docs.SchemaDocument(["title"], [], { width: 200, height: 200, title: "a schema collection" })); let addTreeNode = action(() => Docs.TreeDocument([CurrentUserUtils.UserDocument], { width: 250, height: 400, title: "Library:" + CurrentUserUtils.email, dropAction: "alias" })); // let addTreeNode = action(() => Docs.TreeDocument(this._northstarSchemas, { width: 250, height: 400, title: "northstar schemas", dropAction: "copy" })); let addVideoNode = action(() => Docs.VideoDocument(videourl, { width: 200, title: "video node" })); @@ -300,40 +284,6 @@ export class Main extends React.Component {
); } - - // --------------- Northstar hooks ------------- / - private _northstarSchemas: Doc[] = []; - - @action SetNorthstarCatalog(ctlog: Catalog) { - CurrentUserUtils.NorthstarDBCatalog = ctlog; - if (ctlog && ctlog.schemas) { - ctlog.schemas.map(schema => { - let schemaDocuments: Doc[] = []; - let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema); - Promise.all(attributesToBecomeDocs.reduce((promises, attr) => { - promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt) => { - if (field instanceof Doc) { - schemaDocuments.push(field); - } else { - var atmod = new ColumnAttributeModel(attr); - let histoOp = new HistogramOperation(schema.displayName!, - new AttributeTransformationModel(atmod, AggregateFunction.None), - new AttributeTransformationModel(atmod, AggregateFunction.Count), - new AttributeTransformationModel(atmod, AggregateFunction.Count)); - schemaDocuments.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! })); - } - }))); - return promises; - }, [] as Promise[])).finally(() => - this._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! }))); - }); - } - } - async initializeNorthstar(): Promise { - const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" }); - NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json()); - Gateway.Instance.ClearCatalog().then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog())); - } } (async () => { diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 9ecccc559..f4ad5b357 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -20,11 +20,20 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fields/Doc"; -import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { List } from "../../../new_fields/List"; import { Id } from "../../../new_fields/RefField"; import { isUndefined } from "typescript-collections/dist/lib/util"; +import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; +import { Gateway } from "../../northstar/manager/Gateway"; +import { DocServer } from "../../DocServer"; +import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel"; +import { HistogramOperation } from "../../northstar/operations/HistogramOperation"; +import { AggregateFunction } from "../../northstar/model/idea/idea"; +import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel"; +import { Docs } from "../../documents/Documents"; +import { ContextMenu } from "../ContextMenu"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 @@ -207,6 +216,32 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } } + onContextMenu = (e: React.MouseEvent): void => { + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + ContextMenu.Instance.addItem({ description: "Make DB", event: this.makeDB }); + } + } + + @action + makeDB = async () => { + let csv: string = this.columns.reduce((val, col) => val + col + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + let self = this; + DocListCast(this.props.Document.data).map(doc => { + csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); + csv = csv.substr(0, csv.length - 1) + "\n"; + }) + csv.substring(0, csv.length - 1); + let dbName = StrCast(this.props.Document.title); + let res = await Gateway.Instance.PostSchema(csv, dbName); + if (self.props.CollectionView.props.addDocument) { + let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); + if (schemaDoc) { + self.props.CollectionView.props.addDocument(schemaDoc, false); + } + } + } + @action addColumn = () => { this.columns.push(this._newKeyName); @@ -325,7 +360,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { const children = this.children; return (
this.onDrop(e, {})} ref={this.createTarget}> + onDrop={(e: React.DragEvent) => this.onDrop(e, {})} onContextMenu={this.onContextMenu} ref={this.createTarget}>
({ diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 24dea200e..be7cddca6 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -17,6 +17,9 @@ import { InkField, StrokeData } from "../../../../new_fields/InkField"; import { List } from "../../../../new_fields/List"; import { ImageField } from "../../../../new_fields/URLField"; import { Template, Templates } from "../../Templates"; +import { Gateway } from "../../../northstar/manager/Gateway"; +import { DocServer } from "../../../DocServer"; +import { Id } from "../../../../new_fields/RefField"; interface MarqueeViewProps { getContainerTransform: () => Transform; @@ -111,8 +114,8 @@ export class MarqueeView extends React.Component doc.title = i.toString(); docList.push(doc); } - let newCol = Docs.SchemaDocument(docList, { x: x, y: y, title: "-dropped table-", width: 300, height: 100 }); - newCol.proto!.schemaColumns = new List([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)]); + let newCol = Docs.SchemaDocument([...(groupAttr ? ["_group"] : []), ...columns.filter(c => c)], docList, { x: x, y: y, title: "droppedTable", width: 300, height: 100 }); + this.props.addDocument(newCol, false); } })(); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b7ad9249a..c97bcbd94 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -306,7 +306,7 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: "Find aliases", event: async () => { const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(aliases, {})); + CollectionDockingView.Instance.AddRightSplit(Docs.SchemaDocument(["title"], aliases, {})); } }); cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) }); diff --git a/src/server/authentication/models/current_user_utils.ts b/src/server/authentication/models/current_user_utils.ts index 5f45d7bcc..5b63ac356 100644 --- a/src/server/authentication/models/current_user_utils.ts +++ b/src/server/authentication/models/current_user_utils.ts @@ -1,15 +1,21 @@ import { computed, observable, action, runInAction } from "mobx"; import * as rp from 'request-promise'; import { Docs } from "../../../client/documents/Documents"; -import { Attribute, AttributeGroup, Catalog, Schema } from "../../../client/northstar/model/idea/idea"; +import { Attribute, AttributeGroup, Catalog, Schema, AggregateFunction } from "../../../client/northstar/model/idea/idea"; import { ArrayUtil } from "../../../client/northstar/utils/ArrayUtil"; import { RouteStore } from "../../RouteStore"; import { DocServer } from "../../../client/DocServer"; -import { Doc } from "../../../new_fields/Doc"; +import { Doc, Opt, Field } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { CollectionViewType } from "../../../client/views/collections/CollectionBaseView"; import { CollectionTreeView } from "../../../client/views/collections/CollectionTreeView"; import { CollectionView } from "../../../client/views/collections/CollectionView"; +import { NorthstarSettings, Gateway } from "../../../client/northstar/manager/Gateway"; +import { AttributeTransformationModel } from "../../../client/northstar/core/attribute/AttributeTransformationModel"; +import { ColumnAttributeModel } from "../../../client/northstar/core/attribute/AttributeModel"; +import { HistogramOperation } from "../../../client/northstar/operations/HistogramOperation"; +import { Cast, PromiseValue } from "../../../new_fields/Types"; +import { listSpec } from "../../../new_fields/Schema"; export class CurrentUserUtils { private static curr_email: string; @@ -31,13 +37,13 @@ export class CurrentUserUtils { doc.title = this.email; doc.data = new List(); doc.excludeFromLibrary = true; - doc.optionalRightCollection = Docs.SchemaDocument([], { title: "Pending documents" }); + doc.optionalRightCollection = Docs.SchemaDocument(["title"], [], { title: "Pending documents" }); // doc.library = Docs.TreeDocument([doc], { title: `Library: ${CurrentUserUtils.email}` }); // (doc.library as Doc).excludeFromLibrary = true; return doc; } - public static loadCurrentUser(): Promise { + public static async loadCurrentUser(): Promise { let userPromise = rp.get(DocServer.prepend(RouteStore.getCurrUser)).then(response => { if (response) { let obj = JSON.parse(response); @@ -47,7 +53,7 @@ export class CurrentUserUtils { throw new Error("There should be a user! Why does Dash think there isn't one?"); } }); - let userDocPromise = rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => { + let userDocPromise = await rp.get(DocServer.prepend(RouteStore.getUserDocumentId)).then(id => { if (id) { return DocServer.GetRefField(id).then(field => runInAction(() => this.user_document = field instanceof Doc ? field : this.createUserDocument(id))); @@ -55,14 +61,63 @@ export class CurrentUserUtils { throw new Error("There should be a user id! Why does Dash think there isn't one?"); } }); + try { + const getEnvironment = await fetch("/assets/env.json", { redirect: "follow", method: "GET", credentials: "include" }); + NorthstarSettings.Instance.UpdateEnvironment(await getEnvironment.json()); + await Gateway.Instance.ClearCatalog(); + const extraSchemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []); + let extras = await Promise.all(extraSchemas.map(async sc => await Gateway.Instance.GetSchema("", sc))); + let catprom = CurrentUserUtils.SetNorthstarCatalog(await Gateway.Instance.GetCatalog(), extras); + if (catprom) await Promise.all(catprom); + } catch (e) { + + } return Promise.all([userPromise, userDocPromise]); } /* Northstar catalog ... really just for testing so this should eventually go away */ + // --------------- Northstar hooks ------------- / + static _northstarSchemas: Doc[] = []; @observable private static _northstarCatalog?: Catalog; @computed public static get NorthstarDBCatalog() { return this._northstarCatalog; } + + @action static SetNorthstarCatalog(ctlog: Catalog, extras: Catalog[]) { + CurrentUserUtils.NorthstarDBCatalog = ctlog; + if (ctlog && ctlog.schemas) { + extras.map(ex => ctlog.schemas!.push(ex)); + return ctlog.schemas.map(async schema => { + let schemaDocuments: Doc[] = []; + let attributesToBecomeDocs = CurrentUserUtils.GetAllNorthstarColumnAttributes(schema); + await Promise.all(attributesToBecomeDocs.reduce((promises, attr) => { + promises.push(DocServer.GetRefField(attr.displayName! + ".alias").then(action((field: Opt) => { + if (field instanceof Doc) { + schemaDocuments.push(field); + } else { + var atmod = new ColumnAttributeModel(attr); + let histoOp = new HistogramOperation(schema.displayName!, + new AttributeTransformationModel(atmod, AggregateFunction.None), + new AttributeTransformationModel(atmod, AggregateFunction.Count), + new AttributeTransformationModel(atmod, AggregateFunction.Count)); + schemaDocuments.push(Docs.HistogramDocument(histoOp, { width: 200, height: 200, title: attr.displayName! })); + } + }))); + return promises; + }, [] as Promise[])); + return CurrentUserUtils._northstarSchemas.push(Docs.TreeDocument(schemaDocuments, { width: 50, height: 100, title: schema.displayName! })); + }); + } + } public static set NorthstarDBCatalog(ctlog: Catalog | undefined) { this._northstarCatalog = ctlog; } + public static AddNorthstarSchema(schema: Schema, schemaDoc: Doc) { + if (this._northstarCatalog && CurrentUserUtils._northstarSchemas) { + this._northstarCatalog.schemas!.push(schema); + CurrentUserUtils._northstarSchemas.push(schemaDoc); + let schemas = Cast(CurrentUserUtils.UserDocument.DBSchemas, listSpec("string"), []); + schemas.push(schema.displayName!); + CurrentUserUtils.UserDocument.DBSchemas = new List(schemas); + } + } public static GetNorthstarSchema(name: string): Schema | undefined { return !this._northstarCatalog || !this._northstarCatalog.schemas ? undefined : ArrayUtil.FirstOrDefault(this._northstarCatalog.schemas, (s: Schema) => s.displayName === name); -- cgit v1.2.3-70-g09d2 From b29a0d1cef60b55f609fcd94ad38232ae557e681 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Thu, 16 May 2019 18:32:57 -0400 Subject: Fixed linter errors --- src/client/goldenLayout.d.ts | 3 +++ src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/model/ModelHelpers.ts | 9 +++---- src/client/util/DragManager.ts | 2 +- src/client/util/RichTextSchema.tsx | 16 +++++------ src/client/util/TooltipTextMenu.tsx | 13 ++++----- src/client/views/DocumentDecorations.tsx | 31 +++++++++++----------- src/client/views/PresentationView.tsx | 4 +-- src/client/views/TemplateMenu.tsx | 4 +-- .../views/collections/CollectionDockingView.tsx | 5 ++-- .../views/collections/CollectionSchemaView.tsx | 10 +++---- .../views/collections/CollectionTreeView.tsx | 9 ++++--- .../collections/collectionFreeForm/MarqueeView.tsx | 13 ++++----- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FormattedTextBox.tsx | 8 +++--- src/client/views/nodes/ImageBox.tsx | 2 +- src/client/views/nodes/KeyValueBox.tsx | 2 +- src/client/views/nodes/KeyValuePair.tsx | 3 ++- src/client/views/nodes/VideoBox.tsx | 22 +++++++-------- src/new_fields/CursorField.ts | 6 ++--- src/new_fields/Doc.ts | 4 +-- src/new_fields/ObjectField.ts | 2 +- .../authentication/models/current_user_utils.ts | 2 +- 24 files changed, 91 insertions(+), 85 deletions(-) create mode 100644 src/client/goldenLayout.d.ts (limited to 'src/client/northstar') diff --git a/src/client/goldenLayout.d.ts b/src/client/goldenLayout.d.ts new file mode 100644 index 000000000..b50240563 --- /dev/null +++ b/src/client/goldenLayout.d.ts @@ -0,0 +1,3 @@ + +declare const GoldenLayout: any; +export = GoldenLayout; \ No newline at end of file diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index aabc77bb2..1ee2189b9 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -52,7 +52,7 @@ export class HistogramField extends ObjectField { [Copy]() { let y = this.HistoOp; - let z = this.HistoOp["Copy"]; + let z = this.HistoOp.Copy; return new HistogramField(HistogramOperation.Duplicate(this.HistoOp)); } } \ No newline at end of file diff --git a/src/client/northstar/model/ModelHelpers.ts b/src/client/northstar/model/ModelHelpers.ts index 80bb71224..88e6e72b8 100644 --- a/src/client/northstar/model/ModelHelpers.ts +++ b/src/client/northstar/model/ModelHelpers.ts @@ -32,12 +32,9 @@ export class ModelHelpers { public static GetAggregateParametersIndex(histogramResult: HistogramResult, aggParameters?: AggregateParameters): number { return Array.from(histogramResult.aggregateParameters!).findIndex((value, i, set) => { - if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) - return true; - if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) - return true; - if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) - return true; + if (set[i] instanceof CountAggregateParameters && value instanceof CountAggregateParameters) return true; + if (set[i] instanceof MarginAggregateParameters && value instanceof MarginAggregateParameters) return true; + if (set[i] instanceof SumAggregateParameters && value instanceof SumAggregateParameters) return true; return false; }); } diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 26da34e67..05eb5c38a 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -41,7 +41,7 @@ export function SetupDrag(_reference: React.RefObject, docFunc: () export async function DragLinksAsDocuments(dragEle: HTMLElement, x: number, y: number, sourceDoc: Doc) { let srcTarg = sourceDoc.proto; let draggedDocs: Doc[] = []; - let draggedFromDocs: Doc[] = [] + let draggedFromDocs: Doc[] = []; if (srcTarg) { let linkToDocs = await DocListCastAsync(srcTarg.linkedToDocs); let linkFromDocs = await DocListCastAsync(srcTarg.linkedFromDocs); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index c0e6f7899..3e3e98206 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -97,13 +97,13 @@ export const nodes: { [index: string]: NodeSpec } = { title: dom.getAttribute("title"), alt: dom.getAttribute("alt"), width: Math.min(100, Number(dom.getAttribute("width"))), - } + }; } }], // TODO if we don't define toDom, something weird happens: dragging the image will not move it but clone it. Why? toDOM(node) { - const attrs = { style: `width: ${node.attrs.width}` } - return ["img", { ...node.attrs, ...attrs }] + const attrs = { style: `width: ${node.attrs.width}` }; + return ["img", { ...node.attrs, ...attrs }]; } }, @@ -375,7 +375,7 @@ export class ImageResizeView { const currentX = e.pageX; const diffInPx = currentX - startX; self._outer.style.width = `${startWidth + diffInPx}`; - } + }; const onpointerup = () => { document.removeEventListener("pointermove", onpointermove); @@ -384,11 +384,11 @@ export class ImageResizeView { view.state.tr.setNodeMarkup(getPos(), null, { src: node.attrs.src, width: self._outer.style.width }) .setSelection(view.state.selection)); - } + }; - document.addEventListener("pointermove", onpointermove) - document.addEventListener("pointerup", onpointerup) - } + document.addEventListener("pointermove", onpointermove); + document.addEventListener("pointerup", onpointerup); + }; this._outer.appendChild(this._handle); this._outer.appendChild(this._img); diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 6eb654319..223921428 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -175,7 +175,7 @@ export class TooltipTextMenu { this.linkText.style.width = "150px"; this.linkText.style.overflow = "hidden"; this.linkText.style.color = "white"; - this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); } + this.linkText.onpointerdown = (e: PointerEvent) => { e.stopPropagation(); }; let linkBtn = document.createElement("div"); linkBtn.textContent = ">>"; linkBtn.style.width = "20px"; @@ -192,8 +192,9 @@ export class TooltipTextMenu { let docid = href.replace(DocServer.prepend("/doc/"), ""); DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); + } else CollectionDockingView.Instance.AddRightSplit(f); } })); @@ -201,7 +202,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.linkDrag = document.createElement("img"); this.linkDrag.src = "https://seogurusnyc.com/wp-content/uploads/2016/12/link-1.png"; this.linkDrag.style.width = "20px"; @@ -216,12 +217,12 @@ export class TooltipTextMenu { { handlers: { dragComplete: action(() => { - let m = dragData.droppedDocuments as Doc[]; + let m = dragData.droppedDocuments; this.makeLink(DocServer.prepend("/doc/" + m[0][Id])); }), }, hideSource: false - }) + }); }; this.linkEditor.appendChild(this.linkDrag); this.linkEditor.appendChild(this.linkText); @@ -239,7 +240,7 @@ export class TooltipTextMenu { e.stopPropagation(); e.preventDefault(); } - } + }; this.tooltip.appendChild(this.linkEditor); } diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index b2c65a31f..7083b1003 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -250,22 +250,21 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> selectedDocs[0].props.removeDocument && selectedDocs[0].props.removeDocument(this._iconDoc); } if (!this._removeIcon) { - if (selectedDocs.length === 1) + if (selectedDocs.length === 1) { this.getIconDoc(selectedDocs[0]).then(icon => selectedDocs[0].props.toggleMinimized()); - else - if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && - Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { - let docViews = SelectionManager.ViewsSortedVertically(); - let topDocView = docViews[0]; - let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); - if (ind !== -1) { - topDocView.templates.splice(ind, 1); - topDocView.props.Document.subBulletDocs = undefined; - } else { - topDocView.addTemplate(Templates.Bullet); - topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); - } + } else if (Math.abs(e.pageX - this._downX) < Utils.DRAG_THRESHOLD && + Math.abs(e.pageY - this._downY) < Utils.DRAG_THRESHOLD) { + let docViews = SelectionManager.ViewsSortedVertically(); + let topDocView = docViews[0]; + let ind = topDocView.templates.indexOf(Templates.Bullet.Layout); + if (ind !== -1) { + topDocView.templates.splice(ind, 1); + topDocView.props.Document.subBulletDocs = undefined; + } else { + topDocView.addTemplate(Templates.Bullet); + topDocView.props.Document.subBulletDocs = new List(docViews.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); } + } } this._removeIcon = false; } @@ -537,9 +536,9 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (temp !== Templates.Bullet.Layout || i === 0) { res.push(temp); } - }) + }); } - return res + return res; }, [] as string[]); let checked = false; docTemps.forEach(temp => { diff --git a/src/client/views/PresentationView.tsx b/src/client/views/PresentationView.tsx index 098e725c7..7d0dc2913 100644 --- a/src/client/views/PresentationView.tsx +++ b/src/client/views/PresentationView.tsx @@ -1,7 +1,7 @@ import { observer } from "mobx-react"; -import React = require("react") +import React = require("react"); import { observable, action, runInAction, reaction } from "mobx"; -import "./PresentationView.scss" +import "./PresentationView.scss"; import "./Main.tsx"; import { DocumentManager } from "../util/DocumentManager"; import { Utils } from "../../Utils"; diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index cfe1b0663..e5b679e24 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -43,7 +43,7 @@ export class TemplateMenu extends React.Component { @action toggleTemplate = (event: React.ChangeEvent, template: Template): void => { if (event.target.checked) { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); @@ -52,7 +52,7 @@ export class TemplateMenu extends React.Component { } this.props.templates.set(template, true); } else { - if (template.Name == "Bullet") { + if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.removeTemplate(template); topDocView.props.Document.subBulletDocs = undefined; diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 58f1e33a1..deec64225 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -83,7 +83,7 @@ export class CollectionDockingView extends React.Component tab.config.component === "DocumentFrameRenderer").some((tab: any, j: number) => { if (Doc.AreProtosEqual(DocumentManager.Instance.getDocumentViewById(tab.config.props.documentId)!.Document, document)) { child.contentItems[j].remove(); @@ -94,8 +94,9 @@ export class CollectionDockingView extends React.Component doc) { let fieldContentView = ; let reference = React.createRef(); let onItemDown = (e: React.PointerEvent) => - (this.props.CollectionView!.props.isSelected() ? + (this.props.CollectionView.props.isSelected() ? SetupDrag(reference, () => props.Document, this.props.moveDocument)(e) : undefined); let applyToDoc = (doc: Doc, run: (args?: { [name: string]: any }) => any) => { const res = run({ this: doc }); @@ -127,7 +127,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { } const run = script.run; //TODO This should be able to be refactored to compile the script once - const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]) + const val = await DocListCastAsync(this.props.Document[this.props.fieldKey]); val && val.forEach(doc => applyToDoc(doc, run)); }}> @@ -230,14 +230,14 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { DocListCast(this.props.Document.data).map(doc => { csv += self.columns.reduce((val, col) => val + (doc[col] ? doc[col]!.toString() : "") + ",", ""); csv = csv.substr(0, csv.length - 1) + "\n"; - }) + }); csv.substring(0, csv.length - 1); let dbName = StrCast(this.props.Document.title); let res = await Gateway.Instance.PostSchema(csv, dbName); if (self.props.CollectionView.props.addDocument) { let schemaDoc = await Docs.DBDocument("https://www.cs.brown.edu/" + dbName, { title: dbName }); if (schemaDoc) { - self.props.CollectionView.props.addDocument(schemaDoc, false); + self.props.CollectionView.props.addDocument(schemaDoc, false); } } } @@ -263,7 +263,7 @@ export class CollectionSchemaView extends CollectionSubView(doc => doc) { get previewDocument(): Doc | undefined { const children = DocListCast(this.props.Document[this.props.fieldKey]); const selected = children.length > this._selectedIndex ? FieldValue(children[this._selectedIndex]) : undefined; - return selected ? (this.previewScript && this.previewScript != "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; + return selected ? (this.previewScript && this.previewScript !== "this" ? FieldValue(Cast(selected[this.previewScript], Doc)) : selected) : undefined; } get tableWidth() { return (this.props.PanelWidth() - 2 * this.borderWidth - this.DIVIDER_WIDTH) * (1 - this.splitPercentage / 100); } get previewRegionHeight() { return this.props.PanelHeight() - 2 * this.borderWidth; } diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index 70c09d97c..6acef434e 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -56,7 +56,7 @@ class TreeView extends React.Component { } else { CollectionDockingView.Instance.AddRightSplit(this.props.document); } - }; + } get children() { return Cast(this.props.document.data, listSpec(Doc), []); // bcz: needed? .filter(doc => FieldValue(doc)); @@ -184,8 +184,9 @@ class TreeView extends React.Component { {TreeView.GetChildElements(doc instanceof Doc ? [doc] : docList, key !== "data", (doc: Doc) => this.remove(doc, key), this.move, this.props.dropAction)}
); - } else + } else { bulletType = BulletType.Collapsed; + } } }); return
{
; } public static GetChildElements(docs: Doc[], allowMinimized: boolean, remove: ((doc: Doc) => void), move: DragManager.MoveFunction, dropAction: dropActionType) { - return docs.filter(child => child instanceof Doc && !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).filter(doc => FieldValue(doc)).map(child => - ); + return docs.filter(child => !child.excludeFromLibrary && (allowMinimized || !child.isMinimized)).map(child => + ); } } diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 12edb2c2a..c3c4115b8 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -63,7 +63,7 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); for (let i = 0; i < ns.length - 1; i++) { while (!(ns[i].trim() === "" || ns[i].endsWith("-\r") || ns[i].endsWith("-") || ns[i].endsWith(";\r") || ns[i].endsWith(";") || @@ -80,7 +80,7 @@ export class MarqueeView extends React.Component let newBox = Docs.TextDocument({ width: 200, height: 35, x: x + indent / 3 * 10, y: y, documentText: "@@@" + line, title: line }); this.props.addDocument(newBox, false); y += 40 * this.props.getTransform().Scale; - }) + }); })(); } else if (e.key === "b" && e.ctrlKey) { //heuristically converts pasted text into a table. @@ -93,9 +93,10 @@ export class MarqueeView extends React.Component e.preventDefault(); (async () => { let text: string = await navigator.clipboard.readText(); - let ns = text.split("\n").filter(t => t.trim() != "\r" && t.trim() != ""); - while (ns.length > 0 && ns[0].split("\t").length < 2) + let ns = text.split("\n").filter(t => t.trim() !== "\r" && t.trim() !== ""); + while (ns.length > 0 && ns[0].split("\t").length < 2) { ns.splice(0, 1); + } if (ns.length > 0) { let columns = ns[0].split("\t"); let docList: Doc[] = []; @@ -109,7 +110,7 @@ export class MarqueeView extends React.Component let doc = new Doc(); columns.forEach((col, i) => doc[columns[i]] = (values.length > i ? ((values[i].indexOf(Number(values[i]).toString()) !== -1) ? Number(values[i]) : values[i]) : undefined)); if (groupAttr) { - doc["_group"] = groupAttr; + doc._group = groupAttr; } doc.title = i.toString(); docList.push(doc); @@ -284,7 +285,7 @@ export class MarqueeView extends React.Component // summarizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], maxx, maxy, maxw, maxh, Date.now(), 0]); // }); this.props.addLiveTextDocument(summary); - }) + }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7c7ca9e25..d4f660b3f 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -149,7 +149,7 @@ export class CollectionFreeFormDocumentView extends DocComponent([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]) + maximizedDoc.isIconAnimating = new List([scrpt[0], scrpt[1], Date.now(), isMinimized ? 1 : 0]); } } }); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index cf8bcbb42..428dd9b36 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -244,7 +244,7 @@ export class DocumentView extends DocComponent(Docu const protoDest = destDoc.proto; const protoSrc = sourceDoc.proto; - if (de.mods == "Control") { + if (de.mods === "Control") { let src = protoSrc ? protoSrc : sourceDoc; let dst = protoDest ? protoDest : destDoc; dst.data = src; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f24d4ae88..f30022508 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -184,7 +184,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), dispatchTransaction: this.dispatchTransaction, nodeViews: { - image(node, view, getPos) { return new ImageResizeView(node, view, getPos) } + image(node, view, getPos) { return new ImageResizeView(node, view, getPos); } } }); let text = StrCast(this.props.Document.documentText); @@ -232,9 +232,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let docid = href.replace(DocServer.prepend("/doc/"), "").split("?")[0]; DocServer.GetRefField(docid).then(action((f: Opt) => { if (f instanceof Doc) { - if (DocumentManager.Instance.getDocumentView(f)) + if (DocumentManager.Instance.getDocumentView(f)) { DocumentManager.Instance.getDocumentView(f)!.props.focus(f); - else CollectionDockingView.Instance.AddRightSplit(f); + } else { + CollectionDockingView.Instance.AddRightSplit(f); + } } })); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 6472ae711..3cc60a6c5 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -165,7 +165,7 @@ export class ImageBox extends DocComponent(ImageD else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, (this.props.PanelWidth as any) as string ? Number((this.props.PanelWidth as any) as string) : 50); let interactive = InkingControl.Instance.selectedTool ? "" : "-interactive"; - let id = this.props.id; // bcz: used to set id = "isExpander" in templates.tsx + let id = (this.props as any).id; // bcz: used to set id = "isExpander" in templates.tsx return (
{ @observable private _keyInput: string = ""; @observable private _valueInput: string = ""; @computed get splitPercentage() { return NumCast(this.props.Document.schemaSplitPercentage, 50); } - get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document } + get fieldDocToLayout() { return this.props.fieldKey ? FieldValue(Cast(this.props.Document[this.props.fieldKey], Doc)) : this.props.Document; } constructor(props: FieldViewProps) { super(props); diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 5de660d57..4f7919f50 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -46,8 +46,9 @@ export class KeyValuePair extends React.Component {
+ {content}
); @@ -42,6 +64,13 @@ class ListViewer extends React.Component<{ field: List }>{ class DocumentViewer extends React.Component<{ field: Doc }> { @observable expanded = false; + + @action + onClick = (e: React.MouseEvent) => { + this.expanded = !this.expanded; + e.stopPropagation(); + } + render() { let content; if (this.expanded) { @@ -50,7 +79,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { return (
({key}): - + applyToDoc(this.props.field, key, value)}>
); }); @@ -67,7 +96,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { } return (
- + {content}
); @@ -75,7 +104,7 @@ class DocumentViewer extends React.Component<{ field: Doc }> { } @observer -class DebugViewer extends React.Component<{ field: FieldResult }> { +class DebugViewer extends React.Component<{ field: FieldResult, setValue(value: string): boolean }> { render() { let content; @@ -90,10 +119,14 @@ class DebugViewer extends React.Component<{ field: FieldResult }> { content =

{field}

; } else if (field instanceof URLField) { content =

{field.url.href}

; + } else if (field instanceof Promise) { + return

Field loading

; } else { - content =

Unrecognized field type

; + return

Unrecognized field type

; } - return content; + + return Field.toScriptString(field)} SetValue={this.props.setValue} + contents={content}>; } } @@ -129,7 +162,7 @@ class Viewer extends React.Component { onChange={this.inputOnChange} onKeyDown={this.onKeyPress} />
- {this.fields.map((field, index) => )} + {this.fields.map((field, index) => false}>)}
); diff --git a/src/new_fields/CursorField.ts b/src/new_fields/CursorField.ts index fc144222c..1be1ec3e0 100644 --- a/src/new_fields/CursorField.ts +++ b/src/new_fields/CursorField.ts @@ -1,7 +1,8 @@ -import { ObjectField, Copy, OnUpdate } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { observable } from "mobx"; import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, createSimpleSchema, object } from "serializr"; +import { OnUpdate, ToScriptString, Copy } from "./FieldSymbols"; export type CursorPosition = { x: number, @@ -52,4 +53,8 @@ export default class CursorField extends ObjectField { [Copy]() { return new CursorField(this.data); } + + [ToScriptString]() { + return "invalid"; + } } \ No newline at end of file diff --git a/src/new_fields/DateField.ts b/src/new_fields/DateField.ts index c0a79f267..fc8abb9d9 100644 --- a/src/new_fields/DateField.ts +++ b/src/new_fields/DateField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, date } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("date") export class DateField extends ObjectField { @@ -15,4 +16,8 @@ export class DateField extends ObjectField { [Copy]() { return new DateField(this.date); } + + [ToScriptString]() { + return `new DateField(new Date(${this.date.toISOString()}))`; + } } diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index 02dd34cb4..f4514c33e 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -5,27 +5,33 @@ import { DocServer } from "../client/DocServer"; import { setter, getter, getField, updateFunction, deleteProperty } from "./util"; import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types"; import { listSpec } from "./Schema"; -import { ObjectField, Parent, OnUpdate } from "./ObjectField"; -import { RefField, FieldId, Id, HandleUpdate } from "./RefField"; - -export function IsField(field: any): field is Field { - return (typeof field === "string") - || (typeof field === "number") - || (typeof field === "boolean") - || (field instanceof ObjectField) - || (field instanceof RefField); +import { ObjectField } from "./ObjectField"; +import { RefField, FieldId } from "./RefField"; +import { ToScriptString, SelfProxy, Parent, OnUpdate, Self, HandleUpdate, Update, Id } from "./FieldSymbols"; + +export namespace Field { + export function toScriptString(field: Field): string { + if (typeof field === "string") { + return `"${field}"`; + } else if (typeof field === "number" || typeof field === "boolean") { + return String(field); + } else { + return field[ToScriptString](); + } + } + export function IsField(field: any): field is Field { + return (typeof field === "string") + || (typeof field === "number") + || (typeof field === "boolean") + || (field instanceof ObjectField) + || (field instanceof RefField); + } } export type Field = number | string | boolean | ObjectField | RefField; export type Opt = T | undefined; export type FieldWaiting = T extends undefined ? never : Promise; export type FieldResult = Opt | FieldWaiting>; -export const Update = Symbol("Update"); -export const Self = Symbol("Self"); -export const SelfProxy = Symbol("SelfProxy"); -export const WidthSym = Symbol("Width"); -export const HeightSym = Symbol("Height"); - /** * Cast any field to either a List of Docs or undefined if the given field isn't a List of Docs. * If a default value is given, that will be returned instead of undefined. @@ -43,6 +49,9 @@ export function DocListCast(field: FieldResult): Doc[] { return Cast(field, listSpec(Doc), []).filter(d => d instanceof Doc) as Doc[]; } +export const WidthSym = Symbol("Width"); +export const HeightSym = Symbol("Height"); + @Deserializable("doc").withFields(["id"]) export class Doc extends RefField { constructor(id?: FieldId, forceSave?: boolean) { @@ -102,6 +111,10 @@ export class Doc extends RefField { public [WidthSym] = () => NumCast(this[SelfProxy].width); // bcz: is this the right way to access width/height? it didn't work with : this.width public [HeightSym] = () => NumCast(this[SelfProxy].height); + [ToScriptString]() { + return "invalid"; + } + public [HandleUpdate](diff: any) { console.log(diff); const set = diff.$set; diff --git a/src/new_fields/FieldSymbols.ts b/src/new_fields/FieldSymbols.ts new file mode 100644 index 000000000..a436dcf2b --- /dev/null +++ b/src/new_fields/FieldSymbols.ts @@ -0,0 +1,10 @@ + +export const Update = Symbol("Update"); +export const Self = Symbol("Self"); +export const SelfProxy = Symbol("SelfProxy"); +export const HandleUpdate = Symbol("HandleUpdate"); +export const Id = Symbol("Id"); +export const OnUpdate = Symbol("OnUpdate"); +export const Parent = Symbol("Parent"); +export const Copy = Symbol("Copy"); +export const ToScriptString = Symbol("Copy"); \ No newline at end of file diff --git a/src/new_fields/HtmlField.ts b/src/new_fields/HtmlField.ts index d998746bb..f952acff9 100644 --- a/src/new_fields/HtmlField.ts +++ b/src/new_fields/HtmlField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, primitive } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("html") export class HtmlField extends ObjectField { @@ -15,4 +16,8 @@ export class HtmlField extends ObjectField { [Copy]() { return new HtmlField(this.html); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/IconField.ts b/src/new_fields/IconField.ts index 1a928389d..62b2cd254 100644 --- a/src/new_fields/IconField.ts +++ b/src/new_fields/IconField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, primitive } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("icon") export class IconField extends ObjectField { @@ -15,4 +16,8 @@ export class IconField extends ObjectField { [Copy]() { return new IconField(this.icon); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/InkField.ts b/src/new_fields/InkField.ts index 2d75f8a19..4e3b7abe0 100644 --- a/src/new_fields/InkField.ts +++ b/src/new_fields/InkField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom, createSimpleSchema, list, object, map } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { Copy, ToScriptString } from "./FieldSymbols"; import { deepCopy } from "../Utils"; export enum InkTool { @@ -40,4 +41,8 @@ export class InkField extends ObjectField { [Copy]() { return new InkField(deepCopy(this.inkData)); } + + [ToScriptString]() { + return "invalid"; + } } diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts index 70e36f911..f1e4c4721 100644 --- a/src/new_fields/List.ts +++ b/src/new_fields/List.ts @@ -1,11 +1,12 @@ import { Deserializable, autoObject } from "../client/util/SerializationHelper"; -import { Field, Update, Self, FieldResult, SelfProxy } from "./Doc"; +import { Field } from "./Doc"; import { setter, getter, deleteProperty, updateFunction } from "./util"; import { serializable, alias, list } from "serializr"; import { observable, action } from "mobx"; -import { ObjectField, OnUpdate, Copy, Parent } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { RefField } from "./RefField"; import { ProxyField } from "./Proxy"; +import { Self, Update, Parent, OnUpdate, SelfProxy, ToScriptString, Copy } from "./FieldSymbols"; const listHandlers: any = { /// Mutator methods @@ -225,7 +226,7 @@ type StoredType = T extends RefField ? ProxyField : T; @Deserializable("list") class ListImpl extends ObjectField { - constructor(fields: T[] = []) { + constructor(fields?: T[]) { super(); const list = new Proxy(this, { set: setter, @@ -244,7 +245,9 @@ class ListImpl extends ObjectField { defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); }, }); this[SelfProxy] = list; - (list as any).push(...fields); + if (fields) { + (list as any).push(...fields); + } return list; } @@ -284,6 +287,11 @@ class ListImpl extends ObjectField { private [Self] = this; private [SelfProxy]: any; + + [ToScriptString]() { + return "invalid"; + // return `new List([${(this as any).map((field => Field.toScriptString(field))}])`; + } } export type List = ListImpl & (T | (T extends RefField ? Promise : never))[]; export const List: { new (fields?: T[]): List } = ListImpl as any; \ No newline at end of file diff --git a/src/new_fields/ObjectField.ts b/src/new_fields/ObjectField.ts index 51768c6db..5f4a6f8fb 100644 --- a/src/new_fields/ObjectField.ts +++ b/src/new_fields/ObjectField.ts @@ -1,14 +1,13 @@ import { Doc } from "./Doc"; import { RefField } from "./RefField"; - -export const OnUpdate = Symbol("OnUpdate"); -export const Parent = Symbol("Parent"); -export const Copy = Symbol("Copy"); +import { OnUpdate, Parent, Copy, ToScriptString } from "./FieldSymbols"; export abstract class ObjectField { protected [OnUpdate](diff?: any) { } private [Parent]?: RefField | ObjectField; abstract [Copy](): ObjectField; + + abstract [ToScriptString](): string; } export namespace ObjectField { diff --git a/src/new_fields/Proxy.ts b/src/new_fields/Proxy.ts index fd99ae1c0..130ec066e 100644 --- a/src/new_fields/Proxy.ts +++ b/src/new_fields/Proxy.ts @@ -3,8 +3,9 @@ import { FieldWaiting } from "./Doc"; import { primitive, serializable } from "serializr"; import { observable, action } from "mobx"; import { DocServer } from "../client/DocServer"; -import { RefField, Id } from "./RefField"; -import { ObjectField, Copy } from "./ObjectField"; +import { RefField } from "./RefField"; +import { ObjectField } from "./ObjectField"; +import { Id, Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("proxy") export class ProxyField extends ObjectField { @@ -26,6 +27,10 @@ export class ProxyField extends ObjectField { return new ProxyField(this.fieldId); } + [ToScriptString]() { + return "invalid"; + } + @serializable(primitive()) readonly fieldId: string = ""; diff --git a/src/new_fields/RefField.ts b/src/new_fields/RefField.ts index 202c65f21..75ce4287f 100644 --- a/src/new_fields/RefField.ts +++ b/src/new_fields/RefField.ts @@ -1,9 +1,8 @@ import { serializable, primitive, alias } from "serializr"; import { Utils } from "../Utils"; +import { Id, HandleUpdate, ToScriptString } from "./FieldSymbols"; export type FieldId = string; -export const HandleUpdate = Symbol("HandleUpdate"); -export const Id = Symbol("Id"); export abstract class RefField { @serializable(alias("id", primitive())) private __id: FieldId; @@ -15,4 +14,6 @@ export abstract class RefField { } protected [HandleUpdate]?(diff: any): void; + + abstract [ToScriptString](): string; } diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index eb30e76de..89d077a47 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -1,6 +1,7 @@ -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; import { serializable } from "serializr"; import { Deserializable } from "../client/util/SerializationHelper"; +import { Copy, ToScriptString } from "./FieldSymbols"; @Deserializable("RichTextField") export class RichTextField extends ObjectField { @@ -15,4 +16,8 @@ export class RichTextField extends ObjectField { [Copy]() { return new RichTextField(this.Data); } + + [ToScriptString]() { + return "invalid"; + } } \ No newline at end of file diff --git a/src/new_fields/URLField.ts b/src/new_fields/URLField.ts index d00a95a16..a6f8f1cc5 100644 --- a/src/new_fields/URLField.ts +++ b/src/new_fields/URLField.ts @@ -1,6 +1,7 @@ import { Deserializable } from "../client/util/SerializationHelper"; import { serializable, custom } from "serializr"; -import { ObjectField, Copy } from "./ObjectField"; +import { ObjectField } from "./ObjectField"; +import { ToScriptString, Copy } from "./FieldSymbols"; function url() { return custom( @@ -13,7 +14,7 @@ function url() { ); } -export class URLField extends ObjectField { +export abstract class URLField extends ObjectField { @serializable(url()) readonly url: URL; @@ -22,6 +23,10 @@ export class URLField extends ObjectField { this.url = url; } + [ToScriptString]() { + return `new ${this.constructor.name}(new URL(${this.url.href}))`; + } + [Copy](): this { return new (this.constructor as any)(this.url); } diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index d94994a07..65a37a0d1 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -1,11 +1,12 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Update, Doc, Field } from "./Doc"; +import { Doc, Field } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField } from "./Proxy"; import { FieldValue } from "./Types"; -import { RefField, Id } from "./RefField"; -import { ObjectField, Parent, OnUpdate } from "./ObjectField"; +import { RefField } from "./RefField"; +import { ObjectField } from "./ObjectField"; import { action } from "mobx"; +import { Parent, OnUpdate, Update, Id } from "./FieldSymbols"; export const setter = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { -- cgit v1.2.3-70-g09d2 From 7e5ba95b02e4ead3ee2b41eca1af0acb72d6f7cd Mon Sep 17 00:00:00 2001 From: bob Date: Tue, 21 May 2019 14:15:06 -0400 Subject: fixes for histogram brushing. --- src/client/northstar/dash-fields/HistogramField.ts | 2 +- src/client/northstar/dash-nodes/HistogramBox.tsx | 4 ++- .../CollectionFreeFormLinksView.tsx | 12 +++---- .../collections/collectionFreeForm/MarqueeView.tsx | 38 ++++++++++++---------- src/client/views/nodes/FieldView.tsx | 2 +- 5 files changed, 31 insertions(+), 27 deletions(-) (limited to 'src/client/northstar') diff --git a/src/client/northstar/dash-fields/HistogramField.ts b/src/client/northstar/dash-fields/HistogramField.ts index 31040a474..e6f32272e 100644 --- a/src/client/northstar/dash-fields/HistogramField.ts +++ b/src/client/northstar/dash-fields/HistogramField.ts @@ -58,6 +58,6 @@ export class HistogramField extends ObjectField { } [ToScriptString]() { - return "invalid"; + return this.toString(); } } \ No newline at end of file diff --git a/src/client/northstar/dash-nodes/HistogramBox.tsx b/src/client/northstar/dash-nodes/HistogramBox.tsx index a9646ed31..d7732ee86 100644 --- a/src/client/northstar/dash-nodes/HistogramBox.tsx +++ b/src/client/northstar/dash-nodes/HistogramBox.tsx @@ -125,9 +125,11 @@ export class HistogramBox extends React.Component { let mapped = brushingDocs.map((brush, i) => { brush.backgroundColor = StyleConstants.BRUSH_COLORS[i % StyleConstants.BRUSH_COLORS.length]; let brushed = DocListCast(brush.brushingDocs); + if (!brushed.length) + return null; return { l: brush, b: brushed[0][Id] === proto[Id] ? brushed[1] : brushed[0] }; }); - this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped); + runInAction(() => this.HistoOp.BrushLinks.splice(0, this.HistoOp.BrushLinks.length, ...mapped.filter(m => m) as { l: Doc, b: Doc }[])); } }, { fireImmediately: true }); reaction(() => this.createOperationParamsCache, () => this.HistoOp.Update(), { fireImmediately: true }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx index e1ff715d1..c5f7ad0d1 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx @@ -32,8 +32,8 @@ export class CollectionFreeFormLinksView extends React.Component)[]) => field.findIndex(brush => { @@ -60,12 +60,12 @@ export class CollectionFreeFormLinksView extends React.Component(); + if (srcTarg.brushingDocs === undefined) srcTarg.brushingDocs = new List(); let dstBrushDocs = Cast(dstTarg.brushingDocs, listSpec(Doc), []); let srcBrushDocs = Cast(srcTarg.brushingDocs, listSpec(Doc), []); - if (dstBrushDocs === undefined) dstTarg.brushingDocs = dstBrushDocs = new List(); - else brushAction(dstBrushDocs); - if (srcBrushDocs === undefined) srcTarg.brushingDocs = srcBrushDocs = new List(); - else brushAction(srcBrushDocs); + brushAction(dstBrushDocs); + brushAction(srcBrushDocs); } }); }); diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx index 7ccf480f3..f0ccda140 100644 --- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx +++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx @@ -228,6 +228,7 @@ export class MarqueeView extends React.Component if (e.key === "c" || e.key === "s" || e.key === "e" || e.key === "p") { this._commandExecuted = true; e.stopPropagation(); + e.preventDefault(); (e as any).propagationIsStopped = true; let bounds = this.Bounds; let selected = this.marqueeSelect(); @@ -260,25 +261,26 @@ export class MarqueeView extends React.Component if (e.key === "s" || e.key === "p") { - htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { - selected.map(d => { - this.props.removeDocument(d); - d.x = NumCast(d.x) - bounds.left - bounds.width / 2; - d.y = NumCast(d.y) - bounds.top - bounds.height / 2; - d.page = -1; - return d; - }); - let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); - summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); - summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); - newCollection.proto!.summaryDoc = summary; - selected = [newCollection]; - newCollection.x = bounds.left + bounds.width; - //this.props.addDocument(newCollection, false); - summary.proto!.summarizedDocs = new List(selected); - summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" - this.props.addLiveTextDocument(summary); + // htmlToImage.toPng(this._mainCont.current!, { width: bounds.width * zoomBasis, height: bounds.height * zoomBasis, quality: 0.2 }).then((dataUrl) => { + selected.map(d => { + this.props.removeDocument(d); + d.x = NumCast(d.x) - bounds.left - bounds.width / 2; + d.y = NumCast(d.y) - bounds.top - bounds.height / 2; + d.page = -1; + return d; }); + let summary = Docs.TextDocument({ x: bounds.left, y: bounds.top, width: 300, height: 100, backgroundColor: "yellow", title: "-summary-" }); + // summary.proto!.thumbnail = new ImageField(new URL(dataUrl)); + // summary.proto!.templates = new List([Templates.ImageOverlay(Math.min(50, bounds.width), bounds.height * Math.min(50, bounds.width) / bounds.width, "thumbnail")]); + newCollection.proto!.summaryDoc = summary; + selected = [newCollection]; + newCollection.x = bounds.left + bounds.width; + //this.props.addDocument(newCollection, false); + summary.proto!.summarizedDocs = new List(selected); + summary.proto!.maximizeLocation = "inTab"; // or "inPlace", or "onRight" + + this.props.addLiveTextDocument(summary); + // }); } else { this.props.addDocument(newCollection, false); diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 5c149af99..092ccb9b0 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -117,7 +117,7 @@ export class FieldView extends React.Component { // return // } else if (!(field instanceof Promise)) { - return

{JSON.stringify(field)}

; + return

{field.toString()}

; } else { return

{"Waiting for server..."}

; -- cgit v1.2.3-70-g09d2