aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoryipstanley <stanley_yip@brown.edu>2019-06-24 13:57:59 -0400
committeryipstanley <stanley_yip@brown.edu>2019-06-24 13:57:59 -0400
commit65288e33b49404d21012323fcb53fefb3f646fbf (patch)
treed9599fc0a8a505e4703056ec9596c746edf33078 /src
parent25561f70206871432ebb24e787e7222e98584a49 (diff)
basic viewspecs
Diffstat (limited to 'src')
-rw-r--r--src/client/views/MainView.tsx3
-rw-r--r--src/client/views/nodes/PDFBox.scss68
-rw-r--r--src/client/views/nodes/PDFBox.tsx83
-rw-r--r--src/client/views/pdf/PDFViewer.tsx36
4 files changed, 180 insertions, 10 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 2645e2789..08755b427 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,5 +1,5 @@
import { IconName, library } from '@fortawesome/fontawesome-svg-core';
-import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faThumbtack, faRedoAlt, faTable, faTree, faUndoAlt, faBell, faCommentAlt, faCut } from '@fortawesome/free-solid-svg-icons';
+import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faCheck, faPenNib, faThumbtack, faRedoAlt, faTable, faTree, faUndoAlt, faBell, faCommentAlt, faCut } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, configure, observable, runInAction, trace } from 'mobx';
import { observer } from 'mobx-react';
@@ -94,6 +94,7 @@ export class MainView extends React.Component {
library.add(faCut);
library.add(faCommentAlt);
library.add(faThumbtack);
+ library.add(faCheck);
this.initEventListeners();
this.initAuthenticationRouters();
}
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 10a346269..aa421ff9c 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -19,6 +19,8 @@ import "./PDFBox.scss";
import React = require("react");
import { CompileScript } from '../../util/Scripting';
import { ScriptField } from '../../../fields/ScriptField';
+import { Flyout, anchorPoints } from '../DocumentDecorations';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>;
const PdfDocument = makeInterface(positionSchema, pageSchema);
@@ -29,8 +31,12 @@ 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 = "";
constructor(props: FieldViewProps) {
super(props);
@@ -45,7 +51,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
);
- let script = CompileScript("return this.page === 2", { params: { this: Doc.name } });
+ let script = CompileScript("return this.page === 0", { params: { this: Doc.name } });
if (script.compiled) {
this.props.Document.filterScript = new ScriptField(script);
}
@@ -55,6 +61,10 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
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;
}
@@ -81,7 +91,75 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
}
- createRef = (ele: HTMLDivElement | null) => {
+ 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;
+ }
+
+ private applyFilter = (e: React.MouseEvent<HTMLButtonElement>) => {
+ 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}`;
+ }
+ 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;
+ }
+
+ settingsPanel() {
+ return !this.props.active() ? (null) :
+ (
+ <div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}>
+ <button className="pdfBox-settingsButton" onClick={this.toggleFlyout}
+ 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 }} />
+ <input placeholder="Value" className="pdfBox-settingsFlyout-input" onChange={this.newValueChange}
+ style={{ gridColumn: 3 }} />
+ </div>
+ <div className="pdfBox-settingsFlyout-kvpInput">
+ <input placeholder="Custom Script" onChange={this.newScriptChange} style={{ gridColumn: "1 / 4" }} />
+ </div>
+ <div className="pdfBox-settingsFlyout-kvpInput">
+ <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) => {
@@ -129,6 +207,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}} 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>
);
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 75a8b042d..1fb208525 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -21,7 +21,7 @@ import React = require("react");
import PDFMenu from "./PDFMenu";
import { UndoManager } from "../../util/UndoManager";
import { ScriptField } from "../../../fields/ScriptField";
-import { CompileScript, CompiledScript } from "../../util/Scripting";
+import { CompileScript, CompiledScript, CompileResult } from "../../util/Scripting";
export const scale = 2;
interface IPDFViewerProps {
@@ -77,7 +77,7 @@ class Viewer extends React.Component<IViewerProps> {
@observable private _pageSizes: { width: number, height: number }[] = [];
@observable private _annotations: Doc[] = [];
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
- @observable private _script: ScriptField | undefined = this.props.parent.Document.filterScript;
+ @observable private _script: CompileResult | undefined;
private _pageBuffer: number = 1;
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
@@ -86,6 +86,14 @@ class Viewer extends React.Component<IViewerProps> {
private _dropDisposer?: DragManager.DragDropDisposer;
private _filterReactionDisposer?: IReactionDisposer;
+ @action
+ constructor(props: IViewerProps) {
+ super(props);
+
+ let scriptfield = Cast(this.props.parent.Document.filterScript, ScriptField);
+ this._script = scriptfield ? CompileScript(scriptfield.scriptString, { params: { this: Doc.name } }) : CompileScript("return true");;
+ }
+
componentDidUpdate = (prevProps: IViewerProps) => {
if (this.scrollY !== prevProps.scrollY) {
this.renderPages();
@@ -112,7 +120,10 @@ class Viewer extends React.Component<IViewerProps> {
this._filterReactionDisposer = reaction(
() => this.props.parent.Document.filterScript || this.props.parent.props.ContainingCollectionView!.props.Document.filterScript,
() => {
- this._script = Cast(this.props.parent.Document.filterScript, ScriptField);
+ runInAction(() => {
+ let scriptfield = Cast(this.props.parent.Document.filterScript, ScriptField);
+ this._script = scriptfield ? CompileScript(scriptfield.scriptString, { params: { this: Doc.name } }) : CompileScript("return true");;
+ });
}
);
}
@@ -121,6 +132,7 @@ class Viewer extends React.Component<IViewerProps> {
componentWillUnmount = () => {
this._reactionDisposer && this._reactionDisposer();
this._annotationReactionDisposer && this._annotationReactionDisposer();
+ this._filterReactionDisposer && this._filterReactionDisposer();
}
@action
@@ -159,10 +171,12 @@ class Viewer extends React.Component<IViewerProps> {
makeAnnotationDocument = (sourceDoc: Doc | undefined, s: number, color: string): Doc => {
let annoDocs: Doc[] = [];
- let mainAnnoDoc = new Doc();
+ let mainAnnoDoc = Docs.CreateInstance(new Doc(), "", {});
+
+ mainAnnoDoc.page = Math.round(Math.random());
this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => {
for (let anno of value) {
- let annoDoc = Docs.CreateInstance(new Doc(), this.props.parent.Document, {});
+ let annoDoc = new Doc();
if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale;
if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale;
if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale;
@@ -360,7 +374,7 @@ class Viewer extends React.Component<IViewerProps> {
}
render() {
- let compiled = this._script ? CompileScript(this._script.scriptString, { params: { this: Doc.name } }) : CompileScript("return true");
+ let compiled = this._script;
return (
<div ref={this.mainCont} style={{ pointerEvents: "all" }}>
<div className="viewer">
@@ -372,7 +386,15 @@ class Viewer extends React.Component<IViewerProps> {
pointerEvents: this.props.parent.props.active() ? "none" : "all"
}}>
<div className="pdfViewer-annotationLayer-subCont" ref={this._annotationLayer}>
- {this._annotations.filter(anno => compiled.compiled ? compiled.run(anno) : true).map(anno => this.renderAnnotation(anno))}
+ {this._annotations.filter(anno => {
+ if (compiled && compiled.compiled) {
+ let run = compiled.run({ this: anno });
+ if (run.success) {
+ return run.result;
+ }
+ }
+ return true;
+ }).map(anno => this.renderAnnotation(anno))}
</div>
</div>
</div >