diff options
-rw-r--r-- | src/client/documents/DocumentTypes.ts | 1 | ||||
-rw-r--r-- | src/client/documents/Documents.ts | 9 | ||||
-rw-r--r-- | src/client/views/GlobalKeyHandler.ts | 2 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/Recommendations.scss | 12 | ||||
-rw-r--r-- | src/client/views/Recommendations.tsx | 172 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentContentsView.tsx | 3 | ||||
-rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 20 |
8 files changed, 132 insertions, 92 deletions
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts index 1578e49fe..08f64fc8e 100644 --- a/src/client/documents/DocumentTypes.ts +++ b/src/client/documents/DocumentTypes.ts @@ -19,4 +19,5 @@ export enum DocumentType { YOUTUBE = "youtube", DRAGBOX = "dragbox", PRES = "presentation", + RECOMMENDATION = "recommendation" }
\ No newline at end of file diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 1e9d1687f..89358d773 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -45,6 +45,7 @@ import { PresBox } from "../views/nodes/PresBox"; import { ComputedField } from "../../new_fields/ScriptField"; import { ProxyField } from "../../new_fields/Proxy"; import { DocumentType } from "./DocumentTypes"; +import { RecommendationsBox } from "../views/Recommendations"; //import { PresBox } from "../views/nodes/PresBox"; //import { PresField } from "../../new_fields/PresField"; var requestImageSize = require('../util/request-image-size'); @@ -170,6 +171,10 @@ export namespace Docs { [DocumentType.DRAGBOX, { layout: { view: DragBox }, options: { width: 40, height: 40 }, + }], + [DocumentType.RECOMMENDATION, { + layout: { view: RecommendationsBox }, + options: { width: 200, height: 200 }, }] ]); @@ -451,6 +456,10 @@ export namespace Docs { return InstanceFromProto(Prototypes.get(DocumentType.IMPORT), new List<Doc>(), options); } + export function RecommendationsDocument(data: Doc[], options: DocumentOptions = {}) { + return InstanceFromProto(Prototypes.get(DocumentType.RECOMMENDATION), new List<Doc>(data), options); + } + export type DocConfig = { doc: Doc, initialWidth?: number diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index d0464bd5f..4135afcb8 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -6,6 +6,7 @@ import { DragManager } from "../util/DragManager"; import { action, runInAction } from "mobx"; import { Doc } from "../../new_fields/Doc"; import { DictationManager } from "../util/DictationManager"; +import { RecommendationsBox } from "./Recommendations"; const modifiers = ["control", "meta", "shift", "alt"]; type KeyHandler = (keycode: string, e: KeyboardEvent) => KeyControlInfo | Promise<KeyControlInfo>; @@ -72,6 +73,7 @@ export default class KeyManager { main.toggleColorPicker(true); SelectionManager.DeselectAll(); DictationManager.Controls.stop(); + // RecommendationsBox.Instance.closeMenu(); break; case "delete": case "backspace": diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 3a5795077..0bc539dca 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,7 +40,7 @@ import { PreviewCursor } from './PreviewCursor'; import { FilterBox } from './search/FilterBox'; import { SchemaHeaderField, RandomPastel } from '../../new_fields/SchemaHeaderField'; //import { DocumentManager } from '../util/DocumentManager'; -import { Recommendations } from './Recommendations'; +import { RecommendationsBox } from './Recommendations'; import PresModeMenu from './presentationview/PresentationModeMenu'; import { PresBox } from './nodes/PresBox'; @@ -204,7 +204,6 @@ export class MainView extends React.Component { const targets = document.elementsFromPoint(e.x, e.y); if (targets && targets.length && targets[0].className.toString().indexOf("contextMenu") === -1) { ContextMenu.Instance.closeMenu(); - Recommendations.Instance.closeMenu(); } }); @@ -567,7 +566,7 @@ export class MainView extends React.Component { {this.miniPresentation} <PreviewCursor /> <ContextMenu /> - <Recommendations /> + {/* <RecommendationsBox /> */} {this.nodesMenu()} {this.miscButtons} <PDFMenu /> diff --git a/src/client/views/Recommendations.scss b/src/client/views/Recommendations.scss index 6619d8df3..dd8a105f6 100644 --- a/src/client/views/Recommendations.scss +++ b/src/client/views/Recommendations.scss @@ -4,7 +4,7 @@ display: inline-block; margin: auto; width: 50; - height: 30px; + height: 150px; border: 1px dashed grey; padding: 10px 10px; } @@ -19,17 +19,20 @@ overflow-y: scroll; overflow-x: hidden; position: absolute; + pointer-events: all; // display: flex; z-index: 10000; box-shadow: gray 0.2vw 0.2vw 0.4vw; // flex-direction: column; background: whitesmoke; padding-bottom: 10px; - border-radius: 15px; + padding-top: 20px; + // border-radius: 15px; border: solid #BBBBBBBB 1px; - width: 250px; + width: 100%; text-align: center; - max-height: 250px; + // max-height: 250px; + height: 100%; text-transform: uppercase; color: grey; letter-spacing: 2px; @@ -48,7 +51,6 @@ background-color: transparent; width: 50%; text-align: center; - height: 35px; margin-left: 5px; } diff --git a/src/client/views/Recommendations.tsx b/src/client/views/Recommendations.tsx index d0105ee18..ff6e66492 100644 --- a/src/client/views/Recommendations.tsx +++ b/src/client/views/Recommendations.tsx @@ -14,27 +14,37 @@ import { DocumentType } from '../documents/DocumentTypes'; import { ClientRecommender } from "../ClientRecommender"; import { DocServer } from "../DocServer"; import { Id } from "../../new_fields/FieldSymbols"; +import { FieldView, FieldViewProps } from "./nodes/FieldView"; +import { DocumentManager } from "../util/DocumentManager"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { library } from "@fortawesome/fontawesome-svg-core"; +import { faBullseye, faLink } from "@fortawesome/free-solid-svg-icons"; +import { DocUtils } from "../documents/Documents"; export interface RecProps { documents: { preview: Doc, similarity: number }[]; node: Doc; } +library.add(faBullseye, faLink); + @observer -export class Recommendations extends React.Component<{}> { +export class RecommendationsBox extends React.Component<FieldViewProps> { + + public static LayoutString(fieldKey?: string) { return FieldView.LayoutString(RecommendationsBox, fieldKey); } - static Instance: Recommendations; - @observable private _display: boolean = false; + static Instance: RecommendationsBox; + // @observable private _display: boolean = false; @observable private _pageX: number = 0; @observable private _pageY: number = 0; @observable private _width: number = 0; @observable private _height: number = 0; - @observable private _documents: { preview: Doc, score: number }[] = []; + // @observable private _documents: { preview: Doc, score: number }[] = []; private previewDocs: Doc[] = []; - constructor(props: {}) { + constructor(props: FieldViewProps) { super(props); - Recommendations.Instance = this; + RecommendationsBox.Instance = this; } private DocumentIcon(doc: Doc) { @@ -52,12 +62,12 @@ export class Recommendations extends React.Component<{}> { }; }, { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE }); } - let returnXDimension = () => 50; - let returnYDimension = () => 50; + let returnXDimension = () => 150; + let returnYDimension = () => 150; let scale = () => returnXDimension() / NumCast(renderDoc.nativeWidth, returnXDimension()); //let scale = () => 1; let newRenderDoc = Doc.MakeAlias(renderDoc); /// newRenderDoc -> renderDoc -> render"data"Doc -> TextProt - newRenderDoc.height = 50; + newRenderDoc.height = NumCast(this.props.Document.documentIconHeight); newRenderDoc.autoHeight = false; const docview = <div> {/* onPointerDown={action(() => { @@ -78,7 +88,8 @@ export class Recommendations extends React.Component<{}> { PanelHeight={returnYDimension} focus={emptyFunction} backgroundColor={returnEmptyString} - selectOnLoad={false} + // selectOnLoad={false} + pinToPres={emptyFunction} parentActive={returnFalse} whenActiveChanged={returnFalse} bringToFront={emptyFunction} @@ -96,83 +107,84 @@ export class Recommendations extends React.Component<{}> { } - @action - closeMenu = () => { - this._display = false; - this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); - this.previewDocs = []; - } - - @action - resetDocuments = () => { - this._documents = []; - } - - @action - addDocuments = (documents: { preview: Doc, score: number }[]) => { - this._documents = documents; - } - - @action - displayRecommendations(x: number, y: number) { - this._pageX = x; - this._pageY = y; - this._display = true; - } + // @action + // closeMenu = () => { + // this._display = false; + // this.previewDocs.forEach(doc => DocServer.DeleteDocument(doc[Id])); + // this.previewDocs = []; + // } + + // @action + // resetDocuments = () => { + // this._documents = []; + // } + + // @action + // displayRecommendations(x: number, y: number) { + // this._pageX = x; + // this._pageY = y; + // this._display = true; + // } static readonly buffer = 20; - get pageX() { - const x = this._pageX; - if (x < 0) { - return 0; - } - const width = this._width; - if (x + width > window.innerWidth - Recommendations.buffer) { - return window.innerWidth - Recommendations.buffer - width; - } - return x; - } - - get pageY() { - const y = this._pageY; - if (y < 0) { - return 0; - } - const height = this._height; - if (y + height > window.innerHeight - Recommendations.buffer) { - return window.innerHeight - Recommendations.buffer - height; - } - return y; - } + // get pageX() { + // const x = this._pageX; + // if (x < 0) { + // return 0; + // } + // const width = this._width; + // if (x + width > window.innerWidth - RecommendationsBox.buffer) { + // return window.innerWidth - RecommendationsBox.buffer - width; + // } + // return x; + // } + + // get pageY() { + // const y = this._pageY; + // if (y < 0) { + // return 0; + // } + // const height = this._height; + // if (y + height > window.innerHeight - RecommendationsBox.buffer) { + // return window.innerHeight - RecommendationsBox.buffer - height; + // } + // return y; + // } render() { - if (!this._display) { - return null; - } - let style = { left: this.pageX, top: this.pageY }; + // if (!this._display) { + // return null; + // } + // let style = { left: this.pageX, top: this.pageY }; //const transform = "translate(" + (NumCast(this.props.node.x) + 350) + "px, " + NumCast(this.props.node.y) + "px" return ( - <Measure offset onResize={action((r: any) => { this._width = r.offset.width; this._height = r.offset.height; })}> - {({ measureRef }) => ( - <div className="rec-scroll" style={style} ref={measureRef}> - <p>Recommendations</p> - {this._documents.map(doc => { - return ( - <div className="content"> - <span className="image-background"> - {this.DocumentIcon(doc.preview)} - </span> - <span className="score">{doc.score.toFixed(4)}</span> - </div> - ); - })} - - </div> - ) - } - - </Measure> + // <Measure offset onResize={action((r: any) => { this._width = r.offset.width; this._height = r.offset.height; })}> + // {({ measureRef }) => ( + <div className="rec-scroll"> + <p>Recommendations</p> + {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, true, undefined, undefined, undefined, this.props.Document.sourceDocContext as Doc)}> + <FontAwesomeIcon className="documentdecorations-icon" icon={"bullseye"} size="sm" /> + </div> + <div style={{ marginRight: 50 }} onClick={() => DocUtils.MakeLink(this.props.Document.sourceDoc as Doc, doc, undefined, "User Selected Link", "Generated from Recommender", undefined)}> + <FontAwesomeIcon className="documentdecorations-icon" icon={"link"} size="sm" /> + </div> + </div> + ); + })} + + </div> + // ); + // } + + // </Measure> ); } }
\ No newline at end of file diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index d77662355..c8a636727 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -29,6 +29,7 @@ import { Cast, StrCast, NumCast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { Doc } from "../../../new_fields/Doc"; import DirectoryImportBox from "../../util/Import & Export/DirectoryImportBox"; +import { RecommendationsBox } from "../../views/Recommendations"; import { ScriptField } from "../../../new_fields/ScriptField"; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? @@ -108,7 +109,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & { if (!this.layout && (this.props.layoutKey !== "overlayLayout" || !this.templates.length)) return (null); return <ObserverJsxParser blacklistedAttrs={[]} - components={{ FormattedTextBox, ImageBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox }} + components={{ FormattedTextBox, ImageBox, RecommendationsBox, IconBox, DirectoryImportBox, DragBox, ButtonBox, FieldView, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, CollectionPDFView, CollectionVideoView, WebBox, KeyValueBox, PDFBox, VideoBox, AudioBox, HistogramBox, PresBox, YoutubeBox }} bindings={this.CreateBindings()} jsx={this.finalLayout} showWarnings={true} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 48a059b8e..d1e87b663 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -41,7 +41,7 @@ import "./DocumentView.scss"; import { FormattedTextBox } from './FormattedTextBox'; import React = require("react"); import requestPromise = require('request-promise'); -import { Recommendations } from '../Recommendations'; +import { RecommendationsBox } from '../Recommendations'; import { SearchUtil } from '../../util/SearchUtil'; import { ClientRecommender } from '../../ClientRecommender'; import { DocumentType } from '../../documents/DocumentTypes'; @@ -739,8 +739,22 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu for (let i = 0; i < doclist.length; i++) { recDocs.push({ preview: doclist[i].actualDoc, score: doclist[i].score }); } - Recommendations.Instance.addDocuments(recDocs); - Recommendations.Instance.displayRecommendations(e.pageX + 100, e.pageY); + + const data = recDocs.map(unit => { + unit.preview.score = unit.score; + return unit.preview; + }); + + console.log(recDocs.map(doc => doc.score)); + + const title = `Showing ${data.length} recommendations for "${StrCast(this.props.Document.title)}"`; + const recommendations = Docs.Create.RecommendationsDocument(data, { title }); + recommendations.documentIconHeight = 150; + recommendations.sourceDoc = this.props.Document; + recommendations.sourceDocContext = this.props.ContainingCollectionView!.props.Document; + CollectionDockingView.Instance.AddRightSplit(recommendations, undefined); + + // RecommendationsBox.Instance.displayRecommendations(e.pageX + 100, e.pageY); } onPointerEnter = (e: React.PointerEvent): void => { Doc.BrushDoc(this.props.Document); }; |