From a16e6592caafb601b59c3d9f7609e8c1af231eba Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 20 Mar 2019 18:00:39 -0400 Subject: initial --- src/client/views/Main.tsx | 47 ++++++++++++++--- src/client/views/nodes/DocumentContentsView.tsx | 4 +- src/client/views/nodes/FieldView.tsx | 7 +-- src/client/views/nodes/HistogramBox.scss | 8 +++ src/client/views/nodes/HistogramBox.tsx | 67 +++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 src/client/views/nodes/HistogramBox.scss create mode 100644 src/client/views/nodes/HistogramBox.tsx (limited to 'src/client/views') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index ac51a7d87..b27f63e52 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -1,4 +1,4 @@ -import { action, configure, observable, runInAction, trace, computed } from 'mobx'; +import { action, configure, observable, runInAction, trace, computed, reaction } from 'mobx'; import "normalize.css"; import * as React from 'react'; import * as ReactDOM from 'react-dom'; @@ -22,7 +22,6 @@ import "./Main.scss"; import { observer } from 'mobx-react'; import { InkingControl } from './InkingControl'; import { RouteStore } from '../../server/RouteStore'; -import { json } from 'body-parser'; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faFont } from '@fortawesome/free-solid-svg-icons'; @@ -42,9 +41,10 @@ import { ServerUtils } from '../../server/ServerUtil'; import { CurrentUserUtils } from '../../server/authentication/models/current_user_utils'; import { Field, Opt } from '../../fields/Field'; import { ListField } from '../../fields/ListField'; -import { map } from 'bluebird'; import { Gateway, Settings } from '../northstar/manager/Gateway'; -import { Catalog } from '../northstar/model/idea/idea'; +import { Catalog, Schema, Attribute, AttributeGroup } from '../northstar/model/idea/idea'; +import { ArrayUtil } from '../northstar/utils/ArrayUtil'; +import '../northstar/model/ModelExtensions' @observer export class Main extends React.Component { @@ -88,16 +88,45 @@ export class Main extends React.Component { this.initEventListeners(); Documents.initProtos(() => this.initAuthenticationRouters()); + + reaction(() => [this.mainContainer, this.ActiveSchema], + () => { + if (this.mainContainer && this.ActiveSchema) { + if (!this.mainContainer!.GetTAsync(KeyStore.ActiveDB, ListField, field => this.NorthstarCatalog = field!.Data as Document[])) { + this.NorthstarCatalog = this.GetAllAttributes().map(a => Documents.HistogramDocument({ width: 200, height: 200, title: a.displayName! })); + this.mainContainer!.SetData(KeyStore.ActiveDB, this.NorthstarCatalog, ListField); + } + } + }) } + NorthstarCatalog: Document[] = []; + @observable ActiveSchema: Schema | undefined; @action SetNorthstarCatalog(ctlog: Catalog) { this._northstarCatalog = ctlog; - if (this._northstarCatalog) { + if (this._northstarCatalog && this._northstarCatalog.schemas) { console.log("CATALOG " + this._northstarCatalog.schemas); + this.ActiveSchema = ArrayUtil.FirstOrDefault(this._northstarCatalog.schemas!, (s: Schema) => s.displayName === "mimic"); } } + public GetAllAttributes() { + if (!this.ActiveSchema || !this.ActiveSchema.rootAttributeGroup) { + return []; + } + const recurs = (attrs: Attribute[], g: AttributeGroup) => { + if (g.attributes) { + attrs.push.apply(attrs, g.attributes); + if (g.attributeGroups) { + g.attributeGroups.forEach(ng => recurs(attrs, ng)); + } + } + }; + const allAttributes: Attribute[] = new Array(); + recurs(allAttributes, this.ActiveSchema.rootAttributeGroup); + return allAttributes; + } async initializeNorthstar(): Promise { - let envPath = "assets/env.json"; + let envPath = "/assets/env.json"; const response = await fetch(envPath, { redirect: "follow", method: "GET", @@ -251,7 +280,7 @@ export class Main extends React.Component { let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Documents.SchemaDocument(this.NorthstarCatalog, { width: 200, height: 200, title: "a schema collection" })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); @@ -269,7 +298,9 @@ export class Main extends React.Component { [React.createRef(), "table", "Add Schema", addSchemaNode], ] - let addClick = (creator: () => Document) => action(() => this.mainfreeform!.GetList(KeyStore.Data, []).push(creator())); + let addClick = (creator: () => Document) => action(() => { + this.mainfreeform!.GetList(KeyStore.Data, []).push(creator()) + }); return < div id="add-nodes-menu" > diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index ce72ab64b..2f0459f88 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -19,6 +19,7 @@ import { KeyValueBox } from "./KeyValueBox"; import { PDFBox } from "./PDFBox"; import { VideoBox } from "./VideoBox"; import { WebBox } from "./WebBox"; +import { HistogramBox } from "./HistogramBox"; import React = require("react"); const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -47,8 +48,7 @@ export class DocumentContentsView extends React.Component { console.log(test) }} diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index b6d50bffb..f6343c631 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -7,7 +7,6 @@ import { TextField } from "../../../fields/TextField"; import { NumberField } from "../../../fields/NumberField"; import { RichTextField } from "../../../fields/RichTextField"; import { ImageField } from "../../../fields/ImageField"; -import { WebField } from "../../../fields/WebField"; import { VideoField } from "../../../fields/VideoField" import { Key } from "../../../fields/Key"; import { FormattedTextBox } from "./FormattedTextBox"; @@ -64,9 +63,11 @@ export class FieldView extends React.Component { } else if (field instanceof AudioField) { return - } else if (field instanceof Document) { + } + else if (field instanceof Document) { return
{field.Title}
- } else if (field instanceof ListField) { + } + else if (field instanceof ListField) { return (
{(field as ListField).Data.map(f => { return f instanceof Document ? f.Title : f.GetValue().toString(); diff --git a/src/client/views/nodes/HistogramBox.scss b/src/client/views/nodes/HistogramBox.scss new file mode 100644 index 000000000..04bf1d732 --- /dev/null +++ b/src/client/views/nodes/HistogramBox.scss @@ -0,0 +1,8 @@ +.histogrambox-container { + padding: 0vw; + position: relative; + text-align: center; + width: 100%; + height: 100%; + } + \ No newline at end of file diff --git a/src/client/views/nodes/HistogramBox.tsx b/src/client/views/nodes/HistogramBox.tsx new file mode 100644 index 000000000..0fcc25e66 --- /dev/null +++ b/src/client/views/nodes/HistogramBox.tsx @@ -0,0 +1,67 @@ +import React = require("react") +import { observer } from "mobx-react"; +import { FieldView, FieldViewProps } from './FieldView'; +import "./VideoBox.scss"; +import { observable, reaction } from "mobx"; +import { HistogramOperation } from "../../northstar/operations/HistogramOperation"; +import { Main } from "../Main"; +import { ColumnAttributeModel } from "../../northstar/core/attribute/AttributeModel"; +import { AttributeTransformationModel } from "../../northstar/core/attribute/AttributeTransformationModel"; +import { AggregateFunction, HistogramResult, DoubleValueAggregateResult } from "../../northstar/model/idea/idea"; +import { ModelHelpers } from "../../northstar/model/ModelHelpers"; + +@observer +export class HistogramBox extends React.Component { + + public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(HistogramBox, fieldStr) } + + constructor(props: FieldViewProps) { + super(props); + } + + @observable _histoResult?: HistogramResult; + _histoOp?: HistogramOperation; + + componentDidMount() { + Main.Instance.GetAllAttributes().map(a => { + if (a.displayName == this.props.doc.Title) { + var atmod = new ColumnAttributeModel(a); + this._histoOp = new HistogramOperation(new AttributeTransformationModel(atmod, AggregateFunction.None), + new AttributeTransformationModel(atmod, AggregateFunction.Count), + new AttributeTransformationModel(atmod, AggregateFunction.Count)); + reaction(() => [this._histoOp && this._histoOp.Result], + () => this._histoResult = this._histoOp ? this._histoOp.Result as HistogramResult : undefined + ); + this._histoOp.Update(); + } + }) + } + + twoString() { + let str = ""; + if (this._histoResult && !this._histoResult.isEmpty) { + for (let key in this._histoResult.bins) { + if (this._histoResult.bins.hasOwnProperty(key)) { + let bin = this._histoResult.bins[key]; + str += JSON.stringify(bin.binIndex!.toJSON()) + " = "; + let valueAggregateKey = ModelHelpers.CreateAggregateKey(this._histoOp!.V, this._histoResult, ModelHelpers.AllBrushIndex(this._histoResult)); + let value = ModelHelpers.GetAggregateResult(bin, valueAggregateKey) as DoubleValueAggregateResult; + if (value && value.hasResult && value.result) { + str += value.result; + } + } + } + } + return str; + } + + render() { + if (!this._histoResult) + return (null); + return ( +
+ `HISTOGRAM RESULT : ${this.twoString()}` +
+ ) + } +} \ No newline at end of file -- cgit v1.2.3-70-g09d2 From d888a56abfee2934e0426258c7b24cfff3ad1a77 Mon Sep 17 00:00:00 2001 From: bob Date: Wed, 20 Mar 2019 18:29:32 -0400 Subject: switched to a tree view for performance and added dragging tree view items. --- src/client/documents/Documents.ts | 3 +++ src/client/views/Main.tsx | 10 ++++++---- src/client/views/collections/CollectionTreeView.tsx | 13 +++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/client/views') diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index b1e1f8c7b..cf6d7d503 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -212,6 +212,9 @@ export namespace Documents { export function SchemaDocument(documents: Array, options: DocumentOptions, id?: string) { return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, [documents, ListField], id), options) } + export function TreeDocument(documents: Array, options: DocumentOptions, id?: string) { + return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Tree }, [documents, ListField], id), options) + } export function DockDocument(config: string, options: DocumentOptions, id?: string) { return assignToDelegate(SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, [config, TextField], id), options) } diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index b27f63e52..113132ae6 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -35,6 +35,7 @@ import { faRedoAlt } from '@fortawesome/free-solid-svg-icons'; import { faPenNib } from '@fortawesome/free-solid-svg-icons'; import { faFilm } from '@fortawesome/free-solid-svg-icons'; import { faMusic } from '@fortawesome/free-solid-svg-icons'; +import { faTree } from '@fortawesome/free-solid-svg-icons'; import Measure from 'react-measure'; import { DashUserModel } from '../../server/authentication/models/user_model'; import { ServerUtils } from '../../server/ServerUtil'; @@ -85,6 +86,7 @@ export class Main extends React.Component { library.add(faPenNib); library.add(faFilm); library.add(faMusic); + library.add(faTree); this.initEventListeners(); Documents.initProtos(() => this.initAuthenticationRouters()); @@ -280,7 +282,8 @@ export class Main extends React.Component { let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); - let addSchemaNode = action(() => Documents.SchemaDocument(this.NorthstarCatalog, { width: 200, height: 200, title: "a schema collection" })); + let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); + let addTreeNode = action(() => Documents.TreeDocument(this.NorthstarCatalog, { width: 200, height: 200, title: "a tree collection" })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); @@ -295,12 +298,11 @@ export class Main extends React.Component { [React.createRef(), "music", "Add Audio", addAudioNode], [React.createRef(), "globe-asia", "Add Web Clipping", addWebNode], [React.createRef(), "object-group", "Add Collection", addColNode], + [React.createRef(), "tree", "Add Tree", addTreeNode], [React.createRef(), "table", "Add Schema", addSchemaNode], ] - let addClick = (creator: () => Document) => action(() => { - this.mainfreeform!.GetList(KeyStore.Data, []).push(creator()) - }); + let addClick = (creator: () => Document) => action(() => this.mainfreeform!.GetList(KeyStore.Data, []).push(creator())); return < div id="add-nodes-menu" > diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index f9da759fd..d6998cd48 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -10,11 +10,12 @@ import "./CollectionTreeView.scss"; import { EditableView } from "../EditableView"; import { setupDrag } from "../../util/DragManager"; import { FieldWaiting } from "../../../fields/Field"; -import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; +import { COLLECTION_BORDER_WIDTH, CollectionView } from "./CollectionView"; import { library } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faTrashAlt, faCaretRight, faCaretDown } from '@fortawesome/free-solid-svg-icons'; +import { CollectionDockingView } from "./CollectionDockingView"; export interface TreeViewProps { document: Document; @@ -41,7 +42,8 @@ class TreeView extends React.Component { collapsed: boolean = false; delete = () => { - this.props.deleteDoc(this.props.document); + CollectionDockingView.Instance.AddRightSplit(this.props.document) + //this.props.deleteDoc(this.props.document); } @@ -55,10 +57,11 @@ class TreeView extends React.Component { renderBullet(type: BulletType) { let onClicked = action(() => this.collapsed = !this.collapsed); + let onDoubleClick = action(() => CollectionDockingView.Instance.AddRightSplit(this.props.document)); switch (type) { case BulletType.Collapsed: - return
+ return
case BulletType.Collapsible: return
case BulletType.List: @@ -70,6 +73,8 @@ class TreeView extends React.Component { * Renders the EditableView title element for placement into the tree. */ renderTitle() { + let reference = React.createRef(); + let onItemDown = setupDrag(reference, () => this.props.document, (containingCollection: CollectionView) => this.props.deleteDoc(this.props.document)); let title = this.props.document.GetT(KeyStore.Title, TextField); // if the title hasn't loaded, immediately return the div @@ -77,7 +82,7 @@ class TreeView extends React.Component { return
; } - return
{ -- cgit v1.2.3-70-g09d2 From 08c35582dc71623c2b7300458238b6ba25ff98d7 Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 21 Mar 2019 15:30:15 -0400 Subject: fixed performance problem with loading schema with a lot of documents. --- .../views/collections/CollectionSchemaView.tsx | 25 +++++++++++++++++----- .../views/collections/CollectionTreeView.tsx | 2 +- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index b986f394c..34b019244 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -2,7 +2,7 @@ import React = require("react") import { library } from '@fortawesome/fontawesome-svg-core'; import { faCog } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable } from "mobx"; +import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import Measure from "react-measure"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; @@ -141,6 +141,7 @@ export class CollectionSchemaView extends CollectionViewBase { }; } + @computed get columns() { return this.props.Document.GetList(KeyStore.ColumnsKey, []); } @@ -167,10 +168,19 @@ export class CollectionSchemaView extends CollectionViewBase { this.props.Document.SetNumber(KeyStore.SchemaSplitPercentage, this.splitPercentage == 0 ? 33 : 0); } } - findAllDocumentKeys = (): { [id: string]: boolean } => { + + @computed + get findAllDocumentKeys(): { [id: string]: boolean } { const docs = this.props.Document.GetList(this.props.fieldKey, []); let keys: { [id: string]: boolean } = {} - docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false))); + if (this._optionsActivated > -1) { + // 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 + // invalidated and re-rendered. This workaround will inquire all of the document fields before the options button is clicked. + // then by the time the options button is clicked, all of the fields should be in place. If a new field is added while this menu + // is displayed (unlikely) it won't show up until something else changes. + untracked(() => docs.map(doc => doc.GetAllPrototypes().map(proto => proto._proxies.forEach((val: any, key: string) => keys[key] = false)))); + } this.columns.forEach(key => keys[key.Id] = true) return keys; } @@ -228,13 +238,18 @@ export class CollectionSchemaView extends CollectionViewBase { } } + @observable _optionsActivated: number = 0; + @action + OptionsMenuDown = (e: React.PointerEvent) => { + this._optionsActivated++; + } render() { library.add(faCog); const columns = this.columns; const children = this.props.Document.GetList(this.props.fieldKey, []); const selected = children.length > this._selectedIndex ? children[this._selectedIndex] : undefined; //all the keys/columns that will be displayed in the schema - const allKeys = this.findAllDocumentKeys(); + const allKeys = this.findAllDocumentKeys; let content = this._selectedIndex == -1 || !selected ? (null) : ( {({ measureRef }) => @@ -274,7 +289,7 @@ export class CollectionSchemaView extends CollectionViewBase {
}> - + ); return ( diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx index ec1bf5d0e..6cc14ebcb 100644 --- a/src/client/views/collections/CollectionTreeView.tsx +++ b/src/client/views/collections/CollectionTreeView.tsx @@ -76,7 +76,7 @@ class TreeView extends React.Component { }} />); return ( -
+
{editableView(this.props.document.Title)}
) -- cgit v1.2.3-70-g09d2 From 2e7d87e6deac8e69d839c852570849924b59fb1b Mon Sep 17 00:00:00 2001 From: bob Date: Thu, 21 Mar 2019 16:00:28 -0400 Subject: tweaked main --- src/client/views/Main.tsx | 95 +++++++++++++++------------------ src/client/views/nodes/HistogramBox.tsx | 2 +- 2 files changed, 45 insertions(+), 52 deletions(-) (limited to 'src/client/views') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index d79907518..53a5aba6e 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -46,6 +46,7 @@ import { Gateway, Settings } from '../northstar/manager/Gateway'; import { Catalog, Schema, Attribute, AttributeGroup } from '../northstar/model/idea/idea'; import { ArrayUtil } from '../northstar/utils/ArrayUtil'; import '../northstar/model/ModelExtensions' +import '../northstar/utils/Extensions' @observer export class Main extends React.Component { @@ -55,7 +56,8 @@ export class Main extends React.Component { @observable private userWorkspaces: Document[] = []; @observable public pwidth: number = 0; @observable public pheight: number = 0; - @observable private _northstarCatalog: Catalog | undefined = undefined; + @observable ActiveSchema: Schema | undefined; + private _northstarColumns: Document[] = []; public mainDocId: string | undefined; private currentUser?: DashUserModel; @@ -71,7 +73,8 @@ export class Main extends React.Component { this.mainDocId = pathname[pathname.length - 1]; }; - this.initializeNorthstar(); + let y = ""; + y.ReplaceAll("a", "B"); CurrentUserUtils.loadCurrentUser(); @@ -88,57 +91,10 @@ export class Main extends React.Component { library.add(faMusic); library.add(faTree); - this.initEventListeners(); Documents.initProtos(() => this.initAuthenticationRouters()); - reaction(() => [this.mainContainer, this.ActiveSchema], - () => { - if (this.mainContainer && this.ActiveSchema) { - if (!this.mainContainer!.GetTAsync(KeyStore.ActiveDB, ListField, field => this.NorthstarCatalog = field!.Data as Document[])) { - this.NorthstarCatalog = this.GetAllAttributes().map(a => Documents.HistogramDocument({ width: 200, height: 200, title: a.displayName! })); - this.mainContainer!.SetData(KeyStore.ActiveDB, this.NorthstarCatalog, ListField); - } - } - }) - } - - NorthstarCatalog: Document[] = []; - @observable ActiveSchema: Schema | undefined; - @action SetNorthstarCatalog(ctlog: Catalog) { - this._northstarCatalog = ctlog; - if (this._northstarCatalog && this._northstarCatalog.schemas) { - console.log("CATALOG " + this._northstarCatalog.schemas); - this.ActiveSchema = ArrayUtil.FirstOrDefault(this._northstarCatalog.schemas!, (s: Schema) => s.displayName === "mimic"); - } - } - public GetAllAttributes() { - if (!this.ActiveSchema || !this.ActiveSchema.rootAttributeGroup) { - return []; - } - const recurs = (attrs: Attribute[], g: AttributeGroup) => { - if (g.attributes) { - attrs.push.apply(attrs, g.attributes); - if (g.attributeGroups) { - g.attributeGroups.forEach(ng => recurs(attrs, ng)); - } - } - }; - const allAttributes: Attribute[] = new Array(); - recurs(allAttributes, this.ActiveSchema.rootAttributeGroup); - return allAttributes; - } - async initializeNorthstar(): Promise { - let envPath = "/assets/env.json"; - const response = await fetch(envPath, { - redirect: "follow", - method: "GET", - credentials: "include" - }); - const env = await response.json(); - Settings.Instance.Update(env); - let cat = Gateway.Instance.ClearCatalog(); - cat.then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog())); + this.initializeNorthstar(); } onHistory = () => { @@ -284,7 +240,7 @@ export class Main extends React.Component { let addTextNode = action(() => Documents.TextDocument({ width: 200, height: 200, title: "a text note" })) let addColNode = action(() => Documents.FreeformDocument([], { width: 200, height: 200, title: "a freeform collection" })); let addSchemaNode = action(() => Documents.SchemaDocument([], { width: 200, height: 200, title: "a schema collection" })); - let addTreeNode = action(() => Documents.TreeDocument(this.NorthstarCatalog, { width: 200, height: 200, title: "a tree collection" })); + let addTreeNode = action(() => Documents.TreeDocument(this._northstarColumns, { width: 200, height: 200, title: "a tree collection" })); let addVideoNode = action(() => Documents.VideoDocument(videourl, { width: 200, height: 200, title: "video node" })); let addPDFNode = action(() => Documents.PdfDocument(pdfurl, { width: 200, height: 200, title: "a schema collection" })); let addImageNode = action(() => Documents.ImageDocument(imgurl, { width: 200, height: 200, title: "an image of a cat" })); @@ -365,6 +321,43 @@ export class Main extends React.Component {
); } + + // --------------- Northstar hooks ------------- / + + @action SetNorthstarCatalog(ctlog: Catalog) { + if (ctlog && ctlog.schemas) { + this.ActiveSchema = ArrayUtil.FirstOrDefault(ctlog.schemas!, (s: Schema) => s.displayName === "mimic"); + this._northstarColumns = this.GetAllNorthstarColumnAttributes().map(a => Documents.HistogramDocument({ width: 200, height: 200, title: a.displayName! })); + } + } + async initializeNorthstar(): Promise { + let envPath = "/assets/env.json"; + const response = await fetch(envPath, { + redirect: "follow", + method: "GET", + credentials: "include" + }); + const env = await response.json(); + Settings.Instance.Update(env); + let cat = Gateway.Instance.ClearCatalog(); + cat.then(async () => this.SetNorthstarCatalog(await Gateway.Instance.GetCatalog())); + } + public GetAllNorthstarColumnAttributes() { + if (!this.ActiveSchema || !this.ActiveSchema.rootAttributeGroup) { + return []; + } + const recurs = (attrs: Attribute[], g: AttributeGroup) => { + if (g.attributes) { + attrs.push.apply(attrs, g.attributes); + if (g.attributeGroups) { + g.attributeGroups.forEach(ng => recurs(attrs, ng)); + } + } + }; + const allAttributes: Attribute[] = new Array(); + recurs(allAttributes, this.ActiveSchema.rootAttributeGroup); + return allAttributes; + } } ReactDOM.render(
, document.getElementById('root')); diff --git a/src/client/views/nodes/HistogramBox.tsx b/src/client/views/nodes/HistogramBox.tsx index 0fcc25e66..223fdf0d8 100644 --- a/src/client/views/nodes/HistogramBox.tsx +++ b/src/client/views/nodes/HistogramBox.tsx @@ -23,7 +23,7 @@ export class HistogramBox extends React.Component { _histoOp?: HistogramOperation; componentDidMount() { - Main.Instance.GetAllAttributes().map(a => { + Main.Instance.GetAllNorthstarColumnAttributes().map(a => { if (a.displayName == this.props.doc.Title) { var atmod = new ColumnAttributeModel(a); this._histoOp = new HistogramOperation(new AttributeTransformationModel(atmod, AggregateFunction.None), -- cgit v1.2.3-70-g09d2 From 1cf618563838f4ce7d8a98c8a0c8d94670bc4e18 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Thu, 21 Mar 2019 21:03:00 -0400 Subject: changes to allow tabs to be dragged into other documents --- src/client/views/collections/CollectionDockingView.tsx | 17 +++++++++++++++++ src/fields/Document.ts | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'src/client/views') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index fd0810242..950df7261 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -17,6 +17,7 @@ import { COLLECTION_BORDER_WIDTH } from "./CollectionView"; import React = require("react"); import { SubCollectionViewProps } from "./CollectionViewBase"; import { ServerUtils } from "../../../server/ServerUtil"; +import { DragManager } from "../../util/DragManager"; @observer export class CollectionDockingView extends React.Component { @@ -190,6 +191,21 @@ export class CollectionDockingView extends React.Component { var className = (e.target as any).className; + if ((className == "lm_title" || className == "lm_tab lm_active") && e.ctrlKey) { + e.stopPropagation(); + e.preventDefault(); + let docid = (e.target as any).DashDocId; + let tab = (e.target as any).parentElement as HTMLElement; + Server.GetField(docid, action((f: Opt) => + DragManager.StartDocumentDrag(tab, new DragManager.DocumentDragData(f as Document), + { + handlers: { + dragComplete: action(() => { }), + }, + hideSource: true + })) + ); + } if (className == "lm_drag_handle" || className == "lm_close" || className == "lm_maximise" || className == "lm_minimise" || className == "lm_close_tab") { this._flush = true; } @@ -208,6 +224,7 @@ export class CollectionDockingView extends React.Component { + tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId; tab.closeElement.off('click') //unbind the current click handler .click(function () { tab.contentItem.remove(); diff --git a/src/fields/Document.ts b/src/fields/Document.ts index b6439364a..2403c670c 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -36,7 +36,7 @@ export class Document extends Field { @computed public get Title() { - return this.GetText(KeyStore.Title, ""); + return this.GetText(KeyStore.Title, "-untitled-"); } @computed -- cgit v1.2.3-70-g09d2