aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/ClientRecommender.tsx63
-rw-r--r--src/client/views/RecommendationsBox.tsx64
-rw-r--r--src/client/views/nodes/ImageBox.tsx1
3 files changed, 83 insertions, 45 deletions
diff --git a/src/client/ClientRecommender.tsx b/src/client/ClientRecommender.tsx
index 90dd240b6..364ec0fe0 100644
--- a/src/client/ClientRecommender.tsx
+++ b/src/client/ClientRecommender.tsx
@@ -1,7 +1,7 @@
import { Doc, FieldResult } from "../new_fields/Doc";
import { StrCast, Cast } from "../new_fields/Types";
import { List } from "../new_fields/List";
-import { CognitiveServices } from "./cognitive_services/CognitiveServices";
+import { CognitiveServices, Confidence, Tag, Service } from "./cognitive_services/CognitiveServices";
import React = require("react");
import { observer } from "mobx-react";
import { observable, action, computed, reaction } from "mobx";
@@ -14,6 +14,8 @@ import { RichTextField } from "../new_fields/RichTextField";
import { ToPlainText } from "../new_fields/FieldSymbols";
import { listSpec } from "../new_fields/Schema";
import { Identified } from "./Network";
+import { ComputedField } from "../new_fields/ScriptField";
+import { ImageField } from "../new_fields/URLField";
export interface RecommenderProps {
title: string;
@@ -31,9 +33,13 @@ export interface RecommenderDocument {
score: number;
}
+const fieldkey = "data";
+
@observer
export class ClientRecommender extends React.Component<RecommenderProps> {
+
+
static Instance: ClientRecommender;
private mainDoc?: RecommenderDocument;
private docVectors: Set<RecommenderDocument> = new Set();
@@ -45,10 +51,6 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
super(props);
if (!ClientRecommender.Instance) ClientRecommender.Instance = this;
ClientRecommender.Instance.docVectors = new Set();
- const parameters: any = {};
- Identified.PostToServer("/IBMAnalysis", parameters).then(response => {
- console.log("ANALYSIS RESULTS! ", response);
- });
//ClientRecommender.Instance.corr_matrix = [[0, 0], [0, 0]];
}
@@ -97,6 +99,10 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
*/
public computeSimilarities(distance_metric: string) {
+ const parameters: any = {};
+ Identified.PostToServer("/IBMAnalysis", parameters).then(response => {
+ console.log("ANALYSIS RESULTS! ", response);
+ });
ClientRecommender.Instance.docVectors.forEach((doc: RecommenderDocument) => {
if (ClientRecommender.Instance.mainDoc) {
const distance = ClientRecommender.Instance.distance(ClientRecommender.Instance.mainDoc.vectorDoc, doc.vectorDoc, distance_metric);
@@ -148,23 +154,58 @@ export class ClientRecommender extends React.Component<RecommenderProps> {
}
/***
+ * Generates tags for an image using Cognitive Services
+ */
+
+ generateMetadata = async (dataDoc: Doc, extDoc: Doc, threshold: Confidence = Confidence.Excellent) => {
+ let converter = (results: any) => {
+ let tagDoc = new Doc;
+ let tagsList = new List();
+ results.tags.map((tag: Tag) => {
+ tagsList.push(tag.name);
+ let sanitized = tag.name.replace(" ", "_");
+ tagDoc[sanitized] = ComputedField.MakeFunction(`(${tag.confidence} >= this.confidence) ? ${tag.confidence} : "${ComputedField.undefined}"`);
+ });
+ extDoc.generatedTags = tagsList;
+ tagDoc.title = "Generated Tags Doc";
+ tagDoc.confidence = threshold;
+ return tagDoc;
+ };
+ const url = this.url(dataDoc);
+ if (url) {
+ return CognitiveServices.Image.Appliers.ProcessImage(extDoc, ["generatedTagsDoc"], url, Service.ComputerVision, converter);
+ }
+ }
+
+ /***
+ * Gets URL of image
+ */
+
+ private url(dataDoc: Doc) {
+ let data = Cast(Doc.GetProto(dataDoc)[fieldkey], ImageField);
+ return data ? data.url.href : undefined;
+ }
+
+ /***
* Uses Cognitive Services to extract keywords from a document
*/
public async extractText(dataDoc: Doc, extDoc: Doc, internal: boolean = true, isMainDoc: boolean = false, image: boolean = false) {
let data: string = "";
let taglist: FieldResult<List<string>> = undefined;
- if (image && extDoc.generatedTags) { // TODO: Automatically generate tags. Need to ask Sam about this.
- taglist = Cast(extDoc.generatedTags, listSpec("string"));
- taglist!.forEach(tag => {
- data += tag + ", ";
- });
+ if (image) {
+ if (!extDoc.generatedTags) await this.generateMetadata(dataDoc, extDoc); // TODO: Automatically generate tags. Need to ask Sam about this.
+ if (extDoc.generatedTags) {
+ taglist = Cast(extDoc.generatedTags, listSpec("string"));
+ taglist!.forEach(tag => {
+ data += tag + ", ";
+ });
+ }
}
else {
let fielddata = Cast(dataDoc.data, RichTextField);
fielddata ? data = fielddata[ToPlainText]() : data = "";
}
-
let converter = async (results: any, data: string, isImage: boolean = false) => {
let keyterms = new List<string>(); // raw keywords
// let keyterms_counted = new List<string>(); // keywords, where each keyword is repeated. input to w2v
diff --git a/src/client/views/RecommendationsBox.tsx b/src/client/views/RecommendationsBox.tsx
index fd128bfca..0e3cfd729 100644
--- a/src/client/views/RecommendationsBox.tsx
+++ b/src/client/views/RecommendationsBox.tsx
@@ -1,6 +1,6 @@
import { observer } from "mobx-react";
import React = require("react");
-import { observable, action, computed } from "mobx";
+import { observable, action, computed, runInAction } from "mobx";
import Measure from "react-measure";
import "./RecommendationsBox.scss";
import { Doc, DocListCast, WidthSym, HeightSym } from "../../new_fields/Doc";
@@ -38,7 +38,7 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
@observable private _pageY: number = 0;
@observable private _width: number = 0;
@observable private _height: number = 0;
- private _docViews: JSX.Element[] = [];
+ @observable.shallow private _docViews: JSX.Element[] = [];
// @observable private _documents: { preview: Doc, score: number }[] = [];
private previewDocs: Doc[] = [];
@@ -46,20 +46,13 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
super(props);
}
+ @action
private DocumentIcon(doc: Doc) {
let layoutresult = StrCast(doc.type);
let renderDoc = doc;
//let box: number[] = [];
if (layoutresult.indexOf(DocumentType.COL) !== -1) {
renderDoc = Doc.MakeDelegate(renderDoc);
- let bounds = DocListCast(renderDoc.data).reduce((bounds, doc) => {
- var [sptX, sptY] = [NumCast(doc.x), NumCast(doc.y)];
- let [bptX, bptY] = [sptX + doc[WidthSym](), sptY + doc[HeightSym]()];
- return {
- x: Math.min(sptX, bounds.x), y: Math.min(sptY, bounds.y),
- r: Math.max(bptX, bounds.r), b: Math.max(bptY, bounds.b)
- };
- }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
}
let returnXDimension = () => 150;
let returnYDimension = () => 150;
@@ -142,27 +135,8 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
// return y;
// }
- get createDocViews() {
- return DocListCast(this.props.Document.data).map(doc => {
- return (
- <div className="content">
- <span style={{ height: NumCast(this.props.Document.documentIconHeight) }} className="image-background">
- {this.DocumentIcon(doc)}
- </span>
- <span className="score">{NumCast(doc.score).toFixed(4)}</span>
- <div style={{ marginRight: 50 }} onClick={() => DocumentManager.Instance.jumpToDocument(doc, false)}>
- <FontAwesomeIcon className="documentdecorations-icon" icon={"bullseye"} size="sm" />
- </div>
- <div style={{ marginRight: 50 }} onClick={() => DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}>
- <FontAwesomeIcon className="documentdecorations-icon" icon={"link"} size="sm" />
- </div>
- </div>
- );
- });
- }
-
- // componentDidMount() {
- // this._docViews = DocListCast(this.props.Document.data).map(doc => {
+ // get createDocViews() {
+ // return DocListCast(this.props.Document.data).map(doc => {
// return (
// <div className="content">
// <span style={{ height: NumCast(this.props.Document.documentIconHeight) }} className="image-background">
@@ -177,10 +151,32 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
// </div>
// </div>
// );
- // })
-
+ // });
// }
+ componentDidMount() { //TODO: invoking a computedFn from outside an reactive context won't be memoized, unless keepAlive is set
+ runInAction(() => {
+ if (this._docViews.length === 0) {
+ this._docViews = DocListCast(this.props.Document.data).map(doc => {
+ return (
+ <div className="content">
+ <span style={{ height: NumCast(this.props.Document.documentIconHeight) }} className="image-background">
+ {this.DocumentIcon(doc)}
+ </span>
+ <span className="score">{NumCast(doc.score).toFixed(4)}</span>
+ <div style={{ marginRight: 50 }} onClick={() => DocumentManager.Instance.jumpToDocument(doc, false)}>
+ <FontAwesomeIcon className="documentdecorations-icon" icon={"bullseye"} size="sm" />
+ </div>
+ <div style={{ marginRight: 50 }} onClick={() => DocUtils.MakeLink({ doc: this.props.Document.sourceDoc as Doc }, { doc: doc }, "User Selected Link", "Generated from Recommender", undefined)}>
+ <FontAwesomeIcon className="documentdecorations-icon" icon={"link"} size="sm" />
+ </div>
+ </div>
+ );
+ });
+ }
+ });
+ }
+
render() { //TODO: Invariant violation: max depth exceeded error. Occurs when images are rendered.
// if (!this._display) {
// return null;
@@ -194,7 +190,7 @@ export class RecommendationsBox extends React.Component<FieldViewProps> {
return (
<div className="rec-scroll">
<p>Recommendations for "{title}"</p>
- {this.createDocViews}
+ {this._docViews}
</div>
);
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 7816c0fe8..1bf2724c3 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -248,6 +248,7 @@ export class ImageBox extends DocAnnotatableComponent<FieldViewProps, ImageDocum
onDotDown(index: number) {
this.Document.curPage = index;
}
+
@computed private get url() {
let data = Cast(Doc.GetProto(this.props.Document)[this.props.fieldKey], ImageField);
return data ? data.url.href : undefined;