diff options
| author | bob <bcz@cs.brown.edu> | 2019-03-20 18:00:39 -0400 |
|---|---|---|
| committer | bob <bcz@cs.brown.edu> | 2019-03-20 18:00:39 -0400 |
| commit | a16e6592caafb601b59c3d9f7609e8c1af231eba (patch) | |
| tree | e732e34c5a9fc371bf328fdd35a08ddd196bf6af /src/client/views | |
| parent | 208a57b15e6b415659311873431dbe9d5b8d8021 (diff) | |
initial
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/Main.tsx | 47 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/FieldView.tsx | 7 | ||||
| -rw-r--r-- | src/client/views/nodes/HistogramBox.scss | 8 | ||||
| -rw-r--r-- | src/client/views/nodes/HistogramBox.tsx | 67 |
5 files changed, 120 insertions, 13 deletions
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<Schema>(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<Attribute>(); + recurs(allAttributes, this.ActiveSchema.rootAttributeGroup); + return allAttributes; + } async initializeNorthstar(): Promise<void> { - 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<HTMLDivElement>(), "table", "Add Schema", addSchemaNode], ] - let addClick = (creator: () => Document) => action(() => this.mainfreeform!.GetList<Document>(KeyStore.Data, []).push(creator())); + let addClick = (creator: () => Document) => action(() => { + this.mainfreeform!.GetList<Document>(KeyStore.Data, []).push(creator()) + }); return < div id="add-nodes-menu" > <input type="checkbox" id="add-menu-toggle" /> 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<DocumentViewProps & { render() { return <JsxParser - components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox }} - bindings={this.CreateBindings()} + components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox }} bindings={this.CreateBindings()} jsx={this.layout} showWarnings={true} onError={(test: any) => { 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<FieldViewProps> { } else if (field instanceof AudioField) { return <AudioBox {...this.props} /> - } else if (field instanceof Document) { + } + else if (field instanceof Document) { return <div>{field.Title}</div> - } else if (field instanceof ListField) { + } + else if (field instanceof ListField) { return (<div> {(field as ListField<Field>).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<FieldViewProps> { + + 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 ( + <div className="histogrambox-container"> + `HISTOGRAM RESULT : ${this.twoString()}` + </div> + ) + } +}
\ No newline at end of file |
