aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kim <andrewdkim@users.noreply.github.com>2019-02-23 16:19:45 -0500
committerAndrew Kim <andrewdkim@users.noreply.github.com>2019-02-23 16:19:45 -0500
commit07f5e56508c362725db003736a0f7980cd72107d (patch)
tree697242d7468203c46a5847cef2d24bd0d4001968
parent5b55e1b6081393989ca35d2964da9604c2a93802 (diff)
PDFNode
-rw-r--r--.DS_Storebin0 -> 6148 bytes
-rw-r--r--.vscode/launch.json2
-rw-r--r--deploy/test.pdfbin0 -> 54836 bytes
-rw-r--r--package-lock.json211
-rw-r--r--package.json5
-rw-r--r--src/.DS_Storebin0 -> 6148 bytes
-rw-r--r--src/Main.tsx14
-rw-r--r--src/Utils.ts2
-rw-r--r--src/documents/Documents.ts28
-rw-r--r--src/fields/ImageField.ts4
-rw-r--r--src/fields/PDFField.ts17
-rw-r--r--src/typings/index.d.ts322
-rw-r--r--src/views/nodes/ImageBox.tsx234
-rw-r--r--src/views/nodes/PDFBox.scss0
-rw-r--r--src/views/nodes/PDFBox.tsx102
-rw-r--r--src/views/nodes/Sticky.tsx90
-rw-r--r--tsconfig.json4
-rw-r--r--webpack.config.js10
18 files changed, 1002 insertions, 43 deletions
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..13ddc33a9
--- /dev/null
+++ b/.DS_Store
Binary files differ
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9a0a9afb4..04dbfecc3 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"name": "Launch Chrome against localhost",
"sourceMaps": true,
"breakOnLoad": true,
- "url": "http://localhost:1050",
+ "url": "http://localhost:1234",
"webRoot": "${workspaceFolder}"
},
{
diff --git a/deploy/test.pdf b/deploy/test.pdf
new file mode 100644
index 000000000..99d31cef1
--- /dev/null
+++ b/deploy/test.pdf
Binary files differ
diff --git a/package-lock.json b/package-lock.json
index 9fbe16195..7c5acda72 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4,6 +4,14 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+ "@babel/runtime": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.3.1.tgz",
+ "integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
+ "requires": {
+ "regenerator-runtime": "^0.12.0"
+ }
+ },
"@fortawesome/fontawesome-common-types": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.14.tgz",
@@ -664,6 +672,22 @@
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ }
+ }
+ },
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -1350,6 +1374,11 @@
"serialize-javascript": "^1.4.0"
}
},
+ "core-js": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.4.tgz",
+ "integrity": "sha512-05qQ5hXShcqGkPZpXEFLIpxayZscVD2kuMBZewxiIPPEagukO4mqgPA9CWhUvFBJfy3ODdK2p9xyHh7FTU9/7A=="
+ },
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -2235,6 +2264,16 @@
"integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
"dev": true
},
+ "file-loader": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
+ "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^1.0.2",
+ "schema-utils": "^1.0.0"
+ }
+ },
"fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -3994,6 +4033,11 @@
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
"integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
},
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
+ },
"lodash.tail": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz",
@@ -4105,6 +4149,11 @@
"integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
"dev": true
},
+ "make-event-props": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/make-event-props/-/make-event-props-1.2.0.tgz",
+ "integrity": "sha512-BmWFkm/jZzVH9A0tEBdkjAARUz/eha+5IRyfOndeSMKRadkgR5DawoBHoRwLxkYmjJOI5bHkXKpaZocxj+dKgg=="
+ },
"map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
@@ -4189,6 +4238,11 @@
"trim-newlines": "^1.0.0"
}
},
+ "merge-class-names": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/merge-class-names/-/merge-class-names-1.1.1.tgz",
+ "integrity": "sha512-+UUWBUoFw9QLY/UlBKU/xk9h6OhyG3BUDDuF2eIJcxmusWb/uedvNpZGkysqMw5b/ds+wkX7NJTDSdUuRsCNyA=="
+ },
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
@@ -4514,6 +4568,11 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
+ "node-ensure": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/node-ensure/-/node-ensure-0.0.0.tgz",
+ "integrity": "sha1-7K52QVDemYYexcgQ/V0Jaxg5Mqc="
+ },
"node-forge": {
"version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
@@ -8037,6 +8096,15 @@
"sha.js": "^2.4.8"
}
},
+ "pdfjs-dist": {
+ "version": "2.0.489",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.489.tgz",
+ "integrity": "sha1-Y+VLKSqGeQpFRpfrRNQ0e4+/rSc=",
+ "requires": {
+ "node-ensure": "^0.0.0",
+ "worker-loader": "^1.1.1"
+ }
+ },
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -8426,6 +8494,11 @@
"unpipe": "1.0.0"
}
},
+ "re-resizable": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/re-resizable/-/re-resizable-4.5.1.tgz",
+ "integrity": "sha512-amjlp4IuTSHs4XG1bP5WbAgBDIZitODKIsqcpZsNhEBYYEidol0dlP4S9zHiN3iu6Tff4WfYuruihLgN7RJeQw=="
+ },
"react": {
"version": "16.7.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz",
@@ -8448,6 +8521,15 @@
"scheduler": "^0.12.0"
}
},
+ "react-draggable": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-3.1.1.tgz",
+ "integrity": "sha512-tqIgDUm4XPSFbxelYpcsnayPU79P26ChnszDl5/RDFKfMuHnRxypS+OFfEyAEO1CtqaB3lrecQ2dyNIE2G0TlQ==",
+ "requires": {
+ "classnames": "^2.2.5",
+ "prop-types": "^15.6.0"
+ }
+ },
"react-golden-layout": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/react-golden-layout/-/react-golden-layout-1.0.6.tgz",
@@ -8506,6 +8588,110 @@
"threads": "^0.8.0"
}
},
+ "react-pdf": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/react-pdf/-/react-pdf-4.0.2.tgz",
+ "integrity": "sha512-r+KCiAS0nggH7SfBHxZDWbvBpInBrr3/zeC0dVsQrgSt0G7JFaqRyLZtd1fduBJvLT8FBQtCVQEef2SBAwcotw==",
+ "requires": {
+ "@babel/runtime": "^7.0.0",
+ "lodash.once": "^4.1.1",
+ "make-event-props": "^1.1.0",
+ "merge-class-names": "^1.1.1",
+ "pdfjs-dist": "2.0.943",
+ "prop-types": "^15.6.2"
+ },
+ "dependencies": {
+ "pdfjs-dist": {
+ "version": "2.0.943",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.943.tgz",
+ "integrity": "sha512-iLhNcm4XceTHRaSU5o22ZGCm4YpuW5+rf4+BJFH/feBhMQLbCGBry+Jet8Q419QDI4qgARaIQzXuiNrsNWS8Yw==",
+ "requires": {
+ "node-ensure": "^0.0.0",
+ "worker-loader": "^2.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "worker-loader": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
+ "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
+ "requires": {
+ "loader-utils": "^1.0.0",
+ "schema-utils": "^0.4.0"
+ }
+ }
+ }
+ },
+ "react-pdf-highlighter": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-pdf-highlighter/-/react-pdf-highlighter-2.1.2.tgz",
+ "integrity": "sha512-aKa/rzpFjOywcRmNyfupvrGdh7mp0VGS9RKCWDbD9p32+P3+DhJvQe/2qCvDAnTXa4LmabNqM+O0RDUcai1C1Q==",
+ "requires": {
+ "lodash": "^4.17.10",
+ "pdfjs-dist": "2.0.489",
+ "react-pointable": "^1.1.1",
+ "react-rnd": "^7.1.5"
+ }
+ },
+ "react-pdf-js": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/react-pdf-js/-/react-pdf-js-4.0.2.tgz",
+ "integrity": "sha512-6IWHYatHSMfmTc/kwfr7KTNUU+Z/oyztgxoSXQIo4ZBmDhprTRtM+uXEpPEuR+qLFF/StssHN+Oo7vFVdkQIFg==",
+ "requires": {
+ "pdfjs-dist": "2.0.943"
+ },
+ "dependencies": {
+ "pdfjs-dist": {
+ "version": "2.0.943",
+ "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.0.943.tgz",
+ "integrity": "sha512-iLhNcm4XceTHRaSU5o22ZGCm4YpuW5+rf4+BJFH/feBhMQLbCGBry+Jet8Q419QDI4qgARaIQzXuiNrsNWS8Yw==",
+ "requires": {
+ "node-ensure": "^0.0.0",
+ "worker-loader": "^2.0.0"
+ }
+ },
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ },
+ "worker-loader": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-2.0.0.tgz",
+ "integrity": "sha512-tnvNp4K3KQOpfRnD20m8xltE3eWh89Ye+5oj7wXEEHKac1P4oZ6p9oTj8/8ExqoSBnk9nu5Pr4nKfQ1hn2APJw==",
+ "requires": {
+ "loader-utils": "^1.0.0",
+ "schema-utils": "^0.4.0"
+ }
+ }
+ }
+ },
+ "react-pointable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/react-pointable/-/react-pointable-1.1.3.tgz",
+ "integrity": "sha512-7skalWy38NLyKk1HcITmuloqCe2INPh69cFHbN7NcCn+Wfb0Ha4XGwGN0iVa4ZzqIHSqFRYOmV0loYNHrZ5/Sg=="
+ },
+ "react-rnd": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/react-rnd/-/react-rnd-7.4.3.tgz",
+ "integrity": "sha512-TLQ35nqXup7rC63qAETebbO6Znilr20CroTTeAdlYu8nvRSwB7BrmPKZhHB2GgeiSucOoeCyAA9pHPhbMpEd/Q==",
+ "requires": {
+ "re-resizable": "4.5.1",
+ "react-draggable": "^3.0.5"
+ }
+ },
"react-split-pane": {
"version": "0.1.85",
"resolved": "https://registry.npmjs.org/react-split-pane/-/react-split-pane-0.1.85.tgz",
@@ -8593,6 +8779,11 @@
"integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==",
"dev": true
},
+ "regenerator-runtime": {
+ "version": "0.12.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
+ "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
+ },
"regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@@ -10828,6 +11019,26 @@
"errno": "~0.1.7"
}
},
+ "worker-loader": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-1.1.1.tgz",
+ "integrity": "sha512-qJZLVS/jMCBITDzPo/RuweYSIG8VJP5P67mP/71alGyTZRe1LYJFdwLjLalY3T5ifx0bMDRD3OB6P2p1escvlg==",
+ "requires": {
+ "loader-utils": "^1.0.0",
+ "schema-utils": "^0.4.0"
+ },
+ "dependencies": {
+ "schema-utils": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.7.tgz",
+ "integrity": "sha512-v/iwU6wvwGK8HbU9yi3/nhGzP0yGSuhQMzL6ySiec1FSrZZDkhm4noOSWzrNFo/jEc+SJY6jRTwuwbSXJPDUnQ==",
+ "requires": {
+ "ajv": "^6.1.0",
+ "ajv-keywords": "^3.1.0"
+ }
+ }
+ }
+ },
"wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
diff --git a/package.json b/package.json
index 9afddb8d9..c102781d4 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"chai": "^4.2.0",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^2.1.0",
+ "file-loader": "^3.0.1",
"mocha": "^5.2.0",
"sass-loader": "^7.1.0",
"scss-loader": "0.0.1",
@@ -40,6 +41,7 @@
"@types/react-table": "^6.7.21",
"@types/typescript": "^2.0.0",
"@types/uuid": "^3.4.4",
+ "babel-runtime": "^6.26.0",
"flexlayout-react": "^0.3.3",
"golden-layout": "^1.5.9",
"mobx": "^5.9.0",
@@ -62,6 +64,9 @@
"react-image-lightbox": "^5.1.0",
"react-jsx-parser": "^1.13.0",
"react-mosaic": "0.0.20",
+ "react-pdf": "^4.0.2",
+ "react-pdf-highlighter": "^2.1.2",
+ "react-pdf-js": "^4.0.2",
"react-split-pane": "^0.1.85",
"react-table": "^6.9.0",
"url-loader": "^1.1.2",
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 000000000..96930b780
--- /dev/null
+++ b/src/.DS_Store
Binary files differ
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
diff --git a/tsconfig.json b/tsconfig.json
index 265ce4403..2dd189740 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -12,5 +12,9 @@
"exclude": [
"node_modules",
"static"
+ ],
+ "typeRoots": [
+ "./node_modules/@types",
+ "./src/typings"
]
}
diff --git a/webpack.config.js b/webpack.config.js
index 1a7c9286e..b630b2a49 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -39,6 +39,14 @@ module.exports = {
]
},
{
+ test: /\.(jpg|png|pdf)$/,
+ use: [
+ {
+ loader: 'file-loader'
+ }
+ ]
+ },
+ {
test: /\.(png|jpg|gif)$/i,
use: [
{
@@ -57,7 +65,7 @@ module.exports = {
compress: false,
host: "localhost",
contentBase: path.join(__dirname, 'deploy'),
- port: 1050,
+ port: 1234,
hot: true,
https: false,
overlay: {