diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/Main.tsx | 45 | ||||
| -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, 11 deletions
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index b0ca347df..d79907518 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'; @@ -36,15 +35,17 @@ 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'; 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 { @@ -85,20 +86,50 @@ export class Main extends React.Component { library.add(faPenNib); library.add(faFilm); 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) { + 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", @@ -253,6 +284,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 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" })); @@ -267,6 +299,7 @@ export class Main extends React.Component { [React.createRef<HTMLDivElement>(), "music", "Add Audio", addAudioNode], [React.createRef<HTMLDivElement>(), "globe-asia", "Add Web Clipping", addWebNode], [React.createRef<HTMLDivElement>(), "object-group", "Add Collection", addColNode], + [React.createRef<HTMLDivElement>(), "tree", "Add Tree", addTreeNode], [React.createRef<HTMLDivElement>(), "table", "Add Schema", addSchemaNode], ] 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 |
