diff options
Diffstat (limited to 'src/client/views/nodes')
| -rw-r--r-- | src/client/views/nodes/ButtonBox.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 11 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 135 | ||||
| -rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 18 | ||||
| -rw-r--r-- | src/client/views/nodes/ImageBox.tsx | 49 | ||||
| -rw-r--r-- | src/client/views/nodes/KeyValuePair.tsx | 17 | ||||
| -rw-r--r-- | src/client/views/nodes/LinkMenuItem.tsx | 4 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.scss | 67 | ||||
| -rw-r--r-- | src/client/views/nodes/PDFBox.tsx | 273 | ||||
| -rw-r--r-- | src/client/views/nodes/WebBox.tsx | 3 |
10 files changed, 245 insertions, 334 deletions
diff --git a/src/client/views/nodes/ButtonBox.tsx b/src/client/views/nodes/ButtonBox.tsx index e2c559c9a..640795789 100644 --- a/src/client/views/nodes/ButtonBox.tsx +++ b/src/client/views/nodes/ButtonBox.tsx @@ -16,7 +16,7 @@ import './ButtonBox.scss'; import { observer } from 'mobx-react'; import { DocumentIconContainer } from './DocumentIcon'; -library.add(faEdit); +library.add(faEdit as any); const ButtonSchema = createSchema({ onClick: ScriptField, diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 7ffd760e0..ee596c841 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -8,6 +8,7 @@ import { DocumentView, DocumentViewProps, positionSchema } from "./DocumentView" import "./DocumentView.scss"; import React = require("react"); import { Doc } from "../../../new_fields/Doc"; +import { returnEmptyString } from "../../../Utils"; export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps { x?: number; @@ -69,6 +70,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF return undefined; } + @computed + get clusterColor() { return this.props.backgroundColor(this.props.Document); } + + clusterColorFunc = (doc: Doc) => this.clusterColor; + render() { const hasPosition = this.props.x !== undefined || this.props.y !== undefined; return ( @@ -77,6 +83,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF transformOrigin: "left top", position: "absolute", backgroundColor: "transparent", + boxShadow: this.props.Document.z ? `#9c9396 ${StrCast(this.props.Document.boxShadow, "10px 10px 0.9vw")}` : + this.clusterColor ? ( + this.props.Document.isBackground ? `0px 0px 50px 50px ${this.clusterColor}` : + `${this.clusterColor} ${StrCast(this.props.Document.boxShadow, `0vw 0vw ${50 / this.props.ContentScaling()}px`)}`) : undefined, borderRadius: this.borderRounding(), transform: this.transform, transition: hasPosition ? "transform 1s" : StrCast(this.props.Document.transition), @@ -87,6 +97,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF <DocumentView {...this.props} ContentScaling={this.contentScaling} ScreenToLocalTransform={this.getTransform} + backgroundColor={this.clusterColorFunc} PanelWidth={this.panelWidth} PanelHeight={this.panelHeight} animateBetweenIcon={this.animateBetweenIcon} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 14f0b5a5a..c8eab85c2 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,19 +1,23 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import * as fa from '@fortawesome/free-solid-svg-icons'; -import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx"; +import { action, computed, IReactionDisposer, reaction, runInAction, trace } from "mobx"; import { observer } from "mobx-react"; -import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc"; +import * as rp from "request-promise"; +import { Doc, DocListCast, DocListCastAsync, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; +import { Copy, Id } from '../../../new_fields/FieldSymbols'; import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; -import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; -import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types"; +import { createSchema, listSpec, makeInterface } from "../../../new_fields/Schema"; +import { BoolCast, Cast, FieldValue, NumCast, StrCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; -import { emptyFunction, Utils, returnFalse, returnTrue } from "../../../Utils"; +import { RouteStore } from '../../../server/RouteStore'; +import { emptyFunction, returnTrue, Utils } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { Docs, DocUtils, DocumentType } from "../../documents/Documents"; +import { Docs, DocUtils } from "../../documents/Documents"; +import { ClientUtils } from '../../util/ClientUtils'; import { DocumentManager } from "../../util/DocumentManager"; import { DragManager, dropActionType } from "../../util/DragManager"; -import { SearchUtil } from "../../util/SearchUtil"; +import { LinkManager } from '../../util/LinkManager'; import { SelectionManager } from "../../util/SelectionManager"; import { Transform } from "../../util/Transform"; import { undoBatch, UndoManager } from "../../util/UndoManager"; @@ -22,27 +26,20 @@ import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { CollectionView } from "../collections/CollectionView"; import { ContextMenu } from "../ContextMenu"; +import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from "../DocComponent"; +import { EditableView } from '../EditableView'; +import { OverlayView } from '../OverlayView'; import { PresentationView } from "../presentationview/PresentationView"; -import { Template, Templates } from "./../Templates"; +import { ScriptingRepl } from '../ScriptingRepl'; +import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; -import * as rp from "request-promise"; import "./DocumentView.scss"; -import React = require("react"); -import { Id, Copy } from '../../../new_fields/FieldSymbols'; -import { ContextMenuProps } from '../ContextMenuItem'; -import { list, object, createSimpleSchema } from 'serializr'; -import { LinkManager } from '../../util/LinkManager'; -import { RouteStore } from '../../../server/RouteStore'; import { FormattedTextBox } from './FormattedTextBox'; -import { OverlayView } from '../OverlayView'; -import { ScriptingRepl } from '../ScriptingRepl'; -import { ClientUtils } from '../../util/ClientUtils'; -import { EditableView } from '../EditableView'; -import { faHandPointer, faHandPointRight } from '@fortawesome/free-regular-svg-icons'; -import { DocumentDecorations } from '../DocumentDecorations'; -import { CognitiveServices } from '../../cognitive_services/CognitiveServices'; -import DictationManager from '../../util/DictationManager'; +import React = require("react"); +import { DictationManager } from '../../util/DictationManager'; +import { MainView } from '../MainView'; +import requestPromise = require('request-promise'); const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(fa.faTrash); @@ -100,6 +97,7 @@ export interface DocumentViewProps { addDocTab: (doc: Doc, dataDoc: Doc | undefined, where: string) => void; collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void; zoomToScale: (scale: number) => void; + backgroundColor: (doc: Doc) => string | undefined; getScale: () => number; animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void; ChromeHeight?: () => number; @@ -121,6 +119,7 @@ export const positionSchema = createSchema({ height: "number", x: "number", y: "number", + z: "number", }); export type PositionDocument = makeInterface<[typeof positionSchema]>; @@ -152,10 +151,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu set templates(templates: List<string>) { this.props.Document.templates = templates; } screenRect = (): ClientRect | DOMRect => this._mainCont.current ? this._mainCont.current.getBoundingClientRect() : new DOMRect(); - constructor(props: DocumentViewProps) { - super(props); - } - _animateToIconDisposer?: IReactionDisposer; _reactionDisposer?: IReactionDisposer; @action @@ -306,7 +301,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu fullScreenAlias.showCaption = true; this.props.addDocTab(fullScreenAlias, this.dataDoc, "inTab"); SelectionManager.DeselectAll(); - this.props.Document.libraryBrush = false; + Doc.UnBrushDoc(this.props.Document); } else if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && @@ -364,12 +359,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu if (!linkedFwdDocs.some(l => l instanceof Promise)) { let maxLocation = StrCast(linkedFwdDocs[0].maximizeLocation, "inTab"); let targetContext = !Doc.AreProtosEqual(linkedFwdContextDocs[altKey ? 1 : 0], this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document) ? linkedFwdContextDocs[altKey ? 1 : 0] : undefined; - DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => { - this.props.focus(this.props.Document, true, 1); - setTimeout(() => - this.props.addDocTab(document, undefined, maxLocation), 1000); - } - , linkedFwdPage[altKey ? 1 : 0], targetContext); + DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, + document => { // open up target if it's not already in view ... + this.props.focus(this.props.Document, true, 1); // by zooming into the button document first + setTimeout(() => this.props.addDocTab(document, undefined, maxLocation), 1000); // then after the 1sec animation, open up the target in a new tab + }, + linkedFwdPage[altKey ? 1 : 0], targetContext); } } } @@ -414,7 +409,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument && this.props.removeDocument(this.props.Document); } @undoBatch - fieldsClicked = (): void => { let kvp = Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }); this.props.addDocTab(kvp, this.dataDoc, "onRight"); } + fieldsClicked = (): void => { + let kvp = Docs.Create.KVPDocument(this.props.Document, { width: 300, height: 300 }); + this.props.addDocTab(kvp, this.dataDoc, "onRight"); + } @undoBatch makeBtnClicked = (): void => { @@ -447,15 +445,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu let targetDoc = this.props.Document; targetDoc.targetContext = de.data.targetContext; let annotations = await DocListCastAsync(annotationDoc.annotations); - if (annotations) { - annotations.forEach(anno => { - anno.target = targetDoc; - }); - } - let pdfDoc = await Cast(annotationDoc.pdfDoc, Doc); - if (pdfDoc) { - DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Annotation from ${StrCast(pdfDoc.title)}`, "", StrCast(pdfDoc.title)); - } + annotations && annotations.forEach(anno => anno.target = targetDoc); + + DocUtils.MakeLink(annotationDoc, targetDoc, this.props.ContainingCollectionView!.props.Document, `Link from ${StrCast(annotationDoc.title)}`); } if (de.data instanceof DragManager.LinkDragData) { let sourceDoc = de.data.linkSourceDocument; @@ -540,8 +532,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu } listen = async () => { - let transcript = await DictationManager.Instance.listen(); - transcript && (Doc.GetProto(this.props.Document).transcript = transcript); + Doc.GetProto(this.props.Document).transcript = await DictationManager.Controls.listen({ + continuous: { indefinite: true }, + interimHandler: (results: string) => { + let main = MainView.Instance; + main.dictationSuccess = true; + main.dictatedPhrase = results; + main.isListening = { interim: true }; + } + }); } @action @@ -586,12 +585,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu }, icon: "window-restore" }); cm.addItem({ description: "Make...", subitems: makes, icon: "hand-point-right" }); - // cm.addItem({ - // description: "Find aliases", event: async () => { - // const aliases = await SearchUtil.GetAliasesOfDocument(this.props.Document); - // this.props.addDocTab && this.props.addDocTab(Docs.Create.SchemaDocument(["title"], aliases, {}), undefined, "onRight"); // bcz: dataDoc? - // }, icon: "search" - // }); if (this.props.Document.detailedLayout && !this.props.Document.isTemplate) { cm.addItem({ description: "Toggle detail", event: () => Doc.ToggleDetailLayout(this.props.Document), icon: "image" }); } @@ -656,8 +649,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu }); } - onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; - onPointerLeave = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = false; }; + onPointerEnter = (e: React.PointerEvent): void => { Doc.BrushDoc(this.props.Document); }; + onPointerLeave = (e: React.PointerEvent): void => { Doc.UnBrushDoc(this.props.Document); }; isSelected = () => SelectionManager.IsSelected(this); @action select = (ctrlPressed: boolean) => { SelectionManager.SelectDoc(this, ctrlPressed); }; @@ -685,12 +678,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu // to determine the render JSX string, otherwise the layout field should directly contain a JSX layout string. return this.props.Document.layout instanceof Doc ? this.props.Document.layout : this.props.Document; } + render() { - if (this.Document.hidden) { - return null; - } - let self = this; - let backgroundColor = StrCast(this.layoutDoc.backgroundColor); + let backgroundColor = this.layoutDoc.isBackground || (this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document.clusterOverridesDefaultBackground && this.layoutDoc.backgroundColor === this.layoutDoc.defaultBackgroundColor) ? + this.props.backgroundColor(this.layoutDoc) || StrCast(this.layoutDoc.backgroundColor) : + StrCast(this.layoutDoc.backgroundColor) || this.props.backgroundColor(this.layoutDoc); let foregroundColor = StrCast(this.layoutDoc.color); var nativeWidth = this.nativeWidth > 0 && !BoolCast(this.props.Document.ignoreAspect) ? `${this.nativeWidth}px` : "100%"; var nativeHeight = BoolCast(this.props.Document.ignoreAspect) ? this.props.PanelHeight() / this.props.ContentScaling() : this.nativeHeight > 0 ? `${this.nativeHeight}px` : "100%"; @@ -700,27 +692,28 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu let templates = Cast(this.layoutDoc.templates, listSpec("string")); if (!showOverlays && templates instanceof List) { templates.map(str => { - if (str.indexOf("{props.Document.title}") !== -1) showTitle = "title"; - if (str.indexOf("fieldKey={\"caption\"}") !== -1) showCaption = "caption"; + if (!showTitle && str.indexOf("{props.Document.title}") !== -1) showTitle = "title"; + if (!showCaption && str.indexOf("fieldKey={\"caption\"}") !== -1) showCaption = "caption"; }); } let showTextTitle = showTitle && StrCast(this.layoutDoc.layout).startsWith("<FormattedTextBox") ? showTitle : undefined; + let brushDegree = Doc.IsBrushedDegree(this.layoutDoc); return ( <div className={`documentView-node${this.topMost ? "-topmost" : ""}`} ref={this._mainCont} style={{ pointerEvents: this.layoutDoc.isBackground && !this.isSelected() ? "none" : "all", color: foregroundColor, - outlineColor: "maroon", - outlineStyle: "dashed", - outlineWidth: BoolCast(this.layoutDoc.libraryBrush) && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ? - `${this.props.ScreenToLocalTransform().Scale}px` : "0px", - marginLeft: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? - `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined, - marginTop: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? - `${-1 * this.props.ScreenToLocalTransform().Scale}px` : undefined, - border: BoolCast(this.layoutDoc.libraryBrush) && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? - `dashed maroon ${this.props.ScreenToLocalTransform().Scale}px` : undefined, + outlineColor: ["transparent", "maroon", "maroon"][brushDegree], + outlineStyle: ["none", "dashed", "solid"][brushDegree], + outlineWidth: brushDegree && !StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${brushDegree * this.props.ScreenToLocalTransform().Scale}px` : "0px", + marginLeft: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${-brushDegree * this.props.ScreenToLocalTransform().Scale}px` : undefined, + marginTop: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${-brushDegree * this.props.ScreenToLocalTransform().Scale}px` : undefined, + border: brushDegree && StrCast(Doc.GetProto(this.props.Document).borderRounding) ? + `${["none", "dashed", "solid"][brushDegree]} ${["transparent", "maroon", "maroon"][brushDegree]} ${this.props.ScreenToLocalTransform().Scale}px` : undefined, borderRadius: "inherit", background: backgroundColor, width: nativeWidth, diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index a2e610fc2..303b1ac88 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -181,14 +181,6 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe } this._applyingChange = true; const fieldkey = "preview"; - if (Object.keys(this.dataDoc).indexOf(fieldkey) !== -1) { - this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); - this.dataDoc[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n"); - } - else { - Doc.GetProto(this.dataDoc)[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); - Doc.GetProto(this.dataDoc)[this.props.fieldKey + "_text"] = state.doc.textBetween(0, state.doc.content.size, "\n\n"); - } if (this.extensionDoc) this.extensionDoc.text = state.doc.textBetween(0, state.doc.content.size, "\n\n"); if (this.extensionDoc) this.extensionDoc.lastModified = new DateField(new Date(Date.now())); this.dataDoc[this.props.fieldKey] = new RichTextField(JSON.stringify(state.toJSON())); @@ -676,16 +668,17 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let self = this; let style = this.props.isOverlay ? "scroll" : "hidden"; let rounded = StrCast(this.props.Document.borderRounding) === "100%" ? "-rounded" : ""; - let interactive = InkingControl.Instance.selectedTool ? "" : "interactive"; + let interactive: "all" | "none" = InkingControl.Instance.selectedTool || this.props.Document.isBackground || + (this.props.Document.isButton && !this.props.isSelected()) ? "none" : "all"; Doc.UpdateDocumentExtensionForField(this.dataDoc, this.props.fieldKey); return ( <div className={`formattedTextBox-cont-${style}`} ref={this._ref} style={{ height: this.props.height ? this.props.height : undefined, background: this.props.hideOnLeave ? "rgba(0,0,0,0.4)" : undefined, - opacity: this.props.hideOnLeave ? (this._entered || this.props.isSelected() || this.props.Document.libraryBrush ? 1 : 0.1) : 1, + opacity: this.props.hideOnLeave ? (this._entered || this.props.isSelected() || Doc.IsBrushed(this.props.Document) ? 1 : 0.1) : 1, color: this.props.color ? this.props.color : this.props.hideOnLeave ? "white" : "inherit", - pointerEvents: interactive ? "all" : "none", + pointerEvents: interactive, fontSize: "13px" }} onKeyDown={this.onKeyPress} @@ -696,12 +689,11 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe onPointerUp={this.onPointerUp} onPointerDown={this.onPointerDown} onMouseDown={this.onMouseDown} - // tfs: do we need this event handler onWheel={this.onPointerWheel} onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} > - <div className={`formattedTextBox-inner${rounded}`} ref={this.createDropTarget} style={{ whiteSpace: "pre-wrap", pointerEvents: this.props.Document.isButton && !this.props.isSelected() ? "none" : "all" }} /> + <div className={`formattedTextBox-inner${rounded}`} ref={this.createDropTarget} style={{ whiteSpace: "pre-wrap" }} /> </div> ); } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 9a0615d68..ca0f637eb 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -1,42 +1,39 @@ import { library } from '@fortawesome/fontawesome-svg-core'; -import { faImage, faFileAudio, faPaintBrush, faAsterisk } from '@fortawesome/free-solid-svg-icons'; -import { action, observable, computed, runInAction } from 'mobx'; +import { faEye } from '@fortawesome/free-regular-svg-icons'; +import { faAsterisk, faFileAudio, faImage, faPaintBrush } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, observable, runInAction } from 'mobx'; import { observer } from "mobx-react"; import Lightbox from 'react-image-lightbox'; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { Doc, HeightSym, WidthSym, DocListCast } from '../../../new_fields/Doc'; +import { Doc, DocListCast, HeightSym, WidthSym } from '../../../new_fields/Doc'; import { List } from '../../../new_fields/List'; import { createSchema, listSpec, makeInterface } from '../../../new_fields/Schema'; -import { Cast, FieldValue, NumCast, StrCast, BoolCast } from '../../../new_fields/Types'; -import { ImageField, AudioField } from '../../../new_fields/URLField'; +import { ComputedField } from '../../../new_fields/ScriptField'; +import { BoolCast, Cast, FieldValue, NumCast, StrCast } from '../../../new_fields/Types'; +import { AudioField, ImageField } from '../../../new_fields/URLField'; +import { RouteStore } from '../../../server/RouteStore'; import { Utils } from '../../../Utils'; +import { CognitiveServices, Confidence, Service, Tag } from '../../cognitive_services/CognitiveServices'; +import { Docs } from '../../documents/Documents'; import { DragManager } from '../../util/DragManager'; +import { CompileScript } from '../../util/Scripting'; import { undoBatch } from '../../util/UndoManager'; import { ContextMenu } from "../../views/ContextMenu"; import { ContextMenuProps } from '../ContextMenuItem'; import { DocComponent } from '../DocComponent'; import { InkingControl } from '../InkingControl'; import { positionSchema } from './DocumentView'; +import FaceRectangles from './FaceRectangles'; import { FieldView, FieldViewProps } from './FieldView'; import "./ImageBox.scss"; import React = require("react"); -import { RouteStore } from '../../../server/RouteStore'; -import { Docs, DocumentType } from '../../documents/Documents'; -import { DocServer } from '../../DocServer'; -import { Font } from '@react-pdf/renderer'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { CognitiveServices, Service, Tag, Confidence } from '../../cognitive_services/CognitiveServices'; -import FaceRectangles from './FaceRectangles'; -import { faEye } from '@fortawesome/free-regular-svg-icons'; -import { ComputedField } from '../../../new_fields/ScriptField'; -import { CompileScript } from '../../util/Scripting'; -import { thisExpression } from 'babel-types'; var requestImageSize = require('../../util/request-image-size'); var path = require('path'); const { Howl } = require('howler'); -library.add(faImage, faEye, faPaintBrush); +library.add(faImage, faEye as any, faPaintBrush); library.add(faFileAudio, faAsterisk); @@ -237,7 +234,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD results.map((face: CognitiveServices.Image.Face) => faceDocs.push(Docs.Get.DocumentHierarchyFromJson(face, `Face: ${face.faceId}`)!)); return faceDocs; }; - CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["faces"], this.url, Service.Face, converter); + if (this.url) { + CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["faces"], this.url, Service.Face, converter); + } } generateMetadata = (threshold: Confidence = Confidence.Excellent) => { @@ -256,7 +255,9 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD tagDoc.confidence = threshold; return tagDoc; }; - CognitiveServices.Image.Manager.analyzer(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter); + if (this.url) { + CognitiveServices.Image.Appliers.ProcessImage(this.extensionDoc, ["generatedTagsDoc"], this.url, Service.ComputerVision, converter); + } } @action @@ -317,14 +318,14 @@ export class ImageBox extends DocComponent<FieldViewProps, ImageDocument>(ImageD resize(srcpath: string, layoutdoc: Doc) { requestImageSize(srcpath) .then((size: any) => { - let aspect = size.height / size.width; let rotation = NumCast(this.dataDoc.rotation) % 180; - if (rotation === 90 || rotation === 270) aspect = 1 / aspect; - if (Math.abs(NumCast(layoutdoc.height) - size.height) > 1 || Math.abs(NumCast(layoutdoc.width) - size.width) > 1) { + let realsize = rotation === 90 || rotation === 270 ? { height: size.width, width: size.height } : size; + let aspect = realsize.height / realsize.width; + if (Math.abs(NumCast(layoutdoc.height) - realsize.height) > 1 || Math.abs(NumCast(layoutdoc.width) - realsize.width) > 1) { setTimeout(action(() => { layoutdoc.height = layoutdoc[WidthSym]() * aspect; - layoutdoc.nativeHeight = size.height; - layoutdoc.nativeWidth = size.width; + layoutdoc.nativeHeight = realsize.height; + layoutdoc.nativeWidth = realsize.width; }), 0); } }) diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx index 3775f0f47..534a42efc 100644 --- a/src/client/views/nodes/KeyValuePair.tsx +++ b/src/client/views/nodes/KeyValuePair.tsx @@ -1,22 +1,19 @@ import { action, observable } from 'mobx'; import { observer } from "mobx-react"; import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app -import { emptyFunction, returnFalse, returnZero, returnTrue, returnOne } from '../../../Utils'; -import { CompileScript, CompiledScript, ScriptOptions } from "../../util/Scripting"; +import { Doc, Field } from '../../../new_fields/Doc'; +import { emptyFunction, returnFalse, returnOne, returnZero } from '../../../Utils'; +import { Docs } from '../../documents/Documents'; import { Transform } from '../../util/Transform'; +import { undoBatch } from '../../util/UndoManager'; +import { CollectionDockingView } from '../collections/CollectionDockingView'; +import { ContextMenu } from '../ContextMenu'; import { EditableView } from "../EditableView"; import { FieldView, FieldViewProps } from './FieldView'; +import { KeyValueBox } from './KeyValueBox'; import "./KeyValueBox.scss"; import "./KeyValuePair.scss"; import React = require("react"); -import { Doc, Opt, Field } from '../../../new_fields/Doc'; -import { FieldValue } from '../../../new_fields/Types'; -import { KeyValueBox } from './KeyValueBox'; -import { DragManager, SetupDrag } from '../../util/DragManager'; -import { ContextMenu } from '../ContextMenu'; -import { Docs } from '../../documents/Documents'; -import { CollectionDockingView } from '../collections/CollectionDockingView'; -import { undoBatch } from '../../util/UndoManager'; // Represents one row in a key value plane diff --git a/src/client/views/nodes/LinkMenuItem.tsx b/src/client/views/nodes/LinkMenuItem.tsx index 1d4fcad69..a119eb39b 100644 --- a/src/client/views/nodes/LinkMenuItem.tsx +++ b/src/client/views/nodes/LinkMenuItem.tsx @@ -6,7 +6,7 @@ import { DocumentManager } from "../../util/DocumentManager"; import { undoBatch } from "../../util/UndoManager"; import './LinkMenu.scss'; import React = require("react"); -import { Doc } from '../../../new_fields/Doc'; +import { Doc, DocListCastAsync } from '../../../new_fields/Doc'; import { StrCast, Cast, FieldValue, NumCast } from '../../../new_fields/Types'; import { observable, action } from 'mobx'; import { LinkManager } from '../../util/LinkManager'; @@ -52,7 +52,7 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> { } if (this.props.destinationDoc === self.props.linkDoc.anchor2 && targetContext) { - DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(targetContext!)); + DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, async document => dockingFunc(document), undefined, targetContext!); } else if (this.props.destinationDoc === self.props.linkDoc.anchor1 && sourceContext) { DocumentManager.Instance.jumpToDocument(jumpToDoc, e.altKey, false, document => dockingFunc(sourceContext!)); diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index e7655d598..c88a94c28 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -1,37 +1,3 @@ -.react-pdf__Page { - transform-origin: left top; - position: absolute; - top: 0; - left: 0; -} - -.react-pdf__Page__textContent span { - user-select: text; -} - -.react-pdf__Document { - position: absolute; -} - -.pdfBox-buttonTray { - position: absolute; - top: 0; - left: 0; - z-index: 25; - pointer-events: all; -} - -.pdfBox-thumbnail { - position: absolute; - width: 100%; -} - -.pdfButton { - pointer-events: all; - width: 100px; - height: 100px; -} - .pdfBox-cont, .pdfBox-cont-interactive { display: flex; @@ -39,30 +5,24 @@ height: 100%; overflow-y: scroll; overflow-x: hidden; + .pdfBox-scrollHack { + pointer-events: none; + } } .pdfBox-cont { pointer-events: none; - - .textlayer { - pointer-events: none; - + .pdfPage-textlayer { span { pointer-events: none !important; + user-select: none; } } - - .page-cont { - pointer-events: none; - } } .pdfBox-cont-interactive { pointer-events: all; - display: flex; - flex-direction: row; - - .textlayer { + .pdfPage-textlayer { span { pointer-events: all !important; user-select: text; @@ -70,11 +30,22 @@ } } -.pdfBox-contentContainer { - position: absolute; +.react-pdf__Page { transform-origin: left top; + position: absolute; + top: 0; + left: 0; } +.react-pdf__Page__textContent span { + user-select: text; +} + +.react-pdf__Document { + position: absolute; +} + + .pdfBox-settingsCont { position: absolute; right: 0; diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index fa072aecf..6450cb826 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -1,31 +1,24 @@ -import { action, IReactionDisposer, observable, reaction, trace, untracked, computed } from 'mobx'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx'; import { observer } from "mobx-react"; +import * as Pdfjs from "pdfjs-dist"; +import "pdfjs-dist/web/pdf_viewer.css"; import 'react-image-lightbox/style.css'; -import { WidthSym, Doc } from "../../../new_fields/Doc"; +import { Doc, WidthSym, Opt } from "../../../new_fields/Doc"; import { makeInterface } from "../../../new_fields/Schema"; -import { Cast, NumCast, BoolCast } from "../../../new_fields/Types"; +import { ScriptField } from '../../../new_fields/ScriptField'; +import { BoolCast, Cast, NumCast } from "../../../new_fields/Types"; import { PdfField } from "../../../new_fields/URLField"; -//@ts-ignore -// import { Document, Page } from "react-pdf"; -// import 'react-pdf/dist/Page/AnnotationLayer.css'; -import { RouteStore } from "../../../server/RouteStore"; +import { KeyCodes } from '../../northstar/utils/KeyCodes'; +import { CompileScript } from '../../util/Scripting'; import { DocComponent } from "../DocComponent"; import { InkingControl } from "../InkingControl"; -import { FilterBox } from "../search/FilterBox"; -import { Annotation } from './Annotation'; import { PDFViewer } from "../pdf/PDFViewer"; import { positionSchema } from "./DocumentView"; import { FieldView, FieldViewProps } from './FieldView'; import { pageSchema } from "./ImageBox"; import "./PDFBox.scss"; import React = require("react"); -import { CompileScript } from '../../util/Scripting'; -import { Flyout, anchorPoints } from '../DocumentDecorations'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { ScriptField } from '../../../new_fields/ScriptField'; -import { KeyCodes } from '../../northstar/utils/KeyCodes'; -import { Utils } from '../../../Utils'; -import { Id } from '../../../new_fields/FieldSymbols'; type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; const PdfDocument = makeInterface(positionSchema, pageSchema); @@ -35,40 +28,34 @@ export const handleBackspace = (e: React.KeyboardEvent) => { if (e.keyCode === K export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } + @observable private _flyout: boolean = false; @observable private _alt = false; - @observable private _scrollY: number = 0; + @observable private _pdf: Opt<Pdfjs.PDFDocumentProxy>; + + @computed get containingCollectionDocument() { return this.props.ContainingCollectionView && this.props.ContainingCollectionView.props.Document; } @computed get dataDoc() { return BoolCast(this.props.Document.isTemplate) && this.props.DataDoc ? this.props.DataDoc : this.props.Document; } + @computed get fieldExtensionDoc() { return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); } - @observable private _flyout: boolean = false; - private _mainCont: React.RefObject<HTMLDivElement>; + private _mainCont: React.RefObject<HTMLDivElement> = React.createRef(); private _reactionDisposer?: IReactionDisposer; private _keyValue: string = ""; private _valueValue: string = ""; private _scriptValue: string = ""; - private _keyRef: React.RefObject<HTMLInputElement>; - private _valueRef: React.RefObject<HTMLInputElement>; - private _scriptRef: React.RefObject<HTMLInputElement>; + private _keyRef: React.RefObject<HTMLInputElement> = React.createRef(); + private _valueRef: React.RefObject<HTMLInputElement> = React.createRef(); + private _scriptRef: React.RefObject<HTMLInputElement> = React.createRef(); - constructor(props: FieldViewProps) { - super(props); + componentDidMount() { + this.props.setPdfBox && this.props.setPdfBox(this); - this._mainCont = React.createRef(); + const pdfUrl = Cast(this.props.Document.data, PdfField); + if (pdfUrl instanceof PdfField) { + Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf)); + } this._reactionDisposer = reaction( - () => this.props.Document.scrollY, - () => { - if (this._mainCont.current) { - this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.scrollY), behavior: "auto" }); - } - } + () => this.props.Document.panY, + () => this._mainCont.current && this._mainCont.current.scrollTo({ top: NumCast(this.Document.panY), behavior: "auto" }) ); - - this._keyRef = React.createRef(); - this._valueRef = React.createRef(); - this._scriptRef = React.createRef(); - } - - componentDidMount() { - if (this.props.setPdfBox) this.props.setPdfBox(this); } componentWillUnmount() { @@ -76,186 +63,144 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen } public GetPage() { - return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1; + return Math.floor(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; } + + @action public BackPage() { - let cp = Math.ceil(NumCast(this.props.Document.scrollY) / NumCast(this.dataDoc.pdfHeight)) + 1; + let cp = Math.ceil(NumCast(this.props.Document.panY) / NumCast(this.dataDoc.nativeHeight)) + 1; cp = cp - 1; if (cp > 0) { this.props.Document.curPage = cp; - this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.pdfHeight); + this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); } } + + @action public GotoPage(p: number) { if (p > 0 && p <= NumCast(this.props.Document.numPages)) { this.props.Document.curPage = p; - this.props.Document.scrollY = (p - 1) * NumCast(this.dataDoc.pdfHeight); + this.props.Document.panY = (p - 1) * NumCast(this.dataDoc.nativeHeight); } } + @action public ForwardPage() { let cp = this.GetPage() + 1; if (cp <= NumCast(this.props.Document.numPages)) { this.props.Document.curPage = cp; - this.props.Document.scrollY = (cp - 1) * NumCast(this.dataDoc.pdfHeight); + this.props.Document.panY = (cp - 1) * NumCast(this.dataDoc.nativeHeight); } } - private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => { - this._keyValue = e.currentTarget.value; - } - - private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => { - this._valueValue = e.currentTarget.value; - } - @action - private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => { - this._scriptValue = e.currentTarget.value; + setPanY = (y: number) => { + this.containingCollectionDocument && (this.containingCollectionDocument.panY = y); } + @action private applyFilter = () => { - let scriptText = ""; - if (this._scriptValue.length > 0) { - scriptText = this._scriptValue; - } else if (this._keyValue.length > 0 && this._valueValue.length > 0) { - scriptText = `return this.${this._keyValue} === ${this._valueValue}`; - } - else { - scriptText = "return true"; - } + let scriptText = this._scriptValue.length > 0 ? this._scriptValue : + this._keyValue.length > 0 && this._valueValue.length > 0 ? + `return this.${this._keyValue} === ${this._valueValue}` : "return true"; let script = CompileScript(scriptText, { params: { this: Doc.name } }); - if (script.compiled) { - this.props.Document.filterScript = new ScriptField(script); - } + script.compiled && (this.props.Document.filterScript = new ScriptField(script)); } - @action - private toggleFlyout = () => { - this._flyout = !this._flyout; + scrollTo = (y: number) => { + this._mainCont.current && this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current.offsetHeight / 2), 0), behavior: "auto" }); } - @action private resetFilters = () => { this._keyValue = this._valueValue = ""; this._scriptValue = "return true"; - if (this._keyRef.current) { - this._keyRef.current.value = ""; - } - if (this._valueRef.current) { - this._valueRef.current.value = ""; - } - if (this._scriptRef.current) { - this._scriptRef.current.value = ""; - } + this._keyRef.current && (this._keyRef.current.value = ""); + this._valueRef.current && (this._valueRef.current.value = ""); + this._scriptRef.current && (this._scriptRef.current.value = ""); this.applyFilter(); } - - scrollTo(y: number) { - if (this._mainCont.current) { - this._mainCont.current.scrollTo({ top: Math.max(y - (this._mainCont.current!.offsetHeight / 2), 0), behavior: "auto" }); - } - } + private newKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => this._keyValue = e.currentTarget.value; + private newValueChange = (e: React.ChangeEvent<HTMLInputElement>) => this._valueValue = e.currentTarget.value; + private newScriptChange = (e: React.ChangeEvent<HTMLInputElement>) => this._scriptValue = e.currentTarget.value; settingsPanel() { return !this.props.active() ? (null) : - ( - <div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}> - <button className="pdfBox-settingsButton" onClick={this.toggleFlyout} title="Open Annotation Settings" - style={{ marginTop: `${NumCast(this.props.ContainingCollectionView!.props.Document.panY)}px` }}> - <div className="pdfBox-settingsButton-arrow" - style={{ - borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`, - borderBottom: `25px solid ${this._flyout ? "#121721" : "transparent"}`, - borderRight: `25px solid ${this._flyout ? "transparent" : "#121721"}`, - transform: `scaleX(${this._flyout ? -1 : 1})` - }}></div> - <div className="pdfBox-settingsButton-iconCont"> - <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="3x" /> - </div> - </button> - <div className="pdfBox-settingsFlyout" style={{ left: `${this._flyout ? -600 : 100}px` }} > - <div className="pdfBox-settingsFlyout-title"> - Annotation View Settings - </div> - <div className="pdfBox-settingsFlyout-kvpInput"> - <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange} - style={{ gridColumn: 1 }} ref={this._keyRef} /> - <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange} - style={{ gridColumn: 3 }} ref={this._valueRef} /> - </div> - <div className="pdfBox-settingsFlyout-kvpInput"> - <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} /> - </div> - <div className="pdfBox-settingsFlyout-kvpInput"> - <button style={{ gridColumn: 1 }} onClick={this.resetFilters}> - <FontAwesomeIcon style={{ color: "white" }} icon="trash" size="lg" /> - Reset Filters - </button> - <button style={{ gridColumn: 3 }} onClick={this.applyFilter}> - <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" /> - Apply - </button> - </div> + (<div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}> + <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" + style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }}> + <div className="pdfBox-settingsButton-arrow" + style={{ + borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`, + borderBottom: `25px solid ${this._flyout ? "#121721" : "transparent"}`, + borderRight: `25px solid ${this._flyout ? "transparent" : "#121721"}`, + transform: `scaleX(${this._flyout ? -1 : 1})` + }} /> + <div className="pdfBox-settingsButton-iconCont"> + <FontAwesomeIcon style={{ color: "white" }} icon="cog" size="3x" /> + </div> + </button> + <div className="pdfBox-settingsFlyout" style={{ left: `${this._flyout ? -600 : 100}px` }} > + <div className="pdfBox-settingsFlyout-title"> + Annotation View Settings + </div> + <div className="pdfBox-settingsFlyout-kvpInput"> + <input placeholder="Key" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newKeyChange} + style={{ gridColumn: 1 }} ref={this._keyRef} /> + <input placeholder="Value" className="pdfBox-settingsFlyout-input" onKeyDown={handleBackspace} onChange={this.newValueChange} + style={{ gridColumn: 3 }} ref={this._valueRef} /> + </div> + <div className="pdfBox-settingsFlyout-kvpInput"> + <input placeholder="Custom Script" onChange={this.newScriptChange} onKeyDown={handleBackspace} style={{ gridColumn: "1 / 4" }} ref={this._scriptRef} /> + </div> + <div className="pdfBox-settingsFlyout-kvpInput"> + <button style={{ gridColumn: 1 }} onClick={this.resetFilters}> + <FontAwesomeIcon style={{ color: "white" }} icon="trash" size="lg" /> + Reset Filters + </button> + <button style={{ gridColumn: 3 }} onClick={this.applyFilter}> + <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" /> + Apply + </button> </div> </div> - ); + </div>); } loaded = (nw: number, nh: number, np: number) => { - if (this.props.Document) { - let doc = this.dataDoc; - doc.numPages = np; - if (doc.nativeWidth && doc.nativeHeight) return; - let oldaspect = NumCast(doc.nativeHeight) / NumCast(doc.nativeWidth, 1); - doc.nativeWidth = nw; - if (doc.nativeHeight) doc.nativeHeight = nw * oldaspect; - else doc.nativeHeight = nh; - let ccv = this.props.ContainingCollectionView; - if (ccv) { - ccv.props.Document.pdfHeight = nh; - } - doc.height = nh * (doc[WidthSym]() / nw); + this.dataDoc.numPages = np; + if (!this.dataDoc.nativeWidth || !this.dataDoc.nativeHeight || !this.dataDoc.scrollHeight) { + let oldaspect = NumCast(this.dataDoc.nativeHeight) / NumCast(this.dataDoc.nativeWidth, 1); + this.dataDoc.nativeWidth = nw; + this.dataDoc.nativeHeight = this.dataDoc.nativeHeight ? nw * oldaspect : nh; + this.dataDoc.height = this.dataDoc[WidthSym]() * (nh / nw); + this.dataDoc.scrollHeight = np * this.dataDoc.nativeHeight; } } @action onScroll = (e: React.UIEvent<HTMLDivElement>) => { - - if (e.currentTarget) { - this._scrollY = e.currentTarget.scrollTop; - let ccv = this.props.ContainingCollectionView; - if (ccv) { - ccv.props.Document.panTransformType = "None"; - ccv.props.Document.scrollY = this._scrollY; - } + if (e.currentTarget && this.containingCollectionDocument) { + this.containingCollectionDocument.panTransformType = "None"; + this.containingCollectionDocument.panY = e.currentTarget.scrollTop; } } - - @computed get fieldExtensionDoc() { - return Doc.resolvedFieldDataDoc(this.props.DataDoc ? this.props.DataDoc : this.props.Document, this.props.fieldKey, "true"); - } render() { - // uses mozilla pdf as default const pdfUrl = Cast(this.props.Document.data, PdfField); - if (!(pdfUrl instanceof PdfField)) return <div>{`pdf, ${this.props.Document.data}, not found`}</div>; let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); - return ( + return (!(pdfUrl instanceof PdfField) || !this._pdf ? + <div>{`pdf, ${this.props.Document.data}, not found`}</div> : <div className={classname} onScroll={this.onScroll} - style={{ - marginTop: `${NumCast(this.props.ContainingCollectionView!.props.Document.panY)}px` - }} - ref={this._mainCont} - onWheel={(e: React.WheelEvent) => { - e.stopPropagation(); - }}> - <PDFViewer url={pdfUrl.url.pathname} loaded={this.loaded} scrollY={this._scrollY} parent={this} /> - {/* <div style={{ width: "100px", height: "300px" }}></div> */} + style={{ marginTop: `${this.containingCollectionDocument ? NumCast(this.containingCollectionDocument.panY) : 0}px` }} + ref={this._mainCont}> + <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + (NumCast(this.props.Document.nativeHeight) - NumCast(this.props.Document.nativeHeight) / NumCast(this.props.Document.scale, 1)), width: "100%" }} /> + <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={NumCast(this.props.Document.panY)} + Document={this.props.Document} DataDoc={this.props.DataDoc} + addDocTab={this.props.addDocTab} setPanY={this.setPanY} + addDocument={this.props.addDocument} + fieldKey={this.props.fieldKey} fieldExtensionDoc={this.fieldExtensionDoc} /> {this.settingsPanel()} - </div> - ); + </div>); } - }
\ No newline at end of file diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index 162ac1d98..c8749b7cd 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -8,6 +8,7 @@ import "./WebBox.scss"; import React = require("react"); import { InkTool } from "../../../new_fields/InkField"; import { Cast, FieldValue, NumCast } from "../../../new_fields/Types"; +import { Utils } from "../../../Utils"; @observer export class WebBox extends React.Component<FieldViewProps> { @@ -52,7 +53,7 @@ export class WebBox extends React.Component<FieldViewProps> { if (field instanceof HtmlField) { view = <span id="webBox-htmlSpan" dangerouslySetInnerHTML={{ __html: field.html }} />; } else if (field instanceof WebField) { - view = <iframe src={field.url.href} style={{ position: "absolute", width: "100%", height: "100%" }} />; + view = <iframe src={Utils.CorsProxy(field.url.href)} style={{ position: "absolute", width: "100%", height: "100%" }} />; } else { view = <iframe src={"https://crossorigin.me/https://cs.brown.edu"} style={{ position: "absolute", width: "100%", height: "100%" }} />; } |
