aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
authorTyler Schicke <tyler_schicke@brown.edu>2019-06-26 22:36:09 -0400
committerTyler Schicke <tyler_schicke@brown.edu>2019-06-26 22:36:09 -0400
commit212c8be0d974a76246193303408d647896ec232c (patch)
treed5fb2629fd57b16bcf1649cb5ce0093065e80bfd /src/client/views/nodes
parent943ee465b4179705257a106948a35c2ef85fa671 (diff)
parent68a71ec1af52e1e23374c2062c9f809e5fc905d6 (diff)
Merge branch 'master' of github-tsch-brown:browngraphicslab/Dash-Web into searchUI
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/DocumentView.tsx25
-rw-r--r--src/client/views/nodes/PDFBox.scss68
-rw-r--r--src/client/views/nodes/PDFBox.tsx143
3 files changed, 224 insertions, 12 deletions
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 522c37989..e6d8086b0 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -23,7 +23,7 @@ import { CollectionVideoView } from "../collections/CollectionVideoView";
import { CollectionView } from "../collections/CollectionView";
import { ContextMenu } from "../ContextMenu";
import { DocComponent } from "../DocComponent";
-import { PresentationView } from "../PresentationView";
+import { PresentationView } from "../presentationview/PresentationView";
import { Template } from "./../Templates";
import { DocumentContentsView } from "./DocumentContentsView";
import * as rp from "request-promise";
@@ -75,12 +75,15 @@ export interface DocumentViewProps {
ContentScaling: () => number;
PanelWidth: () => number;
PanelHeight: () => number;
- focus: (doc: Doc) => void;
+ focus: (doc: Doc, willZoom: boolean) => void;
selectOnLoad: boolean;
parentActive: () => boolean;
whenActiveChanged: (isActive: boolean) => void;
bringToFront: (doc: Doc) => void;
addDocTab: (doc: Doc, where: string) => void;
+ collapseToPoint?: (scrpt: number[], expandedDocs: Doc[] | undefined) => void;
+ zoomToScale: (scale: number) => void;
+ getScale: () => number;
animateBetweenIcon?: (iconPos: number[], startTime: number, maximizing: boolean) => void;
}
@@ -89,6 +92,7 @@ const schema = createSchema({
nativeWidth: "number",
nativeHeight: "number",
backgroundColor: "string",
+ opacity: "number",
hidden: "boolean"
});
@@ -117,6 +121,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
private _mainCont = React.createRef<HTMLDivElement>();
private _dropDisposer?: DragManager.DragDropDisposer;
+ @observable private _opacity: number = this.Document.opacity ? NumCast(this.Document.opacity) : 1;
+
public get ContentDiv() { return this._mainCont.current; }
@computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); }
@computed get topMost(): boolean { return this.props.isTopMost; }
@@ -136,6 +142,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
_animateToIconDisposer?: IReactionDisposer;
_reactionDisposer?: IReactionDisposer;
+ _opacityDisposer?: IReactionDisposer;
@action
componentDidMount() {
if (this._mainCont.current) {
@@ -160,6 +167,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
(values instanceof List) && this.animateBetweenIcon(values, values[2], values[3] ? true : false)
, { fireImmediately: true });
DocumentManager.Instance.DocumentViews.push(this);
+ this._opacityDisposer = reaction(
+ () => NumCast(this.props.Document.opacity),
+ () => {
+ runInAction(() => this._opacity = NumCast(this.props.Document.opacity));
+ }
+ );
}
animateBetweenIcon = (iconPos: number[], startTime: number, maximizing: boolean) => {
@@ -201,6 +214,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (this._reactionDisposer) this._reactionDisposer();
if (this._animateToIconDisposer) this._animateToIconDisposer();
if (this._dropDisposer) this._dropDisposer();
+ if (this._opacityDisposer) this._opacityDisposer();
DocumentManager.Instance.DocumentViews.splice(DocumentManager.Instance.DocumentViews.indexOf(this), 1);
}
@@ -333,7 +347,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (!linkedFwdDocs.some(l => l instanceof Promise)) {
let maxLocation = StrCast(linkedFwdDocs[altKey ? 1 : 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, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext);
+ DocumentManager.Instance.jumpToDocument(linkedFwdDocs[altKey ? 1 : 0], ctrlKey, false, document => this.props.addDocTab(document, maxLocation), linkedFwdPage[altKey ? 1 : 0], targetContext);
}
}
}
@@ -488,7 +502,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.props.addDocTab && this.props.addDocTab(Docs.SchemaDocument(["title"], aliases, {}), "onRight");
}, icon: "search"
});
- cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document), icon: "crosshairs" });
+ cm.addItem({ description: "Center View", event: () => this.props.focus(this.props.Document, false), icon: "crosshairs" });
cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" });
cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" });
cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" });
@@ -559,7 +573,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
background: this.Document.backgroundColor || "",
width: nativeWidth,
height: nativeHeight,
- transform: `scale(${scaling}, ${scaling})`
+ transform: `scale(${scaling}, ${scaling})`,
+ opacity: NumCast(this.props.Document.opacity, 1)
}}
onDrop={this.onDrop} onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index 8bcae4f1e..5edff69f3 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -36,12 +36,15 @@
pointer-events: none;
display: flex;
flex-direction: row;
+
.textlayer {
pointer-events: none;
+
span {
pointer-events: none !important;
}
}
+
.page-cont {
pointer-events: none;
}
@@ -51,6 +54,7 @@
pointer-events: all;
display: flex;
flex-direction: row;
+
.textlayer {
span {
pointer-events: all !important;
@@ -62,4 +66,68 @@
.pdfBox-contentContainer {
position: absolute;
transform-origin: left top;
+}
+
+.pdfBox-settingsCont {
+ position: absolute;
+ right: 0;
+ top: 0;
+
+ .pdfBox-settingsButton {
+ border-bottom-left-radius: 50%;
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+ height: 70px;
+ background: none;
+ padding: 0;
+
+ .pdfBox-settingsButton-arrow {
+ width: 0;
+ height: 0;
+ border-top: 25px solid transparent;
+ border-bottom: 25px solid transparent;
+ border-right: 25px solid #121721;
+ transition: all 0.5s;
+ }
+
+ .pdfBox-settingsButton-iconCont {
+ background: #121721;
+ height: 50px;
+ width: 70px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-left: -2px;
+ border-radius: 3px;
+ }
+ }
+
+ .pdfBox-settingsButton:hover {
+ background: none;
+ }
+
+ .pdfBox-settingsFlyout {
+ width: 600px;
+ position: absolute;
+ background: #323232;
+ box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25);
+ left: -400px;
+ border-radius: 7px;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ font-size: 30px;
+ transition: all 0.5s;
+
+ .pdfBox-settingsFlyout-title {
+ color: white;
+ }
+
+ .pdfBox-settingsFlyout-kvpInput {
+ margin-top: 20px;
+ display: grid;
+ grid-template-columns: 47.5% 5% 47.5%;
+ }
+ }
} \ No newline at end of file
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 02b883d57..b6436d70f 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,7 +1,7 @@
import { action, IReactionDisposer, observable, reaction, trace, untracked } from 'mobx';
import { observer } from "mobx-react";
import 'react-image-lightbox/style.css';
-import { WidthSym } from "../../../new_fields/Doc";
+import { WidthSym, Doc } from "../../../new_fields/Doc";
import { makeInterface } from "../../../new_fields/Schema";
import { Cast, NumCast } from "../../../new_fields/Types";
import { PdfField } from "../../../new_fields/URLField";
@@ -19,6 +19,10 @@ 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';
type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(positionSchema, pageSchema);
@@ -29,12 +33,42 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
@observable private _alt = false;
@observable private _scrollY: number = 0;
+ @observable private _flyout: boolean = false;
+ private _mainCont: React.RefObject<HTMLDivElement>;
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>;
+
+ constructor(props: FieldViewProps) {
+ super(props);
+
+ this._mainCont = React.createRef();
+ 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._keyRef = React.createRef();
+ this._valueRef = React.createRef();
+ this._scriptRef = React.createRef();
+ }
componentDidMount() {
if (this.props.setPdfBox) this.props.setPdfBox(this);
}
+ componentWillUnmount() {
+ this._reactionDisposer && this._reactionDisposer();
+ }
+
public GetPage() {
return Math.floor(NumCast(this.props.Document.scrollY) / NumCast(this.Document.pdfHeight)) + 1;
}
@@ -61,11 +95,105 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
}
- createRef = (ele: HTMLDivElement | null) => {
- if (this._reactionDisposer) this._reactionDisposer();
- this._reactionDisposer = reaction(() => this.props.Document.scrollY, () => {
- ele && ele.scrollTo({ top: NumCast(this.Document.scrollY), behavior: "auto" });
- });
+ 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;
+ }
+
+ 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 script = CompileScript(scriptText, { params: { this: Doc.name } });
+ if (script.compiled) {
+ this.props.Document.filterScript = new ScriptField(script);
+ }
+ }
+
+ @action
+ private toggleFlyout = () => {
+ this._flyout = !this._flyout;
+ }
+
+ @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.applyFilter();
+ }
+
+ scrollTo(y: number) {
+ if (this._mainCont.current) {
+ this._mainCont.current.scrollTo({ top: y });
+ }
+ }
+
+ 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" onChange={this.newKeyChange}
+ style={{ gridColumn: 1 }} ref={this._keyRef} />
+ <input placeholder="Value" className="pdfBox-settingsFlyout-input" onChange={this.newValueChange}
+ style={{ gridColumn: 3 }} ref={this._valueRef} />
+ </div>
+ <div className="pdfBox-settingsFlyout-kvpInput">
+ <input placeholder="Custom Script" onChange={this.newScriptChange} 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" />
+ &nbsp; Reset Filters
+ </button>
+ <button style={{ gridColumn: 3 }} onClick={this.applyFilter}>
+ <FontAwesomeIcon style={{ color: "white" }} icon="check" size="lg" />
+ &nbsp; Apply
+ </button>
+ </div>
+ </div>
+ </div>
+ );
}
loaded = (nw: number, nh: number, np: number) => {
@@ -107,12 +235,13 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
overflowY: "scroll", overflowX: "hidden",
marginTop: `${NumCast(this.props.ContainingCollectionView!.props.Document.panY)}px`
}}
- ref={this.createRef}
+ ref={this._mainCont}
onWheel={(e: React.WheelEvent) => {
e.stopPropagation();
}} className={classname}>
<PDFViewer url={pdfUrl.url.pathname} loaded={this.loaded} scrollY={this._scrollY} parent={this} />
{/* <div style={{ width: "100px", height: "300px" }}></div> */}
+ {this.settingsPanel()}
</div>
);
}