diff options
author | Andrew Kim <andrewdkim@users.noreply.github.com> | 2019-02-23 16:19:45 -0500 |
---|---|---|
committer | Andrew Kim <andrewdkim@users.noreply.github.com> | 2019-02-23 16:19:45 -0500 |
commit | 07f5e56508c362725db003736a0f7980cd72107d (patch) | |
tree | 697242d7468203c46a5847cef2d24bd0d4001968 /src | |
parent | 5b55e1b6081393989ca35d2964da9604c2a93802 (diff) |
PDFNode
Diffstat (limited to 'src')
-rw-r--r-- | src/.DS_Store | bin | 0 -> 6148 bytes | |||
-rw-r--r-- | src/Main.tsx | 14 | ||||
-rw-r--r-- | src/Utils.ts | 2 | ||||
-rw-r--r-- | src/documents/Documents.ts | 28 | ||||
-rw-r--r-- | src/fields/ImageField.ts | 4 | ||||
-rw-r--r-- | src/fields/PDFField.ts | 17 | ||||
-rw-r--r-- | src/typings/index.d.ts | 322 | ||||
-rw-r--r-- | src/views/nodes/ImageBox.tsx | 234 | ||||
-rw-r--r-- | src/views/nodes/PDFBox.scss | 0 | ||||
-rw-r--r-- | src/views/nodes/PDFBox.tsx | 102 | ||||
-rw-r--r-- | src/views/nodes/Sticky.tsx | 90 |
11 files changed, 772 insertions, 41 deletions
diff --git a/src/.DS_Store b/src/.DS_Store Binary files differnew file mode 100644 index 000000000..96930b780 --- /dev/null +++ b/src/.DS_Store diff --git a/src/Main.tsx b/src/Main.tsx index 6730cf799..dd8313ac1 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -14,6 +14,7 @@ import { ContextMenu } from './views/ContextMenu'; import { DocumentView } from './views/nodes/DocumentView'; import { CompileScript } from './util/Scripting'; +//pdf url: https://arxiv.org/pdf/1708.08021.pdf configure({ enforceActions: "observed" @@ -44,8 +45,12 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { doc2.Set(KS.X, new NumberField(150)); doc2.Set(KS.Y, new NumberField(20)); let doc3 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { - x: 450, y: 500, title: "cat 1" + x:0, y: 0, width: 500, height: 500,title: "cat 1" }); + + //let PDFDoc = Documents.PDFDocument("https://arxiv.org/pdf/1708.08021.pdf", { + //x: 450, y: 500, title: "PDF!" + //}) // const schemaDocs = Array.from(Array(5).keys()).map(v => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { // x: 50 + 100 * v, y: 50, width: 100, height: 100, title: "cat" + v // })); @@ -53,10 +58,14 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { // schemaDocs[4].SetData(KS.Author, "Bob", TextField); // schemaDocs.push(doc2); // const doc7 = Documents.SchemaDocument(schemaDocs) - const docset = [doc3]; // [doc1, doc2, doc3, doc7]; + + + + const docset = [doc3]; //pdfDoc let doc4 = Documents.CollectionDocument(docset, { x: 0, y: 400, title: "mini collection" }); + // let doc5 = Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", { // x: 650, y: 500, width: 600, height: 600, title: "cat 2" // }); @@ -72,6 +81,7 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) { // mainNodes.Data.push(doc2); mainNodes.Data.push(doc4); mainNodes.Data.push(doc3); + //mainNodes.Data.push(PDFDoc); // mainNodes.Data.push(doc5); // mainNodes.Data.push(doc1); //mainNodes.Data.push(doc2); diff --git a/src/Utils.ts b/src/Utils.ts index cc1d8f6c6..e2b4309bb 100644 --- a/src/Utils.ts +++ b/src/Utils.ts @@ -19,4 +19,6 @@ export class Utils { return { scale, translateX, translateY }; } + + public static pdf_example = require('../deploy/test.pdf'); }
\ No newline at end of file diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index 90124d36c..cca6f50e9 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -11,6 +11,8 @@ import { ImageField } from "../fields/ImageField"; import { ImageBox } from "../views/nodes/ImageBox"; import { CollectionFreeFormView } from "../views/collections/CollectionFreeFormView"; import { FIELD_ID } from "../fields/Field"; +import { PDFBox } from "../views/nodes/PDFBox"; +import { PDFField } from "../fields/PDFField"; interface DocumentOptions { x?: number; @@ -126,6 +128,32 @@ export namespace Documents { return Server.GetDocument(imageProtoId, true)!; } + let PDFProtoId: FIELD_ID; + function GetPDFPrototype(): Document { + if (PDFProtoId === undefined) { + let PDFProto = new Document(); + PDFProtoId = PDFProto.Id; + PDFProto.Set(KeyStore.Title, new TextField("PDF PROTO")); + PDFProto.Set(KeyStore.X, new NumberField(0)); + PDFProto.Set(KeyStore.Y, new NumberField(0)); + PDFProto.Set(KeyStore.Width, new NumberField(300)); + PDFProto.Set(KeyStore.Height, new NumberField(300)); + PDFProto.Set(KeyStore.Layout, new TextField(PDFBox.LayoutString())); + PDFProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); + Server.AddDocument(PDFProto); + return PDFProto; + } + return Server.GetDocument(PDFProtoId, true)!; + } + + export function PDFDocument(url: string, options: DocumentOptions = {}): Document{ + let doc = GetPDFPrototype().MakeDelegate(); + setupOptions(doc, options); + doc.Set(KeyStore.Data, new PDFField(new URL(url))); + Server.AddDocument(doc); + return Server.GetDocument(doc.Id, true); + } + export function ImageDocument(url: string, options: DocumentOptions = {}): Document { let doc = GetImagePrototype().MakeDelegate(); setupOptions(doc, options); diff --git a/src/fields/ImageField.ts b/src/fields/ImageField.ts index bc2e7cdf4..b7470b657 100644 --- a/src/fields/ImageField.ts +++ b/src/fields/ImageField.ts @@ -1,5 +1,6 @@ import { BasicField } from "./BasicField"; import { Field } from "./Field"; +import {observable} from "mobx" export class ImageField extends BasicField<URL> { constructor(data: URL | undefined = undefined) { @@ -13,5 +14,8 @@ export class ImageField extends BasicField<URL> { Copy(): Field { return new ImageField(this.Data); } + + @observable + Page:Number = 1; }
\ No newline at end of file diff --git a/src/fields/PDFField.ts b/src/fields/PDFField.ts new file mode 100644 index 000000000..fe74cd99e --- /dev/null +++ b/src/fields/PDFField.ts @@ -0,0 +1,17 @@ +import { BasicField } from "./BasicField"; +import { Field } from "./Field"; + +export class PDFField extends BasicField<URL> { + constructor(data: URL | undefined = undefined) { + super(data == undefined ? new URL("") : data); + } + + toString(): string { + return this.Data.href; + } + + Copy(): Field { + return new PDFField(this.Data); + } + +}
\ No newline at end of file diff --git a/src/typings/index.d.ts b/src/typings/index.d.ts new file mode 100644 index 000000000..e4a66f7f2 --- /dev/null +++ b/src/typings/index.d.ts @@ -0,0 +1,322 @@ +/// <reference types="node" /> + +declare module '@react-pdf/renderer' { + import * as React from 'react'; + + namespace ReactPDF { + interface Style { + [property: string]: any; + } + interface Styles { + [key: string]: Style; + } + type Orientation = 'portrait' | 'landscape'; + + interface DocumentProps { + title?: string; + author?: string; + subject?: string; + keywords?: string; + creator?: string; + producer?: string; + onRender?: () => any; + } + + /** + * This component represent the PDF document itself. It must be the root + * of your tree element structure, and under no circumstances should it be + * used as children of another react-pdf component. In addition, it should + * only have childs of type <Page />. + */ + class Document extends React.Component<DocumentProps> {} + + interface NodeProps { + style?: Style | Style[]; + /** + * Render component in all wrapped pages. + * @see https://react-pdf.org/advanced#fixed-components + */ + fixed?: boolean; + /** + * Force the wrapping algorithm to start a new page when rendering the + * element. + * @see https://react-pdf.org/advanced#page-breaks + */ + break?: boolean; + } + + interface PageProps extends NodeProps { + /** + * Enable page wrapping for this page. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + size?: string | [number, number] | {width: number; height: number}; + orientation?: Orientation; + ruler?: boolean; + rulerSteps?: number; + verticalRuler?: boolean; + verticalRulerSteps?: number; + horizontalRuler?: boolean; + horizontalRulerSteps?: number; + ref?: Page; + } + + /** + * Represents single page inside the PDF document, or a subset of them if + * using the wrapping feature. A <Document /> can contain as many pages as + * you want, but ensure not rendering a page inside any component besides + * Document. + */ + class Page extends React.Component<PageProps> {} + + interface ViewProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + render?: (props: {pageNumber: number}) => React.ReactNode; + children?: React.ReactNode; + } + + /** + * The most fundamental component for building a UI and is designed to be + * nested inside other views and can have 0 to many children. + */ + class View extends React.Component<ViewProps> {} + + interface ImageProps extends NodeProps { + debug?: boolean; + src: string | {data: Buffer; format: 'png' | 'jpg'}; + cache?: boolean; + } + + /** + * A React component for displaying network or local (Node only) JPG or + * PNG images, as well as base64 encoded image strings. + */ + class Image extends React.Component<ImageProps> {} + + interface TextProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + render?: ( + props: {pageNumber: number; totalPages: number}, + ) => React.ReactNode; + children?: React.ReactNode; + /** + * How much hyphenated breaks should be avoided. + */ + hyphenationCallback?: number; + } + + /** + * A React component for displaying text. Text supports nesting of other + * Text or Link components to create inline styling. + */ + class Text extends React.Component<TextProps> {} + + interface LinkProps extends NodeProps { + /** + * Enable/disable page wrapping for element. + * @see https://react-pdf.org/components#page-wrapping + */ + wrap?: boolean; + debug?: boolean; + src: string; + children?: React.ReactNode; + } + + /** + * A React component for displaying an hyperlink. Link’s can be nested + * inside a Text component, or being inside any other valid primitive. + */ + class Link extends React.Component<LinkProps> {} + + interface NoteProps extends NodeProps { + children: string; + } + + class Note extends React.Component<NoteProps> {} + + interface BlobProviderParams { + blob: Blob | null; + url: string | null; + loading: boolean; + error: Error | null; + } + interface BlobProviderProps { + document: React.ReactElement<DocumentProps>; + children: (params: BlobProviderParams) => React.ReactNode; + } + + /** + * Easy and declarative way of getting document's blob data without + * showing it on screen. + * @see https://react-pdf.org/advanced#on-the-fly-rendering + * @platform web + */ + class BlobProvider extends React.Component<BlobProviderProps> {} + + interface PDFViewerProps { + width?: number; + height?: number; + style?: Style | Style[]; + className?: string; + children?: React.ReactElement<DocumentProps>; + } + + /** + * Iframe PDF viewer for client-side generated documents. + * @platform web + */ + class PDFViewer extends React.Component<PDFViewerProps> {} + + interface PDFDownloadLinkProps { + document: React.ReactElement<DocumentProps>; + fileName?: string; + style?: Style | Style[]; + className?: string; + children?: + | React.ReactNode + | ((params: BlobProviderParams) => React.ReactNode); + } + + /** + * Anchor tag to enable generate and download PDF documents on the fly. + * @see https://react-pdf.org/advanced#on-the-fly-rendering + * @platform web + */ + class PDFDownloadLink extends React.Component<PDFDownloadLinkProps> {} + + interface EmojiSource { + url: string; + format: string; + } + interface RegisteredFont { + src: string; + loaded: boolean; + loading: boolean; + data: any; + [key: string]: any; + } + type HyphenationCallback = ( + words: string[], + glyphString: {[key: string]: any}, + ) => string[]; + + const Font: { + register: ( + src: string, + options: {family: string; [key: string]: any}, + ) => void; + getEmojiSource: () => EmojiSource; + getRegisteredFonts: () => string[]; + registerEmojiSource: (emojiSource: EmojiSource) => void; + registerHyphenationCallback: ( + hyphenationCallback: HyphenationCallback, + ) => void; + getHyphenationCallback: () => HyphenationCallback; + getFont: (fontFamily: string) => RegisteredFont | undefined; + load: ( + fontFamily: string, + document: React.ReactElement<DocumentProps>, + ) => Promise<void>; + clear: () => void; + reset: () => void; + }; + + const StyleSheet: { + hairlineWidth: number; + create: <TStyles>(styles: TStyles) => TStyles; + resolve: ( + style: Style, + container: { + width: number; + height: number; + orientation: Orientation; + }, + ) => Style; + flatten: (...styles: Style[]) => Style; + absoluteFillObject: { + position: 'absolute'; + left: 0; + right: 0; + top: 0; + bottom: 0; + }; + }; + + const version: any; + + const PDFRenderer: any; + + const createInstance: ( + element: { + type: string; + props: {[key: string]: any}; + }, + root?: any, + ) => any; + + const pdf: ( + document: React.ReactElement<DocumentProps>, + ) => { + isDirty: () => boolean; + updateContainer: (document: React.ReactElement<any>) => void; + toBuffer: () => NodeJS.ReadableStream; + toBlob: () => Blob; + toString: () => string; + }; + + const renderToStream: ( + document: React.ReactElement<DocumentProps>, + ) => NodeJS.ReadableStream; + + const renderToFile: ( + document: React.ReactElement<DocumentProps>, + filePath: string, + callback?: (output: NodeJS.ReadableStream, filePath: string) => any, + ) => Promise<NodeJS.ReadableStream>; + + const render: typeof renderToFile; + } + + const Document: typeof ReactPDF.Document; + const Page: typeof ReactPDF.Page; + const View: typeof ReactPDF.View; + const Image: typeof ReactPDF.Image; + const Text: typeof ReactPDF.Text; + const Link: typeof ReactPDF.Link; + const Note: typeof ReactPDF.Note; + const Font: typeof ReactPDF.Font; + const StyleSheet: typeof ReactPDF.StyleSheet; + const createInstance: typeof ReactPDF.createInstance; + const PDFRenderer: typeof ReactPDF.PDFRenderer; + const version: typeof ReactPDF.version; + const pdf: typeof ReactPDF.pdf; + + export default ReactPDF; + export { + Document, + Page, + View, + Image, + Text, + Link, + Note, + Font, + StyleSheet, + createInstance, + PDFRenderer, + version, + pdf, + }; + }
\ No newline at end of file diff --git a/src/views/nodes/ImageBox.tsx b/src/views/nodes/ImageBox.tsx index 123c76d19..2f7cbbcc4 100644 --- a/src/views/nodes/ImageBox.tsx +++ b/src/views/nodes/ImageBox.tsx @@ -10,15 +10,29 @@ import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView import { FieldWaiting } from '../../fields/Field'; import { observer } from "mobx-react" import { observable, action } from 'mobx'; +import 'react-pdf/dist/Page/AnnotationLayer.css' +//@ts-ignore +import { Document, Page, PDFPageProxy, PageAnnotation} from "react-pdf"; +import { Utils } from '../../Utils'; +import { any } from 'prop-types'; +import { Sticky } from './Sticky'; @observer export class ImageBox extends React.Component<FieldViewProps> { public static LayoutString() { return FieldView.LayoutString("ImageBox"); } + private _ref: React.RefObject<HTMLDivElement>; + + private _mainDiv = React.createRef<HTMLDivElement>() + private _downX: number = 0; private _downY: number = 0; private _lastTap: number = 0; + + @observable + private stickies:any[] = [] + @observable private _photoIndex: number = 0; @observable private _isOpen: boolean = false; @@ -38,55 +52,197 @@ export class ImageBox extends React.Component<FieldViewProps> { componentWillUnmount() { } - onPointerDown = (e: React.PointerEvent): void => { - if (Date.now() - this._lastTap < 300) { - if (e.buttons === 1 && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { - e.stopPropagation(); - this._downX = e.clientX; - this._downY = e.clientY; - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - } else { - this._lastTap = Date.now(); + + + @action + onPageBack = () => { + if (this.page > 1){ + this.page -= 1; + this.stickies = this.stickiesPerPage[this.page - 1]; } } + @action - onPointerUp = (e: PointerEvent): void => { - document.removeEventListener("pointerup", this.onPointerUp); - if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { - this._isOpen = true; + onPageForward = () => { + if (this.page < this.numPage){ + this.page += 1; + this.stickies = this.stickiesPerPage[this.page - 1]; } - e.stopPropagation(); } - lightbox = (path: string) => { - const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; - if (this._isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { - return (<Lightbox - mainSrc={images[this._photoIndex]} - nextSrc={images[(this._photoIndex + 1) % images.length]} - prevSrc={images[(this._photoIndex + images.length - 1) % images.length]} - onCloseRequest={() => this.setState({ isOpen: false })} - onMovePrevRequest={action(() => - this._photoIndex = (this._photoIndex + images.length - 1) % images.length - )} - onMoveNextRequest={action(() => - this._photoIndex = (this._photoIndex + 1) % images.length - )} - />) + + @observable + searchText:string = ''; + + @observable + page:number = 1; //default is the first page. + + @observable + numPage:number = 1; //default number of pages + + @observable + stickiesPerPage: any = [...Array(this.numPage)].map(() => Array(1)); //makes 2d array for storage + + private textContent:any = null; + + private initX:number = 0; + private initY:number = 0; + + private _toolOn:boolean = false; + + + selectionTool = () => { + this._toolOn = true; + } + + private _highlighter:boolean = false; + + + onPointerDown = (e: React.PointerEvent) => { + + if (this._toolOn){ + let mouse = e.nativeEvent; + this.initX = mouse.offsetX; + this.initY = mouse.offsetY; + } + if (this._highlighter){ + } } - render() { - let field = this.props.doc.Get(this.props.fieldKey); - let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : - field instanceof ImageField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif"; + makeEditableAndHighlight = (colour:string) => { + var range, sel = window.getSelection(); + if (sel.rangeCount && sel.getRangeAt) { + range = sel.getRangeAt(0); + } + document.designMode = "on"; + if (range) { + sel.removeAllRanges(); + sel.addRange(range); + } + if (!document.execCommand("HiliteColor", false, colour)) { + document.execCommand("HIliteColor", false, colour); + } + document.designMode = "off"; + } + + + highlight = (colour:string) => { + var range, sel; + if (window.getSelection()) { + try { + console.log(document.getSelection()) + + + if (!document.execCommand("HiliteColor", false, colour)) { + this.makeEditableAndHighlight(colour); + } else if (document.execCommand("HiliteColor", false, "rgba(76, 175, 80, 0.3)")) { + this.makeEditableAndHighlight("black"); + } + } catch (ex) { + this.makeEditableAndHighlight(colour) + } + + } + } + + @action + onPointerUp = (e:React.PointerEvent) => { + this.highlight("rgba(76, 175, 80, 0.3)"); + + if (this._toolOn){ + + let mouse = e.nativeEvent; + let finalX = mouse.offsetX; + let finalY = mouse.offsetY; + let width = Math.abs(finalX - this.initX); + let height = Math.abs(finalY - this.initY); + + if (this._mainDiv.current){ + let sticky = <Sticky key ={Utils.GenerateGuid()}Height = {height} Width = {width} X = {this.initX} Y = {this.initY}/> + this.stickies.push(sticky); + //this.stickiesPerPage[this.page - 1].push(sticky); + } + + this._toolOn = false; + } + + } + + + displaySticky = () => { + try{ + this.stickies.filter( () => { + return this.stickies[this.stickies.length - 1] + }).map( (element: any) => { + return element + }) + } catch (ex) { + console.log(ex); //should be null + } + } + render() { return ( - <div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} > - <img src={path} width="100%" alt="Image not found" /> - {this.lightbox(path)} - </div>) + <div ref = {this._mainDiv} + onPointerDown ={this.onPointerDown} + onPointerUp = {this.onPointerUp} + > + { this.stickies.filter( () => { + return this.stickies[this.stickies.length - 1] + }).map( (element: any) => { + return element + }) + } + + + + } + } + + + <button onClick = {this.onPageBack}>{"<"}</button> + <button onClick = {this.onPageForward}>{">"}</button> + <button onClick ={this.selectionTool}>{"Area"}</button> + <Document + file={Utils.pdf_example} + + onLoadError={ + (error: any) => { + console.log(error); + } + } + > + <Page + pageNumber={this.page} + + onLoadSuccess={ + (page: PDFPageProxy) => { + page.getTextContent().then((obj:any) => { + this.textContent = obj + }); + this.numPage = page.transport.numPages + + } + } + + onGetAnnotationSuccess = { + (anno: any) => { + console.log(anno) + } + } + + + + /> + + + + + </Document> + + + </div> + ); } }
\ No newline at end of file diff --git a/src/views/nodes/PDFBox.scss b/src/views/nodes/PDFBox.scss new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/views/nodes/PDFBox.scss diff --git a/src/views/nodes/PDFBox.tsx b/src/views/nodes/PDFBox.tsx new file mode 100644 index 000000000..6d881d530 --- /dev/null +++ b/src/views/nodes/PDFBox.tsx @@ -0,0 +1,102 @@ +import Lightbox from 'react-image-lightbox'; +import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app +import { SelectionManager } from "../../util/SelectionManager"; +import "./ImageBox.scss"; +import React = require("react") +import { PDFField } from '../../fields/PDFField'; +import { FieldViewProps, FieldView } from './FieldView'; +import { CollectionFreeFormDocumentView } from './CollectionFreeFormDocumentView'; +import { FieldWaiting } from '../../fields/Field'; +import { observer } from "mobx-react" + +const {PdfLoader, + PdfHighlighter, + Tip, + Highlight, + Popup, + Spinner, + AreaHighlight} = require( "react-pdf-highlighter" ) + +import { observable, action } from 'mobx'; + +@observer +export class PDFBox extends React.Component<FieldViewProps> { + + public static LayoutString() { return FieldView.LayoutString("ImageBox"); } + private _ref: React.RefObject<HTMLDivElement>; + private _downX: number = 0; + private _downY: number = 0; + private _lastTap: number = 0; + @observable private _photoIndex: number = 0; + @observable private _isOpen: boolean = false; + + constructor(props: FieldViewProps) { + super(props); + + this._ref = React.createRef(); + this.state = { + photoIndex: 0, + isOpen: false, + + }; + } + + componentDidMount() { + } + + componentWillUnmount() { + } + + onPointerDown = (e: React.PointerEvent): void => { + if (Date.now() - this._lastTap < 300) { + if (e.buttons === 1 && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { + e.stopPropagation(); + this._downX = e.clientX; + + this._downY = e.clientY; + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); + } + } else { + this._lastTap = Date.now(); + } + } + @action + onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointerup", this.onPointerUp); + if (Math.abs(e.clientX - this._downX) < 2 && Math.abs(e.clientY - this._downY) < 2) { + this._isOpen = true; + } + e.stopPropagation(); + } + + lightbox = (path: string) => { + const images = [path, "http://www.cs.brown.edu/~bcz/face.gif"]; + if (this._isOpen && this.props.DocumentViewForField instanceof CollectionFreeFormDocumentView && SelectionManager.IsSelected(this.props.DocumentViewForField)) { + return (<Lightbox + mainSrc={images[this._photoIndex]} + nextSrc={images[(this._photoIndex + 1) % images.length]} + prevSrc={images[(this._photoIndex + images.length - 1) % images.length]} + onCloseRequest={() => this.setState({ isOpen: false })} + onMovePrevRequest={action(() => + this._photoIndex = (this._photoIndex + images.length - 1) % images.length + )} + onMoveNextRequest={action(() => + this._photoIndex = (this._photoIndex + 1) % images.length + )} + />) + } + } + + render() { + let field = this.props.doc.Get(this.props.fieldKey); + let path = field == FieldWaiting ? "https://image.flaticon.com/icons/svg/66/66163.svg" : + field instanceof PDFField ? field.Data.href : "http://www.cs.brown.edu/~bcz/face.gif"; + + return ( + <div className="imageBox-cont" onPointerDown={this.onPointerDown} ref={this._ref} > + <PdfLoader url={"https://arxiv.org/pdf/1708.08021.pdf"}/> + + </div>) + } +}
\ No newline at end of file diff --git a/src/views/nodes/Sticky.tsx b/src/views/nodes/Sticky.tsx new file mode 100644 index 000000000..254c410c2 --- /dev/null +++ b/src/views/nodes/Sticky.tsx @@ -0,0 +1,90 @@ +import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app +import { SelectionManager } from "../../util/SelectionManager"; +import "./ImageBox.scss"; +import React = require("react") +import { FieldViewProps, FieldView } from './FieldView'; +import { observer } from "mobx-react" +import { observable, action } from 'mobx'; +import 'react-pdf/dist/Page/AnnotationLayer.css' +//@ts-ignore +import { Document, Page, PDFPageProxy, PageAnnotation} from "react-pdf"; +import { Utils } from '../../Utils'; + + +interface IProps{ + Height:number; + Width:number; + X:number; + Y:number; +} + + + +@observer +export class Sticky extends React.Component<IProps> { + + + private initX:number = 0; + private initY:number = 0; + + private _ref = React.createRef<HTMLCanvasElement>(); + private ctx:any; + + + + drawDown = (e:React.PointerEvent) => { + if (this._ref.current){ + this.ctx = this._ref.current.getContext("2d"); + let mouse = e.nativeEvent; + this.initX = mouse.offsetX; + this.initY = mouse.offsetY; + + //do thiiissss + this.ctx.lineWidth; + + this.ctx.beginPath(); + this.ctx.lineTo(this.initX, this.initY); + this.ctx.strokeStyle = "black"; + + document.addEventListener("pointermove", this.drawMove); + document.addEventListener("pointerup", this.drawUp); + } + } + + //when user drags + drawMove = (e: PointerEvent):void =>{ + //x and y mouse movement + let x = this.initX += e.movementX, + y = this.initY += e.movementY; + //connects the point + this.ctx.lineTo(x, y); + this.ctx.stroke(); + } + + drawUp = (e:PointerEvent) => { + this.ctx.closePath(); + document.removeEventListener("pointermove", this.drawMove); + } + + + + render() { + return ( + <div onPointerDown = {this.drawDown}> + <canvas ref = {this._ref} height = {this.props.Height} width = {this.props.Width} + + style = {{position:"absolute", + top: "20px", + left: "0px", + zIndex: 1, + background: "yellow", + transform: `translate(${this.props.X}px, ${this.props.Y}px)`, + opacity: 0.4 + }} + + /> + + </div> + ); + } +}
\ No newline at end of file |