aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.DS_Storebin0 -> 6148 bytes
-rw-r--r--package-lock.json119
-rw-r--r--src/.DS_Storebin0 -> 6148 bytes
-rw-r--r--src/client/documents/Documents.ts221
-rw-r--r--src/client/util/DragManager.ts8
-rw-r--r--src/client/views/Main.tsx18
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx7
-rw-r--r--src/client/views/nodes/DocumentView.tsx6
-rw-r--r--src/client/views/nodes/FieldView.tsx13
-rw-r--r--src/client/views/nodes/ImageBox.tsx1
-rw-r--r--src/client/views/nodes/WebBox.scss14
-rw-r--r--src/client/views/nodes/WebBox.tsx38
-rw-r--r--src/client/views/nodes/WebView.tsx22
-rw-r--r--src/fields/Document.ts5
-rw-r--r--src/fields/WebField.ts30
-rw-r--r--src/server/Message.ts2
-rw-r--r--src/server/ServerUtil.ts3
17 files changed, 331 insertions, 176 deletions
diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 000000000..8493b4a74
--- /dev/null
+++ b/.DS_Store
Binary files differ
diff --git a/package-lock.json b/package-lock.json
index d74c77819..4f3176751 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,8 @@
"integrity": "sha512-7jGW8ppV0ant637pIqAcFfQDDH1orEPGJb8aXfUozuCU3QqX7rX4DA8iwrbPrR1hcH0FTTHz47yQnk+bl5xHQA==",
"requires": {
"regenerator-runtime": "^0.12.0"
+<<<<<<< HEAD
+=======
},
"dependencies": {
"regenerator-runtime": {
@@ -17,6 +19,7 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz",
"integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg=="
}
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@fortawesome/fontawesome-common-types": {
@@ -67,6 +70,8 @@
"requires": {
"@types/connect": "*",
"@types/node": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/bson": {
@@ -75,6 +80,7 @@
"integrity": "sha512-j+UcCWI+FsbI5/FQP/Kj2CXyplWAz39ktHFkXk84h7dNblKRSoNJs95PZFRd96NQGqsPEPgeclqnznWZr14ZDA==",
"requires": {
"@types/node": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/caseless": {
@@ -94,6 +100,8 @@
"integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==",
"requires": {
"@types/node": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/connect-flash": {
@@ -102,6 +110,7 @@
"integrity": "sha512-QC93TwnTZ0sk//bfT81o7U4GOedbOZAcgvqi0v1vJqCESC8tqIVnhzB1CHiAUBUWFjoxG5JQF0TYaNa6DMb6Ig==",
"requires": {
"@types/express": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/express": {
@@ -112,6 +121,8 @@
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/serve-static": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/express-flash": {
@@ -121,6 +132,7 @@
"requires": {
"@types/connect-flash": "*",
"@types/express": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/express-serve-static-core": {
@@ -130,6 +142,8 @@
"requires": {
"@types/node": "*",
"@types/range-parser": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/express-session": {
@@ -155,6 +169,7 @@
"integrity": "sha512-JAMFhOaHIciYVh8fb5/83nmuO/AHwmto+Hq7a9y8FzLDcC1KCU344XDOMEmahnrTFlHjgh4L0WJFczNIX2GxnQ==",
"requires": {
"@types/node": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/jquery": {
@@ -163,6 +178,8 @@
"integrity": "sha512-FhJvBninYD36v3k6c+bVk1DSZwh7B5Dpb/Pyk3HKVsiohn0nhbefZZ+3JXbWQhFyt0MxSl2jRDdGQPHeOHFXrQ==",
"requires": {
"@types/sizzle": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/jsonwebtoken": {
@@ -171,6 +188,7 @@
"integrity": "sha512-YKnUTR4VxwljbPORPrRon9E3uel1aD8nUdvzqArCCdMTWPvo0gnI2UZkwIHN2QATdj6HYXV/Iq3/KcecAO42Ww==",
"requires": {
"@types/node": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/lodash": {
@@ -378,6 +396,8 @@
"integrity": "sha512-XiYCcn/CBajrj18vLA3kO79AHr5yZTCJe2kl87ZNTRxLO14y9D0IGeGZ3xLsqhfYrJSkkVzAJV8v+bQ4nuKCRQ==",
"requires": {
"@types/react": "*"
+<<<<<<< HEAD
+=======
}
},
"@types/request": {
@@ -389,6 +409,7 @@
"@types/form-data": "*",
"@types/node": "*",
"@types/tough-cookie": "*"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"@types/serve-static": {
@@ -1204,6 +1225,8 @@
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
+<<<<<<< HEAD
+=======
}
},
"better-assert": {
@@ -1212,6 +1235,7 @@
"integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
"requires": {
"callsite": "1.0.0"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"big.js": {
@@ -1639,6 +1663,8 @@
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
+<<<<<<< HEAD
+=======
}
},
"character-parser": {
@@ -1647,6 +1673,7 @@
"integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
"requires": {
"is-regex": "^1.0.3"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"check-error": {
@@ -2587,6 +2614,8 @@
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
+<<<<<<< HEAD
+=======
}
},
"ecdsa-sig-formatter": {
@@ -2595,6 +2624,7 @@
"integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
"requires": {
"safe-buffer": "^5.0.1"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"ee-first": {
@@ -2639,6 +2669,8 @@
"dev": true,
"requires": {
"once": "^1.4.0"
+<<<<<<< HEAD
+=======
}
},
"engine.io": {
@@ -2702,6 +2734,7 @@
"base64-arraybuffer": "0.1.5",
"blob": "0.0.5",
"has-binary2": "~1.0.2"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"enhanced-resolve": {
@@ -2991,6 +3024,8 @@
"resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz",
"integrity": "sha512-r0nrHTCYtAMrFwZ0kBzZEXa1vtPVrw0dKvGSrKP4dahwBQ1BJpF2/y1Pp4sCD/0kvxV4zZeclyvfmw0B4RMJQA==",
"requires": {
+<<<<<<< HEAD
+=======
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"crc": "3.4.4",
@@ -3026,6 +3061,7 @@
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
"integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
"requires": {
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"assign-symbols": "^1.0.0",
"is-extendable": "^1.0.1"
},
@@ -3139,6 +3175,8 @@
"promise": "^7.0.3",
"ua-parser-js": "^0.7.9",
"whatwg-fetch": "^0.9.0"
+<<<<<<< HEAD
+=======
},
"dependencies": {
"core-js": {
@@ -3146,6 +3184,7 @@
"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
}
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"figgy-pudding": {
@@ -4074,6 +4113,8 @@
"requires": {
"ajv": "^6.5.5",
"har-schema": "^2.0.0"
+<<<<<<< HEAD
+=======
}
},
"has": {
@@ -4082,6 +4123,7 @@
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"has-ansi": {
@@ -4090,6 +4132,8 @@
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"requires": {
"ansi-regex": "^2.0.0"
+<<<<<<< HEAD
+=======
}
},
"has-binary2": {
@@ -4105,6 +4149,7 @@
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
"integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4="
}
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"has-cors": {
@@ -4853,6 +4898,8 @@
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"requires": {
"minimist": "^1.2.0"
+<<<<<<< HEAD
+=======
}
},
"jsonwebtoken": {
@@ -4876,6 +4923,7 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"jsprim": {
@@ -5540,6 +5588,8 @@
"dev": true,
"requires": {
"has-flag": "^3.0.0"
+<<<<<<< HEAD
+=======
}
}
}
@@ -5589,6 +5639,7 @@
"integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==",
"requires": {
"lodash": "^4.17.10"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"ms": {
@@ -5615,6 +5666,8 @@
"mkdirp": "^0.5.1",
"rimraf": "^2.5.4",
"run-queue": "^1.0.3"
+<<<<<<< HEAD
+=======
}
},
"mpath": {
@@ -5647,6 +5700,7 @@
"ms": "2.0.0"
}
}
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"ms": {
@@ -6553,8 +6607,12 @@
},
"copy-concurrently": {
"version": "1.0.5",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
"integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"aproba": "^1.1.1",
"fs-write-stream-atomic": "^1.0.8",
@@ -7020,8 +7078,12 @@
},
"gauge": {
"version": "2.7.4",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"aproba": "^1.0.3",
"console-control-strings": "^1.0.0",
@@ -7057,8 +7119,12 @@
},
"gentle-fs": {
"version": "2.0.1",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/gentle-fs/-/gentle-fs-2.0.1.tgz",
"integrity": "sha512-cEng5+3fuARewXktTEGbwsktcldA+YsnUEaXZwcK/3pjSE1X9ObnTs+/8rYf8s+RnIcQm2D5x3rwpN7Zom8Bew==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"aproba": "^1.1.2",
"fs-vacuum": "^1.2.10",
@@ -7126,8 +7192,12 @@
},
"got": {
"version": "6.7.1",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz",
"integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"create-error-class": "^3.0.0",
"duplexer3": "^0.1.4",
@@ -7470,8 +7540,12 @@
},
"libcipm": {
"version": "3.0.3",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/libcipm/-/libcipm-3.0.3.tgz",
"integrity": "sha512-71V5CpTI+zFydTc5IjJ/tx8JHbXEJvmYF2zaSVW1V3X1rRnRjXqh44iuiyry1xgi3ProUQ1vX1uwFiWs00+2og==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"bin-links": "^1.1.2",
"bluebird": "^3.5.1",
@@ -7492,8 +7566,12 @@
},
"libnpm": {
"version": "2.0.1",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/libnpm/-/libnpm-2.0.1.tgz",
"integrity": "sha512-qTKoxyJvpBxHZQB6k0AhSLajyXq9ZE/lUsZzuHAplr2Bpv9G+k4YuYlExYdUCeVRRGqcJt8hvkPh4tBwKoV98w==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"bin-links": "^1.1.2",
"bluebird": "^3.5.3",
@@ -7795,8 +7873,12 @@
},
"make-fetch-happen": {
"version": "4.0.1",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz",
"integrity": "sha512-7R5ivfy9ilRJ1EMKIOziwrns9fGeAD4bAha8EB7BIiBBLHm2KeTUGCrICFt2rbHfzheTLynv50GnNTK1zDTrcQ==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"agentkeepalive": "^3.4.1",
"cacache": "^11.0.1",
@@ -7906,8 +7988,12 @@
},
"move-concurrently": {
"version": "1.0.1",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
"integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"aproba": "^1.1.1",
"copy-concurrently": "^1.0.0",
@@ -7946,8 +8032,12 @@
},
"node-gyp": {
"version": "3.8.0",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"fstream": "^1.0.0",
"glob": "^7.0.3",
@@ -8037,8 +8127,12 @@
},
"npm-lifecycle": {
"version": "2.1.0",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-2.1.0.tgz",
"integrity": "sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"byline": "^5.0.0",
"graceful-fs": "^4.1.11",
@@ -8228,8 +8322,12 @@
},
"pacote": {
"version": "9.4.0",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/pacote/-/pacote-9.4.0.tgz",
"integrity": "sha512-WQ1KL/phGMkedYEQx9ODsjj7xvwLSpdFJJdEXrLyw5SILMxcTNt5DTxT2Z93fXuLFYJBlZJdnwdalrQdB/rX5w==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"bluebird": "^3.5.3",
"cacache": "^11.3.2",
@@ -8586,8 +8684,12 @@
},
"request": {
"version": "2.88.0",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
@@ -8986,8 +9088,12 @@
},
"tar": {
"version": "4.4.8",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"chownr": "^1.1.1",
"fs-minipass": "^1.2.5",
@@ -9334,8 +9440,12 @@
},
"yargs": {
"version": "11.0.0",
+<<<<<<< HEAD
+ "bundled": true,
+=======
"resolved": "https://registry.npmjs.org/yargs/-/yargs-11.0.0.tgz",
"integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==",
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.1.1",
@@ -10103,6 +10213,8 @@
"parse-asn1": "^5.0.0",
"randombytes": "^2.0.1",
"safe-buffer": "^5.1.2"
+<<<<<<< HEAD
+=======
}
},
"pug": {
@@ -10212,6 +10324,7 @@
"integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=",
"requires": {
"pug-error": "^1.3.2"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"pug-walk": {
@@ -11138,6 +11251,8 @@
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "^1.1.5"
+<<<<<<< HEAD
+=======
}
}
}
@@ -11222,6 +11337,7 @@
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"isarray": {
@@ -13247,6 +13363,8 @@
"graceful-fs": "^4.1.11",
"imurmurhash": "^0.1.4",
"signal-exit": "^3.0.2"
+<<<<<<< HEAD
+=======
}
},
"ws": {
@@ -13255,6 +13373,7 @@
"integrity": "sha512-tbSxiT+qJI223AP4iLfQbkbxkwdFcneYinM2+x46Gx2wgvbaOMO36czfdfVUBRTHvzAMRhDd98sA5d/BuWbQdg==",
"requires": {
"async-limiter": "~1.0.0"
+>>>>>>> bb418216efa9cc2e191b970e4cbe5080f4fd2b87
}
},
"xdg-basedir": {
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 000000000..4d6acb95a
--- /dev/null
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 9770e5cdc..8b733507b 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -7,10 +7,12 @@ import { ListField } from "../../fields/ListField";
import { FormattedTextBox } from "../views/nodes/FormattedTextBox";
import { ImageField } from "../../fields/ImageField";
import { ImageBox } from "../views/nodes/ImageBox";
+import { WebField } from "../../fields/WebField";
+import { WebBox } from "../views/nodes/WebBox";
import { CollectionView, CollectionViewType } from "../views/collections/CollectionView";
-import { FieldView } from "../views/nodes/FieldView";
import { HtmlField } from "../../fields/HtmlField";
-import { WebView } from "../views/nodes/WebView";
+import { Key } from "../../fields/Key"
+import { Field } from "../../fields/Field";
export interface DocumentOptions {
x?: number;
@@ -20,109 +22,110 @@ export interface DocumentOptions {
nativeWidth?: number;
nativeHeight?: number;
title?: string;
+ panx?: number;
+ pany?: number;
+ scale?: number;
+ layout?: string;
+ layoutKeys?: Key[];
+ viewType?: number;
}
export namespace Documents {
+ let textProto: Document;
+ let imageProto: Document;
+ let webProto: Document;
+ let collProto: Document;
+ const textProtoId = "textProto";
+ const imageProtoId = "imageProto";
+ const webProtoId = "webProto";
+ const collProtoId = "collectionProto";
+
export function initProtos(callback: () => void) {
- Server.GetFields([collectionProtoId, textProtoId, imageProtoId], (fields) => {
- collectionProto = fields[collectionProtoId] as Document;
+ Server.GetFields([collProtoId, textProtoId, imageProtoId], (fields) => {
+ collProto = fields[collProtoId] as Document;
imageProto = fields[imageProtoId] as Document;
textProto = fields[textProtoId] as Document;
+ webProto = fields[webProtoId] as Document;
callback()
});
}
+ function assignOptions(doc: Document, options: DocumentOptions): Document {
+ if (options.x !== undefined) { doc.SetNumber(KeyStore.X, options.x); }
+ if (options.y !== undefined) { doc.SetNumber(KeyStore.Y, options.y); }
+ if (options.width !== undefined) { doc.SetNumber(KeyStore.Width, options.width); }
+ if (options.height !== undefined) { doc.SetNumber(KeyStore.Height, options.height); }
+ if (options.nativeWidth !== undefined) { doc.SetNumber(KeyStore.NativeWidth, options.nativeWidth); }
+ if (options.nativeHeight !== undefined) { doc.SetNumber(KeyStore.NativeHeight, options.nativeHeight); }
+ if (options.title !== undefined) { doc.SetText(KeyStore.Title, options.title); }
+ if (options.panx !== undefined) { doc.SetNumber(KeyStore.PanX, options.panx); }
+ if (options.pany !== undefined) { doc.SetNumber(KeyStore.PanY, options.pany); }
+ if (options.scale !== undefined) { doc.SetNumber(KeyStore.Scale, options.scale); }
+ if (options.viewType !== undefined) { doc.SetNumber(KeyStore.ViewType, options.viewType); }
+ if (options.layout !== undefined) { doc.SetText(KeyStore.Layout, options.layout); }
+ if (options.layoutKeys !== undefined) { doc.Set(KeyStore.LayoutKeys, new ListField(options.layoutKeys)); }
+ return doc;
+ }
+ function setupPrototypeOptions(protoId: string, title: string, layout: string, options: DocumentOptions): Document {
+ return assignOptions(new Document(protoId), { ...options, title: title, layout: layout });
+ }
+ function SetInstanceOptions<T, U extends Field & { Data: T }>(doc: Document, options: DocumentOptions, value: T, ctor: { new(): U }, id?: string) {
+ var deleg = doc.MakeDelegate(id);
+ deleg.SetData(KeyStore.Data, value, ctor);
+ return assignOptions(deleg, options);
+ }
- function setupOptions(doc: Document, options: DocumentOptions): void {
- if (options.x !== undefined) {
- doc.SetData(KeyStore.X, options.x, NumberField);
- }
- if (options.y !== undefined) {
- doc.SetData(KeyStore.Y, options.y, NumberField);
- }
- if (options.width !== undefined) {
- doc.SetData(KeyStore.Width, options.width, NumberField);
- }
- if (options.height !== undefined) {
- doc.SetData(KeyStore.Height, options.height, NumberField);
- }
- if (options.nativeWidth !== undefined) {
- doc.SetData(KeyStore.NativeWidth, options.nativeWidth, NumberField);
- }
- if (options.nativeHeight !== undefined) {
- doc.SetData(KeyStore.NativeHeight, options.nativeHeight, NumberField);
- }
- if (options.title !== undefined) {
- doc.SetData(KeyStore.Title, options.title, TextField);
+ function GetImagePrototype(): Document {
+ if (!imageProto) {
+ imageProto = setupPrototypeOptions(imageProtoId, "IMAGE_PROTO", CollectionView.LayoutString("AnnotationsKey"),
+ { x: 0, y: 0, nativeWidth: 300, width: 300, layoutKeys: [KeyStore.Data, KeyStore.Annotations] });
+ imageProto.SetText(KeyStore.BackgroundLayout, ImageBox.LayoutString());
}
- doc.SetData(KeyStore.Scale, 1, NumberField);
- doc.SetData(KeyStore.PanX, 0, NumberField);
- doc.SetData(KeyStore.PanY, 0, NumberField);
+ return imageProto;
}
-
- let textProto: Document;
- const textProtoId = "textProto";
function GetTextPrototype(): Document {
- if (!textProto) {
- textProto = new Document(textProtoId);
- textProto.Set(KeyStore.X, new NumberField(0));
- textProto.Set(KeyStore.Y, new NumberField(0));
- textProto.Set(KeyStore.Width, new NumberField(300));
- textProto.Set(KeyStore.Height, new NumberField(150));
- textProto.Set(KeyStore.Layout, new TextField(FormattedTextBox.LayoutString()));
- textProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
- }
- return textProto;
+ return textProto ? textProto :
+ textProto = setupPrototypeOptions(textProtoId, "TEXT_PROTO", FormattedTextBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 150, layoutKeys: [KeyStore.Data] });
}
-
- export function TextDocument(options: DocumentOptions = {}): Document {
- let doc = GetTextPrototype().MakeDelegate();
- setupOptions(doc, options);
- // doc.SetField(KeyStore.Data, new RichTextField());
- return doc;
+ function GetWebPrototype(): Document {
+ return webProto ? webProto :
+ webProto = setupPrototypeOptions(webProtoId, "WEB_PROTO", WebBox.LayoutString(),
+ { x: 0, y: 0, width: 300, height: 300, layoutKeys: [KeyStore.Data] });
}
-
- let htmlProto: Document;
- const htmlProtoId = "htmlProto";
- function GetHtmlPrototype(): Document {
- if (!htmlProto) {
- htmlProto = new Document(htmlProtoId);
- htmlProto.Set(KeyStore.X, new NumberField(0));
- htmlProto.Set(KeyStore.Y, new NumberField(0));
- htmlProto.Set(KeyStore.Width, new NumberField(300));
- htmlProto.Set(KeyStore.Height, new NumberField(150));
- htmlProto.Set(KeyStore.Layout, new TextField(WebView.LayoutString()));
- htmlProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
- }
- return htmlProto;
+ function GetCollectionPrototype(): Document {
+ return collProto ? collProto :
+ collProto = setupPrototypeOptions(collProtoId, "COLLECTION_PROTO", CollectionView.LayoutString("DataKey"),
+ { panx: 0, pany: 0, scale: 1, layoutKeys: [KeyStore.Data] });
}
- export function HtmlDocument(html: string, options: DocumentOptions = {}): Document {
- let doc = GetHtmlPrototype().MakeDelegate();
- setupOptions(doc, options);
- doc.Set(KeyStore.Data, new HtmlField(html));
+ export function ImageDocument(url: string, options: DocumentOptions = {}) {
+ let doc = SetInstanceOptions(GetImagePrototype(), { ...options, layoutKeys: [KeyStore.Data, KeyStore.Annotations, KeyStore.Caption] },
+ new URL(url), ImageField);
+ doc.SetText(KeyStore.Caption, "my caption...");
+ doc.SetText(KeyStore.BackgroundLayout, EmbeddedCaption());
+ doc.SetText(KeyStore.OverlayLayout, FixedCaption());
return doc;
}
+ export function TextDocument(options: DocumentOptions = {}) {
+ return SetInstanceOptions(GetTextPrototype(), options, "", TextField);
+ }
+ export function WebDocument(url: string, options: DocumentOptions = {}) {
+ return SetInstanceOptions(GetWebPrototype(), options, new URL(url), WebField);
+ }
+ export function HtmlDocument(html: string, options: DocumentOptions = {}) {
+ return SetInstanceOptions(GetWebPrototype(), options, html, HtmlField);
+ }
+ export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
+ return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Freeform }, documents, ListField, id)
+ }
+ export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
+ return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Schema }, documents, ListField, id)
+ }
+ export function DockDocument(config: string, options: DocumentOptions, id?: string) {
+ return SetInstanceOptions(GetCollectionPrototype(), { ...options, viewType: CollectionViewType.Docking }, config, TextField, id)
+ }
- let imageProto: Document;
- const imageProtoId = "imageProto";
- function GetImagePrototype(): Document {
- if (!imageProto) {
- imageProto = new Document(imageProtoId);
- imageProto.Set(KeyStore.Title, new TextField("IMAGE PROTO"));
- imageProto.Set(KeyStore.X, new NumberField(0));
- imageProto.Set(KeyStore.Y, new NumberField(0));
- imageProto.Set(KeyStore.NativeWidth, new NumberField(300));
- imageProto.Set(KeyStore.Width, new NumberField(300));
- imageProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("AnnotationsKey")));
- imageProto.SetNumber(KeyStore.ViewType, CollectionViewType.Freeform)
- imageProto.Set(KeyStore.BackgroundLayout, new TextField(ImageBox.LayoutString()));
- // imageProto.SetField(KeyStore.Layout, new TextField('<div style={"background-image: " + {Data}} />'));
- imageProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations]));
- return imageProto;
- }
- return imageProto;
- }
// example of custom display string for an image that shows a caption.
function EmbeddedCaption() {
@@ -140,54 +143,4 @@ export namespace Documents {
+ FormattedTextBox.LayoutString("CaptionKey") +
`</div>
</div>` };
-
- export function ImageDocument(url: string, options: DocumentOptions = {}): Document {
- let doc = GetImagePrototype().MakeDelegate();
- setupOptions(doc, options);
- doc.Set(KeyStore.Data, new ImageField(new URL(url)));
- doc.Set(KeyStore.Caption, new TextField("my caption..."));
- doc.Set(KeyStore.BackgroundLayout, new TextField(EmbeddedCaption()));
- doc.Set(KeyStore.OverlayLayout, new TextField(FixedCaption()));
- doc.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data, KeyStore.Annotations, KeyStore.Caption]));
- console.log("" + doc.GetNumber(KeyStore.Height, 311));
- return doc;
- }
-
- let collectionProto: Document;
- const collectionProtoId = "collectionProto";
- function GetCollectionPrototype(): Document {
- if (!collectionProto) {
- collectionProto = new Document(collectionProtoId);
- collectionProto.Set(KeyStore.Scale, new NumberField(1));
- collectionProto.Set(KeyStore.PanX, new NumberField(0));
- collectionProto.Set(KeyStore.PanY, new NumberField(0));
- collectionProto.Set(KeyStore.Layout, new TextField(CollectionView.LayoutString("DataKey")));
- collectionProto.Set(KeyStore.LayoutKeys, new ListField([KeyStore.Data]));
- }
- return collectionProto;
- }
-
- export function CollectionDocument(data: Array<Document> | string, viewType: CollectionViewType, options: DocumentOptions = {}, id?: string): Document {
- let doc = GetCollectionPrototype().MakeDelegate(id);
- setupOptions(doc, options);
- if (typeof data === "string") {
- doc.SetText(KeyStore.Data, data);
- } else {
- doc.SetData(KeyStore.Data, data, ListField);
- }
- doc.SetNumber(KeyStore.ViewType, viewType);
- return doc;
- }
-
- export function FreeformDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
- return CollectionDocument(documents, CollectionViewType.Freeform, options, id)
- }
-
- export function SchemaDocument(documents: Array<Document>, options: DocumentOptions, id?: string) {
- return CollectionDocument(documents, CollectionViewType.Schema, options, id)
- }
-
- export function DockDocument(config: string, options: DocumentOptions, id?: string) {
- return CollectionDocument(config, CollectionViewType.Docking, options, id)
- }
} \ No newline at end of file
diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts
index 6b4b8ca57..60910a40b 100644
--- a/src/client/util/DragManager.ts
+++ b/src/client/util/DragManager.ts
@@ -133,7 +133,6 @@ export namespace DragManager {
if (hideSource) {
ele.hidden = true;
}
-
const moveHandler = (e: PointerEvent) => {
e.stopPropagation();
e.preventDefault();
@@ -158,14 +157,19 @@ export namespace DragManager {
}
const upHandler = (e: PointerEvent) => {
abortDrag();
- FinishDrag(dragElement, e, dragData, options);
+ FinishDrag(ele, e, dragData, options);
};
document.addEventListener("pointermove", moveHandler, true);
document.addEventListener("pointerup", upHandler);
}
function FinishDrag(dragEle: HTMLElement, e: PointerEvent, dragData: { [index: string]: any }, options?: DragOptions) {
+ let parent = dragEle.parentElement;
+ if (parent)
+ parent.removeChild(dragEle);
const target = document.elementFromPoint(e.x, e.y);
+ if (parent)
+ parent.appendChild(dragEle);
if (!target) {
return;
}
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 7ef4b6132..578aecd1e 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -84,6 +84,9 @@ Documents.initProtos(() => {
let addImageNode = action(() => Documents.ImageDocument("https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Cat03.jpg/1200px-Cat03.jpg", {
width: 200, height: 200, title: "an image of a cat"
}));
+ let addWebNode = action(() => Documents.WebDocument("https://cs.brown.edu/courses/cs166/", {
+ width: 200, height: 200, title: "a sample web page"
+ }));
let addClick = (creator: any) => action(() => {
var img = creator();
@@ -93,6 +96,7 @@ Documents.initProtos(() => {
});
let imgRef = React.createRef<HTMLDivElement>();
+ let webRef = React.createRef<HTMLDivElement>();
let textRef = React.createRef<HTMLDivElement>();
let schemaRef = React.createRef<HTMLDivElement>();
let colRef = React.createRef<HTMLDivElement>();
@@ -110,15 +114,17 @@ Documents.initProtos(() => {
<ContextMenu />
<div style={{ position: 'absolute', bottom: '0px', left: '0px', width: '150px' }} ref={imgRef} >
<button onPointerDown={setupDrag(imgRef, addImageNode)} onClick={addClick(addImageNode)}>Add Image</button></div>
- <div style={{ position: 'absolute', bottom: '25px', left: '0px', width: '150px' }} ref={textRef}>
+ <div style={{ position: 'absolute', bottom: '25px', left: '0px', width: '150px' }} ref={webRef} >
+ <button onPointerDown={setupDrag(webRef, addWebNode)} onClick={addClick(addWebNode)}>Add Web</button></div>
+ <div style={{ position: 'absolute', bottom: '50px', left: '0px', width: '150px' }} ref={textRef}>
<button onPointerDown={setupDrag(textRef, addTextNode)} onClick={addClick(addTextNode)}>Add Text</button></div>
- <div style={{ position: 'absolute', bottom: '50px', left: '0px', width: '150px' }} ref={colRef}>
+ <div style={{ position: 'absolute', bottom: '75px', left: '0px', width: '150px' }} ref={colRef}>
<button onPointerDown={setupDrag(colRef, addColNode)} onClick={addClick(addColNode)}>Add Collection</button></div>
- <div style={{ position: 'absolute', bottom: '75px', left: '0px', width: '150px' }} ref={schemaRef}>
+ <div style={{ position: 'absolute', bottom: '100px', left: '0px', width: '150px' }} ref={schemaRef}>
<button onPointerDown={setupDrag(schemaRef, addSchemaNode)} onClick={addClick(addSchemaNode)}>Add Schema</button></div>
- <button style={{ position: 'absolute', bottom: '100px', left: '0px', width: '150px' }} onClick={clearDatabase}>Clear Database</button>
- <button style={{ position: 'absolute', bottom: '25', right: '0px', width: '150px' }} onClick={() => UndoManager.Undo()}>Undo</button>
- <button style={{ position: 'absolute', bottom: '0', right: '0px', width: '150px' }} onClick={() => UndoManager.Redo()}>Redo</button>
+ <button style={{ position: 'absolute', bottom: '125px', left: '0px', width: '150px' }} onClick={clearDatabase}>Clear Database</button>
+ <button style={{ position: 'absolute', bottom: '25px', right: '0px', width: '150px' }} onClick={() => UndoManager.Undo()}>Undo</button>
+ <button style={{ position: 'absolute', bottom: '0px', right: '0px', width: '150px' }} onClick={() => UndoManager.Redo()}>Redo</button>
</div>),
document.getElementById('root'));
})
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 12909c151..2edd5d953 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -10,13 +10,12 @@ import { Transform } from "../../util/Transform";
import { undoBatch } from "../../util/UndoManager";
import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionSchemaView } from "../collections/CollectionSchemaView";
-import { CollectionTreeView } from "../collections/CollectionTreeView";
import { CollectionView } from "../collections/CollectionView";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
import { DocumentView } from "../nodes/DocumentView";
-import { WebView } from "../nodes/WebView";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
+import { WebBox } from "../nodes/WebBox";
import "./CollectionFreeFormView.scss";
import { COLLECTION_BORDER_WIDTH } from "./CollectionView";
import { CollectionViewBase } from "./CollectionViewBase";
@@ -200,7 +199,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
get backgroundView() {
return !this.backgroundLayout ? (null) :
(<JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
bindings={this.props.bindings}
jsx={this.backgroundLayout}
showWarnings={true}
@@ -211,7 +210,7 @@ export class CollectionFreeFormView extends CollectionViewBase {
get overlayView() {
return !this.overlayLayout ? (null) :
(<JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
bindings={this.props.bindings}
jsx={this.overlayLayout}
showWarnings={true}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index feecde921..c929f9d54 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -12,10 +12,10 @@ import { CollectionDockingView } from "../collections/CollectionDockingView";
import { CollectionFreeFormView } from "../collections/CollectionFreeFormView";
import { CollectionSchemaView } from "../collections/CollectionSchemaView";
import { CollectionView, CollectionViewType } from "../collections/CollectionView";
-import { WebView } from "./WebView";
import { ContextMenu } from "../ContextMenu";
import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
+import { WebBox } from "../nodes/WebBox";
import "./DocumentView.scss";
import React = require("react");
const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
@@ -119,6 +119,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return;
}
if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
+ document.removeEventListener("pointermove", this.onPointerMove)
+ document.removeEventListener("pointerup", this.onPointerUp)
this._contextMenuCanOpen = false;
if (this._mainCont.current != null && !this.topMost) {
this._contextMenuCanOpen = false;
@@ -195,7 +197,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
@computed get mainContent() {
var val = this.props.Document.Id;
return <JsxParser
- components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebView }}
+ components={{ FormattedTextBox, ImageBox, CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox }}
bindings={this._documentBindings}
jsx={this.layout}
showWarnings={true}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index b71309bf5..a883fa672 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -7,11 +7,12 @@ import { TextField } from "../../../fields/TextField";
import { NumberField } from "../../../fields/NumberField";
import { RichTextField } from "../../../fields/RichTextField";
import { ImageField } from "../../../fields/ImageField";
+import { WebField } from "../../../fields/WebField";
import { Key } from "../../../fields/Key";
import { FormattedTextBox } from "./FormattedTextBox";
import { ImageBox } from "./ImageBox";
+import { WebBox } from "./WebBox";
import { HtmlField } from "../../../fields/HtmlField";
-import { WebView } from "./WebView";
//
// these properties get assigned through the render() method of the DocumentView when it creates this node.
@@ -50,12 +51,16 @@ export class FieldView extends React.Component<FieldViewProps> {
else if (field instanceof ImageField) {
return <ImageBox {...this.props} />
}
+ else if (field instanceof WebField) {
+ return <WebBox {...this.props} />
+ }
+ // bcz: this belongs here, but it doesn't render well so taking it out for now
+ // else if (field instanceof HtmlField) {
+ // return <WebBox {...this.props} />
+ // }
else if (field instanceof NumberField) {
return <p>{field.Data}</p>
}
- else if (field instanceof HtmlField) {
- return <WebView {...this.props} />
- }
else if (field != FieldWaiting) {
return <p>{JSON.stringify(field.GetValue())}</p>
}
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 4fe73fb8d..e206bf8d5 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -9,7 +9,6 @@ import { FieldWaiting } from '../../../fields/Field';
import { observer } from "mobx-react"
import { observable, action } from 'mobx';
import { KeyStore } from '../../../fields/KeyStore';
-import { element } from 'prop-types';
@observer
export class ImageBox extends React.Component<FieldViewProps> {
diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss
new file mode 100644
index 000000000..e72b3c4da
--- /dev/null
+++ b/src/client/views/nodes/WebBox.scss
@@ -0,0 +1,14 @@
+
+.webBox-cont {
+ padding: 0vw;
+ position: absolute;
+ width: 100%;
+ height: 100%;
+}
+
+.webBox-button {
+ padding : 0vw;
+ border: none;
+ width : 100%;
+ height: 100%;
+} \ No newline at end of file
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
new file mode 100644
index 000000000..2ca8d49ce
--- /dev/null
+++ b/src/client/views/nodes/WebBox.tsx
@@ -0,0 +1,38 @@
+import "./WebBox.scss";
+import React = require("react")
+import { WebField } from '../../../fields/WebField';
+import { FieldViewProps, FieldView } from './FieldView';
+import { FieldWaiting } from '../../../fields/Field';
+import { observer } from "mobx-react"
+import { computed } from 'mobx';
+import { KeyStore } from '../../../fields/KeyStore';
+
+@observer
+export class WebBox extends React.Component<FieldViewProps> {
+
+ public static LayoutString() { return FieldView.LayoutString(WebBox); }
+
+ constructor(props: FieldViewProps) {
+ super(props);
+ }
+
+ @computed get html(): string { return this.props.doc.GetHtml(KeyStore.Data, ""); }
+
+ 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 WebField ? field.Data.href : "https://crossorigin.me/" + "https://cs.brown.edu";
+
+ let content = this.html ?
+ <span dangerouslySetInnerHTML={{ __html: this.html }}></span> :
+ <div style={{ width: "100%", height: "100%", position: "absolute" }}>
+ <iframe src={path} style={{ position: "absolute", width: "100%", height: "100%" }}></iframe>
+ {this.props.isSelected() ? (null) : <div style={{ width: "100%", height: "100%", position: "absolute" }} />}
+ </div>;
+
+ return (
+ <div className="webBox-cont" >
+ {content}
+ </div>)
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/WebView.tsx b/src/client/views/nodes/WebView.tsx
deleted file mode 100644
index 717aa8bf5..000000000
--- a/src/client/views/nodes/WebView.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { FieldViewProps, FieldView } from "./FieldView";
-import { computed } from "mobx";
-import { observer } from "mobx-react";
-import { KeyStore } from "../../../fields/KeyStore";
-import React = require('react')
-import { TextField } from "../../../fields/TextField";
-import { HtmlField } from "../../../fields/HtmlField";
-import { RichTextField } from "../../../fields/RichTextField";
-
-@observer
-export class WebView extends React.Component<FieldViewProps> {
- public static LayoutString(fieldStr: string = "DataKey") { return FieldView.LayoutString(WebView, fieldStr) }
-
- @computed
- get html(): string {
- return this.props.doc.GetData(KeyStore.Data, HtmlField, "" as string);
- }
-
- render() {
- return <span dangerouslySetInnerHTML={{ __html: this.html }}></span>
- }
-} \ No newline at end of file
diff --git a/src/fields/Document.ts b/src/fields/Document.ts
index 6193ea56c..5b91de6ed 100644
--- a/src/fields/Document.ts
+++ b/src/fields/Document.ts
@@ -8,6 +8,7 @@ import { ListField } from "./ListField";
import { Server } from "../client/Server";
import { Types } from "../server/Message";
import { UndoManager } from "../client/util/UndoManager";
+import { HtmlField } from "./HtmlField";
export class Document extends Field {
public fields: ObservableMap<string, { key: Key, field: Field }> = new ObservableMap();
@@ -125,6 +126,10 @@ export class Document extends Field {
return vval;
}
+ GetHtml(key: Key, defaultVal: string): string {
+ return this.GetData(key, HtmlField, defaultVal);
+ }
+
GetNumber(key: Key, defaultVal: number): number {
return this.GetData(key, NumberField, defaultVal);
}
diff --git a/src/fields/WebField.ts b/src/fields/WebField.ts
new file mode 100644
index 000000000..8f945d686
--- /dev/null
+++ b/src/fields/WebField.ts
@@ -0,0 +1,30 @@
+import { BasicField } from "./BasicField";
+import { Field, FieldId } from "./Field";
+import { Types } from "../server/Message";
+
+export class WebField extends BasicField<URL> {
+ constructor(data: URL | undefined = undefined, id?: FieldId, save: boolean = true) {
+ super(data == undefined ? new URL("https://crossorigin.me/" + "https://cs.brown.edu/") : data, save, id);
+ }
+
+ toString(): string {
+ return this.Data.href;
+ }
+
+ ToScriptString(): string {
+ return `new WebField("${this.Data}")`;
+ }
+
+ Copy(): Field {
+ return new WebField(this.Data);
+ }
+
+ ToJson(): { type: Types, data: URL, _id: string } {
+ return {
+ type: Types.Web,
+ data: this.Data,
+ _id: this.Id
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/server/Message.ts b/src/server/Message.ts
index 80fc9a80d..148e6e723 100644
--- a/src/server/Message.ts
+++ b/src/server/Message.ts
@@ -45,7 +45,7 @@ export class GetFieldArgs {
}
export enum Types {
- Number, List, Key, Image, Document, Text, RichText, DocumentReference, Html
+ Number, List, Key, Image, Web, Document, Text, RichText, DocumentReference, Html
}
export class DocumentTransfer implements Transferable {
diff --git a/src/server/ServerUtil.ts b/src/server/ServerUtil.ts
index 08e72fdae..a53fb5d2b 100644
--- a/src/server/ServerUtil.ts
+++ b/src/server/ServerUtil.ts
@@ -10,6 +10,7 @@ import { Server } from './../client/Server';
import { Types } from './Message';
import { Utils } from '../Utils';
import { HtmlField } from '../fields/HtmlField';
+import { WebField } from '../fields/WebField';
export class ServerUtils {
public static FromJson(json: any): Field {
@@ -30,6 +31,8 @@ export class ServerUtils {
return new TextField(data, id, false)
case Types.Html:
return new HtmlField(data, id, false)
+ case Types.Web:
+ return new WebField(new URL(data), id, false)
case Types.RichText:
return new RichTextField(data, id, false)
case Types.Key: